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>
PR c++/69056
......
......@@ -4120,9 +4120,7 @@ walk_subobject_offsets (tree type,
/* Avoid recursing into objects that are not interesting. */
if (!CLASS_TYPE_P (element_type)
|| !CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type)
|| !domain
/* Flexible array members have no upper bound. */
|| !TYPE_MAX_VALUE (domain))
|| !domain)
return 0;
/* Step through each of the elements in the array. */
......@@ -6645,7 +6643,7 @@ find_flexarrays (tree t, flexmems_t *fmem)
for (next = fld;
(next = DECL_CHAIN (next))
&& TREE_CODE (next) != FIELD_DECL; );
tree fldtype = TREE_TYPE (fld);
if (TREE_CODE (fld) != TYPE_DECL
&& RECORD_OR_UNION_TYPE_P (fldtype)
......@@ -6672,22 +6670,20 @@ find_flexarrays (tree t, flexmems_t *fmem)
/* Remember the first non-static data member. */
if (!fmem->first)
fmem->first = fld;
/* Remember the first non-static data member after the flexible
array member, if one has been found, or the zero-length array
if it has been found. */
if (!fmem->after && fmem->array)
fmem->after = fld;
}
/* Skip non-arrays. */
if (TREE_CODE (fldtype) != ARRAY_TYPE)
continue;
/* Determine the upper bound of the array if it has one. */
tree dom = TYPE_DOMAIN (fldtype);
if (dom && TYPE_MAX_VALUE (dom))
if (tree dom = TYPE_DOMAIN (fldtype))
{
if (fmem->array)
{
......@@ -6710,14 +6706,13 @@ find_flexarrays (tree t, flexmems_t *fmem)
{
/* Replace the zero-length array if it's been stored and
reset the after pointer. */
dom = TYPE_DOMAIN (TREE_TYPE (fmem->array));
if (dom && TYPE_MAX_VALUE (dom))
if (TYPE_DOMAIN (TREE_TYPE (fmem->array)))
{
fmem->array = fld;
fmem->after = NULL_TREE;
}
}
else
else
fmem->array = fld;
}
}
......@@ -6737,8 +6732,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
const char *msg = 0;
const_tree dom = TYPE_DOMAIN (TREE_TYPE (fmem->array));
if (dom && TYPE_MAX_VALUE (dom))
if (const_tree dom = TYPE_DOMAIN (TREE_TYPE (fmem->array)))
{
if (fmem->after)
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)
inform (DECL_SOURCE_LOCATION (fmem->after),
"next member %q#D declared here",
fmem->after);
inform (location_of (t), "in the definition of %q#T", t);
}
}
......@@ -6844,7 +6838,7 @@ check_flexarrays (tree t, flexmems_t *fmem /* = NULL */)
find_flexarrays (t, fmem);
if (fmem == &flexmems)
{
{
/* Issue diagnostics for invalid flexible and zero-length array members
found in base classes or among the members of the current class. */
diagnose_flexarrays (t, fmem);
......
......@@ -8645,10 +8645,9 @@ fold_sizeof_expr (tree t)
return r;
}
/* Given the SIZE (i.e., number of elements) in an array, compute an
appropriate index type for the array. When SIZE is null, the array
is a flexible array member. If non-NULL, NAME is the name of
the entity being declared. */
/* Given the SIZE (i.e., number of elements) in an array, compute
an appropriate index type for the array. If non-NULL, NAME is
the name of the entity being declared. */
tree
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 osize = size;
if (size == NULL_TREE)
return build_index_type (NULL_TREE);
if (error_operand_p (size))
return error_mark_node;
......@@ -10967,11 +10963,10 @@ grokdeclarator (const cp_declarator *declarator,
error ("flexible array member in union");
type = error_mark_node;
}
else
else
{
tree itype = compute_array_index_type (dname, NULL_TREE,
tf_warning_or_error);
type = build_cplus_array_type (TREE_TYPE (type), itype);
/* Flexible array member has a null domain. */
type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
}
}
......
......@@ -875,10 +875,10 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags)
case ARRAY_TYPE:
pp_maybe_space (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);
/* Zero-length arrays have an upper bound of SIZE_MAX. */
if (integer_all_onesp (max))
pp_character (pp, '0');
else if (tree_fits_shwi_p (max))
......
......@@ -3280,8 +3280,10 @@ write_template_template_arg (const tree decl)
::= A <expression> _ </element/ type>
"Array types encode the dimension (number of elements) and the
element type. For variable length arrays, the dimension (but not
the '_' separator) is omitted." */
element type. For variable length arrays, the dimension (but not
the '_' separator) is omitted."
Note that for flexible array members, like for other arrays of
unspecified size, the dimension is also omitted. */
static void
write_array_type (const tree type)
......@@ -3290,29 +3292,31 @@ write_array_type (const tree type)
if (TYPE_DOMAIN (type))
{
tree index_type;
tree max;
index_type = TYPE_DOMAIN (type);
/* The INDEX_TYPE gives the upper and lower bounds of the
array. */
max = TYPE_MAX_VALUE (index_type);
if (TREE_CODE (max) == INTEGER_CST)
/* The INDEX_TYPE gives the upper and lower bounds of the array.
It's null for flexible array members which have no upper bound
(this is a change from GCC 5 and prior where such members were
incorrectly mangled as zero-length arrays). */
if (tree max = TYPE_MAX_VALUE (index_type))
{
/* The ABI specifies that we should mangle the number of
elements in the array, not the largest allowed index. */
offset_int wmax = wi::to_offset (max) + 1;
/* Truncate the result - this will mangle [0, SIZE_INT_MAX]
number of elements as zero. */
wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max)));
gcc_assert (wi::fits_uhwi_p (wmax));
write_unsigned_number (wmax.to_uhwi ());
}
else
{
max = TREE_OPERAND (max, 0);
write_expression (max);
if (TREE_CODE (max) == INTEGER_CST)
{
/* The ABI specifies that we should mangle the number of
elements in the array, not the largest allowed index. */
offset_int wmax = wi::to_offset (max) + 1;
/* Truncate the result - this will mangle [0, SIZE_INT_MAX]
number of elements as zero. */
wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max)));
gcc_assert (wi::fits_uhwi_p (wmax));
write_unsigned_number (wmax.to_uhwi ());
}
else
{
max = TREE_OPERAND (max, 0);
write_expression (max);
}
}
}
write_char ('_');
write_type (TREE_TYPE (type));
......
......@@ -12846,14 +12846,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (t == integer_type_node)
return t;
if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST)
{
if (!TYPE_MAX_VALUE (t))
return compute_array_index_type (NULL_TREE, NULL_TREE, complain);
if (TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
return t;
}
if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
&& TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
return t;
{
tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
......
......@@ -2586,8 +2586,19 @@ build_ctor_subob_ref (tree index, tree type, tree obj)
obj = build_class_member_access_expr (obj, index, NULL_TREE,
/*reference*/false, tf_none);
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;
}
......
......@@ -1015,14 +1015,13 @@ digest_init_r (tree type, tree init, bool nested, int flags,
them if they were present. */
if (code == ARRAY_TYPE)
{
if (nested
&& (!TYPE_DOMAIN (type) || !TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
if (nested && !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,
"initialization of a flexible array member");
}
tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
if (char_type_p (typ1)
/*&& init */
......@@ -1061,9 +1060,7 @@ digest_init_r (tree type, tree init, bool nested, int flags,
init = copy_node (init);
TREE_TYPE (init) = type;
}
if (TYPE_DOMAIN (type)
&& TYPE_MAX_VALUE (TYPE_DOMAIN (type))
&& TREE_CONSTANT (TYPE_SIZE (type)))
if (TYPE_DOMAIN (type) && TREE_CONSTANT (TYPE_SIZE (type)))
{
/* Not a flexible array member. */
int size = TREE_INT_CST_LOW (TYPE_SIZE (type));
......@@ -1252,12 +1249,11 @@ process_init_constructor_array (tree type, tree init,
if (TREE_CODE (type) == ARRAY_TYPE)
{
/* C++ flexible array members have a null domain. */
tree domain = TYPE_DOMAIN (type);
/* Flexible array members have no upper bound. */
tree maxval = domain ? TYPE_MAX_VALUE (domain) : NULL_TREE;
if (domain && maxval && TREE_CONSTANT (maxval))
len = wi::ext (wi::to_offset (maxval)
- wi::to_offset (TYPE_MIN_VALUE (domain)) + 1,
if (domain && TREE_CONSTANT (TYPE_MAX_VALUE (domain)))
len = wi::ext (wi::to_offset (TYPE_MAX_VALUE (domain))
- wi::to_offset (TYPE_MIN_VALUE (domain)) + 1,
TYPE_PRECISION (TREE_TYPE (domain)),
TYPE_SIGN (TREE_TYPE (domain))).to_uhwi ();
else
......@@ -1451,9 +1447,7 @@ process_init_constructor_record (tree type, tree init,
/* Warn when some struct elements are implicitly initialized
to zero. However, avoid issuing the warning for flexible
array members since they need not have any elements. */
if ((TREE_CODE (fldtype) != ARRAY_TYPE
|| (TYPE_DOMAIN (fldtype)
&& TYPE_MAX_VALUE (TYPE_DOMAIN (fldtype))))
if ((TREE_CODE (fldtype) != ARRAY_TYPE || TYPE_DOMAIN (fldtype))
&& (complain & tf_warning)
&& !EMPTY_CONSTRUCTOR_P (init))
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>
* 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
__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 } } */
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