summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/DeclCXX.h5
-rw-r--r--clang/lib/AST/DeclCXX.cpp22
-rw-r--r--clang/lib/Sema/SemaDecl.cpp4
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp6
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp5
5 files changed, 28 insertions, 14 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index d663dbeea87..13921a132cf 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -464,6 +464,8 @@ class CXXRecordDecl : public RecordDecl {
/// \brief Whether we are currently parsing base specifiers.
unsigned IsParsingBaseSpecifiers : 1;
+ unsigned HasODRHash : 1;
+
/// \brief A hash of parts of the class to help in ODR checking.
unsigned ODRHash;
@@ -712,8 +714,7 @@ public:
return data().IsParsingBaseSpecifiers;
}
- void computeODRHash();
- unsigned getODRHash() const { return data().ODRHash; }
+ unsigned getODRHash() const;
/// \brief Sets the base classes of this struct or class.
void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index a1aed332a13..2e5cec9c108 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -73,8 +73,9 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
ImplicitCopyAssignmentHasConstParam(true),
HasDeclaredCopyConstructorWithConstParam(false),
HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false),
- IsParsingBaseSpecifiers(false), ODRHash(0), NumBases(0), NumVBases(0),
- Bases(), VBases(), Definition(D), FirstFriend() {}
+ IsParsingBaseSpecifiers(false), HasODRHash(false), ODRHash(0),
+ NumBases(0), NumVBases(0), Bases(), VBases(), Definition(D),
+ FirstFriend() {}
CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const {
return Bases.get(Definition->getASTContext().getExternalSource());
@@ -381,16 +382,23 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
data().IsParsingBaseSpecifiers = false;
}
-void CXXRecordDecl::computeODRHash() {
- if (!DefinitionData)
- return;
+unsigned CXXRecordDecl::getODRHash() const {
+ assert(hasDefinition() && "ODRHash only for records with definitions");
- ODRHash Hash;
- Hash.AddCXXRecordDecl(this);
+ // Previously calculated hash is stored in DefinitionData.
+ if (DefinitionData->HasODRHash)
+ return DefinitionData->ODRHash;
+ // Only calculate hash on first call of getODRHash per record.
+ ODRHash Hash;
+ Hash.AddCXXRecordDecl(getDefinition());
+ DefinitionData->HasODRHash = true;
DefinitionData->ODRHash = Hash.CalculateHash();
+
+ return DefinitionData->ODRHash;
}
+
void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
// C++11 [class.copy]p11:
// A defaulted copy/move constructor for a class X is defined as
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 02cbca8b2bb..c6a0b0101d3 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13797,10 +13797,8 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
RD->completeDefinition();
}
- if (auto *RD = dyn_cast<CXXRecordDecl>(Tag)) {
+ if (isa<CXXRecordDecl>(Tag)) {
FieldCollector->FinishClass();
- if (Context.getLangOpts().Modules)
- RD->computeODRHash();
}
// Exit this scope of this tag's definition.
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index db7d55ec0b8..2fb882c1bec 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1536,6 +1536,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
Data.HasDeclaredCopyConstructorWithConstParam = Record.readInt();
Data.HasDeclaredCopyAssignmentWithConstParam = Record.readInt();
Data.ODRHash = Record.readInt();
+ Data.HasODRHash = true;
if (Record.readInt()) {
Reader.BodySource[D] = Loc.F->Kind == ModuleKind::MK_MainFile
@@ -1673,7 +1674,6 @@ void ASTDeclReader::MergeDefinitionData(
OR_FIELD(HasDeclaredCopyConstructorWithConstParam)
OR_FIELD(HasDeclaredCopyAssignmentWithConstParam)
MATCH_FIELD(IsLambda)
- MATCH_FIELD(ODRHash)
#undef OR_FIELD
#undef MATCH_FIELD
@@ -1697,6 +1697,10 @@ void ASTDeclReader::MergeDefinitionData(
// when they occur within the body of a function template specialization).
}
+ if (D->getODRHash() != MergeDD.ODRHash) {
+ DetectedOdrViolation = true;
+ }
+
if (DetectedOdrViolation)
Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition);
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index ec59250e192..6f0d0eed5b9 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -5769,7 +5769,10 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
Record->push_back(Data.ImplicitCopyAssignmentHasConstParam);
Record->push_back(Data.HasDeclaredCopyConstructorWithConstParam);
Record->push_back(Data.HasDeclaredCopyAssignmentWithConstParam);
- Record->push_back(Data.ODRHash);
+
+ // getODRHash will compute the ODRHash if it has not been previously computed.
+ Record->push_back(D->getODRHash());
+
bool ModularCodegen = Writer->Context->getLangOpts().ModularCodegen &&
Writer->WritingModule && !D->isDependentType();
Record->push_back(ModularCodegen);
OpenPOWER on IntegriCloud