From: Jakub Jelinek Date: Wed, 25 Nov 2020 09:37:58 +0000 (+0100) Subject: middle-end: Reject flexible array members in __builtin_clear_padding [PR97943] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a7285c8659689e9ade53fcb996b26d874455a4f3;p=gcc.git middle-end: Reject flexible array members in __builtin_clear_padding [PR97943] 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. 2020-11-25 Jakub Jelinek 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. --- diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 905c0a057cb..1f0a609706e 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -4329,6 +4329,17 @@ clear_padding_union (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz) 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; @@ -4446,11 +4457,12 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz) 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); @@ -4513,6 +4525,16 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz) } } } + 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); diff --git a/gcc/testsuite/c-c++-common/builtin-clear-padding-2.c b/gcc/testsuite/c-c++-common/builtin-clear-padding-2.c new file mode 100644 index 00000000000..67c03c898d6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/builtin-clear-padding-2.c @@ -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'" } */ +} diff --git a/gcc/testsuite/c-c++-common/builtin-clear-padding-3.c b/gcc/testsuite/c-c++-common/builtin-clear-padding-3.c new file mode 100644 index 00000000000..d16cc6aad05 --- /dev/null +++ b/gcc/testsuite/c-c++-common/builtin-clear-padding-3.c @@ -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); +} diff --git a/gcc/testsuite/g++.dg/ext/builtin-clear-padding-1.C b/gcc/testsuite/g++.dg/ext/builtin-clear-padding-1.C new file mode 100644 index 00000000000..d1881869e02 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/builtin-clear-padding-1.C @@ -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'" } +} diff --git a/gcc/testsuite/gcc.dg/builtin-clear-padding-2.c b/gcc/testsuite/gcc.dg/builtin-clear-padding-2.c new file mode 100644 index 00000000000..641d47d70f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-clear-padding-2.c @@ -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'" } */ +}