[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