]> granicus.if.org Git - clang/commitdiff
[ODRHash] Hash typedefs and usings statements in classes.
authorRichard Trieu <rtrieu@google.com>
Wed, 8 Mar 2017 00:13:19 +0000 (00:13 +0000)
committerRichard Trieu <rtrieu@google.com>
Wed, 8 Mar 2017 00:13:19 +0000 (00:13 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@297246 91177308-0d34-0410-b5e6-96231b3b80d8

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

index a0b870f4dacce85a285ea0baca50af1b6db65160..d72eebbe8e48f5bf79218798096bcb467b14a2a2 100644 (file)
@@ -211,6 +211,20 @@ public:
 
     Inherited::VisitCXXMethodDecl(D);
   }
+
+  void VisitTypedefNameDecl(const TypedefNameDecl *D) {
+    AddQualType(D->getUnderlyingType());
+
+    Inherited::VisitTypedefNameDecl(D);
+  }
+
+  void VisitTypedefDecl(const TypedefDecl *D) {
+    Inherited::VisitTypedefDecl(D);
+  }
+
+  void VisitTypeAliasDecl(const TypeAliasDecl *D) {
+    Inherited::VisitTypeAliasDecl(D);
+  }
 };
 
 // Only allow a small portion of Decl's to be processed.  Remove this once
@@ -226,6 +240,8 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) {
     case Decl::CXXMethod:
     case Decl::Field:
     case Decl::StaticAssert:
+    case Decl::TypeAlias:
+    case Decl::Typedef:
       return true;
   }
 }
@@ -313,6 +329,7 @@ public:
 
   void VisitTypedefType(const TypedefType *T) {
     AddDecl(T->getDecl());
+    Hash.AddQualType(T->getDecl()->getUnderlyingType());
     VisitType(T);
   }
 };
index 9063cd1ea769a80b761089297c5b2406ae0d6376..00730a0e579cc42f1fd05dbd541155a84bb4e127 100644 (file)
@@ -430,6 +430,99 @@ struct NestedNamespaceSpecifier {};
 #endif
 }  // namespace SelfReference
 
+namespace TypeDef {
+#if defined(FIRST)
+struct S1 {
+  typedef int a;
+};
+#elif defined(SECOND)
+struct S1 {
+  typedef double a;
+};
+#else
+S1 s1;
+// expected-error@first.h:* {{'TypeDef::S1::a' from module 'FirstModule' is not present in definition of 'TypeDef::S1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'a' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S2 {
+  typedef int a;
+};
+#elif defined(SECOND)
+struct S2 {
+  typedef int b;
+};
+#else
+S2 s2;
+// expected-error@first.h:* {{'TypeDef::S2::a' from module 'FirstModule' is not present in definition of 'TypeDef::S2' in module 'SecondModule'}}
+// expected-note@second.h:* {{definition has no member 'a'}}
+#endif
+
+#if defined(FIRST)
+typedef int T;
+struct S3 {
+  typedef T a;
+};
+#elif defined(SECOND)
+typedef double T;
+struct S3 {
+  typedef T a;
+};
+#else
+S3 s3;
+// expected-error@first.h:* {{'TypeDef::S3::a' from module 'FirstModule' is not present in definition of 'TypeDef::S3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'a' does not match}}
+#endif
+}  // namespace TypeDef
+
+namespace Using {
+#if defined(FIRST)
+struct S1 {
+  using a = int;
+};
+#elif defined(SECOND)
+struct S1 {
+  using a = double;
+};
+#else
+S1 s1;
+// expected-error@first.h:* {{'Using::S1::a' from module 'FirstModule' is not present in definition of 'Using::S1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'a' does not match}}
+#endif
+
+#if defined(FIRST)
+struct S2 {
+  using a = int;
+};
+#elif defined(SECOND)
+struct S2 {
+  using b = int;
+};
+#else
+S2 s2;
+// expected-error@first.h:* {{'Using::S2::a' from module 'FirstModule' is not present in definition of 'Using::S2' in module 'SecondModule'}}
+// expected-note@second.h:* {{definition has no member 'a'}}
+#endif
+
+#if defined(FIRST)
+typedef int T;
+struct S3 {
+  using a = T;
+};
+#elif defined(SECOND)
+typedef double T;
+struct S3 {
+  using a = T;
+};
+#else
+S3 s3;
+// expected-error@first.h:* {{'Using::S3::a' from module 'FirstModule' is not present in definition of 'Using::S3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'a' does not match}}
+#endif
+}  // namespace Using
+
+
 // 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.
 namespace AllDecls {
@@ -460,6 +553,9 @@ struct S {
   inline void inline_method() {}
   void volatile_method() volatile {}
   void const_method() const {}
+
+  typedef int typedef_int;
+  using using_int = int;
 };
 #elif defined(SECOND)
 typedef int INT;
@@ -488,6 +584,9 @@ struct S {
   inline void inline_method() {}
   void volatile_method() volatile {}
   void const_method() const {}
+
+  typedef int typedef_int;
+  using using_int = int;
 };
 #else
 S *s;
@@ -521,6 +620,9 @@ struct T {
   void volatile_method() volatile {}
   void const_method() const {}
 
+  typedef int typedef_int;
+  using using_int = int;
+
   private:
 };
 #elif defined(SECOND)
@@ -551,6 +653,9 @@ struct T {
   void volatile_method() volatile {}
   void const_method() const {}
 
+  typedef int typedef_int;
+  using using_int = int;
+
   public:
 };
 #else