]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c: Correct type compatibility for bit-fields [PR117828]
authorMartin Uecker <uecker@tugraz.at>
Thu, 28 Nov 2024 19:06:16 +0000 (20:06 +0100)
committerMartin Uecker <uecker@gcc.gnu.org>
Fri, 29 Nov 2024 13:14:56 +0000 (14:14 +0100)
Add missing test for consistency of bit-fields when comparing tagged
types for compatibility.

PR c/117828

gcc/c/ChangeLog:
* c-typeck.cc (tagged_types_tu_compatible_p): Add check.

gcc/testsuite/ChangeLog:
* gcc.dg/c23-tag-bitfields-1.c: New test.
* gcc.dg/pr117828.c: New test.

gcc/c/c-typeck.cc
gcc/testsuite/gcc.dg/c23-tag-bitfields-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr117828.c [new file with mode: 0644]

index 0189a800c11f52538a7fe599c9daa6be530dea47..611daccb926d3042fe90f782a6b8186014126ce6 100644 (file)
@@ -1909,18 +1909,33 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
            gcc_assert (TREE_CODE (s1) == FIELD_DECL);
            gcc_assert (TREE_CODE (s2) == FIELD_DECL);
 
+           tree ft1 = TREE_TYPE (s1);
+           tree ft2 = TREE_TYPE (s2);
+
            if (DECL_NAME (s1) != DECL_NAME (s2))
              return false;
 
            if (DECL_ALIGN (s1) != DECL_ALIGN (s2))
              return false;
 
+           if (DECL_C_BIT_FIELD (s1) != DECL_C_BIT_FIELD (s2))
+              return false;
+
+           if (DECL_C_BIT_FIELD (s1))
+             {
+               if (!tree_int_cst_equal (DECL_SIZE (s1), DECL_SIZE (s2)))
+                 return false;
+
+               ft1 = DECL_BIT_FIELD_TYPE (s1);
+               ft2 = DECL_BIT_FIELD_TYPE (s2);
+             }
+
            data->anon_field = !DECL_NAME (s1);
            data->pointedto = false;
 
            const struct tagged_tu_seen_cache *cache = data->cache;
            data->cache = &entry;
-           bool ret = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), data);
+           bool ret = comptypes_internal (ft1, ft2, data);
            data->cache = cache;
            if (!ret)
              return false;
diff --git a/gcc/testsuite/gcc.dg/c23-tag-bitfields-1.c b/gcc/testsuite/gcc.dg/c23-tag-bitfields-1.c
new file mode 100644 (file)
index 0000000..d775d9f
--- /dev/null
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23" } */
+
+struct bar0 { int r : 16; };
+struct bar0 { int r : 16; };
+
+struct bar1 { int r : 16; };
+struct bar1 { int r : 17; };                   /* { dg-error "redefinition" } */
+
+extern struct { int r : 14; } a;
+extern struct { int r : 14; } b;
+
+extern struct { int r : 14; } x;
+extern struct { int r : 13; } x;               /* { dg-error "conflicting" } */
+
+struct bar2 { int s; int: 0; };
+struct bar2 { int s; int: 15; };               /* { dg-error "redefinition" } */
+
+struct bar3 { int s; int : 0; };
+struct bar3 { int s; };                                /* { dg-error "redefinition" } */
+
+struct bar4 { int r : 3; };
+struct bar4 { const int r : 3; };              /* { dg-error "redefinition" } */
+
+struct bar5 { int r : 16; };
+struct bar5 { int r; };                                /* { dg-error "redefinition" } */
+
+union ubar { int r : 16; };
+union ubar { int r : 16; };
+
+union ubar1 { int r : 16; };
+union ubar1 { int r : 17; };                   /* { dg-error "redefinition" } */
+
+extern union { int r : 14; } c;
+extern union { int r : 14; } d;
+
+extern union { int r : 14; } y;
+extern union { int r : 13; } y;                        /* { dg-error "conflicting" } */
+
+union ubar2 { int s; int : 0; };
+union ubar2 { int s; int : 15; };              /* { dg-error "redefinition" } */
+
+union ubar3 { int s: 3; int: 0; };
+union ubar3 { int s: 3; };                     /* { dg-error "redefinition" } */
+
+union ubar4 { int r : 3; };
+union ubar4 { const int r : 3; };              /* { dg-error "redefinition" } */
+
+union ubar5 { int r : 16; };
+union ubar5 { int r; };                                /* { dg-error "redefinition" } */
+
diff --git a/gcc/testsuite/gcc.dg/pr117828.c b/gcc/testsuite/gcc.dg/pr117828.c
new file mode 100644 (file)
index 0000000..d675031
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-g" } */
+
+struct {
+  struct {
+    int Reserved : 32;
+  } u;
+} v;
+struct {
+  struct {
+    int Reserved;
+  } u;
+} w;
+