This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, C++] Fix PR c++/88261
- From: Bernd Edlinger <bernd dot edlinger at hotmail dot de>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>, Jeff Law <law at redhat dot com>, Jason Merrill <jason at redhat dot com>, Nathan Sidwell <nathan at acm dot org>
- Date: Sat, 15 Dec 2018 08:36:25 +0000
- Subject: [PATCH, C++] Fix PR c++/88261
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.edlinger@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.edlinger@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)" } */
+}