Hi!

As mentioned in the PR, we currently ICE on flexible array members in
structs and unions during __builtin_clear_padding processing.

Jason said in the PR he'd prefer an error in these cases over forcefully
handling it as [0] arrays (everything is padding then) or consider the
arrays to have as many whole elements as would fit into the tail padding.

So, this patch implements that.

Ok for trunk if it passes bootstrap/regtest?  So far has been tested just
on the dg.exp=builtin-clear-padding* dg-torture.exp=builtin-clear-padding*
check-gcc check-c++-all testsuite, but the builtin is currently not used
in anything else.

2020-11-24  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/97943
        * gimple-fold.c (clear_padding_union, clear_padding_type): Error on and
        ignore flexible array member fields.  Ignore fields with
        error_mark_node type.

        * c-c++-common/builtin-clear-padding-2.c: New test.
        * c-c++-common/builtin-clear-padding-3.c: New test.
        * g++.dg/ext/builtin-clear-padding-1.C: New test.
        * gcc.dg/builtin-clear-padding-2.c: New test.

--- gcc/gimple-fold.c.jj        2020-11-23 17:01:48.255054823 +0100
+++ gcc/gimple-fold.c   2020-11-24 09:53:17.724943252 +0100
@@ -4255,6 +4255,17 @@ clear_padding_union (clear_padding_struc
   for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     if (TREE_CODE (field) == FIELD_DECL)
       {
+       if (DECL_SIZE_UNIT (field) == NULL_TREE)
+         {
+           if (TREE_TYPE (field) == error_mark_node)
+             continue;
+           gcc_assert (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
+                       && !COMPLETE_TYPE_P (TREE_TYPE (field)));
+           error_at (buf->loc, "flexible array member %qD does not have "
+                               "well defined padding bits for %qs",
+                     field, "__builtin_clear_padding");
+           continue;
+         }
        HOST_WIDE_INT fldsz = tree_to_shwi (DECL_SIZE_UNIT (field));
        gcc_assert (union_buf->size == 0);
        union_buf->off = start_off;
@@ -4372,11 +4383,12 @@ clear_padding_type (clear_padding_struct
       for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
        if (TREE_CODE (field) == FIELD_DECL)
          {
+           tree ftype = TREE_TYPE (field);
            if (DECL_BIT_FIELD (field))
              {
                if (DECL_NAME (field) == NULL_TREE)
                  continue;
-               HOST_WIDE_INT fldsz = TYPE_PRECISION (TREE_TYPE (field));
+               HOST_WIDE_INT fldsz = TYPE_PRECISION (ftype);
                if (fldsz == 0)
                  continue;
                HOST_WIDE_INT pos = int_byte_position (field);
@@ -4439,6 +4451,16 @@ clear_padding_type (clear_padding_struct
                      }
                  }
              }
+           else if (DECL_SIZE_UNIT (field) == NULL_TREE)
+             {
+               if (ftype == error_mark_node)
+                 continue;
+               gcc_assert (TREE_CODE (ftype) == ARRAY_TYPE
+                           && !COMPLETE_TYPE_P (ftype));
+               error_at (buf->loc, "flexible array member %qD does not have "
+                                   "well defined padding bits for %qs",
+                         field, "__builtin_clear_padding");
+             }
            else
              {
                HOST_WIDE_INT pos = int_byte_position (field);
--- gcc/testsuite/c-c++-common/builtin-clear-padding-2.c.jj     2020-11-24 
09:54:36.331055770 +0100
+++ gcc/testsuite/c-c++-common/builtin-clear-padding-2.c        2020-11-24 
10:16:30.468221320 +0100
@@ -0,0 +1,17 @@
+/* PR middle-end/97943 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct S { int a; char b[] __attribute__((aligned (2 * sizeof (int)))); };
+struct T { int a; struct S b; };
+union U { int a; struct S b; };
+struct V { int a; union U b; };
+
+void
+foo (struct S *s, struct T *t, union U *u, struct V *v)
+{
+  __builtin_clear_padding (s); /* { dg-error "flexible array member '(S::)?b' 
does not have well defined padding bits for '__builtin_clear_padding'" } */
+  __builtin_clear_padding (t); /* { dg-error "flexible array member '(S::)?b' 
does not have well defined padding bits for '__builtin_clear_padding'" } */
+  __builtin_clear_padding (u); /* { dg-error "flexible array member '(S::)?b' 
does not have well defined padding bits for '__builtin_clear_padding'" } */
+  __builtin_clear_padding (v); /* { dg-error "flexible array member '(S::)?b' 
does not have well defined padding bits for '__builtin_clear_padding'" } */
+}
--- gcc/testsuite/c-c++-common/builtin-clear-padding-3.c.jj     2020-11-24 
10:09:34.735913452 +0100
+++ gcc/testsuite/c-c++-common/builtin-clear-padding-3.c        2020-11-24 
10:16:41.732094196 +0100
@@ -0,0 +1,15 @@
+/* PR middle-end/97943 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+union U { int a; char b[] __attribute__((aligned (2 * sizeof (int)))); };      
/* { dg-error "flexible array member in union" } */
+struct V { int a; union U b; };
+struct W { int a; union U b; int c; };
+
+void
+foo (union U *u, struct V *v, struct W *w)
+{
+  __builtin_clear_padding (u);
+  __builtin_clear_padding (v);
+  __builtin_clear_padding (w);
+}
--- gcc/testsuite/g++.dg/ext/builtin-clear-padding-1.C.jj       2020-11-24 
10:10:49.315071724 +0100
+++ gcc/testsuite/g++.dg/ext/builtin-clear-padding-1.C  2020-11-24 
10:17:22.461634498 +0100
@@ -0,0 +1,15 @@
+// PR middle-end/97943
+// { dg-do compile }
+// { dg-options "" }
+
+struct S { int a; char b[] __attribute__((aligned (2 * sizeof (int)))); }; // 
{ dg-error "flexible array member 'S::b' not at end of 'struct \[TV]'" }
+struct T { int a; struct S b; int c; };        // { dg-message "next member 
'int T::c' declared here|in the definition of 'struct T'" }
+union U { int a; struct S b; };
+struct V { int a; union U b; int : 15; int c; };       // { dg-message "next 
member 'int V::c' declared here|in the definition of 'struct V'" }
+
+void
+foo (struct T *t, struct V *v)
+{
+  __builtin_clear_padding (t); // { dg-error "flexible array member 'S::b' 
does not have well defined padding bits for '__builtin_clear_padding'" }
+  __builtin_clear_padding (v); // { dg-error "flexible array member 'S::b' 
does not have well defined padding bits for '__builtin_clear_padding'" }
+}
--- gcc/testsuite/gcc.dg/builtin-clear-padding-2.c.jj   2020-11-24 
10:08:47.543446090 +0100
+++ gcc/testsuite/gcc.dg/builtin-clear-padding-2.c      2020-11-24 
10:17:03.031853796 +0100
@@ -0,0 +1,15 @@
+/* PR middle-end/97943 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct S { int a; char b[] __attribute__((aligned (2 * sizeof (int)))); };
+struct T { int a; struct S b; int c; };
+union U { int a; struct S b; };
+struct V { int a; union U b; int : 15; int c; };
+
+void
+foo (struct T *t, struct V *v)
+{
+  __builtin_clear_padding (t); /* { dg-error "flexible array member 'b' does 
not have well defined padding bits for '__builtin_clear_padding'" } */
+  __builtin_clear_padding (v); /* { dg-error "flexible array member 'b' does 
not have well defined padding bits for '__builtin_clear_padding'" } */
+}

        Jakub

Reply via email to