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-02 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-02 Martin 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.
@@ -4120,9 +4120,8 @@ 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))
+ /* Flexible array members have a null domain. */
+ || !domain)
return 0;
/* Step through each of the elements in the array. */
@@ -6645,7 +6644,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 +6671,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 +6707,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 +6733,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 (TYPE_DOMAIN (TREE_TYPE (fmem->array)))
{
if (fmem->after)
msg = G_("zero-size array member %qD not at end of %q#T");
@@ -6770,7 +6765,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 +6839,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,11 @@ 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)))
+ /* C++ flexible array members have a null domain. */
+ 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))
@@ -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,
new file mode 100644
@@ -0,0 +1,46 @@
+// 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_ } }
new file mode 100644
@@ -0,0 +1,24 @@
+// 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_ } }
new file mode 100644
@@ -0,0 +1,33 @@
+// 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);
+}
new file mode 100644
@@ -0,0 +1,19 @@
+// 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" }
+}
new file mode 100644
@@ -0,0 +1,63 @@
+// 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;
+}
new file mode 100644
@@ -0,0 +1,64 @@
+// { 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);
+ }
+}
new file mode 100644
@@ -0,0 +1,17 @@
+// 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 } } */