diff options
| author | Richard Trieu <rtrieu@google.com> | 2017-03-08 00:13:19 +0000 |
|---|---|---|
| committer | Richard Trieu <rtrieu@google.com> | 2017-03-08 00:13:19 +0000 |
| commit | 33562c2dcc208ce8dca7a51900a856be9cf70f0b (patch) | |
| tree | ac5060fb7e0b4dc782cf99983c5a0b3e1224ed9d | |
| parent | 1351db49b2be3a92909ced637664e08ecd035548 (diff) | |
| download | bcm5719-llvm-33562c2dcc208ce8dca7a51900a856be9cf70f0b.tar.gz bcm5719-llvm-33562c2dcc208ce8dca7a51900a856be9cf70f0b.zip | |
[ODRHash] Hash typedefs and usings statements in classes.
llvm-svn: 297246
| -rw-r--r-- | clang/lib/AST/ODRHash.cpp | 17 | ||||
| -rw-r--r-- | clang/test/Modules/odr_hash.cpp | 105 |
2 files changed, 122 insertions, 0 deletions
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index a0b870f4dac..d72eebbe8e4 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/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/clang/test/Modules/odr_hash.cpp b/clang/test/Modules/odr_hash.cpp index 9063cd1ea76..00730a0e579 100644 --- a/clang/test/Modules/odr_hash.cpp +++ b/clang/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 |

