2017-12-15 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): Renamed to ...
+ (find_flexarray_init): ... this. Return NULL_TREE if init is
+ error_mark_node. Don't look through nested CONSTRUCTORs.
+ (warn_placement_new_too_small): Adjust caller.
+
PR c++/83217
* decl.c (cp_finish_decomp): If decl's type is REFERENCE_TYPE,
call complete_type (TREE_TYPE (type)).
return build_cxx_call (fn, 0, NULL, tf_warning_or_error);
}
-/* Attempt to find the initializer for field T in the initializer INIT,
- when non-null. Returns the initializer when successful and NULL
- otherwise. */
+/* Attempt to find the initializer for flexible array field T in the
+ initializer INIT, when non-null. Returns the initializer when
+ successful and NULL otherwise. */
static tree
-find_field_init (tree t, tree init)
+find_flexarray_init (tree t, tree init)
{
- if (!init)
+ if (!init || init == error_mark_node)
return NULL_TREE;
unsigned HOST_WIDE_INT idx;
/* Iterate over all top-level initializer elements. */
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, field, elt)
- {
- /* 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;
- }
+ /* If the member T is found, return it. */
+ if (field == t)
+ return elt;
+
return NULL_TREE;
}
extension). If the array member has been initialized,
determine its size from the initializer. Otherwise,
the array size is zero. */
- if (tree init = find_field_init (oper, DECL_INITIAL (var_decl)))
+ if (tree init = find_flexarray_init (oper,
+ DECL_INITIAL (var_decl)))
bytes_avail = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (init)));
}
else
#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
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);
/* 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;
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)
}
}
+ 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))
{
}
/* 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)
/* 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,
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 "
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
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). */
/* 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);
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;
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. */
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
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. */
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;
if (ce)
{
gcc_assert (ce->value);
- next = massage_init_elt (type, next, complain);
+ next = massage_init_elt (type, next, nested, complain);
++idx;
}
}
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)
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;
}
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);
}
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 ();
2017-12-15 Jakub Jelinek <jakub@redhat.com>
+ PR c++/80135
+ PR c++/81922
+ * 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.
+
PR c++/83217
* g++.dg/cpp1z/decomp33.C: New test.
{ 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);
- }
}
--- /dev/null
+// 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" };
--- /dev/null
+// 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" }
--- /dev/null
+// 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" }
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 }
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;
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;
--- /dev/null
+// { 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" }
+}