r303233 - [ODRHash] Support NestedNameSpecifier
Richard Trieu via cfe-commits
cfe-commits at lists.llvm.org
Tue May 16 20:23:36 PDT 2017
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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 {
More information about the cfe-commits
mailing list