]> granicus.if.org Git - clang/commitdiff
[ODRHash] Add handling of bitfields
authorRichard Trieu <rtrieu@google.com>
Fri, 24 Feb 2017 20:59:28 +0000 (20:59 +0000)
committerRichard Trieu <rtrieu@google.com>
Fri, 24 Feb 2017 20:59:28 +0000 (20:59 +0000)
Differential Revision: https://reviews.llvm.org/D21675

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@296170 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSerializationKinds.td
lib/AST/ODRHash.cpp
lib/Serialization/ASTReader.cpp
test/Modules/odr_hash.cpp

index 77d97b1ee6da5d4736e1c0077dc5f6645a024d0e..fd381aeb6c04b3beaf4af34130fe0962781aad5d 100644 (file)
@@ -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__">,
index d1473948b0b5c65a2267d4796b95f39d1427f587..208d5f3c49c5d03eb707a802f0c37dccc41d77dc 100644 (file)
@@ -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());
+    }
   }
 };
 
index 932803885fafd5c1ba1c81fcad391d73863d53d1..2e78e5999c9689762fcd8b3f0b2d119e77764307 100644 (file)
@@ -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;
       }
       }
index 8e51a2dc70178e0789d79aa2963e554e9ba1472d..2a7a65c2ec682feef2c3f681cf1cecb96f1142c1 100644 (file)
@@ -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