[gcc r17-2218] c: harmonize checking for flex array member type

Martin Uecker via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
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);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.