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