diff mbox series

handle VLAs with arbitrary many bounds (PR 100619)

Message ID 98d354fa-d850-ef3f-993d-aee24700fdaf@gmail.com
State New
Headers show
Series handle VLAs with arbitrary many bounds (PR 100619) | expand

Commit Message

Martin Sebor May 19, 2021, 8:59 p.m. UTC
The GCC 11 -Warray-parameter and -Wvla-parameter enhancement uses
a small local buffer to format the description of the VLA bounds
for the internal attribute access.  When the number of bounds is
in excess of the size of the buffer the code asserts as the test
case in pr100619 shows.  The attached change does away with
the small buffer and instead formats the description into
the destination string itself, thus letting it handle VLAs with
arbitrarily many bounds.

Tested on x86_64-linux.

Martin

Comments

Joseph Myers May 19, 2021, 10:02 p.m. UTC | #1
On Wed, 19 May 2021, Martin Sebor via Gcc-patches wrote:

> The GCC 11 -Warray-parameter and -Wvla-parameter enhancement uses
> a small local buffer to format the description of the VLA bounds
> for the internal attribute access.  When the number of bounds is
> in excess of the size of the buffer the code asserts as the test
> case in pr100619 shows.  The attached change does away with
> the small buffer and instead formats the description into
> the destination string itself, thus letting it handle VLAs with
> arbitrarily many bounds.
> 
> Tested on x86_64-linux.

OK.
diff mbox series

Patch

PR c/100619 - ICE on a VLA parameter with too many dimensions

gcc/c-family/ChangeLog:

	PR c/100619
	* c-attribs.c (build_attr_access_from_parms): Handle arbitrarily many
	bounds.

gcc/testsuite/ChangeLog:

	PR c/100619
	* gcc.dg/pr100619.c: New test.

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index ecb32c70172..ccf9e4ccf0b 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -5043,16 +5043,25 @@  build_attr_access_from_parms (tree parms, bool skip_voidptr)
       /* Create the attribute access string from the arg spec string,
 	 optionally followed by position of the VLA bound argument if
 	 it is one.  */
-      char specbuf[80];
-      int len = snprintf (specbuf, sizeof specbuf, "%c%u%s",
-			  attr_access::mode_chars[access_deferred],
-			  argpos, s);
-      gcc_assert ((size_t) len < sizeof specbuf);
-
-      if (!spec.length ())
-	spec += '+';
+      {
+	size_t specend = spec.length ();
+	if (!specend)
+	  {
+	    spec = '+';
+	    specend = 1;
+	  }
 
-      spec += specbuf;
+	/* Format the access string in place.  */
+	int len = snprintf (NULL, 0, "%c%u%s",
+			    attr_access::mode_chars[access_deferred],
+			    argpos, s);
+	spec.resize (specend + len + 1);
+	sprintf (&spec[specend], "%c%u%s",
+		 attr_access::mode_chars[access_deferred],
+		 argpos, s);
+	/* Trim the trailing NUL.  */
+	spec.resize (specend + len);
+      }
 
       /* The (optional) list of expressions denoting the VLA bounds
 	 N in ARGTYPE <arg>[Ni]...[Nj]...[Nk].  */
@@ -5077,8 +5086,13 @@  build_attr_access_from_parms (tree parms, bool skip_voidptr)
 		{
 		  /* BOUND previously seen in the parameter list.  */
 		  TREE_PURPOSE (vb) = size_int (*psizpos);
-		  sprintf (specbuf, "$%u", *psizpos);
-		  spec += specbuf;
+		  /* Format the position string in place.  */
+		  int len = snprintf (NULL, 0, "$%u", *psizpos);
+		  size_t specend = spec.length ();
+		  spec.resize (specend + len + 1);
+		  sprintf (&spec[specend], "$%u", *psizpos);
+		  /* Trim the trailing NUL.  */
+		  spec.resize (specend + len);
 		}
 	      else
 		{
diff --git a/gcc/testsuite/gcc.dg/pr100619.c b/gcc/testsuite/gcc.dg/pr100619.c
new file mode 100644
index 00000000000..89b62938797
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr100619.c
@@ -0,0 +1,24 @@ 
+/* PR c/100619 - ICE on a VLA parameter with too many dimensions
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+extern int n;
+
+#define A10     [n][n][n][n][n][n][n][n][n][n]
+#define A100    A10 A10 A10 A10 A10 A10 A10 A10 A10 A10 A10
+#define A1000   A100 A100 A100 A100 A100 A100 A100 A100 A100 A100 A100
+
+void f10 (int A10);
+void f10 (int A10);
+
+void f100 (int A100);
+void f100 (int A100);
+
+void f1000 (int A1000);
+void f1000 (int A1000);
+
+void fx_1000 (int [ ]A1000);
+void fx_1000 (int [1]A1000);        // { dg-warning "-Warray-parameter=" }
+
+void fn_1000 (int [n    ]A1000);
+void fn_1000 (int [n + 1]A1000);    // { dg-warning "-Wvla-parameter=" }