summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/AST/ODRHash.cpp64
-rw-r--r--clang/test/Modules/odr_hash.cpp14
2 files changed, 76 insertions, 2 deletions
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 35af0e98a91..b75de54e07f 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -102,6 +102,10 @@ public:
}
}
+ void AddQualType(QualType T) {
+ Hash.AddQualType(T);
+ }
+
void Visit(const Decl *D) {
ID.AddInteger(D->getKind());
Inherited::Visit(D);
@@ -112,6 +116,11 @@ public:
Inherited::VisitNamedDecl(D);
}
+ void VisitValueDecl(const ValueDecl *D) {
+ AddQualType(D->getType());
+ Inherited::VisitValueDecl(D);
+ }
+
void VisitAccessSpecDecl(const AccessSpecDecl *D) {
ID.AddInteger(D->getAccess());
Inherited::VisitAccessSpecDecl(D);
@@ -185,8 +194,59 @@ void ODRHash::AddDecl(const Decl *D) {
ID.AddInteger(D->getKind());
}
-void ODRHash::AddType(const Type *T) {}
-void ODRHash::AddQualType(QualType T) {}
+// Process a Type pointer. Add* methods call back into ODRHash while Visit*
+// methods process the relevant parts of the Type.
+class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
+ typedef TypeVisitor<ODRTypeVisitor> Inherited;
+ llvm::FoldingSetNodeID &ID;
+ ODRHash &Hash;
+
+public:
+ ODRTypeVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash)
+ : ID(ID), Hash(Hash) {}
+
+ void AddStmt(Stmt *S) {
+ Hash.AddBoolean(S);
+ if (S) {
+ Hash.AddStmt(S);
+ }
+ }
+
+ void Visit(const Type *T) {
+ ID.AddInteger(T->getTypeClass());
+ Inherited::Visit(T);
+ }
+
+ void VisitType(const Type *T) {}
+
+ void VisitBuiltinType(const BuiltinType *T) {
+ ID.AddInteger(T->getKind());
+ VisitType(T);
+ }
+};
+
+void ODRHash::AddType(const Type *T) {
+ assert(T && "Expecting non-null pointer.");
+ auto Result = TypeMap.insert(std::make_pair(T, TypeMap.size()));
+ ID.AddInteger(Result.first->second);
+ // On first encounter of a Type pointer, process it. Every time afterwards,
+ // only the index value is needed.
+ if (!Result.second) {
+ return;
+ }
+
+ ODRTypeVisitor(ID, *this).Visit(T);
+}
+
+void ODRHash::AddQualType(QualType T) {
+ AddBoolean(T.isNull());
+ if (T.isNull())
+ return;
+ SplitQualType split = T.split();
+ ID.AddInteger(split.Quals.getAsOpaqueValue());
+ AddType(split.Ty);
+}
+
void ODRHash::AddBoolean(bool Value) {
Bools.push_back(Value);
}
diff --git a/clang/test/Modules/odr_hash.cpp b/clang/test/Modules/odr_hash.cpp
index 2b2a788efc7..7b696346be3 100644
--- a/clang/test/Modules/odr_hash.cpp
+++ b/clang/test/Modules/odr_hash.cpp
@@ -148,6 +148,20 @@ S2 s2;
// expected-error@second.h:* {{'Field::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'y'}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x'}}
#endif
+
+#if defined(FIRST)
+struct S3 {
+ double x;
+};
+#elif defined(SECOND)
+struct S3 {
+ int x;
+};
+#else
+S3 s3;
+// expected-error@first.h:* {{'Field::S3::x' from module 'FirstModule' is not present in definition of 'Field::S3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
} // namespace Field
// Naive parsing of AST can lead to cycles in processing. Ensure
OpenPOWER on IntegriCloud