Commit 05dd97db by Martin Sebor

PR c++/69251 - [6 Regression] ICE in unify_array_domain on a flexible array

PR c++/69251 - [6 Regression] ICE in unify_array_domain on a flexible array
               member
PR c++/69253 - [6 Regression] ICE in cxx_incomplete_type_diagnostic initializing
               a flexible array member with empty string
PR c++/69290 - [6 Regression] ICE on invalid initialization of a flexible array
               member
PR c++/69277 - [6 Regression] ICE mangling a flexible array member
PR c++/69349 - template substitution error for flexible array members

gcc/testsuite/ChangeLog:
2016-02-03  Martin Sebor  <msebor@redhat.com>

	PR c++/69251
	PR c++/69253
	PR c++/69290
	PR c++/69277
	PR c++/69349
	* g++.dg/ext/flexarray-mangle-2.C: New test.
	* g++.dg/ext/flexarray-mangle.C: New test.
	* g++.dg/ext/flexarray-subst.C: New test.
	* g++.dg/ext/flexary11.C: New test.
	* g++.dg/ext/flexary12.C: New test.
	* g++.dg/ext/flexary13.C: New test.
	* g++.dg/ext/flexary14.C: New test.
	* g++.dg/other/dump-ada-spec-2.C: Adjust.

gcc/cp/ChangeLog:
2016-02-03  Martain Sebor  <msebor@redhat.com>

	PR c++/69251
	PR c++/69253
	PR c++/69290
	PR c++/69277
	PR c++/69349
	* class.c (walk_subobject_offsets): Avoid testing the upper bound
	of a flexible array member for equality to null.
	(find_flexarrays): Remove spurious whitespace introduced in r231665.
	(diagnose_flexarrays): Avoid checking the upper bound of arrays.
	(check_flexarrays): Same.
	* decl.c (compute_array_index_type): Avoid special case for flexible
	array members.
	(grokdeclarator): Avoid calling compute_array_index_type for flexible
	array members.
	* error.c (dump_type_suffix): Revert changes introduced in r231665
	and rendered unnecessary by the changes above.
	* pt.c (tsubst):  Same.
	* tree.c (build_ctor_subob_ref): Handle flexible array members.
	* typeck2.c (digest_init_r): Revert changes introduced in r231665.
	(process_init_constructor_array): Same.
	(process_init_constructor_record): Same.

From-SVN: r233126
parent dac2fc29
2016-02-02 Martain Sebor <msebor@redhat.com>
PR c++/69251
PR c++/69253
PR c++/69290
PR c++/69277
PR c++/69349
* class.c (walk_subobject_offsets): Avoid testing the upper bound
of a flexible array member for equality to null.
(find_flexarrays): Remove spurious whitespace introduced in r231665.
(diagnose_flexarrays): Avoid checking the upper bound of arrays.
(check_flexarrays): Same.
* decl.c (compute_array_index_type): Avoid special case for flexible
array members.
(grokdeclarator): Avoid calling compute_array_index_type for flexible
array members.
* error.c (dump_type_suffix): Revert changes introduced in r231665
and rendered unnecessary by the changes above.
* pt.c (tsubst): Same.
* tree.c (build_ctor_subob_ref): Handle flexible array members.
* typeck2.c (digest_init_r): Revert changes introduced in r231665.
(process_init_constructor_array): Same.
(process_init_constructor_record): Same.
2016-02-03 Patrick Palka <ppalka@gcc.gnu.org> 2016-02-03 Patrick Palka <ppalka@gcc.gnu.org>
PR c++/69056 PR c++/69056
......
...@@ -4120,9 +4120,7 @@ walk_subobject_offsets (tree type, ...@@ -4120,9 +4120,7 @@ walk_subobject_offsets (tree type,
/* Avoid recursing into objects that are not interesting. */ /* Avoid recursing into objects that are not interesting. */
if (!CLASS_TYPE_P (element_type) if (!CLASS_TYPE_P (element_type)
|| !CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type) || !CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type)
|| !domain || !domain)
/* Flexible array members have no upper bound. */
|| !TYPE_MAX_VALUE (domain))
return 0; return 0;
/* Step through each of the elements in the array. */ /* Step through each of the elements in the array. */
...@@ -6645,7 +6643,7 @@ find_flexarrays (tree t, flexmems_t *fmem) ...@@ -6645,7 +6643,7 @@ find_flexarrays (tree t, flexmems_t *fmem)
for (next = fld; for (next = fld;
(next = DECL_CHAIN (next)) (next = DECL_CHAIN (next))
&& TREE_CODE (next) != FIELD_DECL; ); && TREE_CODE (next) != FIELD_DECL; );
tree fldtype = TREE_TYPE (fld); tree fldtype = TREE_TYPE (fld);
if (TREE_CODE (fld) != TYPE_DECL if (TREE_CODE (fld) != TYPE_DECL
&& RECORD_OR_UNION_TYPE_P (fldtype) && RECORD_OR_UNION_TYPE_P (fldtype)
...@@ -6672,22 +6670,20 @@ find_flexarrays (tree t, flexmems_t *fmem) ...@@ -6672,22 +6670,20 @@ find_flexarrays (tree t, flexmems_t *fmem)
/* Remember the first non-static data member. */ /* Remember the first non-static data member. */
if (!fmem->first) if (!fmem->first)
fmem->first = fld; fmem->first = fld;
/* Remember the first non-static data member after the flexible /* Remember the first non-static data member after the flexible
array member, if one has been found, or the zero-length array array member, if one has been found, or the zero-length array
if it has been found. */ if it has been found. */
if (!fmem->after && fmem->array) if (!fmem->after && fmem->array)
fmem->after = fld; fmem->after = fld;
} }
/* Skip non-arrays. */ /* Skip non-arrays. */
if (TREE_CODE (fldtype) != ARRAY_TYPE) if (TREE_CODE (fldtype) != ARRAY_TYPE)
continue; continue;
/* Determine the upper bound of the array if it has one. */ /* Determine the upper bound of the array if it has one. */
tree dom = TYPE_DOMAIN (fldtype); if (tree dom = TYPE_DOMAIN (fldtype))
if (dom && TYPE_MAX_VALUE (dom))
{ {
if (fmem->array) if (fmem->array)
{ {
...@@ -6710,14 +6706,13 @@ find_flexarrays (tree t, flexmems_t *fmem) ...@@ -6710,14 +6706,13 @@ find_flexarrays (tree t, flexmems_t *fmem)
{ {
/* Replace the zero-length array if it's been stored and /* Replace the zero-length array if it's been stored and
reset the after pointer. */ reset the after pointer. */
dom = TYPE_DOMAIN (TREE_TYPE (fmem->array)); if (TYPE_DOMAIN (TREE_TYPE (fmem->array)))
if (dom && TYPE_MAX_VALUE (dom))
{ {
fmem->array = fld; fmem->array = fld;
fmem->after = NULL_TREE; fmem->after = NULL_TREE;
} }
} }
else else
fmem->array = fld; fmem->array = fld;
} }
} }
...@@ -6737,8 +6732,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem) ...@@ -6737,8 +6732,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
const char *msg = 0; const char *msg = 0;
const_tree dom = TYPE_DOMAIN (TREE_TYPE (fmem->array)); if (const_tree dom = TYPE_DOMAIN (TREE_TYPE (fmem->array)))
if (dom && TYPE_MAX_VALUE (dom))
{ {
if (fmem->after) if (fmem->after)
msg = G_("zero-size array member %qD not at end of %q#T"); msg = G_("zero-size array member %qD not at end of %q#T");
...@@ -6770,7 +6764,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem) ...@@ -6770,7 +6764,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
inform (DECL_SOURCE_LOCATION (fmem->after), inform (DECL_SOURCE_LOCATION (fmem->after),
"next member %q#D declared here", "next member %q#D declared here",
fmem->after); fmem->after);
inform (location_of (t), "in the definition of %q#T", t); inform (location_of (t), "in the definition of %q#T", t);
} }
} }
...@@ -6844,7 +6838,7 @@ check_flexarrays (tree t, flexmems_t *fmem /* = NULL */) ...@@ -6844,7 +6838,7 @@ check_flexarrays (tree t, flexmems_t *fmem /* = NULL */)
find_flexarrays (t, fmem); find_flexarrays (t, fmem);
if (fmem == &flexmems) if (fmem == &flexmems)
{ {
/* Issue diagnostics for invalid flexible and zero-length array members /* Issue diagnostics for invalid flexible and zero-length array members
found in base classes or among the members of the current class. */ found in base classes or among the members of the current class. */
diagnose_flexarrays (t, fmem); diagnose_flexarrays (t, fmem);
......
...@@ -8645,10 +8645,9 @@ fold_sizeof_expr (tree t) ...@@ -8645,10 +8645,9 @@ fold_sizeof_expr (tree t)
return r; return r;
} }
/* Given the SIZE (i.e., number of elements) in an array, compute an /* Given the SIZE (i.e., number of elements) in an array, compute
appropriate index type for the array. When SIZE is null, the array an appropriate index type for the array. If non-NULL, NAME is
is a flexible array member. If non-NULL, NAME is the name of the name of the entity being declared. */
the entity being declared. */
tree tree
compute_array_index_type (tree name, tree size, tsubst_flags_t complain) compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
...@@ -8656,9 +8655,6 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) ...@@ -8656,9 +8655,6 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
tree itype; tree itype;
tree osize = size; tree osize = size;
if (size == NULL_TREE)
return build_index_type (NULL_TREE);
if (error_operand_p (size)) if (error_operand_p (size))
return error_mark_node; return error_mark_node;
...@@ -10967,11 +10963,10 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -10967,11 +10963,10 @@ grokdeclarator (const cp_declarator *declarator,
error ("flexible array member in union"); error ("flexible array member in union");
type = error_mark_node; type = error_mark_node;
} }
else else
{ {
tree itype = compute_array_index_type (dname, NULL_TREE, /* Flexible array member has a null domain. */
tf_warning_or_error); type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
type = build_cplus_array_type (TREE_TYPE (type), itype);
} }
} }
......
...@@ -875,10 +875,10 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags) ...@@ -875,10 +875,10 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags)
case ARRAY_TYPE: case ARRAY_TYPE:
pp_maybe_space (pp); pp_maybe_space (pp);
pp_cxx_left_bracket (pp); pp_cxx_left_bracket (pp);
if (TYPE_DOMAIN (t) && TYPE_MAX_VALUE (TYPE_DOMAIN (t))) if (tree dtype = TYPE_DOMAIN (t))
{ {
tree dtype = TYPE_DOMAIN (t);
tree max = TYPE_MAX_VALUE (dtype); tree max = TYPE_MAX_VALUE (dtype);
/* Zero-length arrays have an upper bound of SIZE_MAX. */
if (integer_all_onesp (max)) if (integer_all_onesp (max))
pp_character (pp, '0'); pp_character (pp, '0');
else if (tree_fits_shwi_p (max)) else if (tree_fits_shwi_p (max))
......
...@@ -3280,8 +3280,10 @@ write_template_template_arg (const tree decl) ...@@ -3280,8 +3280,10 @@ write_template_template_arg (const tree decl)
::= A <expression> _ </element/ type> ::= A <expression> _ </element/ type>
"Array types encode the dimension (number of elements) and the "Array types encode the dimension (number of elements) and the
element type. For variable length arrays, the dimension (but not element type. For variable length arrays, the dimension (but not
the '_' separator) is omitted." */ the '_' separator) is omitted."
Note that for flexible array members, like for other arrays of
unspecified size, the dimension is also omitted. */
static void static void
write_array_type (const tree type) write_array_type (const tree type)
...@@ -3290,29 +3292,31 @@ write_array_type (const tree type) ...@@ -3290,29 +3292,31 @@ write_array_type (const tree type)
if (TYPE_DOMAIN (type)) if (TYPE_DOMAIN (type))
{ {
tree index_type; tree index_type;
tree max;
index_type = TYPE_DOMAIN (type); index_type = TYPE_DOMAIN (type);
/* The INDEX_TYPE gives the upper and lower bounds of the /* The INDEX_TYPE gives the upper and lower bounds of the array.
array. */ It's null for flexible array members which have no upper bound
max = TYPE_MAX_VALUE (index_type); (this is a change from GCC 5 and prior where such members were
if (TREE_CODE (max) == INTEGER_CST) incorrectly mangled as zero-length arrays). */
if (tree max = TYPE_MAX_VALUE (index_type))
{ {
/* The ABI specifies that we should mangle the number of if (TREE_CODE (max) == INTEGER_CST)
elements in the array, not the largest allowed index. */ {
offset_int wmax = wi::to_offset (max) + 1; /* The ABI specifies that we should mangle the number of
/* Truncate the result - this will mangle [0, SIZE_INT_MAX] elements in the array, not the largest allowed index. */
number of elements as zero. */ offset_int wmax = wi::to_offset (max) + 1;
wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max))); /* Truncate the result - this will mangle [0, SIZE_INT_MAX]
gcc_assert (wi::fits_uhwi_p (wmax)); number of elements as zero. */
write_unsigned_number (wmax.to_uhwi ()); wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max)));
} gcc_assert (wi::fits_uhwi_p (wmax));
else write_unsigned_number (wmax.to_uhwi ());
{ }
max = TREE_OPERAND (max, 0); else
write_expression (max); {
max = TREE_OPERAND (max, 0);
write_expression (max);
}
} }
} }
write_char ('_'); write_char ('_');
write_type (TREE_TYPE (type)); write_type (TREE_TYPE (type));
......
...@@ -12846,14 +12846,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -12846,14 +12846,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (t == integer_type_node) if (t == integer_type_node)
return t; return t;
if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST) if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
{ && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
if (!TYPE_MAX_VALUE (t)) return t;
return compute_array_index_type (NULL_TREE, NULL_TREE, complain);
if (TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
return t;
}
{ {
tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0); tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
......
...@@ -2586,8 +2586,19 @@ build_ctor_subob_ref (tree index, tree type, tree obj) ...@@ -2586,8 +2586,19 @@ build_ctor_subob_ref (tree index, tree type, tree obj)
obj = build_class_member_access_expr (obj, index, NULL_TREE, obj = build_class_member_access_expr (obj, index, NULL_TREE,
/*reference*/false, tf_none); /*reference*/false, tf_none);
if (obj) if (obj)
gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, {
TREE_TYPE (obj))); tree objtype = TREE_TYPE (obj);
if (TREE_CODE (objtype) == ARRAY_TYPE && !TYPE_DOMAIN (objtype))
{
/* When the destination object refers to a flexible array member
verify that it matches the type of the source object except
for its domain. */
gcc_assert (comptypes (type, objtype, COMPARE_REDECLARATION));
}
else
gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, objtype));
}
return obj; return obj;
} }
......
...@@ -1015,14 +1015,13 @@ digest_init_r (tree type, tree init, bool nested, int flags, ...@@ -1015,14 +1015,13 @@ digest_init_r (tree type, tree init, bool nested, int flags,
them if they were present. */ them if they were present. */
if (code == ARRAY_TYPE) if (code == ARRAY_TYPE)
{ {
if (nested if (nested && !TYPE_DOMAIN (type))
&& (!TYPE_DOMAIN (type) || !TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
{ {
/* Flexible array members do not have an upper bound. */ /* C++ flexible array members have a null domain. */
pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wpedantic, pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wpedantic,
"initialization of a flexible array member"); "initialization of a flexible array member");
} }
tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
if (char_type_p (typ1) if (char_type_p (typ1)
/*&& init */ /*&& init */
...@@ -1061,9 +1060,7 @@ digest_init_r (tree type, tree init, bool nested, int flags, ...@@ -1061,9 +1060,7 @@ digest_init_r (tree type, tree init, bool nested, int flags,
init = copy_node (init); init = copy_node (init);
TREE_TYPE (init) = type; TREE_TYPE (init) = type;
} }
if (TYPE_DOMAIN (type) if (TYPE_DOMAIN (type) && TREE_CONSTANT (TYPE_SIZE (type)))
&& TYPE_MAX_VALUE (TYPE_DOMAIN (type))
&& TREE_CONSTANT (TYPE_SIZE (type)))
{ {
/* Not a flexible array member. */ /* Not a flexible array member. */
int size = TREE_INT_CST_LOW (TYPE_SIZE (type)); int size = TREE_INT_CST_LOW (TYPE_SIZE (type));
...@@ -1252,12 +1249,11 @@ process_init_constructor_array (tree type, tree init, ...@@ -1252,12 +1249,11 @@ process_init_constructor_array (tree type, tree init,
if (TREE_CODE (type) == ARRAY_TYPE) if (TREE_CODE (type) == ARRAY_TYPE)
{ {
/* C++ flexible array members have a null domain. */
tree domain = TYPE_DOMAIN (type); tree domain = TYPE_DOMAIN (type);
/* Flexible array members have no upper bound. */ if (domain && TREE_CONSTANT (TYPE_MAX_VALUE (domain)))
tree maxval = domain ? TYPE_MAX_VALUE (domain) : NULL_TREE; len = wi::ext (wi::to_offset (TYPE_MAX_VALUE (domain))
if (domain && maxval && TREE_CONSTANT (maxval)) - wi::to_offset (TYPE_MIN_VALUE (domain)) + 1,
len = wi::ext (wi::to_offset (maxval)
- wi::to_offset (TYPE_MIN_VALUE (domain)) + 1,
TYPE_PRECISION (TREE_TYPE (domain)), TYPE_PRECISION (TREE_TYPE (domain)),
TYPE_SIGN (TREE_TYPE (domain))).to_uhwi (); TYPE_SIGN (TREE_TYPE (domain))).to_uhwi ();
else else
...@@ -1451,9 +1447,7 @@ process_init_constructor_record (tree type, tree init, ...@@ -1451,9 +1447,7 @@ process_init_constructor_record (tree type, tree init,
/* Warn when some struct elements are implicitly initialized /* Warn when some struct elements are implicitly initialized
to zero. However, avoid issuing the warning for flexible to zero. However, avoid issuing the warning for flexible
array members since they need not have any elements. */ array members since they need not have any elements. */
if ((TREE_CODE (fldtype) != ARRAY_TYPE if ((TREE_CODE (fldtype) != ARRAY_TYPE || TYPE_DOMAIN (fldtype))
|| (TYPE_DOMAIN (fldtype)
&& TYPE_MAX_VALUE (TYPE_DOMAIN (fldtype))))
&& (complain & tf_warning) && (complain & tf_warning)
&& !EMPTY_CONSTRUCTOR_P (init)) && !EMPTY_CONSTRUCTOR_P (init))
warning (OPT_Wmissing_field_initializers, warning (OPT_Wmissing_field_initializers,
......
2016-02-03 Martin Sebor <msebor@redhat.com>
PR c++/69251
PR c++/69253
PR c++/69290
PR c++/69277
PR c++/69349
* g++.dg/ext/flexarray-mangle-2.C: New test.
* g++.dg/ext/flexarray-mangle.C: New test.
* g++.dg/ext/flexarray-subst.C: New test.
* g++.dg/ext/flexary11.C: New test.
* g++.dg/ext/flexary12.C: New test.
* g++.dg/ext/flexary13.C: New test.
* g++.dg/ext/flexary14.C: New test.
* g++.dg/other/dump-ada-spec-2.C: Adjust.
2016-02-03 H.J. Lu <hongjiu.lu@intel.com> 2016-02-03 H.J. Lu <hongjiu.lu@intel.com>
* gcc.target/i386/iamcu/test_passing_unions.c (check_union_passing6): * gcc.target/i386/iamcu/test_passing_unions.c (check_union_passing6):
......
// PR c++/69277 - [6 Regression] ICE mangling a flexible array member
// { dg-do compile { target c++11 } }
struct A {
int n;
char a [];
};
// Declare but do not define function templates.
template <class T>
void foo ();
template <typename T>
void fooref (T&);
// Rvalue references are a C++ 11 feature.
template <typename T>
void foorefref (T&&);
void bar (A a)
{
// Decltype is also a C++ 11 feature.
// Verify that decltype gets the right type and that foo is
// mangled correctly.
foo<decltype (a.a)>();
// Verify that function templates taking a reference and an rvalue
// references (as in PR c++/69277) are also mangled correctly.
fooref (a.a);
foorefref (a.a);
}
// In G++ versions prior to 6, flexible array members were incorrectly
// mangled as arrays of zero elements. Verify that flexible array
// members are mangled correctly as arrays of an unspecified number
// of elements.
// void foo<char []>():
// { dg-final { scan-assembler _Z3fooIA_cEvv } }
// The following is derived from PR c++/69277:
// void fooref<char []>(char (&) [])
// { dg-final { scan-assembler _Z6foorefIA_cEvRT_ } }
// void foorefref<char (&) []>(char (&) [])
// { dg-final { scan-assembler _Z9foorefrefIRA_cEvOT_ } }
// PR c++/69277 - [6 Regression] ICE mangling a flexible array member
// { dg-do compile }
struct A {
int n;
char a [];
};
// Declare but do not define function templates.
template <typename T>
void fooref (T&);
void bar (A a)
{
fooref (a.a);
}
// In G++ versions prior to 6, flexible array members were incorrectly
// mangled as arrays of zero elements. Verify that flexible array
// members are mangled correctly as arrays of an unspecified number
// of elements.
// void fooref<char []>(char (&) [])
// { dg-final { scan-assembler _Z6foorefIA_cEvRT_ } }
// PR c++/69251 - [6 Regression] ICE (segmentation fault) in unify_array_domain
// on i686-linux-gnu
// { dg-do compile }
struct A { int n; char a[]; };
template <class>
struct B;
// The following definition shouldn't be needed but is provided to prevent
// the test from failing with an error due to PR c++/69349 - template
// substitution error for flexible array members. (This doesn't compromise
// the validity of this test since all it tests for is the absennce of
// the ICE.)
template <class>
struct B { typedef int X; };
template <class T>
struct B<T[]> { typedef int X; };
template <class T>
struct C { typedef typename B<T>::X X; };
template <class T>
int foo (T&, typename C<T>::X = 0)
{
return 0;
}
void bar (A *a)
{
foo (a->a);
}
// PR c++/69253 - [6 Regression] g++ ICE at -O0 on x86_64-linux-gnu
// in "cxx_incomplete_type_diagnostic"
// { dg-do compile }
struct A {
int n;
char a [];
};
void f ()
{
// Compound literals and flexible array members are G++ extensions
// accepted for compatibility with C and GCC.
// The following use of a flexible array member in a compound literal
// is invalid in C and rejected by GCC in C mode and so it's also
// rejected in C++ mode.
(struct A){ 1, "" }; // { dg-error "forbids compound-literals|initialization of a flexible array member|invalid use of a flexible array member" }
}
// PR c++/69290 - [6 Regression] g++ ICE on invalid initialization
// of a flexible array member
// { dg-do compile }
// Suppress pedantic errors about initialization of a flexible array member.
// { dg-options "-Wno-pedantic" }
struct A {
int a []; // { dg-error "flexible array member .A::a. in an otherwise empty .struct A." }
};
void f1 ()
{
// This is the meat of the test from c++/69290:
struct A a
= { "c" }; // { dg-error "invalid conversion from .const char\\*. to .int." }
(void)&a;
}
// Exercise other forms of invalid initialization besides the one in the bug.
struct B {
int n;
int a [];
};
void f2 ()
{
struct B b1
= { 0, "c" }; // { dg-error "invalid conversion from .const char\\*. to .int." }
(void)&b1;
const char s[] = "c";
struct B b2
= { 0, s }; // { dg-error "invalid conversion from .const char\\*. to .int." }
(void)&b2;
}
struct D {
int a []; // { dg-error "flexible array member .D::a. in an otherwise empty .struct D." }
D ();
};
D::D ():
a ("c") // { dg-error "incompatible types in assignment of .const char \\\[2\\\]. to .int \\\[\\\]." }
{ }
template <class T>
struct C {
T a []; // { dg-error "flexible array member" }
};
void f3 ()
{
struct C<double> cd
= { "c" }; // { dg-error "cannot convert .const char\\*. to .double." }
(void)&cd;
}
// { dg-do compile }
// { dg-options -Wno-pedantic }
#define STR(s) #s
#define ASSERT(exp) \
((exp) ? (void)0 : (void)(__builtin_printf ("%s:%i: assertion %s failed\n", \
__FILE__, __LINE__, STR(exp)), \
__builtin_abort ()))
struct Ax { int n, a[]; };
struct AAx { int i; Ax ax; };
int i = 12345678;
int main ()
{
{
Ax s = { 0 };
ASSERT (s.n == 0);
}
{
Ax s =
{ 0, { } }; // dg-warning "initialization of a flexible array member" }
ASSERT (s.n == 0);
}
{
Ax s =
{ 1, { 2 } }; // dg-warning "initialization of a flexible array member" }
ASSERT (s.n == 1 && s.a [0] == 2);
}
{
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 =
{ 123, i }; // dg-warning "initialization of a flexible array member" }
ASSERT (s.n == 123 && s.a [0] == i);
}
{
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 =
{ 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);
}
{
AAx s =
{ 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);
}
}
// PR c++/69349 - template substitution error for flexible array members
// { dg-do compile }
template <class>
struct A;
template <class T>
struct A<T[]> { typedef int X; };
template <class T> int foo (T&, typename A<T>::X = 0) { return 0; }
struct B { int n, a[]; };
void bar (B *b)
{
foo (b->a);
}
...@@ -7,5 +7,5 @@ struct S ...@@ -7,5 +7,5 @@ struct S
__extension__ unsigned char data[]; __extension__ unsigned char data[];
}; };
/* { dg-final { scan-ada-spec "array \\(0 .. 0\\)" } } */ /* { dg-final { scan-ada-spec "array \\(size_t\\)" } } */
/* { dg-final { cleanup-ada-spec } } */ /* { dg-final { cleanup-ada-spec } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment