c: correct type compatibility for bit-fields [PR117828]

Message ID 6fca734702a1ba4225cb8fde9c5cbfad665b87a3.camel@tugraz.at
State New
Headers
Series c: correct type compatibility for bit-fields [PR117828] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

Martin Uecker Nov. 28, 2024, 9:17 p.m. UTC
  Bit-fields need additional checks for type compatiblity.


Bootstrapped and regression tested on x86_64.



    c: correct type compatibility for bit-fields [PR117828]
    
    Add missing test for consistency of bit-fields when comparing tagged
    types for compatibility.
    
            PR c/117828
    
    gcc/c/ChangeLog:
            * c-typeck.c (tagged_types_tu_compatible_p): Add check.
    
    gcc/testsuite/ChangeLog:
            * c23-tag-bitfields-1.c: New test.
            * pr117828.c: New test.
  

Comments

Joseph Myers Nov. 28, 2024, 11:14 p.m. UTC | #1
On Thu, 28 Nov 2024, Martin Uecker wrote:

> Bit-fields need additional checks for type compatiblity.
> 
> 
> Bootstrapped and regression tested on x86_64.
> 
> 
> 
>     c: correct type compatibility for bit-fields [PR117828]
>     
>     Add missing test for consistency of bit-fields when comparing tagged
>     types for compatibility.
>     
>             PR c/117828
>     
>     gcc/c/ChangeLog:
>             * c-typeck.c (tagged_types_tu_compatible_p): Add check.
>     
>     gcc/testsuite/ChangeLog:
>             * c23-tag-bitfields-1.c: New test.
>             * pr117828.c: New test.

OK (with the file names corrected in the ChangeLog entries, it's 
c-typeck.cc, and gcc.dg/ is needed in the test names).
  

Patch

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 23ce0fc788d..dd13f212cd5 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -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
index 00000000000..d775d9f67a1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-bitfields-1.c
@@ -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
index 00000000000..a219f8e51a2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr117828.c
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+/* { dg-options "-g" } */
+
+struct {
+  struct {
+    int Reserved : 32;
+  } u;
+} v;
+struct {
+  struct {
+    int Reserved;
+  } u;
+} w;
+
+