-Warray-parameter and -Wvla-parameter assume that array bounds
in function parameters are either constant integers or variable,
but not something in between like a cast of a constant that's
not recognized as an INTEGER_CST until we strip the cast from
it.  This leads to an ICE as the the internal checks fail.

The attached patch fixes the problem by stripping the casts
earlier than before, preventing the inconsistency.  In addition,
it also folds the array bound, avoiding a class of false
positives and negatives that not doing so would lead to otherwise.

Tested on x86_64-linux.

Martin
Handle folded nonconstant array bounds [PR101702]

PR c/101702 - ICE: in handle_argspec_attribute, at c-family/c-attribs.c:3623

gcc/c/ChangeLog:

	PR c/101702
	* c-decl.c (get_parm_array_spec): Strip casts earlier and fold array
	bounds before deciding if they're constant.

gcc/testsuite/ChangeLog:

	PR c/101702
	* gcc.dg/Warray-parameter-11.c: New test.

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 186fa1692c1..63d806a84c9 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -5866,6 +5866,12 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs)
       if (pd->u.array.static_p)
 	spec += 's';
 
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (nelts)))
+	/* Avoid invalid NELTS.  */
+	return attrs;
+
+      STRIP_NOPS (nelts);
+      nelts = c_fully_fold (nelts, false, nullptr);
       if (TREE_CODE (nelts) == INTEGER_CST)
 	{
 	  /* Skip all constant bounds except the most significant one.
@@ -5883,13 +5889,9 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs)
 	  spec += buf;
 	  break;
 	}
-      else if (!INTEGRAL_TYPE_P (TREE_TYPE (nelts)))
-	/* Avoid invalid NELTS.  */
-	return attrs;
 
       /* Each variable VLA bound is represented by a dollar sign.  */
       spec += "$";
-      STRIP_NOPS (nelts);
       vbchain = tree_cons (NULL_TREE, nelts, vbchain);
     }
 
diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-11.c b/gcc/testsuite/gcc.dg/Warray-parameter-11.c
new file mode 100644
index 00000000000..8ca1b55bd28
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-parameter-11.c
@@ -0,0 +1,24 @@
+/* PR c/101702 - ICE on invalid function redeclaration
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+
+#define copysign(x, y) __builtin_copysign (x, y)
+
+void f0 (double[!copysign (~2, 3)]);
+
+void f1 (double[!copysign (~2, 3)]);
+void f1 (double[1]);                    // { dg-warning "-Warray-parameter" }
+
+void f2 (int[(int)+1.0]);
+void f2 (int[(int)+1.1]);
+
+/* Also verify that equivalent expressions don't needlessly cause false
+   positives or negatives.  */
+struct S { int a[1]; };
+extern struct S *sp;
+
+void f3 (int[(intptr_t)((char*)sp->a - (char*)sp)]);
+void f3 (int[(intptr_t)((char*)&sp->a[0] - (char*)sp)]);
+void f3 (int[(intptr_t)((char*)&sp->a[1] - (char*)sp)]);   // { dg-warning "-Warray-parameter" }

Reply via email to