Bootstrapped and regression tested on x86_64.
c: harmonize checking for flex array member type.
We already have a helper function to detect the type of a flexible
array member. Rename it for consistency and move it to tree.cc.
Also use the function for some additional cases instead of using a
direct test. In digest_init the change removes the warning for
zero-sized arrays, but it is misleading and redundant as we already
warn for excess initializers (and with -Wpedantic also for the use
of zero-sized arrays).
gcc/c-family/ChangeLog:
* c-family/c-attribs.cc (handle_counted_by_attribute): Adapt.
* c-family/c-common.h (c_flexible_array_member_type_p): Remove.
* c-family/c-common.cc (c_flexible_array_member_type_p): Remove.
gcc/c/ChangeLog:
* c/c-decl.cc (grokdeclarator): Add assertion.
(add_flexible_array_elts_to_size): Adapt.
(is_flexible_array_member_p): Adapt.
(verify_counted_by_attribute): Adapt.
(finish_struct): Adapt.
* c/c-typeck.cc (check_counted_by_attribute): Adapt.
(build_counted_by_ref): Adapt.
(build_access_with_size_for_counted_by): Adapt.
(handle_counted_by_for_component_ref): Adapt.
(c_incomplete_type_error): Use new helper function.
(digest_init): Use new helper function.
(pop_init_level): Use new helper function.
gcc/ChangeLog:
* tree.h (flexible_array_member_type_p): New helper function.
* tree.cc (flexible_array_member_type_p): New helper function.
(flexible_array_type_p): Use new helper function.
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 88293c37e4e..d668ab96630 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -2963,7 +2963,7 @@ handle_counted_by_attribute (tree *node, tree name,
}
/* This attribute only applies to a C99 flexible array member type. */
else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
- && !c_flexible_array_member_type_p (TREE_TYPE (decl)))
+ && !flexible_array_member_type_p (TREE_TYPE (decl)))
{
error_at (DECL_SOURCE_LOCATION (decl),
"%qE attribute is not allowed for a non-flexible"
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index a16288f4441..c298ff11a83 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -10561,19 +10561,6 @@ c_common_finalize_early_debug (void)
(*debug_hooks->early_global_decl) (cnode->decl);
}
-/* Determine whether TYPE is an ISO C99 flexible array member type "[]". */
-bool
-c_flexible_array_member_type_p (const_tree type)
-{
- if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_SIZE (type) == NULL_TREE
- && TYPE_DOMAIN (type) != NULL_TREE
- && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
- return true;
-
- return false;
-}
-
/* Get the LEVEL of the strict_flex_array for the ARRAY_FIELD based on the
values of attribute strict_flex_array and the flag_strict_flex_arrays. */
unsigned int
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 5711e174049..bf7bc5eda5b 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -928,7 +928,6 @@ extern tree fold_for_warn (tree);
extern tree c_common_get_narrower (tree, int *);
extern bool get_attribute_operand (tree, unsigned HOST_WIDE_INT *);
extern void c_common_finalize_early_debug (void);
-extern bool c_flexible_array_member_type_p (const_tree);
extern unsigned int c_strict_flex_array_level_of (tree);
extern bool c_option_is_from_cpp_diagnostics (int);
extern tree c_hardbool_type_attr_1 (tree, tree *, tree *);
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 1b2f2b4edec..39951db5c01 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -5563,7 +5563,7 @@ add_flexible_array_elts_to_size (tree decl, tree init)
elt = CONSTRUCTOR_ELTS (init)->last ().value;
type = TREE_TYPE (elt);
- if (c_flexible_array_member_type_p (type))
+ if (flexible_array_member_type_p (type))
{
complete_array_type (&type, elt, false);
/* For a structure, add the size of the initializer to the DECL's
@@ -7314,6 +7314,8 @@ grokdeclarator (const struct c_declarator *declarator,
declarator = declarator->declarator;
+ bool flexible_array_member = false;
+
/* Check for some types that there cannot be arrays of. */
if (VOID_TYPE_P (type))
@@ -7526,7 +7528,6 @@ grokdeclarator (const struct c_declarator *declarator,
}
else if (decl_context == FIELD)
{
- bool flexible_array_member = false;
if (array_parm_vla_unspec_p)
/* Field names can in fact have function prototype
scope so [*] is disallowed here through making
@@ -7624,6 +7625,10 @@ grokdeclarator (const struct c_declarator *declarator,
type = error_mark_node;
}
+ gcc_assert (type == error_mark_node
+ || flexible_array_member
+ == flexible_array_member_type_p (type));
+
if (decl_context != PARM
&& (array_ptr_quals != TYPE_UNQUALIFIED
|| array_ptr_attrs != NULL_TREE
@@ -9412,7 +9417,7 @@ is_flexible_array_member_p (bool is_last_field,
bool is_zero_length_array = zero_length_array_type_p (TREE_TYPE (x));
bool is_one_element_array = one_element_array_type_p (TREE_TYPE (x));
- bool is_flexible_array = c_flexible_array_member_type_p (TREE_TYPE (x));
+ bool is_flexible_array = flexible_array_member_type_p (TREE_TYPE (x));
unsigned int strict_flex_array_level = c_strict_flex_array_level_of (x);
@@ -9538,7 +9543,7 @@ verify_counted_by_attribute (tree outmost_struct_type,
for (tree field = TYPE_FIELDS (cur_struct_type); field;
field = TREE_CHAIN (field))
{
- if (c_flexible_array_member_type_p (TREE_TYPE (field))
+ if (flexible_array_member_type_p (TREE_TYPE (field))
|| TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE)
{
tree attr_counted_by = lookup_attribute ("counted_by",
@@ -9741,7 +9746,7 @@ finish_struct (location_t loc, tree t, tree fieldlist,
tree attributes,
DECL_PACKED (x) = 1;
/* Detect flexible array member in an invalid context. */
- if (c_flexible_array_member_type_p (TREE_TYPE (x)))
+ if (flexible_array_member_type_p (TREE_TYPE (x)))
{
if (TREE_CODE (t) == UNION_TYPE)
pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
@@ -9788,7 +9793,7 @@ finish_struct (location_t loc, tree t, tree fieldlist,
tree attributes,
the result for multiple last_fields. */
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
TYPE_INCLUDES_FLEXARRAY (t)
- |= is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x));
+ |= is_last_field && flexible_array_member_type_p (TREE_TYPE (x));
/* Recursively set TYPE_INCLUDES_FLEXARRAY for the context of x, t
when x is an union or record and is the last field. */
else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index c8127cc1f05..86e088c582a 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -265,7 +265,7 @@ c_incomplete_type_error (location_t loc, const_tree value,
const_tree type)
case ARRAY_TYPE:
if (TYPE_DOMAIN (type))
{
- if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL)
+ if (flexible_array_member_type_p (type))
{
error_at (loc, "invalid use of flexible array member");
return;
@@ -3089,7 +3089,7 @@ check_counted_by_attribute (location_t loc, tree ref)
tree subdatum = TREE_OPERAND (ref, 1);
tree sub_type = TREE_TYPE (subdatum);
- if (!c_flexible_array_member_type_p (sub_type)
+ if (!flexible_array_member_type_p (sub_type)
&& TREE_CODE (sub_type) != POINTER_TYPE)
return;
@@ -3137,7 +3137,7 @@ build_counted_by_ref (tree datum, tree subdatum,
tree *counted_by_type)
{
tree sub_type = TREE_TYPE (subdatum);
- if (!c_flexible_array_member_type_p (sub_type)
+ if (!flexible_array_member_type_p (sub_type)
&& TREE_CODE (sub_type) != POINTER_TYPE)
return NULL_TREE;
@@ -3232,10 +3232,10 @@ build_access_with_size_for_counted_by (location_t loc,
tree ref,
tree counted_by_ref,
tree counted_by_type)
{
- gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref))
+ gcc_assert (flexible_array_member_type_p (TREE_TYPE (ref))
|| TREE_CODE (TREE_TYPE (ref)) == POINTER_TYPE);
- bool is_fam = c_flexible_array_member_type_p (TREE_TYPE (ref));
+ bool is_fam = flexible_array_member_type_p (TREE_TYPE (ref));
/* The result type of the call is a pointer to the flexible array type;
or is the original pointer type to the pointer field with counted_by. */
@@ -3285,7 +3285,7 @@ handle_counted_by_for_component_ref (location_t loc, tree
ref)
tree subdatum = TREE_OPERAND (ref, 1);
tree counted_by_type = NULL_TREE;
- if (!(c_flexible_array_member_type_p (TREE_TYPE (ref))
+ if (!(flexible_array_member_type_p (TREE_TYPE (ref))
|| TREE_CODE (TREE_TYPE (ref)) == POINTER_TYPE))
return ref;
@@ -9944,7 +9944,7 @@ digest_init (location_t init_loc, tree decl, tree type,
tree init,
expr.m_decimal = 0;
maybe_warn_string_init (init_loc, type, expr);
- if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ if (flexible_array_member_type_p (type))
pedwarn_init (init_loc, OPT_Wpedantic,
"initialization of a flexible array member");
@@ -10915,12 +10915,9 @@ pop_init_level (location_t loc, int implicit,
p = constructor_stack;
- /* Error for initializing a flexible array member, or a zero-length
- array member in an inappropriate context. */
+ /* Error for initializing a flexible array member. */
if (constructor_type && constructor_fields
- && TREE_CODE (constructor_type) == ARRAY_TYPE
- && TYPE_DOMAIN (constructor_type)
- && !TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
+ && flexible_array_member_type_p (constructor_type))
{
/* Silently discard empty initializations. The parser will
already have pedwarned for empty brackets for C17 and earlier. */
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 90c8f2a35ea..a020303aaf1 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -15140,6 +15140,22 @@ default_is_empty_record (const_tree type)
return is_empty_type (TYPE_MAIN_VARIANT (type));
}
+
+/* Determine whether TYPE is an ISO C99 flexible array member type "[]". */
+
+bool
+flexible_array_member_type_p (const_tree type)
+{
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_SIZE (type) == NULL_TREE
+ && TYPE_DOMAIN (type) != NULL_TREE
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
+ return true;
+
+ return false;
+}
+
+
/* Determine whether TYPE is a structure with a flexible array member,
or a union containing such a structure (possibly recursively). */
@@ -15156,12 +15172,7 @@ flexible_array_type_p (const_tree type)
last = x;
if (last == NULL_TREE)
return false;
- if (TREE_CODE (TREE_TYPE (last)) == ARRAY_TYPE
- && TYPE_SIZE (TREE_TYPE (last)) == NULL_TREE
- && TYPE_DOMAIN (TREE_TYPE (last)) != NULL_TREE
- && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (last))) == NULL_TREE)
- return true;
- return false;
+ return flexible_array_member_type_p (TREE_TYPE (last));
case UNION_TYPE:
for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
{
diff --git a/gcc/tree.h b/gcc/tree.h
index 73a26dbe75c..d038d2afd33 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -7019,6 +7019,7 @@ extern void gt_pch_nx (tree_raw_data *,
gt_pointer_operator, void *);
extern bool nonnull_arg_p (const_tree);
extern bool is_empty_type (const_tree);
extern bool default_is_empty_record (const_tree);
+extern bool flexible_array_member_type_p (const_tree);
extern bool flexible_array_type_p (const_tree);
extern HOST_WIDE_INT arg_int_size_in_bytes (const_tree);
extern tree arg_size_in_bytes (const_tree);