summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2017-03-08 00:13:19 +0000
committerRichard Trieu <rtrieu@google.com>2017-03-08 00:13:19 +0000
commit8e9494e0deb9375409f9fe35996d67145bc5fde1 (patch)
treebff080a2cdbf7a9ee8c5bb306ddfc3fab027ebf0
parent07aa97ba3392ffeb85cf8ceea331830c23a8cede (diff)
[ODRHash] Hash typedefs and usings statements in classes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@297246 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ODRHash.cpp17
-rw-r--r--test/Modules/odr_hash.cpp105
2 files changed, 122 insertions, 0 deletions
diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp
index a0b870f4da..d72eebbe8e 100644
--- a/lib/AST/ODRHash.cpp
+++ b/lib/AST/ODRHash.cpp
@@ -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);
}
};
diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp
index 9063cd1ea7..00730a0e57 100644
--- a/test/Modules/odr_hash.cpp
+++ b/test/Modules/odr_hash.cpp
@@ -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