c: minor fixes related to arrays of unspecified size [PR116284,PR117391]

Message ID b2cbc67013f84875b59d729385dc8df831e11eca.camel@tugraz.at
State New
Headers
Series c: minor fixes related to arrays of unspecified size [PR116284,PR117391] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 fail Test failed
linaro-tcwg-bot/tcwg_gcc_check--master-arm fail Test failed

Commit Message

Martin Uecker Nov. 2, 2024, 10:38 a.m. UTC
  The recent patch to improve detection of variably modified types
also fixed some issues related to unspecified sizes.

https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=9eae9268e41463927c9383004e58708048ec379f 

There are some loose ends / possible cleanups which I missed and
which are addressed by this patch.

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.  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.
  

Comments

Joseph Myers Nov. 4, 2024, 11:08 p.m. UTC | #1
On Sat, 2 Nov 2024, Martin Uecker wrote:

>     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.  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.

These should go in gcc/c/ChangeLog without the c/ prefix.

>     
>     gcc/testsuite/ChangeLog:
>             * gcc.dg/pr116284.c: New test.
>             * gcc.dg/pr117391.c: New test.

The patch is OK with the above ChangeLog entry fix.
  

Patch

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..22fd80046b6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr116284.c
@@ -0,0 +1,13 @@ 
+/* { dg-do compile } */
+
+// 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'" } */
+}
+