gcc/testsuite/ChangeLog:
2015-12-02 Martin Sebor <msebor@redhat.com>
c++/42121
c++/68478
c++/68613
c++/68689
* g++.dg/ext/flexary2.C: Expect a sole flexible array member
to be rejected. Add a test case exercising zero-length array.
* g++.dg/ext/flexary3.C: Expect a sole flexible array member
to be rejected.
* g++.dg/ext/flexary4.C: New file.
* g++.dg/ext/flexary5.C: New file.
* g++.dg/ext/flexary6.C: New file.
* g++.dg/ext/flexary7.C: New file.
* g++.dg/other/dump-ada-spec-2.C: Adjust to reflect flexible
array members.
* g++.dg/parse/pr43765.C: Add a member to make a struct with
a flexible array member valid. Adjust expected error message.
* g++.dg/torture/pr64280.C: Expect a sole flexible array member
to be rejected.
* g++.dg/torture/pr64312.C: Add a member to make a struct with
a flexible array member valid.
* g++.dg/ubsan/object-size-1.C: Adjust expected diagnostic.
* g++.dg/other/dump-ada-spec-2.C: Adjust expected type.
gcc/cp/ChangeLog:
2015-12-02 Martin Sebor <msebor@redhat.com>
c++/42121
c++/68478
c++/68613
c++/68689
* class.c (walk_subobject_offsets): Avoid assuming type domain
is non-null or has an upper bound.
(layout_class_type): Include type size in error message.
(all_bases_empty_p, field_nonempty_p): New helper functions.
(check_flexarrays): New function.
(finish_struct_1): Call check_flexarrays.
* decl.c (compute_array_index_type): Distinguish flexible array
members from zero-length arrays.
(grokdeclarator): Reject flexible array members in unions. Avoid
rejecting members of incomplete types that are flexible array members.
* error.c (dump_type_suffix): Handle flexible array members with null
upper bound.
* init.c (perform_member_init): Same.
* pt.c (instantiate_class_template_1): Allow flexible array members.
(tsubst): Handle flexible array members with null upper bound.
* typeck2.c (digest_init_r): Warn for initialization of flexible
array members.
(process_init_constructor_record): Handle flexible array members.
gcc/c/ChangeLog:
2015-12-02 Martin Sebor <msebor@redhat.com>
c++/42121
* c-decl.c (grokdeclarator): Include type size in error message.
(finish_struct): Same.
gcc/ChangeLog:
2015-12-02 Martin Sebor <msebor@redhat.com>
c++/42121
* tree-chkp.c (chkp_find_bound_slots_1): Handle flexible array
members.
* tree.c (type_contains_placeholder_1): Avoid assuming type has
a non-null domain or an upper bound to handle flexible array
members.
* varasm.c (array_size_for_constructor): Same.
(output_constructor_regular_field): Same.
(output_constructor): Set min_index to integer_zero_node rather
than null when a type has no domain to avoid crashing later.
@@ -5868,10 +5868,12 @@ grokdeclarator (const struct c_declarator *declarator,
&& !int_fits_type_p (size, index_type))
{
if (name)
- error_at (loc, "size of array %qE is too large",
- name);
+ error_at (loc, "size of array %qE is too large "
+ "(%qE bytes)",
+ name, size);
else
- error_at (loc, "size of unnamed array is too large");
+ error_at (loc, "size of unnamed array is too large"
+ " (%qE bytes)", size);
type = error_mark_node;
continue;
}
@@ -7701,7 +7703,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
&& TREE_CODE (TYPE_SIZE_UNIT (t)) == INTEGER_CST
&& !TREE_OVERFLOW (TYPE_SIZE_UNIT (t))
&& !valid_constant_size_p (TYPE_SIZE_UNIT (t)))
- error ("type %qT is too large", t);
+ error ("size of type %qT is too large (%qE bytes)", t, TYPE_SIZE_UNIT (t));
/* Give bit-fields their proper types and rewrite the type of array fields
with scalar component if the enclosing type has reverse storage order. */
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "convert.h"
#include "dumpfile.h"
#include "gimplify.h"
+#include "intl.h"
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
@@ -4114,7 +4115,10 @@ 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))
+ || !CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type)
+ || !domain
+ /* Flexible array members have no upper bound. */
+ || !TYPE_MAX_VALUE (domain))
return 0;
/* Step through each of the elements in the array. */
@@ -6531,7 +6535,7 @@ layout_class_type (tree t, tree *virtuals_p)
&& TREE_CODE (TYPE_SIZE_UNIT (t)) == INTEGER_CST
&& !TREE_OVERFLOW (TYPE_SIZE_UNIT (t))
&& !valid_constant_size_p (TYPE_SIZE_UNIT (t)))
- error ("type %qT is too large", t);
+ error ("size of type %qT is too large (%qE bytes)", t, TYPE_SIZE_UNIT (t));
/* Warn about bases that can't be talked about due to ambiguity. */
warn_about_ambiguous_bases (t);
@@ -6598,12 +6602,184 @@ sorted_fields_type_new (int n)
}
+/* Return true when all base classes of class T (a class type) are
+ empty, false otherwise. */
+
+static bool
+all_bases_empty_p (tree t)
+{
+ int i;
+ tree binfo;
+ tree base_binfo;
+
+ for (binfo = TYPE_BINFO (t), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ {
+ tree basetype = TREE_TYPE (base_binfo);
+ gcc_assert (COMPLETE_TYPE_P (basetype));
+
+ if (!is_empty_class (basetype))
+ return false;
+ }
+
+ return true;
+}
+
+/* Helper of finish_struct_1. Return true when FLD refers to a non-static
+ class data member of non-zero size, otherwise false. */
+
+static inline bool
+field_nonempty_p (const_tree fld)
+{
+ if (TREE_CODE (fld) == ERROR_MARK)
+ return false;
+
+ tree type = TREE_TYPE (fld);
+ if (TREE_CODE (fld) == FIELD_DECL
+ && TREE_CODE (type) != ERROR_MARK
+ && (DECL_NAME (fld) || RECORD_OR_UNION_TYPE_P (type)))
+ {
+
+ return TYPE_SIZE (type)
+ && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
+ || !tree_int_cst_equal (size_zero_node, TYPE_SIZE (type)));
+ }
+
+ return false;
+}
+
+/* Check to make sure any definitions of flexible array members
+ and zero-size arrays in a chain of FIELDS are valid, and
+ diagnose those that aren't. T denotes a struct, class, or
+ union whose fields are being checked. SEEN_FIELD is used
+ internally by recursive invocations of the function to set
+ the pointed-to object to true when a declaration of a non-
+ empty non-static data member precedes the declaration of
+ a flexible array member or a zero-size array.
+*/
+
+static tree
+check_flexarrays (tree t, tree fields, bool *seen_field)
+{
+ /* Members of anonymous structs and unions are considered to be members
+ of the containing struct or union. */
+ if (TYPE_ANONYMOUS_P (t))
+ return NULL_TREE;
+
+ /* Unlike the C front end, the C++ front end sets the upper bound
+ of a flexible array member to SIZE_MAX. Precompute that value
+ up front to avoid recomputing it on each iteration. */
+ tree size_max_node =
+ int_const_binop (MINUS_EXPR, size_zero_node, size_one_node);
+
+ /* Iterate over struct members, looking for definitions of non-static
+ flexible array members and zero-size arrays and determine whether
+ each is valid. */
+ for (tree fld = fields, next, f; fld;
+ *seen_field = *seen_field || field_nonempty_p (f), fld = next)
+ {
+ next = DECL_CHAIN (fld);
+
+ /* Use f below to check the current field, or to substitute
+ for it the flexible array member or zero-size array of
+ the anonymous struct it represents. */
+ f = fld;
+
+ const_tree fldtype = TREE_TYPE (f);
+ if (TREE_CODE (f) != TYPE_DECL
+ && RECORD_OR_UNION_TYPE_P (fldtype)
+ && TYPE_ANONYMOUS_P (fldtype))
+ {
+ /* Descend into the anonymous struct or union and check
+ its fields. The recursive call to the function will
+ either return 0 or the flexible array member whose
+ validity depends on whether any non-static data members
+ are declared in the enclosing struct. */
+ tree flexarray =
+ check_flexarrays (t, TYPE_FIELDS (fldtype), seen_field);
+ if (flexarray)
+ {
+ f = flexarray;
+ fldtype = TREE_TYPE (flexarray);
+ }
+ }
+
+ /* Skip anything that's not a (non-static) data member. */
+ if (TREE_CODE (f) != FIELD_DECL)
+ continue;
+
+ /* Skip non-arrays. */
+ if (TREE_CODE (fldtype) != ARRAY_TYPE || !DECL_CHAIN (f))
+ continue;
+
+ /* Determine the upper bound of the array if it has one. */
+ const_tree dom = TYPE_DOMAIN (fldtype);
+
+ /* Skip arrays whose upper bound is less than SIZE_MAX. */
+ if (dom && TYPE_MAX_VALUE (dom)
+ && !tree_int_cst_equal (size_max_node, TYPE_MAX_VALUE (dom)))
+ continue;
+
+ if (dom && TYPE_MAX_VALUE (dom))
+ {
+ /* Zero-length arrays have a domain with an upper bound
+ of SIZE_MAX. */
+ const char *msg = 0;
+
+ if (next && TREE_CODE (next) == FIELD_DECL)
+ msg = G_("zero-size array member %qD not at end of %q#T");
+ else if (!*seen_field && all_bases_empty_p (t))
+ msg = G_("zero-size array member %qD in an otherwise empty %q#T");
+
+ if (msg && pedwarn (DECL_SOURCE_LOCATION (f), OPT_Wpedantic,
+ msg, f, t))
+ inform (input_location, "%q#T declared here",
+ DECL_FIELD_CONTEXT (f));
+ }
+ else
+ {
+ /* Flexible array members don't have an upper bound. */
+ const char *msg = 0;
+
+ if (next && TREE_CODE (next) == FIELD_DECL)
+ msg = G_("flexible array member %qD not at end of %q#T");
+ else if (!*seen_field && all_bases_empty_p (t))
+ {
+ /* When f is a member of anonymous struct, return
+ the (possibly invalid) flexible array member to
+ the (recursive) caller to determine whether it
+ is followed by any other data members in the
+ containing struct. */
+ if (DECL_CONTEXT (fld) != t)
+ return f;
+
+ msg = G_("flexible array member %qD in an otherwise empty %q#T");
+ }
+
+ if (msg)
+ {
+ error_at (DECL_SOURCE_LOCATION (f), msg, f, t);
+ inform (input_location, "%q#T declared here",
+ DECL_FIELD_CONTEXT (f));
+ }
+ }
+ }
+
+ return NULL_TREE;
+}
+
/* Perform processing required when the definition of T (a class type)
- is complete. */
+ is complete. Diagnose invalid definitions of flexible array members
+ and zero-size arrays. */
void
finish_struct_1 (tree t)
{
+ {
+ bool dummy = false;
+ check_flexarrays (t, TYPE_FIELDS (t), &dummy);
+ }
+
tree x;
/* A TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. */
tree virtuals = NULL_TREE;
@@ -8610,8 +8610,9 @@ fold_sizeof_expr (tree t)
}
/* 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 thing being declared. */
+ 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. */
tree
compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
@@ -8619,6 +8620,9 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
tree itype;
tree osize = size;
+ if (NULL_TREE == size)
+ return build_index_type (NULL_TREE);
+
if (error_operand_p (size))
return error_mark_node;
@@ -8739,11 +8743,11 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
return error_mark_node;
else if (in_system_header_at (input_location))
/* Allow them in system headers because glibc uses them. */;
- else if (name)
- pedwarn (input_location, OPT_Wpedantic, "ISO C++ forbids zero-size array %qD", name);
else
- pedwarn (input_location, OPT_Wpedantic, "ISO C++ forbids zero-size array");
+ pedwarn (input_location, OPT_Wpedantic,
+ "ISO C++ forbids zero-size arrays");
}
+
}
else if (TREE_CONSTANT (size)
/* We don't allow VLAs at non-function scopes, or during
@@ -10888,7 +10892,7 @@ grokdeclarator (const cp_declarator *declarator,
}
{
- tree decl;
+ tree decl = NULL_TREE;
if (decl_context == PARM)
{
@@ -10912,11 +10916,19 @@ grokdeclarator (const cp_declarator *declarator,
if (!staticp && TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE)
{
- tree itype = compute_array_index_type (dname, integer_zero_node,
+ if (TREE_CODE (ctype) == UNION_TYPE
+ || TREE_CODE (ctype) == QUAL_UNION_TYPE)
+ {
+ error ("flexible array member in union");
+ type = error_mark_node;
+ }
+ else
+ {
+ tree itype = compute_array_index_type (dname, NULL_TREE,
tf_warning_or_error);
type = build_cplus_array_type (TREE_TYPE (type), itype);
}
-
+ }
if (type == error_mark_node)
{
/* Happens when declaring arrays of sizes which
@@ -11082,6 +11094,10 @@ grokdeclarator (const cp_declarator *declarator,
|| !COMPLETE_TYPE_P (TREE_TYPE (type))
|| initialized == 0))
{
+ if (TREE_CODE (type) != ARRAY_TYPE
+ || !COMPLETE_TYPE_P (TREE_TYPE (type)))
+ {
+
if (unqualified_id)
{
error ("field %qD has incomplete type %qT",
@@ -11094,6 +11110,7 @@ grokdeclarator (const cp_declarator *declarator,
type = error_mark_node;
decl = NULL_TREE;
}
+ }
else
{
if (friendp)
@@ -875,7 +875,7 @@ 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))
+ if (TYPE_DOMAIN (t) && TYPE_MAX_VALUE (TYPE_DOMAIN (t)))
{
tree dtype = TYPE_DOMAIN (t);
tree max = TYPE_MAX_VALUE (dtype);
@@ -729,10 +729,15 @@ perform_member_init (tree member, tree init)
|| same_type_ignoring_top_level_qualifiers_p (type,
TREE_TYPE (init)))
{
+ if (TYPE_DOMAIN (type) && TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ {
+ /* Initialize the array only if it's not a flexible
+ array member (i.e., if it has an upper bound). */
init = build_vec_init_expr (type, init, tf_warning_or_error);
init = build2 (INIT_EXPR, type, decl, init);
finish_expr_stmt (init);
}
+ }
else
error ("invalid initializer for array member %q#D", member);
}
@@ -10005,7 +10005,16 @@ instantiate_class_template_1 (tree type)
if (can_complete_type_without_circularity (rtype))
complete_type (rtype);
- if (!COMPLETE_TYPE_P (rtype))
+ if (TREE_CODE (r) == FIELD_DECL
+ && TREE_CODE (rtype) == ARRAY_TYPE
+ && COMPLETE_TYPE_P (TREE_TYPE (rtype))
+ && !COMPLETE_TYPE_P (rtype))
+ {
+ /* Flexible array mmembers of elements
+ of complete type have an incomplete type
+ and that's okay. */
+ }
+ else if (!COMPLETE_TYPE_P (rtype))
{
cxx_incomplete_type_error (r, rtype);
TREE_TYPE (r) = error_mark_node;
@@ -12730,9 +12739,14 @@ 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
- && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
+ 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;
+ }
{
tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
@@ -1013,6 +1013,14 @@ 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))))
+ {
+ /* Flexible array members do not have an upper bound. */
+ 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 */
@@ -1051,8 +1059,11 @@ digest_init_r (tree type, tree init, bool nested, int flags,
init = copy_node (init);
TREE_TYPE (init) = type;
}
- if (TYPE_DOMAIN (type) != 0 && TREE_CONSTANT (TYPE_SIZE (type)))
+ if (TYPE_DOMAIN (type)
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
+ && TREE_CONSTANT (TYPE_SIZE (type)))
{
+ /* Not a flexible array member. */
int size = TREE_INT_CST_LOW (TYPE_SIZE (type));
size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
/* In C it is ok to subtract 1 from the length of the string
@@ -1240,8 +1251,10 @@ process_init_constructor_array (tree type, tree init,
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree domain = TYPE_DOMAIN (type);
- if (domain && TREE_CONSTANT (TYPE_MAX_VALUE (domain)))
- len = wi::ext (wi::to_offset (TYPE_MAX_VALUE (domain))
+ /* 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,
TYPE_PRECISION (TREE_TYPE (domain)),
TYPE_SIGN (TREE_TYPE (domain))).to_uhwi ();
@@ -1417,14 +1430,15 @@ process_init_constructor_record (tree type, tree init,
}
else
{
- if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
+ const_tree fldtype = TREE_TYPE (field);
+ if (TREE_CODE (fldtype) == REFERENCE_TYPE)
{
if (complain & tf_error)
error ("member %qD is uninitialized reference", field);
else
return PICFLAG_ERRONEOUS;
}
- else if (CLASSTYPE_REF_FIELDS_NEED_INIT (TREE_TYPE (field)))
+ else if (CLASSTYPE_REF_FIELDS_NEED_INIT (fldtype))
{
if (complain & tf_error)
error ("member %qD with uninitialized reference fields", field);
@@ -1433,13 +1447,17 @@ process_init_constructor_record (tree type, tree init,
}
/* Warn when some struct elements are implicitly initialized
- to zero. */
- if ((complain & tf_warning)
+ 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))))
+ && (complain & tf_warning)
&& !EMPTY_CONSTRUCTOR_P (init))
warning (OPT_Wmissing_field_initializers,
"missing initializer for member %qD", field);
- if (!zero_init_p (TREE_TYPE (field))
+ if (!zero_init_p (fldtype)
|| skipped < 0)
next = build_zero_init (TREE_TYPE (field), /*nelts=*/NULL_TREE,
/*static_storage_p=*/false);
@@ -1,7 +1,16 @@
// Test for throwing bad_array_new_length on invalid array length
// { dg-do run { target c++11 } }
-#include <new>
+// #include <new>
+
+namespace std {
+struct exception {
+ virtual ~exception () { }
+};
+
+struct bad_alloc: exception { };
+struct bad_array_new_length { };
+}
void * f(int i)
{
@@ -1,4 +1,10 @@
-// PR c++/46688
+// PR c++/46688 - [4.6 Regression] g++ requires a function declaration
+// when it should not
+// Note that although the definition of struct B in the test case for
+// c++/46688 was thought to be valid, it is, in fact, invalid, in C and
+// as noted in c++/42121, should be treated as invalid in C++ as well.
+// The test verifies that gcc detects and reports the right error.
+
// { dg-options "" }
struct A {
@@ -7,5 +13,10 @@ struct A {
struct B {
B() {}
- A a[];
+ A a[]; // { dg-error "extension|flexible array .* in an otherwise empty" }
+};
+
+struct C {
+ C() {}
+ A a[0]; // -Wpedantic warning: ISO C++ forbids zero-size arrays
};
@@ -1,7 +1,18 @@
-// PR c++/54441
+// PR c++/54441 - [4.7/4.8 Regression] Infinite loop with brace initializer
+// on zero-length array
+// Note that although the definition of struct s in the test case for
+// c++/54441 was accepted as valid, it is, in fact, invalid in C, and
+// as noted in c++/42121, should be treated as invalid in C++ as well.
+// The test verifies that gcc detects, reports, and handles both errors
+// gracefully.
+// Note also that the error(s) issued for the invalid initializer depend
+// on c++/55606.
+
// { dg-options "" }
-struct s { char c[]; };
+struct s {
+ char c[]; // { dg-error "flexible array member .* in an otherwise empty" }
+};
int main()
{
new file mode 100644
@@ -0,0 +1,328 @@
+// PR c++/42121 - g++ should warn or error on internal 0 size array in struct
+// { dg-do compile }
+// { dg-options "-Wno-error=pedantic" }
+
+// Flexible array members are a feature of C99 (and newer) not provided
+// by C++ 2014 and prior. G++ supports both the C99/C11 kind of flexible
+// array members and pre-C99 zero-size arrays (defining an array of size
+// zero). Since both features are provided for compatibility with C,
+// G++ allows them in the same contexts as in C.
+
+struct Sx {
+ int a[]; // { dg-error "flexible array member" }
+};
+
+// Verify that non-data members or static data members don't suppress
+// the diagnostic.
+struct Sx2 {
+ int a[]; // { dg-error "flexible array member" }
+ typedef int I;
+};
+
+struct Sx3 {
+ typedef int I;
+ int a[]; // { dg-error "flexible array member" }
+};
+
+struct Sx4 {
+ int a[]; // { dg-error "flexible array member" }
+ enum E { e };
+};
+
+struct Sx5 {
+ enum E { e };
+ int a[]; // { dg-error "flexible array member" }
+};
+
+struct Sx6 {
+ int a[]; // { dg-error "flexible array member" }
+ static int i;
+};
+
+int Sx6::i;
+
+struct Sx7 {
+ static int i;
+ int a[]; // { dg-error "flexible array member" }
+};
+
+int Sx7::i;
+
+struct Sx8 {
+ int a[]; // { dg-error "flexible array member" }
+ Sx8 () { }
+};
+
+struct Sx9 {
+ Sx9 () { }
+ int a[]; // { dg-error "flexible array member" }
+};
+
+struct Sx10 {
+ int a[]; // { dg-error "flexible array member" }
+ virtual ~Sx10 () { }
+};
+
+struct Sx11 {
+ virtual ~Sx11 () { }
+ int a[]; // { dg-error "flexible array member" }
+};
+
+struct Sx12 {
+ int a[]; // { dg-error "flexible array member" }
+ virtual void foo () = 0;
+};
+
+struct Sx13 {
+ virtual void foo () = 0;
+ int a[]; // { dg-error "flexible array member" }
+};
+
+struct Sx14 {
+ int a[][1]; // { dg-error "flexible array member" }
+};
+
+struct Sx15 {
+ typedef int A[];
+ A a; // { dg-error "flexible array member" }
+};
+
+// Verify also that a zero-size array doesn't suppress the diagnostic.
+struct Sx16 {
+ // a_0 below is diagnosed with -Wpedantic only and emits
+ // warning: ISO C++ forbids zero-size arrays
+ int a_0 [0];
+ int a_x []; // { dg-error "flexible array member" }
+};
+
+struct Sx17 {
+ int a_x []; // { dg-error "flexible array member" }
+
+ // a_0 below is diagnosed with -Wpedantic only and emits
+ // warning: ISO C++ forbids zero-size arrays
+ int a_0 [0];
+};
+
+struct Sx18 {
+ int a_x []; // { dg-error "flexible array member" }
+ struct S { };
+};
+
+struct Sx19 {
+ struct S { };
+ int a_x []; // { dg-error "flexible array member" }
+};
+
+struct Sx20 {
+ struct S { } s;
+ int a_x [];
+};
+
+struct Sx21 {
+ int a_x []; // { dg-error "not at end" }
+ struct S { } s;
+};
+
+struct Sx22 {
+ int a_x []; // { dg-error "not at end" }
+ union { int i; };
+};
+
+struct Sx23 {
+ union { int i; };
+ int a_x [];
+};
+
+struct Sx24 {
+ struct S;
+ S a_x []; // { dg-error "incomplete type" }
+};
+
+struct Sx25 {
+ struct S { };
+ S a_x []; // { dg-error "flexible array member" }
+};
+
+struct Sx26 {
+ struct { }
+ a_x []; // { dg-error "flexible array member" }
+};
+
+struct Sx27 {
+ int i;
+ struct { }
+ a_x [];
+};
+
+struct Sx28 {
+ struct { }
+ a_x []; // { dg-error "not at end" }
+ int i;
+};
+
+struct Sx29 {
+ // Pointer to an array of unknown size.
+ int (*a_x)[];
+};
+
+struct Sx30 {
+ // Reference to an array of unknown size.
+ int (&a_x)[];
+};
+
+struct Sx31 {
+ int a []; // { dg-error "not at end" }
+ unsigned i: 1;
+};
+
+struct Sx32 {
+ unsigned i: 1;
+ int a [];
+};
+
+struct S_S_S_x {
+ struct A {
+ struct B {
+ int a[]; // { dg-error "flexible array member" }
+ } b;
+ } a;
+};
+
+// Since members of an anonymous struct or union are considered to be
+// members of the enclosing union the below defintions are valid and
+// must be accepted.
+
+struct Anon1 {
+ int n;
+ struct {
+ int good[];
+ };
+};
+
+struct Anon2 {
+ struct {
+ int n;
+ struct {
+ int good[];
+ };
+ };
+};
+
+struct Anon3 {
+ struct {
+ struct {
+ int n;
+ int good[];
+ };
+ };
+};
+
+struct Anon4 {
+ struct {
+ int in_empty_struct[];// { dg-error "in an otherwise empty" }
+ };
+};
+
+struct Anon5 {
+ struct {
+ int not_at_end[]; // { dg-error "not at end" }
+ };
+ int n;
+};
+
+struct Anon6 {
+ struct {
+ struct {
+ int not_at_end[]; // { dg-error "not at end" }
+ };
+ int n;
+ };
+};
+
+
+struct Anon7 {
+ struct {
+ struct {
+ int not_at_end[]; // { dg-error "not at end" }
+ };
+ };
+ int n;
+};
+
+
+struct Six {
+ int i;
+ int a[];
+};
+
+class Cx {
+ int a[]; // { dg-error "flexible array member" }
+};
+
+class Cix {
+ int i;
+ int a[];
+};
+
+struct Sxi {
+ int a[]; // { dg-error "not at end" }
+ int i;
+};
+
+struct S0 {
+ int a[0];
+};
+
+struct S0i {
+ int a[0];
+ int i;
+};
+
+struct S_a0_ax {
+ int a1[0];
+ int ax[]; // { dg-error "flexible array member" }
+};
+
+struct S_a0_i_ax {
+ int a1[0];
+ int i;
+ int ax[];
+};
+
+struct Si_a0_ax {
+ int i;
+ int a1[0];
+ int ax[];
+};
+
+struct S_u_ax {
+ struct {
+ // An empty struct is in C++ treated as if it had a single
+ // member of type char. Arguably, though, since neither
+ // the struct nor the member has a name, the flexible array
+ // member should be diagnosed because its size cannot easily
+ // be stored in the contaning object. This seems like too
+ // much of a corner case to worry about.
+ };
+ int ax[]; // no warning because of the above
+};
+
+struct S_u0_ax {
+ union { } u[0];
+ int ax[]; // { dg-error "flexible array member" }
+};
+
+struct S_a1_s2 {
+ int a[1];
+ int b[2];
+};
+
+union U_i_ax {
+ int i;
+ int a[]; // { dg-error "flexible array member in union" }
+};
+
+union U_i_a0 {
+ int i;
+ int a[0];
+};
new file mode 100644
@@ -0,0 +1,52 @@
+// { dg-do compile }
+// { dg-options "-Wno-error=pedantic" }
+
+// Flexible array members are a feature of C99 (and newer) not provided
+// by C++ 2014 and prior. G++ supports both the C99/C11 kind of flexible
+// array members and pre-C99 zero-size arrays (defining an array of size
+// zero). Since both features are provided for compatibility with C,
+// G++ allows them in the same contexts as in C. This test verifies
+// that invalid flexible array members are diagnosed in templates that
+// are instantiated and not otherwise.
+
+template <class T>
+struct S_no_diag: T {
+ char a[]; // cannot be diagnosed unless/until T is known
+};
+
+template <class T>
+struct STx_1: T {
+ char a[]; // { dg-error "flexible array member" }
+};
+
+template <class T, int I>
+struct STI: T {
+ char a[I]; // cannot be diagnosed unless/until T and I are known
+};
+
+template <class T, int I>
+struct STIx: T {
+ char a[I];
+};
+
+template <int>
+struct Empty { };
+
+STx_1<Empty<0> > stx_empty_1;
+STIx<Empty<0>, 0> stix_empty_1;
+
+struct EmptyBase1: Empty<0>, Empty<1> { };
+struct EmptyBase2: Empty<2>, Empty<3> { };
+struct EmptyDerived: EmptyBase1, EmptyBase2
+{
+ char a[]; // { dg-error "flexible array member" }
+};
+
+struct NonEmpty { int i; };
+struct NonEmptyBase: NonEmpty { };
+struct NonEmptyDerived: NonEmptyBase { };
+
+struct FinalDerived: EmptyBase1, EmptyBase2, NonEmpty, Empty<4>
+{
+ char a[]; // okay
+};
new file mode 100644
@@ -0,0 +1,25 @@
+// PR c++/68478 - flexible array members have complete type
+// { dg-do compile }
+// { dg-options "-Wno-error=pedantic" }
+
+// Test to verify that attempting to use a flexible array member where
+// a complete type is required is rejected.
+
+struct A {
+ int n;
+ int a[];
+ enum {
+ e = sizeof a // { dg-error "invalid application of .sizeof. to incomplete type" }
+ };
+};
+
+struct B {
+ int n;
+ typedef int A[];
+ A a;
+ enum {
+ // Verify that attempting to use a flexible array member where
+ // a complete type is required is rejected.
+ e = sizeof a // { dg-error "invalid application of .sizeof. to incomplete type" }
+ };
+};
new file mode 100644
@@ -0,0 +1,57 @@
+// PR c++/68613 - initializer-string for array of chars is too long error
+// on flexible array member
+// { dg-do compile }
+// { dg-options "-Wpedantic -Wno-error=pedantic" }
+
+struct FlexChar {
+ int n;
+ char a[];
+};
+
+struct FlexChar ac =
+ { 4, { "abc" } }; // { dg-warning "initialization of a flexible array member" }
+
+
+#if !__cplusplus
+typedef __WCHAR_TYPE__ wchar_t;
+#endif
+
+struct FlexWchar {
+ int n;
+ wchar_t a[];
+};
+
+struct FlexWchar awc =
+ { 3, { L"ab" } }; // { dg-warning "initialization of a flexible array member" }
+
+
+struct FlexInt {
+ int n;
+ int a[];
+};
+
+// Verify that no warning is issued for the case when a flexible array
+// member is not initialized (i.e., that a -Wmissing-field-initializer
+// isn't issued) because such arrays need not have any elements.
+struct FlexInt ai0 =
+ { 0 };
+
+struct FlexInt ai0_ =
+ { 0, { } }; // { dg-warning "initialization of a flexible array member" }
+
+struct FlexInt ai2 =
+ { 2, { 1, 2 } }; // { dg-warning "initialization of a flexible array member" }
+
+
+#if __cplusplus
+
+template <class T>
+struct FlexT {
+ int n;
+ T a[];
+};
+
+struct FlexT<char> atc =
+ { 4, { "abc" } }; // { dg-warning "initialization of a flexible array member" }
+
+#endif
@@ -7,5 +7,5 @@ struct S
__extension__ unsigned char data[];
};
-/* { dg-final { scan-ada-spec "array \\(0 .. -1\\)" } } */
+/* { dg-final { scan-ada-spec "array \\(0 .. 0\\)" } } */
/* { dg-final { cleanup-ada-spec } } */
@@ -3,12 +3,15 @@
struct SomeType
{
+ int n;
const char *values[];
};
const char *temp[] = {"607", "612", 0};
SomeType vals[] =
{
- { values : temp, },
+ { 0, values : temp, },
0
- }; // { dg-error "invalid" }
+ }; // { dg-error "GNU-style designated initializer for an array|cannot convert" }
+// (note the error above is on the wrong line)
+
@@ -15,7 +15,7 @@ public:
typedef int jmp_buf[];
struct C
{
- jmp_buf cond_;
+ jmp_buf cond_; // { dg-error "flexible array member" }
};
class F
{
@@ -43,6 +43,7 @@ protected:
class F
{
public:
+ int nelems;
int elems[];
int *
m_fn1 ()
@@ -1,9 +1,9 @@
// { dg-do compile }
-// { dg-options "-fsanitize=undefined -fpermissive" }
+// { dg-options "-Wpedantic -Wno-error=pedantic -fsanitize=undefined -fpermissive" }
struct T { int c; char d[]; };
-struct T t = { 1, "a" }; // { dg-warning "initializer-string for array of chars is too long" }
+struct T t = { 1, "a" }; // { dg-warning "initialization of a flexible array member " }
int
baz (int i)
@@ -1664,8 +1664,10 @@ chkp_find_bound_slots_1 (const_tree type, bitmap have_bound,
offs + field_offs);
}
}
- else if (TREE_CODE (type) == ARRAY_TYPE)
+ else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
{
+ /* The object type is an array of complete type, i.e., other
+ than a flexible array. */
tree maxval = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
tree etype = TREE_TYPE (type);
HOST_WIDE_INT esize = TREE_INT_CST_LOW (TYPE_SIZE (etype));
@@ -3588,9 +3588,10 @@ type_contains_placeholder_1 (const_tree type)
|| CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
case ARRAY_TYPE:
- /* We have already checked the component type above, so just check the
- domain type. */
- return type_contains_placeholder_p (TYPE_DOMAIN (type));
+ /* We have already checked the component type above, so just check
+ the domain type. Flexible array members have a null domain. */
+ return TYPE_DOMAIN (type) ?
+ type_contains_placeholder_p (TYPE_DOMAIN (type)) : false;
case RECORD_TYPE:
case UNION_TYPE:
@@ -4821,8 +4821,7 @@ array_size_for_constructor (tree val)
{
tree max_index;
unsigned HOST_WIDE_INT cnt;
- tree index, value, tmp;
- offset_int i;
+ tree index, value;
/* This code used to attempt to handle string constants that are not
arrays of single-bytes, but nothing else does, so there's no point in
@@ -4842,9 +4841,14 @@ array_size_for_constructor (tree val)
if (max_index == NULL_TREE)
return 0;
+ offset_int i = wi::to_offset (max_index) + 1;
+
+ if (TYPE_DOMAIN (TREE_TYPE (val)))
+ {
/* Compute the total number of array elements. */
- tmp = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)));
- i = wi::to_offset (max_index) - wi::to_offset (tmp) + 1;
+ tree tmp = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)));
+ i -= wi::to_offset (tmp);
+ }
/* Multiply by the array element unit size to find number of bytes. */
i *= wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
@@ -4974,13 +4978,15 @@ output_constructor_regular_field (oc_local_state *local)
but we cannot do this until the deprecated support for
initializing zero-length array members is removed. */
if (TREE_CODE (TREE_TYPE (local->field)) == ARRAY_TYPE
- && TYPE_DOMAIN (TREE_TYPE (local->field))
- && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (local->field))))
+ && (!TYPE_DOMAIN (TREE_TYPE (local->field))
+ || !TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (local->field)))))
{
fieldsize = array_size_for_constructor (local->val);
- /* Given a non-empty initialization, this field had
- better be last. */
- gcc_assert (!fieldsize || !DECL_CHAIN (local->field));
+ /* Given a non-empty initialization, this field had better
+ be last. Given a flexible array member, the next field
+ on the chain is a TYPE_DECL of the enclosing struct. */
+ const_tree next = DECL_CHAIN (local->field);
+ gcc_assert (!fieldsize || !next || TREE_CODE (next) != FIELD_DECL);
}
else
fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));
@@ -5196,7 +5202,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
if (TREE_CODE (local.type) == ARRAY_TYPE && TYPE_DOMAIN (local.type))
local.min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (local.type));
else
- local.min_index = NULL_TREE;
+ local.min_index = integer_zero_node;
local.total_bytes = 0;
local.byte_buffer_in_use = outer != NULL;