Author: rtrieu Date: Tue May 16 22:23:35 2017 New Revision: 303233 URL: http://llvm.org/viewvc/llvm-project?rev=303233&view=rev Log: [ODRHash] Support NestedNameSpecifier
Modified: cfe/trunk/lib/AST/ODRHash.cpp cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/test/Modules/odr_hash.cpp Modified: cfe/trunk/lib/AST/ODRHash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=303233&r1=303232&r2=303233&view=diff ============================================================================== --- cfe/trunk/lib/AST/ODRHash.cpp (original) +++ cfe/trunk/lib/AST/ODRHash.cpp Tue May 16 22:23:35 2017 @@ -81,7 +81,35 @@ void ODRHash::AddDeclarationName(Declara } } -void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {} +void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { + assert(NNS && "Expecting non-null pointer."); + const auto *Prefix = NNS->getPrefix(); + AddBoolean(Prefix); + if (Prefix) { + AddNestedNameSpecifier(Prefix); + } + auto Kind = NNS->getKind(); + ID.AddInteger(Kind); + switch (Kind) { + case NestedNameSpecifier::Identifier: + AddIdentifierInfo(NNS->getAsIdentifier()); + break; + case NestedNameSpecifier::Namespace: + AddDecl(NNS->getAsNamespace()); + break; + case NestedNameSpecifier::NamespaceAlias: + AddDecl(NNS->getAsNamespaceAlias()); + break; + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + AddType(NNS->getAsType()); + break; + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: + break; + } +} + void ODRHash::AddTemplateName(TemplateName Name) {} void ODRHash::AddTemplateArgument(TemplateArgument TA) {} void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {} Modified: cfe/trunk/lib/Serialization/ASTReader.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=303233&r1=303232&r2=303233&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue May 16 22:23:35 2017 @@ -9348,12 +9348,6 @@ void ASTReader::diagnoseOdrViolations() return Hash.CalculateHash(); }; - auto ComputeDeclNameODRHash = [&Hash](const DeclarationName Name) { - Hash.clear(); - Hash.AddDeclarationName(Name); - return Hash.CalculateHash(); - }; - auto ComputeQualTypeODRHash = [&Hash](QualType Ty) { Hash.clear(); Hash.AddQualType(Ty); @@ -9446,11 +9440,8 @@ void ASTReader::diagnoseOdrViolations() QualType FirstType = FirstField->getType(); QualType SecondType = SecondField->getType(); - const TypedefType *FirstTypedef = dyn_cast<TypedefType>(FirstType); - const TypedefType *SecondTypedef = dyn_cast<TypedefType>(SecondType); - - if ((FirstTypedef && !SecondTypedef) || - (!FirstTypedef && SecondTypedef)) { + if (ComputeQualTypeODRHash(FirstType) != + ComputeQualTypeODRHash(SecondType)) { ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), FieldTypeName) << FirstII << FirstType; @@ -9462,24 +9453,6 @@ void ASTReader::diagnoseOdrViolations() break; } - if (FirstTypedef && SecondTypedef) { - unsigned FirstHash = ComputeDeclNameODRHash( - FirstTypedef->getDecl()->getDeclName()); - unsigned SecondHash = ComputeDeclNameODRHash( - SecondTypedef->getDecl()->getDeclName()); - if (FirstHash != SecondHash) { - ODRDiagError(FirstField->getLocation(), - FirstField->getSourceRange(), FieldTypeName) - << FirstII << FirstType; - ODRDiagNote(SecondField->getLocation(), - SecondField->getSourceRange(), FieldTypeName) - << SecondII << SecondType; - - Diagnosed = true; - break; - } - } - const bool IsFirstBitField = FirstField->isBitField(); const bool IsSecondBitField = SecondField->isBitField(); if (IsFirstBitField != IsSecondBitField) { Modified: cfe/trunk/test/Modules/odr_hash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=303233&r1=303232&r2=303233&view=diff ============================================================================== --- cfe/trunk/test/Modules/odr_hash.cpp (original) +++ cfe/trunk/test/Modules/odr_hash.cpp Tue May 16 22:23:35 2017 @@ -707,6 +707,165 @@ S1 s1; #endif } +namespace NestedNamespaceSpecifier { +#if defined(FIRST) +namespace LevelA1 { +using Type = int; +} + +struct S1 { + LevelA1::Type x; +}; +# elif defined(SECOND) +namespace LevelB1 { +namespace LevelC1 { +using Type = int; +} +} + +struct S1 { + LevelB1::LevelC1::Type x; +}; +#else +S1 s1; +// expected-error@second.h:* {{'NestedNamespaceSpecifier::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'LevelB1::LevelC1::Type' (aka 'int')}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'LevelA1::Type' (aka 'int')}} +#endif + +#if defined(FIRST) +namespace LevelA2 { using Type = int; } +struct S2 { + LevelA2::Type x; +}; +# elif defined(SECOND) +struct S2 { + int x; +}; +#else +S2 s2; +// expected-error@second.h:* {{'NestedNamespaceSpecifier::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'int'}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'LevelA2::Type' (aka 'int')}} +#endif + +namespace LevelA3 { using Type = int; } +namespace LevelB3 { using Type = int; } +#if defined(FIRST) +struct S3 { + LevelA3::Type x; +}; +# elif defined(SECOND) +struct S3 { + LevelB3::Type x; +}; +#else +S3 s3; +// expected-error@second.h:* {{'NestedNamespaceSpecifier::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'LevelB3::Type' (aka 'int')}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'LevelA3::Type' (aka 'int')}} +#endif + +#if defined(FIRST) +struct TA4 { using Type = int; }; +struct S4 { + TA4::Type x; +}; +# elif defined(SECOND) +struct TB4 { using Type = int; }; +struct S4 { + TB4::Type x; +}; +#else +S4 s4; +// expected-error@second.h:* {{'NestedNamespaceSpecifier::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'TB4::Type' (aka 'int')}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'TA4::Type' (aka 'int')}} +#endif + +#if defined(FIRST) +struct T5 { using Type = int; }; +struct S5 { + T5::Type x; +}; +# elif defined(SECOND) +namespace T5 { using Type = int; }; +struct S5 { + T5::Type x; +}; +#else +S5 s5; +// expected-error@second.h:* {{'NestedNamespaceSpecifier::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'T5::Type' (aka 'int')}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'T5::Type' (aka 'int')}} +#endif + +#if defined(FIRST) +namespace N6 {using I = int;} +struct S6 { + NestedNamespaceSpecifier::N6::I x; +}; +# elif defined(SECOND) +using I = int; +struct S6 { + ::NestedNamespaceSpecifier::I x; +}; +#else +S6 s6; +// expected-error@second.h:* {{'NestedNamespaceSpecifier::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '::NestedNamespaceSpecifier::I' (aka 'int')}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'NestedNamespaceSpecifier::N6::I' (aka 'int')}} +#endif + +#if defined(FIRST) +template <class T, class U> +class S7 { + typename T::type *x = {}; + int z = x->T::foo(); +}; +#elif defined(SECOND) +template <class T, class U> +class S7 { + typename T::type *x = {}; + int z = x->U::foo(); +}; +#else +template <class T, class U> +using U7 = S7<T, U>; +// expected-error@second.h:* {{'NestedNamespaceSpecifier::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'z' with an initializer}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'z' with a different initializer}} +#endif + +#if defined(FIRST) +template <class T> +class S8 { + int x = T::template X<int>::value; +}; +#elif defined(SECOND) +template <class T> +class S8 { + int x = T::template Y<int>::value; +}; +#else +template <class T> +using U8 = S8<T>; +// expected-error@second.h:* {{'NestedNamespaceSpecifier::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with an initializer}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with a different initializer}} +#endif + +#if defined(FIRST) +namespace N9 { using I = int; } +namespace O9 = N9; +struct S9 { + O9::I x; +}; +#elif defined(SECOND) +namespace N9 { using I = int; } +namespace P9 = N9; +struct S9 { + P9::I x; +}; +#else +S9 s9; +// expected-error@second.h:* {{'NestedNamespaceSpecifier::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'P9::I' (aka 'int')}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'O9::I' (aka 'int')}} +#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. namespace AllDecls { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits