This version of the already approved patch only adds the missing
word "size" to the commit message and a missing "-std=gnu23" to 
the first test.  If there are no new comments, I will commit this
once the pre-commit CI tests are complete.


Bootstrapped and regression tested on x86_64.

Martin



    c: minor fixes related to arrays of unspecified size
    
    The patch for PR117145 and PR117245 also fixed PR100420 and PR116284 which
    are bugs related to arrays of unspecified size.  Those are now represented
    as variable size arrays with size (0, 0).  There are still some loose ends,
    which are resolved here by
    
    1. adding a testcase for PR116284,
    2. moving code related to creation and detection of arrays of unspecified
    sizes in their own functions,
    3. preferring a specified size over an unspecified size when forming
    a composite type as required by C99 (PR118391)
    4. removing useless code in comptypes_internal and composite_type_internal.
    
            PR c/116284
            PR c/117391
    
    gcc/ChangeLog:
            * c/c-tree.h (c_type_unspecified_p): New inline function.
            * c/c-typeck.cc (c_build_array_type_unspecified): New function.
            (comptypes_interal): Remove useless code.
            (composite_type_internal): Update.
            * c/c-decl.cc (grokdeclarator): Revise.
    
    gcc/testsuite/ChangeLog:
            * gcc.dg/pr116284.c: New test.
            * gcc.dg/pr117391.c: New test.

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 42d329e4fd5..ac47ef24a3d 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -7501,10 +7501,6 @@ grokdeclarator (const struct c_declarator *declarator,
                /* C99 6.7.5.2p4 */
                if (decl_context == TYPENAME)
                  warning (0, "%<[*]%> not in a declaration");
-               /* Array of unspecified size.  */
-               tree upper = build2 (COMPOUND_EXPR, TREE_TYPE (size_zero_node),
-                                    integer_zero_node, size_zero_node);
-               itype = build_index_type (upper);
                size_varies = true;
              }
 
@@ -7540,7 +7536,10 @@ grokdeclarator (const struct c_declarator *declarator,
                if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
                  type = c_build_qualified_type (type,
                                                 ENCODE_QUAL_ADDR_SPACE (as));
-               type = c_build_array_type (type, itype);
+               if (array_parm_vla_unspec_p)
+                 type = c_build_array_type_unspecified (type);
+               else
+                 type = c_build_array_type (type, itype);
              }
 
            if (type != error_mark_node)
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index c8e9731bfc4..f6bcbabb9d5 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -776,12 +776,22 @@ extern struct c_switch *c_switch_stack;
 extern bool null_pointer_constant_p (const_tree);
 
 
-inline
-bool c_type_variably_modified_p (tree t)
+inline bool
+c_type_variably_modified_p (tree t)
 {
   return error_mark_node != t && C_TYPE_VARIABLY_MODIFIED (t);
 }
 
+inline bool
+c_type_unspecified_p (tree t)
+{
+  return error_mark_node != t
+        && C_TYPE_VARIABLE_SIZE (t) && TREE_CODE (t) == ARRAY_TYPE
+        && TYPE_DOMAIN (t) && TYPE_MAX_VALUE (TYPE_DOMAIN (t))
+        && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == COMPOUND_EXPR
+        && integer_zerop (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0))
+        && integer_zerop (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 1));
+}
 
 extern bool char_type_p (tree);
 extern tree c_objc_common_truthvalue_conversion (location_t, tree,
@@ -883,10 +893,10 @@ extern tree c_reconstruct_complex_type (tree, tree);
 extern tree c_build_type_attribute_variant (tree ntype, tree attrs);
 extern tree c_build_pointer_type (tree type);
 extern tree c_build_array_type (tree type, tree domain);
+extern tree c_build_array_type_unspecified (tree type);
 extern tree c_build_function_type (tree type, tree args, bool no = false);
 extern tree c_build_pointer_type_for_mode (tree type, machine_mode mode, bool 
m);
 
-
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
 
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 6673cbf7294..201d75d2e9c 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -358,7 +358,7 @@ qualify_type (tree type, tree like)
 }
 
 
-/* Check consistency of type TYP.E  For derived types, we test that
+/* Check consistency of type TYPE.  For derived types, we test that
    C_TYPE_VARIABLE_SIZE and C_TYPE_VARIABLY_MODIFIED are consistent with
    the requirements of the base type.  We also check that arrays with a
    non-constant length are marked with C_TYPE_VARIABLE_SIZE. If any
@@ -490,6 +490,17 @@ c_build_array_type (tree type, tree domain)
   return c_set_type_bits (ret, type);
 }
 
+
+/* Build an array type of unspecified size.  */
+tree
+c_build_array_type_unspecified (tree type)
+{
+  tree upper = build2 (COMPOUND_EXPR, TREE_TYPE (size_zero_node),
+                      integer_zero_node, size_zero_node);
+  return c_build_array_type (type, build_index_type (upper));
+}
+
+
 tree
 c_build_type_attribute_qual_variant (tree type, tree attrs, int quals)
 {
@@ -660,15 +671,23 @@ composite_type_internal (tree t1, tree t2, struct 
composite_cache* cache)
        d2_variable = (!d2_zero
                       && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
-       d1_variable = d1_variable || (d1_zero && C_TYPE_VARIABLE_SIZE (t1));
-       d2_variable = d2_variable || (d2_zero && C_TYPE_VARIABLE_SIZE (t2));
+
+       bool use1 = TYPE_DOMAIN (t1)
+                   && (d2_variable || d2_zero || !d1_variable);
+       bool use2 = TYPE_DOMAIN (t2)
+                   && (d1_variable || d1_zero || !d2_variable);
+
+       /* If the first is an unspecified size pick the other one.  */
+       if (d2_variable && c_type_unspecified_p (t1))
+         {
+           gcc_assert (use1 && use2);
+           use1 = false;
+         }
 
        /* Save space: see if the result is identical to one of the args.  */
-       if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)
-           && (d2_variable || d2_zero || !d1_variable))
+       if (elt == TREE_TYPE (t1) && use1)
          return c_build_type_attribute_variant (t1, attributes);
-       if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)
-           && (d1_variable || d1_zero || !d2_variable))
+       if (elt == TREE_TYPE (t2) && use2)
          return c_build_type_attribute_variant (t2, attributes);
 
        if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
@@ -683,13 +702,7 @@ composite_type_internal (tree t1, tree t2, struct 
composite_cache* cache)
           back at the end.  */
        quals = TYPE_QUALS (strip_array_types (elt));
        unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
-       t1 = c_build_array_type (unqual_elt,
-                                TYPE_DOMAIN ((TYPE_DOMAIN (t1)
-                                             && (d2_variable
-                                                 || d2_zero
-                                                 || !d1_variable))
-                                             ? t1
-                                             : t2));
+       t1 = c_build_array_type (unqual_elt, TYPE_DOMAIN (use1 ? t1 : t2));
 
        /* Check that a type which has a varying outermost dimension
           got marked has having a variable size.  */
@@ -1658,8 +1671,6 @@ comptypes_internal (const_tree type1, const_tree type2,
        d2_variable = (!d2_zero
                       && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
-       d1_variable = d1_variable || (d1_zero && C_TYPE_VARIABLE_SIZE (t1));
-       d2_variable = d2_variable || (d2_zero && C_TYPE_VARIABLE_SIZE (t2));
 
        if (d1_variable != d2_variable)
          data->different_types_p = true;
diff --git a/gcc/testsuite/gcc.dg/pr116284.c b/gcc/testsuite/gcc.dg/pr116284.c
new file mode 100644
index 00000000000..c28318247a1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr116284.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu23" } */
+
+// There should be no warning about variably-modified types
+
+static int a[0];
+static int b[sizeof a];
+
+void foo(int (*x)[*]);
+
+static int c[0];
+static int d[sizeof c];
+
+
diff --git a/gcc/testsuite/gcc.dg/pr117391.c b/gcc/testsuite/gcc.dg/pr117391.c
new file mode 100644
index 00000000000..d3d03ada4d0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr117391.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+int foo(int n, char (*buf)[*]);
+int bar(int n, char (*buf)[n]);
+
+void test()
+{
+       (1 ? foo : bar)(0);     /* { dg-error "too few arguments to function 
'\\\(int \\\(\\\*\\\)\\\(int,  char \\\(\\\*\\\)\\\[n]\\\)\\\)&foo'" } */
+       (0 ? bar : foo)(0);     /* { dg-error "too few arguments to function 
'\\\(int \\\(\\\*\\\)\\\(int,  char \\\(\\\*\\\)\\\[n]\\\)\\\)&foo'" } */
+       (0 ? foo : bar)(0);     /* { dg-error "too few arguments to function 
'bar'" } */
+       (1 ? bar : foo)(0);     /* { dg-error "too few arguments to function 
'bar'" } */
+}
+

Reply via email to