Redeclaring a function that takes a VLA parameter with attribute
access that references the same parameter can cause conflicts
when the two aren't in sync.  The conflicts are detected and
diagnosed but also have to be resolved.  The code wasn't robust
enough to handle all cases gracefully, leading to the ICE reported
in the PR.  After testing on x86_64-linux I have committed in
r11-3571 the attached fix to improve it and avoid the ICE.

Martin

Avoid assuming a VLA access specification string contains a closing bracket (PR middle-end/97189).

Resolves:
PR middle-end/97189 - ICE on redeclaration of a function with VLA argument and attribute access

gcc/ChangeLog:

	PR middle-end/97189
	* attribs.c (attr_access::array_as_string): Avoid assuming a VLA
	access specification string contains a closing bracket.

gcc/c-family/ChangeLog:

	PR middle-end/97189
	* c-attribs.c (append_access_attr): Use the function declaration
	location for a warning about an attribute access argument.

gcc/testsuite/ChangeLog:

	PR middle-end/97189
	* gcc.dg/attr-access-2.c: Adjust caret location.
	* gcc.dg/Wvla-parameter-6.c: New test.
	* gcc.dg/Wvla-parameter-7.c: New test.

diff --git a/gcc/attribs.c b/gcc/attribs.c
index 3f6ec3d3aa3..94b9e02699f 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -2270,11 +2270,11 @@ attr_access::array_as_string (tree type) const
 	     bound is nonconstant and whose access string has "$]" in it)
 	     extract the bound expression from SIZE.  */
 	  const char *p = end;
-	  for ( ; *p-- != ']'; );
+	  for ( ; p != str && *p-- != ']'; );
 	  if (*p == '$')
 	    index_type = build_index_type (TREE_VALUE (size));
 	}
-      else  if (minsize)
+      else if (minsize)
 	index_type = build_index_type (size_int (minsize - 1));
 
       tree arat = NULL_TREE;
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 70b00037d98..c779d13f023 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -4151,18 +4151,12 @@ append_access_attr (tree node[3], tree attrs, const char *attrstr,
 				 "missing in previous designation",
 				 attrstr);
 	  else if (newa->internal_p || cura->internal_p)
-	    {
-	      /* Mismatch in the value of the size argument and a VLA
-		 bound.  */
-	      location_t argloc = curloc;
-	      if (tree arg = get_argument (node[2], newa->sizarg))
-		argloc = DECL_SOURCE_LOCATION (arg);
-	      warned = warning_at (argloc, OPT_Wattributes,
-				   "attribute %qs positional argument 2 "
-				   "conflicts with previous designation "
-				   "by argument %u",
-				   attrstr, cura->sizarg + 1);
-	    }
+	    /* Mismatch in the value of the size argument and a VLA bound.  */
+	    warned = warning_at (curloc, OPT_Wattributes,
+				 "attribute %qs positional argument 2 "
+				 "conflicts with previous designation "
+				 "by argument %u",
+				 attrstr, cura->sizarg + 1);
 	  else
 	    /* Mismatch in the value of the size argument between two
 	       explicit access attributes.  */
diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-6.c b/gcc/testsuite/gcc.dg/Wvla-parameter-6.c
new file mode 100644
index 00000000000..268aeec9251
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wvla-parameter-6.c
@@ -0,0 +1,34 @@
+/* PR middle-end/97189 - ICE on redeclaration of a function with VLA argument
+   and attribute access
+   Also verify the right arguments are underlined in the notes.
+   { dg-do compile }
+   { dg-options "-Wall -fdiagnostics-show-caret" } */
+
+#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__)))
+
+RW (2, 3) void f1 (int n, int[n], int);
+/* { dg-warning "attribute 'access \\(read_write, 2, 3\\)' positional argument 2 conflicts with previous designation by argument 3" "warning" { target *-*-* } .-1 }
+   { dg-begin-multiline-output "" }
+ RW (2, 3) void f1 (int n, int[n], int);
+                ^~
+   { dg-end-multiline-output "" }
+   { dg-message "designating the bound of variable length array argument 2" "note" { target *-*-* } .-6 }
+   { dg-begin-multiline-output "" }
+ RW (2, 3) void f1 (int n, int[n], int);
+                    ~~~~^  ~~~~~~
+   { dg-end-multiline-output "" } */
+
+
+RW (2)    void f2 (int, int[*], int);
+/* { dg-message "previously declared as a variable length array 'int\\\[\\\*]'" "note" { target *-*-* } .-1 }
+   { dg-begin-multiline-output "" }
+ RW (2, 3) void f2 (int, int[], int);
+                         ^~~~~
+   { dg-end-multiline-output "" } */
+
+RW (2, 3) void f2 (int, int[], int);
+/* { dg-warning "argument 2 of type 'int\\\[]' declared as an ordinary array" "warning" { target *-*-* } .-1 }
+   { dg-begin-multiline-output "" }
+ RW (2)    void f2 (int, int[*], int);
+                         ^~~~~~
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-7.c b/gcc/testsuite/gcc.dg/Wvla-parameter-7.c
new file mode 100644
index 00000000000..14ce75f3e2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wvla-parameter-7.c
@@ -0,0 +1,36 @@
+/* PR middle-end/97189 - ICE on redeclaration of a function with VLA argument
+   and attribute access
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__)))
+
+RW (2, 3) void f1 (int n, int[n], int);
+/* { dg-warning "attribute 'access \\(read_write, 2, 3\\)' positional argument 2 conflicts with previous designation by argument 3" "warning" { target *-*-* } .-1 }
+   { dg-message "designating the bound of variable length array argument 2" "note" { target *-*-* } .-2 } */
+
+void call_f1 (int *p)
+{
+  /* Verify that a warning is issued.  Ideally, it seems the VLA bound
+     should take precedence over the attribute and the warning would
+     reference argument 1 but since the conflict in the redeclarations
+     of the function is already diagnosed don't test that (and let it
+     be acceptable for this warning to reference argument 3).  */
+  f1 (-1, p, -1);
+  // { dg-warning "argument \\d value -1 is negative" "warning" { target *-*-* } .-1 }
+}
+
+RW (2)    void f2 (int, int[*], int);
+// { dg-message "previously declared as a variable length array 'int\\\[\\\*]'" "note" { target *-*-* } .-1 }
+RW (2, 3) void f2 (int, int[], int);
+// { dg-warning "argument 2 of type 'int\\\[]' declared as an ordinary array" "warning" { target *-*-* } .-1 }
+
+void call_f2 (int *p)
+{
+  f2 (-1, p, 0);
+
+  /* Verify that the attribute access on the redeclaration of f2() takes
+     precedence over the one on the first declaration.  */
+  f2 (0, p, -1);
+  // { dg-warning "argument 3 value -1 is negative" "warning" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/gcc.dg/attr-access-2.c b/gcc/testsuite/gcc.dg/attr-access-2.c
index 74762610f98..76baddffc9f 100644
--- a/gcc/testsuite/gcc.dg/attr-access-2.c
+++ b/gcc/testsuite/gcc.dg/attr-access-2.c
@@ -112,5 +112,11 @@ typedef void G1 (int n, int[n], int);
 
 G1 g1;
 
-RW (2, 3) void g1 (int n, int[n], int);     // { dg-warning "24: attribute 'access *\\\(read_write, 2, 3\\\)' positional argument 2 conflicts with previous designation by argument 3" }
-// { dg-message "designating the bound of variable length array argument 2" "note" { target *-*-* } .-1 }
+/* The warning is about the attribute positional argument 2 which refers
+   to the last function argument.  Ideally, the caret would be under
+   the corresponding function argument, i.e., the last one here) but
+   that location isn't available yet.  Verify that the caret doesn't
+   point to function argument 1 which is the VLA bound (that's what
+   the caret in the note points to).  */
+RW (2, 3) void g1 (int n, int[n], int);     // { dg-warning "16: attribute 'access *\\\(read_write, 2, 3\\\)' positional argument 2 conflicts with previous designation by argument 3" }
+// { dg-message "24:designating the bound of variable length array argument 2" "note" { target *-*-* } .-1 }

Reply via email to