From: Richard Trieu Date: Fri, 24 Feb 2017 20:59:28 +0000 (+0000) Subject: [ODRHash] Add handling of bitfields X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=085bd22d14dffe8beb5725e6e8986985c57e84ae;p=clang [ODRHash] Add handling of bitfields Differential Revision: https://reviews.llvm.org/D21675 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@296170 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index 77d97b1ee6..fd381aeb6c 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -133,14 +133,20 @@ def err_module_odr_violation_mismatch_decl_diff : Error< "static assert with condition|" "static assert with message|" "static assert with %select{|no }4message|" - "field %4|field %4 with type %5}3">; + "field %4|" + "field %4 with type %5|" + "%select{non-|}5bitfield %4|" + "bitfield %4 with one width expression}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|field %2 with type %3}1">; + "field %2|" + "field %2 with type %3|" + "%select{non-|}3bitfield %2|" + "bitfield %2 with different width expression}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 d1473948b0..208d5f3c49 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -183,6 +183,13 @@ public: void VisitFieldDecl(const FieldDecl *D) { Inherited::VisitFieldDecl(D); + + const bool IsBitfield = D->isBitField(); + Hash.AddBoolean(IsBitfield); + + if (IsBitfield) { + AddStmt(D->getBitWidth()); + } } }; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 932803885f..2e78e5999c 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -9063,6 +9063,8 @@ void ASTReader::diagnoseOdrViolations() { StaticAssertOnlyMessage, FieldName, FieldTypeName, + FieldSingleBitField, + FieldDifferentWidthBitField }; // These lambdas have the common portions of the ODR diagnostics. This @@ -9213,6 +9215,30 @@ void ASTReader::diagnoseOdrViolations() { } } + const bool IsFirstBitField = FirstField->isBitField(); + const bool IsSecondBitField = SecondField->isBitField(); + if (IsFirstBitField != IsSecondBitField) { + ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), + FieldSingleBitField) + << FirstII << IsFirstBitField; + ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), + FieldSingleBitField) + << SecondII << IsSecondBitField; + Diagnosed = true; + break; + } + + if (IsFirstBitField && IsSecondBitField) { + ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(), + FieldDifferentWidthBitField) + << FirstII << FirstField->getBitWidth()->getSourceRange(); + ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(), + FieldDifferentWidthBitField) + << SecondII << SecondField->getBitWidth()->getSourceRange(); + Diagnosed = true; + break; + } + break; } } diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index 8e51a2dc70..2a7a65c2ec 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -191,6 +191,47 @@ S5 s5; // expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'A' (aka 'int')}} #endif +#if defined(FIRST) +struct S6 { + unsigned x; +}; +#elif defined(SECOND) +struct S6 { + unsigned x : 1; +}; +#else +S6 s6; +// expected-error@second.h:* {{'Field::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found bitfield 'x'}} +// expected-note@first.h:* {{but in 'FirstModule' found non-bitfield 'x'}} +#endif + +#if defined(FIRST) +struct S7 { + unsigned x : 2; +}; +#elif defined(SECOND) +struct S7 { + unsigned x : 1; +}; +#else +S7 s7; +// expected-error@second.h:* {{'Field::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found bitfield 'x' with one width expression}} +// expected-note@first.h:* {{but in 'FirstModule' found bitfield 'x' with different width expression}} +#endif + +#if defined(FIRST) +struct S8 { + unsigned x : 2; +}; +#elif defined(SECOND) +struct S8 { + unsigned x : 1 + 1; +}; +#else +S8 s8; +// expected-error@second.h:* {{'Field::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found bitfield 'x' with one width expression}} +// expected-note@first.h:* {{but in 'FirstModule' found bitfield 'x' with different width expression}} +#endif } // namespace Field @@ -236,6 +277,9 @@ struct S { double y; INT z; + + unsigned a : 1; + unsigned b : 2*2 + 5/2; }; #elif defined(SECOND) typedef int INT; @@ -251,6 +295,9 @@ struct S { double y; INT z; + + unsigned a : 1; + unsigned b : 2 * 2 + 5 / 2; }; #else S s; @@ -271,6 +318,9 @@ struct T { INT z; + unsigned a : 1; + unsigned b : 2 * 2 + 5 / 2; + private: }; #elif defined(SECOND) @@ -288,6 +338,9 @@ struct T { INT z; + unsigned a : 1; + unsigned b : 2 * 2 + 5 / 2; + public: }; #else