https://gcc.gnu.org/g:ed1d15e94f5ce28a9fdba6e3b255efef420c93f0
commit r17-2218-ged1d15e94f5ce28a9fdba6e3b255efef420c93f0 Author: Martin Uecker <[email protected]> Date: Sun Jun 28 20:04:14 2026 +0200 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-attribs.cc (handle_counted_by_attribute): Adapt. * c-common.h (c_flexible_array_member_type_p): Remove. * c-common.cc (c_flexible_array_member_type_p): Remove. gcc/c/ChangeLog: * 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-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: --- gcc/c-family/c-attribs.cc | 2 +- gcc/c-family/c-common.cc | 13 ------------- gcc/c-family/c-common.h | 1 - gcc/c/c-decl.cc | 17 +++++++++++------ gcc/c/c-typeck.cc | 21 +++++++++------------ gcc/tree.cc | 23 +++++++++++++++++------ gcc/tree.h | 1 + 7 files changed, 39 insertions(+), 39 deletions(-) diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 88293c37e4ee..d668ab96630a 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 a16288f4441c..c298ff11a83c 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 5711e1740498..bf7bc5eda5be 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 4dc1e94394bc..aae2bf3e42b0 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -5564,7 +5564,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 @@ -7315,6 +7315,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)) @@ -7527,7 +7529,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 @@ -7625,6 +7626,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 @@ -9413,7 +9418,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); @@ -9539,7 +9544,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", @@ -9742,7 +9747,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, @@ -9789,7 +9794,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 643035b50a08..5fe3332c79ad 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 411752d14636..977bdaa0845c 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -15137,6 +15137,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). */ @@ -15153,12 +15169,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 73a26dbe75c7..d038d2afd332 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);
