Author: rtrieu Date: Thu Feb 23 20:59:12 2017 New Revision: 296078 URL: http://llvm.org/viewvc/llvm-project?rev=296078&view=rev Log: [ODRHash] Add handling of TypedefType and DeclarationName
Differential Revision: https://reviews.llvm.org/D21675 Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td cfe/trunk/lib/AST/ODRHash.cpp cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/test/Modules/odr_hash.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td?rev=296078&r1=296077&r2=296078&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Thu Feb 23 20:59:12 2017 @@ -133,14 +133,14 @@ def err_module_odr_violation_mismatch_de "static assert with condition|" "static assert with message|" "static assert with %select{|no }4message|" - "field %4}3">; + "field %4|field %4 with type %5}3">; def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "%select{" "static assert with different condition|" "static assert with different message|" "static assert with %select{|no }2message|" - "field %2}1">; + "field %2|field %2 with type %3}1">; def warn_module_uses_date_time : Warning< "%select{precompiled header|module}0 uses __DATE__ or __TIME__">, Modified: cfe/trunk/lib/AST/ODRHash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=296078&r1=296077&r2=296078&view=diff ============================================================================== --- cfe/trunk/lib/AST/ODRHash.cpp (original) +++ cfe/trunk/lib/AST/ODRHash.cpp Thu Feb 23 20:59:12 2017 @@ -32,9 +32,57 @@ void ODRHash::AddIdentifierInfo(const Id ID.AddString(II->getName()); } +void ODRHash::AddDeclarationName(DeclarationName Name) { + AddBoolean(Name.isEmpty()); + if (Name.isEmpty()) + return; + + auto Kind = Name.getNameKind(); + ID.AddInteger(Kind); + switch (Kind) { + case DeclarationName::Identifier: + AddIdentifierInfo(Name.getAsIdentifierInfo()); + break; + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: { + Selector S = Name.getObjCSelector(); + AddBoolean(S.isNull()); + AddBoolean(S.isKeywordSelector()); + AddBoolean(S.isUnarySelector()); + unsigned NumArgs = S.getNumArgs(); + for (unsigned i = 0; i < NumArgs; ++i) { + AddIdentifierInfo(S.getIdentifierInfoForSlot(i)); + } + break; + } + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + AddQualType(Name.getCXXNameType()); + break; + case DeclarationName::CXXOperatorName: + ID.AddInteger(Name.getCXXOverloadedOperator()); + break; + case DeclarationName::CXXLiteralOperatorName: + AddIdentifierInfo(Name.getCXXLiteralIdentifier()); + break; + case DeclarationName::CXXConversionFunctionName: + AddQualType(Name.getCXXNameType()); + break; + case DeclarationName::CXXUsingDirective: + break; + case DeclarationName::CXXDeductionGuideName: { + auto *Template = Name.getCXXDeductionGuideTemplate(); + AddBoolean(Template); + if (Template) { + AddDecl(Template); + } + } + } +} + void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {} void ODRHash::AddTemplateName(TemplateName Name) {} -void ODRHash::AddDeclarationName(DeclarationName Name) {} void ODRHash::AddTemplateArgument(TemplateArgument TA) {} void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {} @@ -192,6 +240,10 @@ void ODRHash::AddDecl(const Decl *D) { } ID.AddInteger(D->getKind()); + + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + AddDeclarationName(ND->getDeclName()); + } } // Process a Type pointer. Add* methods call back into ODRHash while Visit* @@ -212,6 +264,13 @@ public: } } + void AddDecl(Decl *D) { + Hash.AddBoolean(D); + if (D) { + Hash.AddDecl(D); + } + } + void Visit(const Type *T) { ID.AddInteger(T->getTypeClass()); Inherited::Visit(T); @@ -223,6 +282,11 @@ public: ID.AddInteger(T->getKind()); VisitType(T); } + + void VisitTypedefType(const TypedefType *T) { + AddDecl(T->getDecl()); + VisitType(T); + } }; void ODRHash::AddType(const Type *T) { Modified: cfe/trunk/lib/Serialization/ASTReader.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=296078&r1=296077&r2=296078&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Feb 23 20:59:12 2017 @@ -9062,6 +9062,7 @@ void ASTReader::diagnoseOdrViolations() StaticAssertMessage, StaticAssertOnlyMessage, FieldName, + FieldTypeName, }; // These lambdas have the common portions of the ODR diagnostics. This @@ -9086,6 +9087,12 @@ void ASTReader::diagnoseOdrViolations() return Hash.CalculateHash(); }; + auto ComputeDeclNameODRHash = [&Hash](const DeclarationName Name) { + Hash.clear(); + Hash.AddDeclarationName(Name); + return Hash.CalculateHash(); + }; + switch (FirstDiffType) { case Other: case EndOfClass: @@ -9166,6 +9173,46 @@ void ASTReader::diagnoseOdrViolations() Diagnosed = true; break; } + + assert( + Context.hasSameType(FirstField->getType(), SecondField->getType())); + + 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)) { + ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), + FieldTypeName) + << FirstII << FirstType; + ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), + FieldTypeName) + << SecondII << SecondType; + + Diagnosed = true; + 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; + } + } + break; } } Modified: cfe/trunk/test/Modules/odr_hash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=296078&r1=296077&r2=296078&view=diff ============================================================================== --- cfe/trunk/test/Modules/odr_hash.cpp (original) +++ cfe/trunk/test/Modules/odr_hash.cpp Thu Feb 23 20:59:12 2017 @@ -162,6 +162,36 @@ S3 s3; // expected-error@first.h:* {{'Field::S3::x' from module 'FirstModule' is not present in definition of 'Field::S3' in module 'SecondModule'}} // expected-note@second.h:* {{declaration of 'x' does not match}} #endif + +#if defined(FIRST) +typedef int A; +struct S4 { + A x; +}; + +struct S5 { + A x; +}; +#elif defined(SECOND) +typedef int B; +struct S4 { + B x; +}; + +struct S5 { + int x; +}; +#else +S4 s4; +// expected-error@second.h:* {{'Field::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'B' (aka 'int')}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'A' (aka 'int')}} + +S5 s5; +// expected-error@second.h:* {{'Field::S5' 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 'A' (aka 'int')}} +#endif + + } // namespace Field // Naive parsing of AST can lead to cycles in processing. Ensure @@ -193,6 +223,7 @@ struct NestedNamespaceSpecifier {}; // while struct T should error at the access specifier mismatch at the end. namespace AllDecls { #if defined(FIRST) +typedef int INT; struct S { public: private: @@ -203,8 +234,11 @@ struct S { int x; double y; + + INT z; }; #elif defined(SECOND) +typedef int INT; struct S { public: private: @@ -215,12 +249,15 @@ struct S { int x; double y; + + INT z; }; #else S s; #endif #if defined(FIRST) +typedef int INT; struct T { public: private: @@ -232,9 +269,12 @@ struct T { int x; double y; + INT z; + private: }; #elif defined(SECOND) +typedef int INT; struct T { public: private: @@ -246,6 +286,8 @@ struct T { int x; double y; + INT z; + public: }; #else _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits