From ff9169747fd24450ddcaa08c34d54d4546ca6774 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Wed, 17 May 2017 02:29:02 +0000 Subject: [PATCH] [ODRHash] Support more types in the ODR checker. Added support for TagType, TypeWithKeyword, and all children types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@303231 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ODRHash.cpp | 50 +++++++++++++++++++++++++++ test/Modules/odr_hash.cpp | 72 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index f4d314a6dd..0c42acd121 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -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) { diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index 58814dd6b3..63bf1e6f5f 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -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@first.h:* {{'RecordType::S1::x' from module 'FirstModule' is not present in definition of 'RecordType::S1' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'x' does not match}} +#endif +} + +namespace DependentType { +#if defined(FIRST) +template +class S1 { + typename T::typeA x; +}; +#elif defined(SECOND) +template +class S1 { + typename T::typeB x; +}; +#else +template +using U1 = S1; +// expected-error@first.h:* {{'DependentType::S1::x' from module 'FirstModule' is not present in definition of 'S1' in module 'SecondModule'}} +// expected-note@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@first.h:* {{'ElaboratedType::S1::x' from module 'FirstModule' is not present in definition of 'ElaboratedType::S1' in module 'SecondModule'}} +// expected-note@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@first.h:* {{'Enum::S1::x' from module 'FirstModule' is not present in definition of 'Enum::S1' in module 'SecondModule'}} +// expected-note@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. -- 2.40.0