From 8e9494e0deb9375409f9fe35996d67145bc5fde1 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Wed, 8 Mar 2017 00:13:19 +0000 Subject: [PATCH] [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 --- lib/AST/ODRHash.cpp | 17 ++++++ test/Modules/odr_hash.cpp | 105 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) 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 -- 2.40.0