Hi, this patch implements an error message, for non-static initialization of a flexible array member. This duplicates the existing error message from the C-FE, to avoid ICE and wrong code generation issues, as pointed out in the PR.
It is a bit funny that a non-functional feature like that has already rather much test coverage. The most easy adjustment seems to change the existing test cases to use static declarations. Bootstrapped and reg-tested on x86_64-pc-linux-gnu. Is it OK for trunk? Thanks Bernd.
gcc/cp: 2018-12-15 Bernd Edlinger <bernd.edlin...@hotmail.de> PR c++/88261 * typeck2.c (digest_init_r): Add a decl parameter. Raise an error for non-static initialization of a flexible array member. (process_init_constructor, digest_init_flags, massage_init_elt, process_init_constructor_array, process_init_constructor_record, process_init_constructor_union, process_init_constructor): Add a decl parameter and pass it thru. (digest_nsdmi_init): Pass decl parameter to digest_init_flags. (digest_init): Pass NULL as decl parameter to digest_init_r. * semantics.c (finish_compound_literal): Likewise. * cp-tree.h (digest_init_flags): Adjust prototype. gcc/testsuite: 2018-12-15 Bernd Edlinger <bernd.edlin...@hotmail.de> PR c++/88261 * gcc.dg/array-6.c: Move to ... * c-c++-common/array-6.c: ... here. * g++.dg/ext/flexary3.C: Adjust test. * g++.dg/ext/flexary12.C: Likewise. * g++.dg/ext/flexary13.C: Likewise. * g++.dg/ext/flexary15.C: Likewise. * g++.dg/warn/Wplacement-new-size-1.C: Likewise. * g++.dg/warn/Wplacement-new-size-2.C: Likewise. * g++.dg/warn/Wplacement-new-size-6.C: Likewise. Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 266971) +++ gcc/cp/cp-tree.h (working copy) @@ -7483,7 +7483,8 @@ extern tree split_nonconstant_init (tree, tree); extern bool check_narrowing (tree, tree, tsubst_flags_t, bool = false); extern tree digest_init (tree, tree, tsubst_flags_t); -extern tree digest_init_flags (tree, tree, int, tsubst_flags_t); +extern tree digest_init_flags (tree, tree, int, + tsubst_flags_t, tree); extern tree digest_nsdmi_init (tree, tree, tsubst_flags_t); extern tree build_scoped_ref (tree, tree, tree *); extern tree build_x_arrow (location_t, tree, Index: gcc/cp/semantics.c =================================================================== --- gcc/cp/semantics.c (revision 266971) +++ gcc/cp/semantics.c (working copy) @@ -2828,7 +2828,7 @@ finish_compound_literal (tree type, tree compound_ return error_mark_node; } compound_literal = digest_init_flags (type, compound_literal, LOOKUP_NORMAL, - complain); + complain, NULL_TREE); if (TREE_CODE (compound_literal) == CONSTRUCTOR) { TREE_HAS_CONSTRUCTOR (compound_literal) = true; Index: gcc/cp/typeck2.c =================================================================== --- gcc/cp/typeck2.c (revision 266971) +++ gcc/cp/typeck2.c (working copy) @@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see static tree process_init_constructor (tree type, tree init, int nested, - tsubst_flags_t complain); + tsubst_flags_t complain, tree decl); /* Print an error message stemming from an attempt to use @@ -813,7 +813,7 @@ store_init_value (tree decl, tree init, vec<tree, value = init; else /* Digest the specified initializer into an expression. */ - value = digest_init_flags (type, init, flags, tf_warning_or_error); + value = digest_init_flags (type, init, flags, tf_warning_or_error, decl); if (TREE_CODE (type) == ARRAY_TYPE && TYPE_STRING_FLAG (TREE_TYPE (type)) @@ -1025,11 +1025,14 @@ check_narrowing (tree type, tree init, tsubst_flag initializer will have the right shape (brace elision has been undone). NESTED is non-zero iff we are being called for an element of a CONSTRUCTOR, - 2 iff the element of a CONSTRUCTOR is inside another CONSTRUCTOR. */ + 2 iff the element of a CONSTRUCTOR is inside another CONSTRUCTOR. + DECL points to the decl which is being initialized. It may be null if + the decl is unknown. In that case, assume it will be non-static. */ + static tree digest_init_r (tree type, tree init, int nested, int flags, - tsubst_flags_t complain) + tsubst_flags_t complain, tree decl) { enum tree_code code = TREE_CODE (type); @@ -1059,8 +1062,18 @@ digest_init_r (tree type, tree init, int nested, i { if (nested && !TYPE_DOMAIN (type)) /* C++ flexible array members have a null domain. */ - pedwarn (loc, OPT_Wpedantic, - "initialization of a flexible array member"); + { + if (decl && TREE_STATIC (decl)) + pedwarn (loc, OPT_Wpedantic, + "initialization of a flexible array member"); + else + { + if (complain & tf_error) + error_at (loc, "non-static initialization of" + " a flexible array member"); + return error_mark_node; + } + } tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); if (char_type_p (typ1) @@ -1175,7 +1188,7 @@ digest_init_r (tree type, tree init, int nested, i if (BRACE_ENCLOSED_INITIALIZER_P (init) && !TYPE_NON_AGGREGATE_CLASS (type)) - return process_init_constructor (type, init, nested, complain); + return process_init_constructor (type, init, nested, complain, decl); else { if (COMPOUND_LITERAL_P (init) && code == ARRAY_TYPE) @@ -1214,13 +1227,14 @@ digest_init_r (tree type, tree init, int nested, i tree digest_init (tree type, tree init, tsubst_flags_t complain) { - return digest_init_r (type, init, 0, LOOKUP_IMPLICIT, complain); + return digest_init_r (type, init, 0, LOOKUP_IMPLICIT, complain, NULL_TREE); } tree -digest_init_flags (tree type, tree init, int flags, tsubst_flags_t complain) +digest_init_flags (tree type, tree init, int flags, tsubst_flags_t complain, + tree decl) { - return digest_init_r (type, init, 0, flags, complain); + return digest_init_r (type, init, 0, flags, complain, decl); } /* Process the initializer INIT for an NSDMI DECL (a FIELD_DECL). */ @@ -1236,7 +1250,7 @@ digest_nsdmi_init (tree decl, tree init, tsubst_fl if (BRACE_ENCLOSED_INITIALIZER_P (init) && CP_AGGREGATE_TYPE_P (type)) init = reshape_init (type, init, complain); - init = digest_init_flags (type, init, flags, complain); + init = digest_init_flags (type, init, flags, complain, decl); if (TREE_CODE (init) == TARGET_EXPR) /* This represents the whole initialization. */ TARGET_EXPR_DIRECT_INIT_P (init) = true; @@ -1273,9 +1287,11 @@ picflag_from_initializer (tree init) /* Adjust INIT for going into a CONSTRUCTOR. */ static tree -massage_init_elt (tree type, tree init, int nested, tsubst_flags_t complain) +massage_init_elt (tree type, tree init, int nested, tsubst_flags_t complain, + tree decl) { - init = digest_init_r (type, init, nested ? 2 : 1, LOOKUP_IMPLICIT, complain); + init = digest_init_r (type, init, nested ? 2 : 1, LOOKUP_IMPLICIT, complain, + decl); /* Strip a simple TARGET_EXPR when we know this is an initializer. */ if (SIMPLE_TARGET_EXPR_P (init)) init = TARGET_EXPR_INITIAL (init); @@ -1294,7 +1310,7 @@ static tree static int process_init_constructor_array (tree type, tree init, int nested, - tsubst_flags_t complain) + tsubst_flags_t complain, tree decl) { unsigned HOST_WIDE_INT i, len = 0; int flags = 0; @@ -1347,7 +1363,8 @@ process_init_constructor_array (tree type, tree in ce->index = error_mark_node; gcc_assert (ce->value); ce->value - = massage_init_elt (TREE_TYPE (type), ce->value, nested, complain); + = massage_init_elt (TREE_TYPE (type), ce->value, nested, complain, + decl); gcc_checking_assert (ce->value == error_mark_node @@ -1371,7 +1388,8 @@ process_init_constructor_array (tree type, tree in we can't rely on the back end to do it for us, so make the initialization explicit by list-initializing from T{}. */ next = build_constructor (init_list_type_node, NULL); - next = massage_init_elt (TREE_TYPE (type), next, nested, complain); + next = massage_init_elt (TREE_TYPE (type), next, nested, complain, + decl); if (initializer_zerop (next)) /* The default zero-initialization is fine for us; don't add anything to the CONSTRUCTOR. */ @@ -1417,7 +1435,7 @@ process_init_constructor_array (tree type, tree in static int process_init_constructor_record (tree type, tree init, int nested, - tsubst_flags_t complain) + tsubst_flags_t complain, tree decl) { vec<constructor_elt, va_gc> *v = NULL; tree field; @@ -1499,7 +1517,7 @@ process_init_constructor_record (tree type, tree i if (ce) { gcc_assert (ce->value); - next = massage_init_elt (type, next, nested, complain); + next = massage_init_elt (type, next, nested, complain, decl); ++idx; } } @@ -1528,7 +1546,8 @@ process_init_constructor_record (tree type, tree i for us, so build up TARGET_EXPRs. If the type in question is a class, just build one up; if it's an array, recurse. */ next = build_constructor (init_list_type_node, NULL); - next = massage_init_elt (TREE_TYPE (field), next, nested, complain); + next = massage_init_elt (TREE_TYPE (field), next, nested, complain, + decl); /* Warn when some struct elements are implicitly initialized. */ if ((complain & tf_warning) @@ -1644,7 +1663,7 @@ process_init_constructor_record (tree type, tree i static int process_init_constructor_union (tree type, tree init, int nested, - tsubst_flags_t complain) + tsubst_flags_t complain, tree decl) { constructor_elt *ce; int len; @@ -1731,7 +1750,7 @@ process_init_constructor_union (tree type, tree in if (ce->value && ce->value != error_mark_node) ce->value = massage_init_elt (TREE_TYPE (ce->index), ce->value, nested, - complain); + complain, decl); return picflag_from_initializer (ce->value); } @@ -1752,7 +1771,7 @@ process_init_constructor_union (tree type, tree in static tree process_init_constructor (tree type, tree init, int nested, - tsubst_flags_t complain) + tsubst_flags_t complain, tree decl) { int flags; @@ -1759,11 +1778,11 @@ process_init_constructor (tree type, tree init, in gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); if (TREE_CODE (type) == ARRAY_TYPE || VECTOR_TYPE_P (type)) - flags = process_init_constructor_array (type, init, nested, complain); + flags = process_init_constructor_array (type, init, nested, complain, decl); else if (TREE_CODE (type) == RECORD_TYPE) - flags = process_init_constructor_record (type, init, nested, complain); + flags = process_init_constructor_record (type, init, nested, complain, decl); else if (TREE_CODE (type) == UNION_TYPE) - flags = process_init_constructor_union (type, init, nested, complain); + flags = process_init_constructor_union (type, init, nested, complain, decl); else gcc_unreachable (); Index: gcc/testsuite/g++.dg/ext/flexary12.C =================================================================== --- gcc/testsuite/g++.dg/ext/flexary12.C (revision 266971) +++ gcc/testsuite/g++.dg/ext/flexary12.C (working copy) @@ -12,7 +12,7 @@ struct A { void f1 () { // This is the meat of the test from c++/69290: - struct A a + static struct A a = { "c" }; // { dg-error "invalid conversion from .const char\\*. to .int." } (void)&a; @@ -27,13 +27,13 @@ struct B { void f2 () { - struct B b1 + static struct B b1 = { 0, "c" }; // { dg-error "invalid conversion from .const char\\*. to .int." } (void)&b1; const char s[] = "c"; - struct B b2 + static struct B b2 = { 0, s }; // { dg-error "invalid conversion from .const char\\*. to .int." } (void)&b2; @@ -57,7 +57,7 @@ struct C { void f3 () { - struct C<double> cd + static struct C<double> cd = { "c" }; // { dg-error "cannot convert .const char\\*. to .double." } (void)&cd; Index: gcc/testsuite/g++.dg/ext/flexary13.C =================================================================== --- gcc/testsuite/g++.dg/ext/flexary13.C (revision 266971) +++ gcc/testsuite/g++.dg/ext/flexary13.C (working copy) @@ -19,33 +19,33 @@ int main () ASSERT (s.n == 0); } { - Ax s = + static Ax s = { 0, { } }; // dg-warning "initialization of a flexible array member" } ASSERT (s.n == 0); } { - Ax s = + static Ax s = { 1, { 2 } }; // dg-warning "initialization of a flexible array member" } ASSERT (s.n == 1 && s.a [0] == 2); } { - Ax s = + static Ax s = { 2, { 3, 4 } }; // dg-warning "initialization of a flexible array member" } ASSERT (s.n = 2 && s.a [0] == 3 && s.a [1] == 4); } { - Ax s = + static Ax s = { 123, i }; // dg-warning "initialization of a flexible array member" } ASSERT (s.n == 123 && s.a [0] == i); } { - Ax s = + static Ax s = { 456, { i } }; // dg-warning "initialization of a flexible array member" } ASSERT (s.n == 456 && s.a [0] == i); } { int j = i + 1, k = j + 1; - Ax s = + static Ax s = { 3, { i, j, k } }; // dg-warning "initialization of a flexible array member" } ASSERT (s.n == 3 && s.a [0] == i && s.a [1] == j && s.a [2] == k); } Index: gcc/testsuite/g++.dg/ext/flexary15.C =================================================================== --- gcc/testsuite/g++.dg/ext/flexary15.C (revision 266971) +++ gcc/testsuite/g++.dg/ext/flexary15.C (working copy) @@ -10,5 +10,5 @@ struct S { void foo (const char *a) { - const S s = { 1, { a, "b" } }; // { dg-warning "invalid conversion" } + static const S s = { 1, { a, "b" } }; // { dg-warning "invalid conversion" } } Index: gcc/testsuite/g++.dg/ext/flexary3.C =================================================================== --- gcc/testsuite/g++.dg/ext/flexary3.C (revision 266971) +++ gcc/testsuite/g++.dg/ext/flexary3.C (working copy) @@ -17,5 +17,6 @@ struct s { int main() { struct s s = { .c = 0 }; // { dg-error "initializer" } + // { dg-error "non-static initialization of a flexible array member" "" { target *-*-* } .-1 } return 0; } Index: gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C (revision 266971) +++ gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C (working copy) @@ -28,7 +28,7 @@ void fAx (Ax *px, Ax &rx) void fAx2 () { - Ax ax2 = { 1, { 2, 3 } }; + static Ax ax2 = { 1, { 2, 3 } }; new (ax2.a) Int16; new (ax2.a) Int32; // { dg-warning "placement" } @@ -82,7 +82,7 @@ void fBx (BAx *pbx, BAx &rbx) void fBx1 () { - BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ {} } }; + static BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ {} } }; new (bax1.ax.a) char; // { dg-warning "placement" } new (bax1.ax.a) char[2]; // { dg-warning "placement" } Index: gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C (revision 266971) +++ gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C (working copy) @@ -36,10 +36,10 @@ void fAx2 () // isn't allowed in C and should perhaps be disallowed in C++ as // well to avoid c++/69696 - incorrect initialization of block-scope // flexible array members. - Ax ax2 = { 1, { 2, 3 } }; + Ax ax2 = { 1, { 2, 3 } }; // { dg-error "non-static initialization of a flexible array member" } - new (ax2.a) Int16; - new (ax2.a) Int16[1]; + new (ax2.a) Int16; // { dg-warning "placement" } + new (ax2.a) Int16[1]; // { dg-warning "placement" } new (ax2.a) Int16[2]; // { dg-warning "placement" } new (ax2.a) Int32; // { dg-warning "placement" } new (ax2.a) Int32[2]; // { dg-warning "placement" } @@ -140,7 +140,7 @@ void fBx (BAx *pbx, BAx &rbx) void fBx1 () { - BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ {} } }; + static BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ {} } }; new (bax1.ax.a) char; // { dg-warning "placement" } new (bax1.ax.a) char[2]; // { dg-warning "placement" } Index: gcc/testsuite/g++.dg/warn/Wplacement-new-size-6.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wplacement-new-size-6.C (revision 266971) +++ gcc/testsuite/g++.dg/warn/Wplacement-new-size-6.C (working copy) @@ -15,7 +15,7 @@ struct BAx { int i; Ax ax; }; void fBx1 () { - BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ { 3 } } }; // { dg-error "initialization of flexible array member in a nested context" } + static BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ { 3 } } }; // { dg-error "initialization of flexible array member in a nested context" } new (bax1.ax.a) char; // { dg-warning "placement" } new (bax1.ax.a) char[2]; // { dg-warning "placement" } @@ -25,7 +25,7 @@ void fBx1 () void fBx2 () { - BAx bax2 = { 1, /* Ax = */ { 2, /* a[] = */ { 3, 4 } } }; // { dg-error "initialization of flexible array member in a nested context" } + static BAx bax2 = { 1, /* Ax = */ { 2, /* a[] = */ { 3, 4 } } }; // { dg-error "initialization of flexible array member in a nested context" } new (bax2.ax.a) char; // { dg-warning "placement" } new (bax2.ax.a) char[2]; // { dg-warning "placement" } @@ -37,7 +37,7 @@ void fBx2 () void fBx3 () { - BAx bax2 = { 1, /* Ax = */ { 3, /* a[] = */ { 4, 5, 6 } } }; // { dg-error "initialization of flexible array member in a nested context" } + static BAx bax2 = { 1, /* Ax = */ { 3, /* a[] = */ { 4, 5, 6 } } }; // { dg-error "initialization of flexible array member in a nested context" } new (bax2.ax.a) char; // { dg-warning "placement" } new (bax2.ax.a) char[2]; // { dg-warning "placement" } Index: gcc/testsuite/gcc.dg/array-6.c =================================================================== --- gcc/testsuite/gcc.dg/array-6.c (revision 266971) +++ gcc/testsuite/gcc.dg/array-6.c (working copy) @@ -1,18 +0,0 @@ -/* PR c/5597 */ -/* { dg-do compile } */ -/* { dg-options "" } */ - -/* Verify that GCC forbids non-static initialization of - flexible array members. */ - -struct str { int len; char s[]; }; - -struct str a = { 2, "a" }; - -void foo() -{ - static struct str b = { 2, "b" }; - struct str c = { 2, "c" }; /* { dg-error "(non-static)|(near initialization)" } */ - struct str d = (struct str) { 2, "d" }; /* { dg-error "(non-static)|(near initialization)" } */ - struct str e = (struct str) { d.len, "e" }; /* { dg-error "(non-static)|(initialization)" } */ -} Index: gcc/testsuite/c-c++-common/array-6.c =================================================================== --- gcc/testsuite/c-c++-common/array-6.c (revision 0) +++ gcc/testsuite/c-c++-common/array-6.c (working copy) @@ -0,0 +1,18 @@ +/* PR c/5597 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +/* Verify that GCC forbids non-static initialization of + flexible array members. */ + +struct str { int len; char s[]; }; + +struct str a = { 2, "a" }; + +void foo() +{ + static struct str b = { 2, "b" }; + struct str c = { 2, "c" }; /* { dg-error "(non-static)|(near initialization)" } */ + struct str d = (struct str) { 2, "d" }; /* { dg-error "(non-static)|(near initialization)" } */ + struct str e = (struct str) { d.len, "e" }; /* { dg-error "(non-static)|(initialization)" } */ +}