[PATCH] middle-end: Reject flexible array members in __builtin_clear_padding [PR97943]

Jakub Jelinek jakub@redhat.com
Tue Nov 24 10:33:17 GMT 2020


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  <jakub@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



More information about the Gcc-patches mailing list