summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSerializationKinds.td10
-rw-r--r--clang/lib/AST/ODRHash.cpp3
-rw-r--r--clang/lib/Serialization/ASTReader.cpp49
-rw-r--r--clang/test/Modules/odr_hash.cpp50
4 files changed, 109 insertions, 3 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td
index fd381aeb6c0..78efc69f577 100644
--- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/clang/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/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 208d5f3c49c..28b2eff6339 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -190,6 +190,9 @@ public:
if (IsBitfield) {
AddStmt(D->getBitWidth());
}
+
+ Hash.AddBoolean(D->isMutable());
+ AddStmt(D->getInClassInitializer());
}
};
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 2e78e5999c9..982f59272e9 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/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/clang/test/Modules/odr_hash.cpp b/clang/test/Modules/odr_hash.cpp
index 2a7a65c2ec6..e485f633f89 100644
--- a/clang/test/Modules/odr_hash.cpp
+++ b/clang/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
OpenPOWER on IntegriCloud