]> granicus.if.org Git - clang/commitdiff
[ODRHash] Handle types in ODR hashing.
authorRichard Trieu <rtrieu@google.com>
Thu, 23 Feb 2017 03:25:57 +0000 (03:25 +0000)
committerRichard Trieu <rtrieu@google.com>
Thu, 23 Feb 2017 03:25:57 +0000 (03:25 +0000)
Fields will now have their types added to the hash, allowing for detection of
mismatched field types.  This detection allows the existing ODR checking to
produce the correct message.

Differential Revision: https://reviews.llvm.org/D21675

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@295931 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ODRHash.cpp
test/Modules/odr_hash.cpp

index 35af0e98a9129a2958893835dac52cde2c66d519..b75de54e07fbf29d227c99b5e2287cdc0e0d9df2 100644 (file)
@@ -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);
 }
index 2b2a788efc7b114497de1779228064eb2ce83cb1..7b696346be306e0918f3c9f99aa4117610555cfd 100644 (file)
@@ -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