]> granicus.if.org Git - clang/commitdiff
[ODRHash] Finish FieldDecl support by handling mutable and initializers.
authorRichard Trieu <rtrieu@google.com>
Fri, 24 Feb 2017 23:35:37 +0000 (23:35 +0000)
committerRichard Trieu <rtrieu@google.com>
Fri, 24 Feb 2017 23:35:37 +0000 (23:35 +0000)
https://reviews.llvm.org/rL296170

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

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

index fd381aeb6c04b3beaf4af34130fe0962781aad5d..78efc69f577afe5aaadae3e18862f49ef8bbc9f1 100644 (file)
@@ -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__">,
index 208d5f3c49c5d03eb707a802f0c37dccc41d77dc..28b2eff633972de8823b5eb6c1789177f02eef39 100644 (file)
@@ -190,6 +190,9 @@ public:
     if (IsBitfield) {
       AddStmt(D->getBitWidth());
     }
+
+    Hash.AddBoolean(D->isMutable());
+    AddStmt(D->getInClassInitializer());
   }
 };
 
index 2e78e5999c9689762fcd8b3f0b2d119e77764307..982f59272e9a43a3946fae231b4515b6ea4b5220 100644 (file)
@@ -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;
       }
       }
index 2a7a65c2ec682feef2c3f681cf1cecb96f1142c1..e485f633f89dfc97efa864674f070b4d60655b05 100644 (file)
@@ -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