r303231 - [ODRHash] Support more types in the ODR checker.

Richard Trieu via cfe-commits cfe-commits at lists.llvm.org
Tue May 16 19:29:03 PDT 2017


Author: rtrieu
Date: Tue May 16 21:29:02 2017
New Revision: 303231

URL: http://llvm.org/viewvc/llvm-project?rev=303231&view=rev
Log:
[ODRHash] Support more types in the ODR checker.

Added support for TagType, TypeWithKeyword, and all children types.

Modified:
    cfe/trunk/lib/AST/ODRHash.cpp
    cfe/trunk/test/Modules/odr_hash.cpp

Modified: cfe/trunk/lib/AST/ODRHash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=303231&r1=303230&r2=303231&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ODRHash.cpp (original)
+++ cfe/trunk/lib/AST/ODRHash.cpp Tue May 16 21:29:02 2017
@@ -335,6 +335,20 @@ public:
     Hash.AddQualType(T);
   }
 
+  void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
+    Hash.AddBoolean(NNS);
+    if (NNS) {
+      Hash.AddNestedNameSpecifier(NNS);
+    }
+  }
+
+  void AddIdentifierInfo(const IdentifierInfo *II) {
+    Hash.AddBoolean(II);
+    if (II) {
+      Hash.AddIdentifierInfo(II);
+    }
+  }
+
   void VisitQualifiers(Qualifiers Quals) {
     ID.AddInteger(Quals.getAsOpaqueValue());
   }
@@ -414,6 +428,42 @@ public:
     AddQualType(T->getDecl()->getUnderlyingType().getCanonicalType());
     VisitType(T);
   }
+
+  void VisitTagType(const TagType *T) {
+    AddDecl(T->getDecl());
+    VisitType(T);
+  }
+
+  void VisitRecordType(const RecordType *T) { VisitTagType(T); }
+  void VisitEnumType(const EnumType *T) { VisitTagType(T); }
+
+  void VisitTypeWithKeyword(const TypeWithKeyword *T) {
+    ID.AddInteger(T->getKeyword());
+    VisitType(T);
+  };
+
+  void VisitDependentNameType(const DependentNameType *T) {
+    AddNestedNameSpecifier(T->getQualifier());
+    AddIdentifierInfo(T->getIdentifier());
+    VisitTypeWithKeyword(T);
+  }
+
+  void VisitDependentTemplateSpecializationType(
+      const DependentTemplateSpecializationType *T) {
+    AddIdentifierInfo(T->getIdentifier());
+    AddNestedNameSpecifier(T->getQualifier());
+    ID.AddInteger(T->getNumArgs());
+    for (const auto &TA : T->template_arguments()) {
+      Hash.AddTemplateArgument(TA);
+    }
+    VisitTypeWithKeyword(T);
+  }
+
+  void VisitElaboratedType(const ElaboratedType *T) {
+    AddNestedNameSpecifier(T->getQualifier());
+    AddQualType(T->getNamedType());
+    VisitTypeWithKeyword(T);
+  }
 };
 
 void ODRHash::AddType(const Type *T) {

Modified: cfe/trunk/test/Modules/odr_hash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=303231&r1=303230&r2=303231&view=diff
==============================================================================
--- cfe/trunk/test/Modules/odr_hash.cpp (original)
+++ cfe/trunk/test/Modules/odr_hash.cpp Tue May 16 21:29:02 2017
@@ -634,6 +634,78 @@ S3 s3;
 #endif
 }  // namespace Using
 
+namespace RecordType {
+#if defined(FIRST)
+struct B1 {};
+struct S1 {
+  B1 x;
+};
+#elif defined(SECOND)
+struct A1 {};
+struct S1 {
+  A1 x;
+};
+#else
+S1 s1;
+// expected-error at first.h:* {{'RecordType::S1::x' from module 'FirstModule' is not present in definition of 'RecordType::S1' in module 'SecondModule'}}
+// expected-note at second.h:* {{declaration of 'x' does not match}}
+#endif
+}
+
+namespace DependentType {
+#if defined(FIRST)
+template <class T>
+class S1 {
+  typename T::typeA x;
+};
+#elif defined(SECOND)
+template <class T>
+class S1 {
+  typename T::typeB x;
+};
+#else
+template<class T>
+using U1 = S1<T>;
+// expected-error at first.h:* {{'DependentType::S1::x' from module 'FirstModule' is not present in definition of 'S1<T>' in module 'SecondModule'}}
+// expected-note at second.h:* {{declaration of 'x' does not match}}
+#endif
+}
+
+namespace ElaboratedType {
+#if defined(FIRST)
+namespace N1 { using type = double; }
+struct S1 {
+  N1::type x;
+};
+#elif defined(SECOND)
+namespace N1 { using type = int; }
+struct S1 {
+  N1::type x;
+};
+#else
+S1 s1;
+// expected-error at first.h:* {{'ElaboratedType::S1::x' from module 'FirstModule' is not present in definition of 'ElaboratedType::S1' in module 'SecondModule'}}
+// expected-note at second.h:* {{declaration of 'x' does not match}}
+#endif
+}
+
+namespace Enum {
+#if defined(FIRST)
+enum A1 {};
+struct S1 {
+  A1 x;
+};
+#elif defined(SECOND)
+enum A2 {};
+struct S1 {
+  A2 x;
+};
+#else
+S1 s1;
+// expected-error at first.h:* {{'Enum::S1::x' from module 'FirstModule' is not present in definition of 'Enum::S1' in module 'SecondModule'}}
+// expected-note at second.h:* {{declaration of 'x' does not match}}
+#endif
+}
 
 // Interesting cases that should not cause errors.  struct S should not error
 // while struct T should error at the access specifier mismatch at the end.




More information about the cfe-commits mailing list