[clang] 007dd12 - [ASTImporter][AST] Fix structural equivalency crash on dependent FieldDecl
Gabor Marton via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 5 05:22:21 PDT 2020
Author: Gabor Marton
Date: 2020-10-05T14:06:09+02:00
New Revision: 007dd12d546814977519b33ca38b1cc8b31fee26
URL: https://github.com/llvm/llvm-project/commit/007dd12d546814977519b33ca38b1cc8b31fee26
DIFF: https://github.com/llvm/llvm-project/commit/007dd12d546814977519b33ca38b1cc8b31fee26.diff
LOG: [ASTImporter][AST] Fix structural equivalency crash on dependent FieldDecl
Differential Revision: https://reviews.llvm.org/D88665
Added:
Modified:
clang/lib/AST/ASTStructuralEquivalence.cpp
clang/test/ASTMerge/struct/test.c
clang/unittests/AST/StructuralEquivalenceTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 98e1b7eeb8c4..2bc5f39b817e 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -1256,48 +1256,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
}
- if (Field1->isBitField() != Field2->isBitField()) {
- if (Context.Complain) {
- Context.Diag2(
- Owner2->getLocation(),
- Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(Owner2);
- if (Field1->isBitField()) {
- Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
- << Field1->getDeclName() << Field1->getType()
- << Field1->getBitWidthValue(Context.FromCtx);
- Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field)
- << Field2->getDeclName();
- } else {
- Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
- << Field2->getDeclName() << Field2->getType()
- << Field2->getBitWidthValue(Context.ToCtx);
- Context.Diag1(Field1->getLocation(), diag::note_odr_not_bit_field)
- << Field1->getDeclName();
- }
- }
- return false;
- }
-
- if (Field1->isBitField()) {
- // Make sure that the bit-fields are the same length.
- unsigned Bits1 = Field1->getBitWidthValue(Context.FromCtx);
- unsigned Bits2 = Field2->getBitWidthValue(Context.ToCtx);
-
- if (Bits1 != Bits2) {
- if (Context.Complain) {
- Context.Diag2(Owner2->getLocation(),
- Context.getApplicableDiagnostic(
- diag::err_odr_tag_type_inconsistent))
- << Context.ToCtx.getTypeDeclType(Owner2);
- Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
- << Field2->getDeclName() << Field2->getType() << Bits2;
- Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
- << Field1->getDeclName() << Field1->getType() << Bits1;
- }
- return false;
- }
- }
+ if (Field1->isBitField())
+ return IsStructurallyEquivalent(Context, Field1->getBitWidth(),
+ Field2->getBitWidth());
return true;
}
diff --git a/clang/test/ASTMerge/struct/test.c b/clang/test/ASTMerge/struct/test.c
index 9ac66d17f60e..3e11dd9e07a8 100644
--- a/clang/test/ASTMerge/struct/test.c
+++ b/clang/test/ASTMerge/struct/test.c
@@ -21,16 +21,6 @@
// CHECK: struct1.c:27:8: note: no corresponding field here
// CHECK: struct2.c:24:31: warning: external variable 'x4' declared with incompatible types in
diff erent translation units ('struct S4' vs. 'struct S4')
// CHECK: struct1.c:27:22: note: declared here with type 'struct S4'
-// CHECK: struct1.c:33:8: warning: type 'struct S6' has incompatible definitions in
diff erent translation units
-// CHECK: struct1.c:33:33: note: bit-field 'j' with type 'unsigned int' and length 8 here
-// CHECK: struct2.c:30:33: note: field 'j' is not a bit-field
-// CHECK: struct2.c:30:38: warning: external variable 'x6' declared with incompatible types in
diff erent translation units ('struct S6' vs. 'struct S6')
-// CHECK: struct1.c:33:42: note: declared here with type 'struct S6'
-// CHECK: struct1.c:36:8: warning: type 'struct S7' has incompatible definitions in
diff erent translation units
-// CHECK: struct1.c:36:33: note: bit-field 'j' with type 'unsigned int' and length 8 here
-// CHECK: struct2.c:33:33: note: bit-field 'j' with type 'unsigned int' and length 16 here
-// CHECK: struct2.c:33:43: warning: external variable 'x7' declared with incompatible types in
diff erent translation units ('struct S7' vs. 'struct S7')
-// CHECK: struct1.c:36:42: note: declared here with type 'struct S7'
// CHECK: struct1.c:56:10: warning: type 'struct DeeperError' has incompatible definitions in
diff erent translation units
// CHECK: struct1.c:56:35: note: field 'f' has type 'int' here
// CHECK: struct2.c:53:37: note: field 'f' has type 'float' here
@@ -52,4 +42,4 @@
// CHECK: struct2.c:129:9: note: field 'S' has type 'struct (anonymous struct at [[PATH_TO_INPUTS]]struct2.c:127:7)' here
// CHECK: struct2.c:138:3: warning: external variable 'x16' declared with incompatible types in
diff erent translation units ('struct DeepUnnamedError' vs. 'struct DeepUnnamedError')
// CHECK: struct1.c:141:3: note: declared here with type 'struct DeepUnnamedError'
-// CHECK: 20 warnings generated
+// CHECK: 17 warnings generated
diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp
index c83bf019bb65..26bd81ce1319 100644
--- a/clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -976,6 +976,39 @@ TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) {
EXPECT_FALSE(testStructuralMatch(t));
}
+TEST_F(StructuralEquivalenceTemplateTest, BitFieldDecl) {
+ const char *Code = "class foo { int a : 2; };";
+ auto t = makeNamedDecls(Code, Code, Lang_CXX03);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceTemplateTest, BitFieldDeclDifferentWidth) {
+ auto t = makeNamedDecls("class foo { int a : 2; };",
+ "class foo { int a : 4; };", Lang_CXX03);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDecl) {
+ const char *Code = "template <class T> class foo { int a : sizeof(T); };";
+ auto t = makeNamedDecls(Code, Code, Lang_CXX03);
+ EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal) {
+ auto t = makeNamedDecls(
+ "template <class A, class B> class foo { int a : sizeof(A); };",
+ "template <class A, class B> class foo { int a : sizeof(B); };",
+ Lang_CXX03);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal2) {
+ auto t = makeNamedDecls(
+ "template <class A> class foo { int a : sizeof(A); };",
+ "template <class A> class foo { int a : sizeof(A) + 1; };", Lang_CXX03);
+ EXPECT_FALSE(testStructuralMatch(t));
+}
+
TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) {
auto Decls = makeNamedDecls(
"template <bool b> struct foo {explicit(b) foo(int);};",
More information about the cfe-commits
mailing list