From: Richard Trieu Date: Fri, 24 Feb 2017 23:35:37 +0000 (+0000) Subject: [ODRHash] Finish FieldDecl support by handling mutable and initializers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0edc6e70059f36689ca1935079be3ca22d2cebfd;p=clang [ODRHash] Finish FieldDecl support by handling mutable and initializers. https://reviews.llvm.org/rL296170 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@296198 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index fd381aeb6c..78efc69f57 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -136,7 +136,10 @@ def err_module_odr_violation_mismatch_decl_diff : Error< "field %4|" "field %4 with type %5|" "%select{non-|}5bitfield %4|" - "bitfield %4 with one width expression}3">; + "bitfield %4 with one width expression|" + "%select{non-|}5mutable field %4|" + "field %4 with %select{no|an}5 initalizer|" + "field %4 with an initializer}3">; def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "%select{" @@ -146,7 +149,10 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "field %2|" "field %2 with type %3|" "%select{non-|}3bitfield %2|" - "bitfield %2 with different width expression}1">; + "bitfield %2 with different width expression|" + "%select{non-|}3mutable field %2|" + "field %2 with %select{no|an}3 initializer|" + "field %2 with a different initializer}1">; def warn_module_uses_date_time : Warning< "%select{precompiled header|module}0 uses __DATE__ or __TIME__">, diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 208d5f3c49..28b2eff633 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -190,6 +190,9 @@ public: if (IsBitfield) { AddStmt(D->getBitWidth()); } + + Hash.AddBoolean(D->isMutable()); + AddStmt(D->getInClassInitializer()); } }; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 2e78e5999c..982f59272e 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -9064,7 +9064,10 @@ void ASTReader::diagnoseOdrViolations() { FieldName, FieldTypeName, FieldSingleBitField, - FieldDifferentWidthBitField + FieldDifferentWidthBitField, + FieldSingleMutable, + FieldSingleInitializer, + FieldDifferentInitializers, }; // These lambdas have the common portions of the ODR diagnostics. This @@ -9239,6 +9242,50 @@ void ASTReader::diagnoseOdrViolations() { break; } + const bool IsFirstMutable = FirstField->isMutable(); + const bool IsSecondMutable = SecondField->isMutable(); + if (IsFirstMutable != IsSecondMutable) { + ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), + FieldSingleMutable) + << FirstII << IsFirstMutable; + ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), + FieldSingleMutable) + << SecondII << IsSecondMutable; + Diagnosed = true; + break; + } + + const Expr *FirstInitializer = FirstField->getInClassInitializer(); + const Expr *SecondInitializer = SecondField->getInClassInitializer(); + if ((!FirstInitializer && SecondInitializer) || + (FirstInitializer && !SecondInitializer)) { + ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), + FieldSingleInitializer) + << FirstII << (FirstInitializer != nullptr); + ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), + FieldSingleInitializer) + << SecondII << (SecondInitializer != nullptr); + Diagnosed = true; + break; + } + + if (FirstInitializer && SecondInitializer) { + unsigned FirstInitHash = ComputeODRHash(FirstInitializer); + unsigned SecondInitHash = ComputeODRHash(SecondInitializer); + if (FirstInitHash != SecondInitHash) { + ODRDiagError(FirstField->getLocation(), + FirstField->getSourceRange(), + FieldDifferentInitializers) + << FirstII << FirstInitializer->getSourceRange(); + ODRDiagNote(SecondField->getLocation(), + SecondField->getSourceRange(), + FieldDifferentInitializers) + << SecondII << SecondInitializer->getSourceRange(); + Diagnosed = true; + break; + } + } + break; } } diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index 2a7a65c2ec..e485f633f8 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -233,6 +233,48 @@ S8 s8; // expected-note@first.h:* {{but in 'FirstModule' found bitfield 'x' with different width expression}} #endif +#if defined(FIRST) +struct S9 { + mutable int x; +}; +#elif defined(SECOND) +struct S9 { + int x; +}; +#else +S9 s9; +// expected-error@second.h:* {{'Field::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found non-mutable field 'x'}} +// expected-note@first.h:* {{but in 'FirstModule' found mutable field 'x'}} +#endif + +#if defined(FIRST) +struct S10 { + unsigned x = 5; +}; +#elif defined(SECOND) +struct S10 { + unsigned x; +}; +#else +S10 s10; +// expected-error@second.h:* {{'Field::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with no initalizer}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with an initializer}} +#endif + +#if defined(FIRST) +struct S11 { + unsigned x = 5; +}; +#elif defined(SECOND) +struct S11 { + unsigned x = 7; +}; +#else +S11 s11; +// expected-error@second.h:* {{'Field::S11' 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 + } // namespace Field // Naive parsing of AST can lead to cycles in processing. Ensure @@ -280,6 +322,8 @@ struct S { unsigned a : 1; unsigned b : 2*2 + 5/2; + + mutable int c = sizeof(x + y); }; #elif defined(SECOND) typedef int INT; @@ -298,6 +342,8 @@ struct S { unsigned a : 1; unsigned b : 2 * 2 + 5 / 2; + + mutable int c = sizeof(x + y); }; #else S s; @@ -321,6 +367,8 @@ struct T { unsigned a : 1; unsigned b : 2 * 2 + 5 / 2; + mutable int c = sizeof(x + y); + private: }; #elif defined(SECOND) @@ -341,6 +389,8 @@ struct T { unsigned a : 1; unsigned b : 2 * 2 + 5 / 2; + mutable int c = sizeof(x + y); + public: }; #else