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);

Reply via email to