This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Harmonize C++ flexible array member initialization with C (PR c++/80135, PR c++/81922)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>, Nathan Sidwell <nathan at acm dot org>
- Cc: gcc-patches at gcc dot gnu dot org, Martin Sebor <msebor at gmail dot com>
- Date: Fri, 8 Dec 2017 17:15:07 +0100
- Subject: [C++ PATCH] Harmonize C++ flexible array member initialization with C (PR c++/80135, PR c++/81922)
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
Martin's patch a few years ago started allowing flexible array members
inside of nested aggregates, similarly to what we were doing in C.
But C rejects cases where we in nested context try to initialize a flexible
array member with a non-empty initializer, because that is something that
can't really work. Say if a flexible array member is inside of a struct
and we are initializing an array of such structs, we can't really have
each array element with a different width based on how large was the
initializer for a particular element's flexible array member.
After Martin's change, we were accepting those and silently generating bogus
assembly (claiming some size of elements but the initializer really followed
the sizes of what was added there), then I think Nathan added some
verification and since then we usually just ICE on those.
This patch does the similar thing in the C++ FE to what the C FE does, i.e.
allow empty initializers of flexible array members ( {}, not "" as that is
already non-zero size) everywhere, and for others allow them only for the
outermost struct/class/union.
Allowing the empty flexible array members is IMHO useful, people can have
say some general structure that is sometimes used as toplevel object and
can be initialized with arbitrarily sized array, and sometimes just use it
inside other structs or arrays if the array isn't needed.
digest_init_r already had a nested argument, but it wasn't actually the
nesting this patch is looking for, because nested true is already in
processing the CONSTRUCTOR for flexible array member, so I've changed it to
an int that tracks limited depth information (just 0 (former nested ==
false), 1 and 2 (both former nested == true), where 2 is used when we
digest_init_r once or more times more).
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2017-12-08 Jakub Jelinek <jakub@redhat.com>
PR c++/80135
PR c++/81922
* typeck2.c (digest_init_r): Change nested argument type from bool to
int. Use code instead of TREE_CODE (type) where possible. If
nested == 2, diagnose initialization of flexible array member with
STRING_CST. Pass nested to process_init_constructor. Formatting fix.
(digest_init, digest_init_flags): Adjust digest_init_r caller.
(massage_init_elt): Add nested argument. Pass 2 instead of 1 to
digest_init_r's nested argument if nested is non-zero.
(process_init_constructor_array): Add nested argument. If nested == 2,
diagnose initialization of flexible array member with non-empty
braced enclosed list. Pass nested to massage_init_elt.
(process_init_constructor_record, process_init_constructor_union): Add
nested argument, pass it to massage_init_elt.
(process_init_constructor): Add nested argument, pass it to
process_init_constructor_{array,record,union}.
* init.c (find_field_init): Return NULL_TREE if init is
error_mark_node. Don't look through nested CONSTRUCTORs.
* g++.dg/warn/Wplacement-new-size-1.C (fBx1): Initialize nested
flexible array member only with {}. Add dg-warning.
(fBx2, fBx3): Remove.
* g++.dg/warn/Wplacement-new-size-2.C (fBx1): Initialize nested
flexible array member only with {}. Add dg-warning.
(fBx2, fBx3): Remove.
* g++.dg/warn/Wplacement-new-size-6.C: New test.
* g++.dg/ext/flexary13.C (main): Remove test for initialization
of nested flexible array member with non-empty initializer.
* g++.dg/ext/flexary25.C: New test.
* g++.dg/ext/flexary26.C: New test.
* g++.dg/ext/flexary27.C: New test.
* g++.dg/parse/pr43765.C: Expect diagnostics about initialization
of nested flexible array member with non-empty initializer. Expect
C++2A diagnostics about mixing of designated and non-designated
initializers.
--- gcc/cp/typeck2.c.jj 2017-12-07 18:04:54.362753051 +0100
+++ gcc/cp/typeck2.c 2017-12-08 12:55:39.740361230 +0100
@@ -34,7 +34,8 @@ along with GCC; see the file COPYING3.
#include "intl.h"
static tree
-process_init_constructor (tree type, tree init, tsubst_flags_t complain);
+process_init_constructor (tree type, tree init, int nested,
+ tsubst_flags_t complain);
/* Print an error message stemming from an attempt to use
@@ -996,10 +997,11 @@ check_narrowing (tree type, tree init, t
For aggregate types, it assumes that reshape_init has already run, thus the
initializer will have the right shape (brace elision has been undone).
- NESTED is true iff we are being called for an element of a CONSTRUCTOR. */
+ 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. */
static tree
-digest_init_r (tree type, tree init, bool nested, int flags,
+digest_init_r (tree type, tree init, int nested, int flags,
tsubst_flags_t complain)
{
enum tree_code code = TREE_CODE (type);
@@ -1011,7 +1013,7 @@ digest_init_r (tree type, tree init, boo
/* We must strip the outermost array type when completing the type,
because the its bounds might be incomplete at the moment. */
- if (!complete_type_or_maybe_complain (TREE_CODE (type) == ARRAY_TYPE
+ if (!complete_type_or_maybe_complain (code == ARRAY_TYPE
? TREE_TYPE (type) : type, NULL_TREE,
complain))
return error_mark_node;
@@ -1029,11 +1031,9 @@ digest_init_r (tree type, tree init, boo
if (code == ARRAY_TYPE)
{
if (nested && !TYPE_DOMAIN (type))
- {
- /* C++ flexible array members have a null domain. */
- pedwarn (loc, OPT_Wpedantic,
- "initialization of a flexible array member");
- }
+ /* C++ flexible array members have a null domain. */
+ pedwarn (loc, OPT_Wpedantic,
+ "initialization of a flexible array member");
tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
if (char_type_p (typ1)
@@ -1069,6 +1069,14 @@ digest_init_r (tree type, tree init, boo
}
}
+ if (nested == 2 && !TYPE_DOMAIN (type))
+ {
+ if (complain & tf_error)
+ error_at (loc, "initialization of flexible array member "
+ "in a nested context");
+ return error_mark_node;
+ }
+
if (type != TREE_TYPE (init)
&& !variably_modified_type_p (type, NULL_TREE))
{
@@ -1093,8 +1101,7 @@ digest_init_r (tree type, tree init, boo
}
/* Handle scalar types (including conversions) and references. */
- if ((TREE_CODE (type) != COMPLEX_TYPE
- || BRACE_ENCLOSED_INITIALIZER_P (init))
+ if ((code != COMPLEX_TYPE || BRACE_ENCLOSED_INITIALIZER_P (init))
&& (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE))
{
if (nested)
@@ -1108,11 +1115,11 @@ digest_init_r (tree type, tree init, boo
/* Come here only for aggregates: records, arrays, unions, complex numbers
and vectors. */
- gcc_assert (TREE_CODE (type) == ARRAY_TYPE
+ gcc_assert (code == ARRAY_TYPE
|| VECTOR_TYPE_P (type)
- || TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE
- || TREE_CODE (type) == COMPLEX_TYPE);
+ || code == RECORD_TYPE
+ || code == UNION_TYPE
+ || code == COMPLEX_TYPE);
/* "If T is a class type and the initializer list has a single
element of type cv U, where U is T or a class derived from T,
@@ -1132,10 +1139,10 @@ digest_init_r (tree type, tree init, boo
if (BRACE_ENCLOSED_INITIALIZER_P (init)
&& !TYPE_NON_AGGREGATE_CLASS (type))
- return process_init_constructor (type, init, complain);
+ return process_init_constructor (type, init, nested, complain);
else
{
- if (COMPOUND_LITERAL_P (init) && TREE_CODE (type) == ARRAY_TYPE)
+ if (COMPOUND_LITERAL_P (init) && code == ARRAY_TYPE)
{
if (complain & tf_error)
error_at (loc, "cannot initialize aggregate of type %qT with "
@@ -1144,7 +1151,7 @@ digest_init_r (tree type, tree init, boo
return error_mark_node;
}
- if (TREE_CODE (type) == ARRAY_TYPE
+ if (code == ARRAY_TYPE
&& !BRACE_ENCLOSED_INITIALIZER_P (init))
{
/* Allow the result of build_array_copy and of
@@ -1171,13 +1178,13 @@ digest_init_r (tree type, tree init, boo
tree
digest_init (tree type, tree init, tsubst_flags_t complain)
{
- return digest_init_r (type, init, false, LOOKUP_IMPLICIT, complain);
+ return digest_init_r (type, init, 0, LOOKUP_IMPLICIT, complain);
}
tree
digest_init_flags (tree type, tree init, int flags, tsubst_flags_t complain)
{
- return digest_init_r (type, init, false, flags, complain);
+ return digest_init_r (type, init, 0, flags, complain);
}
/* Process the initializer INIT for an NSDMI DECL (a FIELD_DECL). */
@@ -1230,9 +1237,9 @@ picflag_from_initializer (tree init)
/* Adjust INIT for going into a CONSTRUCTOR. */
static tree
-massage_init_elt (tree type, tree init, tsubst_flags_t complain)
+massage_init_elt (tree type, tree init, int nested, tsubst_flags_t complain)
{
- init = digest_init_r (type, init, true, LOOKUP_IMPLICIT, complain);
+ init = digest_init_r (type, init, nested ? 2 : 1, LOOKUP_IMPLICIT, complain);
/* Strip a simple TARGET_EXPR when we know this is an initializer. */
if (SIMPLE_TARGET_EXPR_P (init))
init = TARGET_EXPR_INITIAL (init);
@@ -1250,7 +1257,7 @@ massage_init_elt (tree type, tree init,
which describe the initializers. */
static int
-process_init_constructor_array (tree type, tree init,
+process_init_constructor_array (tree type, tree init, int nested,
tsubst_flags_t complain)
{
unsigned HOST_WIDE_INT i, len = 0;
@@ -1273,6 +1280,15 @@ process_init_constructor_array (tree typ
TYPE_SIGN (TREE_TYPE (domain))).to_uhwi ();
else
unbounded = true; /* Take as many as there are. */
+
+ if (nested == 2 && !domain && !vec_safe_is_empty (v))
+ {
+ if (complain & tf_error)
+ error_at (EXPR_LOC_OR_LOC (init, input_location),
+ "initialization of flexible array member "
+ "in a nested context");
+ return PICFLAG_ERRONEOUS;
+ }
}
else
/* Vectors are like simple fixed-size arrays. */
@@ -1301,7 +1317,8 @@ process_init_constructor_array (tree typ
else
ce->index = size_int (i);
gcc_assert (ce->value);
- ce->value = massage_init_elt (TREE_TYPE (type), ce->value, complain);
+ ce->value
+ = massage_init_elt (TREE_TYPE (type), ce->value, nested, complain);
if (ce->value != error_mark_node)
gcc_assert (same_type_ignoring_top_level_qualifiers_p
@@ -1323,7 +1340,7 @@ process_init_constructor_array (tree typ
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, complain);
+ next = massage_init_elt (TREE_TYPE (type), next, nested, complain);
if (initializer_zerop (next))
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
@@ -1354,7 +1371,7 @@ process_init_constructor_array (tree typ
the initializers. */
static int
-process_init_constructor_record (tree type, tree init,
+process_init_constructor_record (tree type, tree init, int nested,
tsubst_flags_t complain)
{
vec<constructor_elt, va_gc> *v = NULL;
@@ -1436,7 +1453,7 @@ process_init_constructor_record (tree ty
if (ce)
{
gcc_assert (ce->value);
- next = massage_init_elt (type, next, complain);
+ next = massage_init_elt (type, next, nested, complain);
++idx;
}
}
@@ -1462,7 +1479,7 @@ process_init_constructor_record (tree ty
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, complain);
+ next = massage_init_elt (TREE_TYPE (field), next, nested, complain);
/* Warn when some struct elements are implicitly initialized. */
if ((complain & tf_warning)
@@ -1576,7 +1593,7 @@ process_init_constructor_record (tree ty
which describe the initializer. */
static int
-process_init_constructor_union (tree type, tree init,
+process_init_constructor_union (tree type, tree init, int nested,
tsubst_flags_t complain)
{
constructor_elt *ce;
@@ -1662,7 +1679,8 @@ process_init_constructor_union (tree typ
}
if (ce->value && ce->value != error_mark_node)
- ce->value = massage_init_elt (TREE_TYPE (ce->index), ce->value, complain);
+ ce->value = massage_init_elt (TREE_TYPE (ce->index), ce->value, nested,
+ complain);
return picflag_from_initializer (ce->value);
}
@@ -1682,18 +1700,19 @@ process_init_constructor_union (tree typ
of error. */
static tree
-process_init_constructor (tree type, tree init, tsubst_flags_t complain)
+process_init_constructor (tree type, tree init, int nested,
+ tsubst_flags_t complain)
{
int flags;
gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
if (TREE_CODE (type) == ARRAY_TYPE || VECTOR_TYPE_P (type))
- flags = process_init_constructor_array (type, init, complain);
+ flags = process_init_constructor_array (type, init, nested, complain);
else if (TREE_CODE (type) == RECORD_TYPE)
- flags = process_init_constructor_record (type, init, complain);
+ flags = process_init_constructor_record (type, init, nested, complain);
else if (TREE_CODE (type) == UNION_TYPE)
- flags = process_init_constructor_union (type, init, complain);
+ flags = process_init_constructor_union (type, init, nested, complain);
else
gcc_unreachable ();
--- gcc/cp/init.c.jj 2017-11-28 09:37:08.000000000 +0100
+++ gcc/cp/init.c 2017-12-08 14:00:07.210615314 +0100
@@ -2459,7 +2459,7 @@ throw_bad_array_new_length (void)
static tree
find_field_init (tree t, tree init)
{
- if (!init)
+ if (!init || init == error_mark_node)
return NULL_TREE;
unsigned HOST_WIDE_INT idx;
@@ -2471,11 +2471,6 @@ find_field_init (tree t, tree init)
/* If the member T is found, return it. */
if (field == t)
return elt;
-
- /* Otherwise continue and/or recurse into nested initializers. */
- if (TREE_CODE (elt) == CONSTRUCTOR
- && (init = find_field_init (t, elt)))
- return init;
}
return NULL_TREE;
}
--- gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C.jj 2016-02-08 18:39:16.000000000 +0100
+++ gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C 2017-12-08 13:38:57.000000000 +0100
@@ -82,38 +82,14 @@ void fBx (BAx *pbx, BAx &rbx)
void fBx1 ()
{
- BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ { 3 } } };
+ BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ {} } };
- new (bax1.ax.a) char;
+ new (bax1.ax.a) char; // { dg-warning "placement" }
new (bax1.ax.a) char[2]; // { dg-warning "placement" }
new (bax1.ax.a) Int16; // { dg-warning "placement" }
new (bax1.ax.a) Int32; // { dg-warning "placement" }
}
-void fBx2 ()
-{
- BAx bax2 = { 1, /* Ax = */ { 2, /* a[] = */ { 3, 4 } } };
-
- new (bax2.ax.a) char;
- new (bax2.ax.a) char[2];
- new (bax2.ax.a) char[3]; // { dg-warning "placement" }
- new (bax2.ax.a) Int16;
- new (bax2.ax.a) char[4]; // { dg-warning "placement" }
- new (bax2.ax.a) Int32; // { dg-warning "placement" }
-}
-
-void fBx3 ()
-{
- BAx bax2 = { 1, /* Ax = */ { 3, /* a[] = */ { 4, 5, 6 } } };
-
- new (bax2.ax.a) char;
- new (bax2.ax.a) char[2];
- new (bax2.ax.a) Int16;
- new (bax2.ax.a) char[3];
- new (bax2.ax.a) char[4]; // { dg-warning "placement" }
- new (bax2.ax.a) Int32; // { dg-warning "placement" }
-}
-
void fB0 (BA0 *pb0, BA0 &rb0)
{
BA0 ba0;
--- gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C.jj 2016-02-08 18:39:16.000000000 +0100
+++ gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C 2017-12-08 13:44:39.000000000 +0100
@@ -140,38 +140,14 @@ void fBx (BAx *pbx, BAx &rbx)
void fBx1 ()
{
- BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ { 3 } } };
+ BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ {} } };
- new (bax1.ax.a) char;
+ new (bax1.ax.a) char; // { dg-warning "placement" }
new (bax1.ax.a) char[2]; // { dg-warning "placement" }
new (bax1.ax.a) Int16; // { dg-warning "placement" }
new (bax1.ax.a) Int32; // { dg-warning "placement" }
}
-void fBx2 ()
-{
- BAx bax2 = { 1, /* Ax = */ { 2, /* a[] = */ { 3, 4 } } };
-
- new (bax2.ax.a) char;
- new (bax2.ax.a) char[2];
- new (bax2.ax.a) char[3]; // { dg-warning "placement" }
- new (bax2.ax.a) Int16;
- new (bax2.ax.a) char[4]; // { dg-warning "placement" }
- new (bax2.ax.a) Int32; // { dg-warning "placement" }
-}
-
-void fBx3 ()
-{
- BAx bax2 = { 1, /* Ax = */ { 3, /* a[] = */ { 4, 5, 6 } } };
-
- new (bax2.ax.a) char;
- new (bax2.ax.a) char[2];
- new (bax2.ax.a) Int16;
- new (bax2.ax.a) char[3];
- new (bax2.ax.a) char[4]; // { dg-warning "placement" }
- new (bax2.ax.a) Int32; // { dg-warning "placement" }
-}
-
void fB0 (BA0 *pb0, BA0 &rb0)
{
BA0 ba0;
--- gcc/testsuite/g++.dg/warn/Wplacement-new-size-6.C.jj 2017-12-08 13:48:24.443433300 +0100
+++ gcc/testsuite/g++.dg/warn/Wplacement-new-size-6.C 2017-12-08 13:48:17.000000000 +0100
@@ -0,0 +1,48 @@
+// { dg-do compile }
+// { dg-options "-Wno-pedantic -Wplacement-new=1" }
+
+typedef __typeof__ (sizeof 0) size_t;
+
+void* operator new (size_t, void *p) { return p; }
+void* operator new[] (size_t, void *p) { return p; }
+
+struct Ax { char n, a []; };
+
+typedef __INT16_TYPE__ Int16;
+typedef __INT32_TYPE__ Int32;
+
+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" }
+
+ new (bax1.ax.a) char; // { dg-warning "placement" }
+ new (bax1.ax.a) char[2]; // { dg-warning "placement" }
+ new (bax1.ax.a) Int16; // { dg-warning "placement" }
+ new (bax1.ax.a) Int32; // { dg-warning "placement" }
+}
+
+void fBx2 ()
+{
+ 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" }
+ new (bax2.ax.a) char[3]; // { dg-warning "placement" }
+ new (bax2.ax.a) Int16; // { dg-warning "placement" }
+ new (bax2.ax.a) char[4]; // { dg-warning "placement" }
+ new (bax2.ax.a) Int32; // { dg-warning "placement" }
+}
+
+void fBx3 ()
+{
+ 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" }
+ new (bax2.ax.a) Int16; // { dg-warning "placement" }
+ new (bax2.ax.a) char[3]; // { dg-warning "placement" }
+ new (bax2.ax.a) char[4]; // { dg-warning "placement" }
+ new (bax2.ax.a) Int32; // { dg-warning "placement" }
+}
--- gcc/testsuite/g++.dg/ext/flexary13.C.jj 2016-02-04 10:00:25.000000000 +0100
+++ gcc/testsuite/g++.dg/ext/flexary13.C 2017-12-08 13:52:22.465431378 +0100
@@ -55,10 +55,4 @@ int main ()
{ 1, { 2 } }; // dg-warning "initialization of a flexible array member" }
ASSERT (s.i == 1 && s.ax.n == 2);
}
-
- {
- AAx s =
- { 1, { 2, { 3 } } }; // dg-warning "initialization of a flexible array member" }
- ASSERT (s.i == 1 && s.ax.n == 2 && s.ax.a [0] == 3);
- }
}
--- gcc/testsuite/g++.dg/ext/flexary25.C.jj 2017-12-08 12:57:41.000000000 +0100
+++ gcc/testsuite/g++.dg/ext/flexary25.C 2017-12-08 12:57:26.000000000 +0100
@@ -0,0 +1,20 @@
+// PR c++/81922
+// { dg-do compile }
+// { dg-options "" }
+
+struct S { const char *a; char b[]; };
+struct T { int a; int b[]; };
+#if __cplusplus >= 201103L
+S c[] { "", "" }; // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+S d[] { "", { 0 } }; // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+T e[] { 1, { 2 }, 3, { 4 } }; // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+T f[] { 1, {}, 3, {} };
+T g { 1, { 1, 2, 3 } };
+S h { "abcd", "" };
+#endif
+S i[] = { "", "", "", "" }; // { dg-error "initialization of flexible array member in a nested context" }
+S j[] = { "", { 1 }, "", { 2, 3 } }; // { dg-error "initialization of flexible array member in a nested context" }
+T k[] = { 1, { 2 }, 3, { 4 } }; // { dg-error "initialization of flexible array member in a nested context" }
+T l[] = { 1, {}, 3, {} };
+T m = { 1, { 1, 2, 3 } };
+S n = { "", "abcde" };
--- gcc/testsuite/g++.dg/ext/flexary26.C.jj 2017-12-08 13:00:45.000000000 +0100
+++ gcc/testsuite/g++.dg/ext/flexary26.C 2017-12-08 13:00:38.000000000 +0100
@@ -0,0 +1,26 @@
+// PR c++/81922
+// { dg-do compile }
+// { dg-options "-Wpedantic" }
+
+struct S { const char *a; char b[]; }; // { dg-warning "forbids flexible array member" }
+struct T { int a; int b[]; }; // { dg-warning "forbids flexible array member" }
+#if __cplusplus >= 201103L
+S c[] { "", "" }; // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+ // { dg-warning "initialization of a flexible array member" "" { target c++11 } .-1 }
+S d[] { "", { 0 } }; // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+ // { dg-warning "initialization of a flexible array member" "" { target c++11 } .-1 }
+T e[] { 1, { 2 }, 3, { 4 } }; // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+ // { dg-warning "initialization of a flexible array member" "" { target c++11 } .-1 }
+T f[] { 1, {}, 3, {} }; // { dg-warning "initialization of a flexible array member" "" { target c++11 } }
+T g { 1, { 1, 2, 3 } }; // { dg-warning "initialization of a flexible array member" "" { target c++11 } }
+S h { "abcd", "" }; // { dg-warning "initialization of a flexible array member" "" { target c++11 } }
+#endif
+S i[] = { "", "", "", "" }; // { dg-error "initialization of flexible array member in a nested context" }
+ // { dg-warning "initialization of a flexible array member" "" { target *-*-* } .-1 }
+S j[] = { "", { 1 }, "", { 2, 3 } }; // { dg-error "initialization of flexible array member in a nested context" }
+ // { dg-warning "initialization of a flexible array member" "" { target *-*-* } .-1 }
+T k[] = { 1, { 2 }, 3, { 4 } }; // { dg-error "initialization of flexible array member in a nested context" }
+ // { dg-warning "initialization of a flexible array member" "" { target *-*-* } .-1 }
+T l[] = { 1, {}, 3, {} }; // { dg-warning "initialization of a flexible array member" }
+T m = { 1, { 1, 2, 3 } }; // { dg-warning "initialization of a flexible array member" }
+S n = { "", "abcde" }; // { dg-warning "initialization of a flexible array member" }
--- gcc/testsuite/g++.dg/ext/flexary27.C.jj 2017-12-08 13:00:53.000000000 +0100
+++ gcc/testsuite/g++.dg/ext/flexary27.C 2017-12-08 13:01:12.000000000 +0100
@@ -0,0 +1,25 @@
+// PR c++/81922
+// { dg-do compile }
+
+struct S { const char *a; char b[]; }; // { dg-error "forbids flexible array member" }
+struct T { int a; int b[]; }; // { dg-error "forbids flexible array member" }
+#if __cplusplus >= 201103L
+S c[] { "", "" }; // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+ // { dg-error "initialization of a flexible array member" "" { target c++11 } .-1 }
+S d[] { "", { 0 } }; // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+ // { dg-error "initialization of a flexible array member" "" { target c++11 } .-1 }
+T e[] { 1, { 2 }, 3, { 4 } }; // { dg-error "initialization of flexible array member in a nested context" "" { target c++11 } }
+ // { dg-error "initialization of a flexible array member" "" { target c++11 } .-1 }
+T f[] { 1, {}, 3, {} }; // { dg-error "initialization of a flexible array member" "" { target c++11 } }
+T g { 1, { 1, 2, 3 } }; // { dg-error "initialization of a flexible array member" "" { target c++11 } }
+S h { "abcd", "" }; // { dg-error "initialization of a flexible array member" "" { target c++11 } }
+#endif
+S i[] = { "", "", "", "" }; // { dg-error "initialization of flexible array member in a nested context" }
+ // { dg-error "initialization of a flexible array member" "" { target *-*-* } .-1 }
+S j[] = { "", { 1 }, "", { 2, 3 } }; // { dg-error "initialization of flexible array member in a nested context" }
+ // { dg-error "initialization of a flexible array member" "" { target *-*-* } .-1 }
+T k[] = { 1, { 2 }, 3, { 4 } }; // { dg-error "initialization of flexible array member in a nested context" }
+ // { dg-error "initialization of a flexible array member" "" { target *-*-* } .-1 }
+T l[] = { 1, {}, 3, {} }; // { dg-error "initialization of a flexible array member" }
+T m = { 1, { 1, 2, 3 } }; // { dg-error "initialization of a flexible array member" }
+S n = { "", "abcde" }; // { dg-error "initialization of a flexible array member" }
--- gcc/testsuite/g++.dg/parse/pr43765.C.jj 2015-12-16 09:02:07.000000000 +0100
+++ gcc/testsuite/g++.dg/parse/pr43765.C 2017-12-08 14:08:48.259251433 +0100
@@ -10,8 +10,8 @@ const char *temp[] = {"607", "612", 0};
SomeType vals[] =
{
- { 0, values : temp, },
+ { 0, values : temp, }, // { dg-error "either all initializer clauses should be designated or none of them should be" "" { target c++2a } }
0
}; // { dg-error "GNU-style designated initializer for an array|cannot convert" }
// (note the error above is on the wrong line)
-
+ // { dg-error "initialization of flexible array member in a nested context" "" { target *-*-* } .-2 }
Jakub