diff mbox series

correct VLA bound traversal (PR 100719)

Message ID 2eebe09c-be23-317e-c2b4-0eb3273c5adb@gmail.com
State New
Headers show
Series correct VLA bound traversal (PR 100719) | expand

Commit Message

Martin Sebor May 26, 2021, 7:29 p.m. UTC
The -Wvla-parameter checking of the bounds of VLA parameters in
function redeclarations has a few bugs: a) it scans the string
that encodes the attribute access representation of the VLA
bounds from the end, failing to consider that the string may
be followed by another for a subsequent VLA, b) it fails to
consider that the chain of VLA bounds is stored in the reverse
order of arguments, and c) it tests the result of TREE_CHAIN
rather than TREE_PURPOSE to determine if a VLA bound has been
specified.  This can cause false negatives.

The attached change fixes these three problems.  It was tested
on x86_64-linux.

Martin

Comments

Jeff Law May 29, 2021, 4:44 p.m. UTC | #1
On 5/26/2021 1:29 PM, Martin Sebor via Gcc-patches wrote:
> The -Wvla-parameter checking of the bounds of VLA parameters in
> function redeclarations has a few bugs: a) it scans the string
> that encodes the attribute access representation of the VLA
> bounds from the end, failing to consider that the string may
> be followed by another for a subsequent VLA, b) it fails to
> consider that the chain of VLA bounds is stored in the reverse
> order of arguments, and c) it tests the result of TREE_CHAIN
> rather than TREE_PURPOSE to determine if a VLA bound has been
> specified.  This can cause false negatives.
>
> The attached change fixes these three problems.  It was tested
> on x86_64-linux.
>
> Martin
>
>
>
> gcc-100719.diff
>
> PR c/100719 - missing -Wvla-parameter on a mismatch in second parameter
>
> gcc/ChangeLog:
>
> 	* attribs.c (init_attr_rdwr_indices): Use VLA bounds in the expected
> 	order.
> 	(attr_access::vla_bounds): Also handle VLA bounds.
>
> gcc/c-family/ChangeLog:
>
> 	* c-warn.c (warn_parm_array_mismatch): Check TREE_PURPOSE to test
> 	for element presence.
>
> gcc/testsuite/ChangeLog:
>
> 	* gcc.dg/Wvla-parameter-10.c: New test.
> 	* gcc.dg/Wvla-parameter-11.c: New test.
OK
jeff
diff mbox series

Patch

PR c/100719 - missing -Wvla-parameter on a mismatch in second parameter

gcc/ChangeLog:

	* attribs.c (init_attr_rdwr_indices): Use VLA bounds in the expected
	order.
	(attr_access::vla_bounds): Also handle VLA bounds.

gcc/c-family/ChangeLog:

	* c-warn.c (warn_parm_array_mismatch): Check TREE_PURPOSE to test
	for element presence.

gcc/testsuite/ChangeLog:

	* gcc.dg/Wvla-parameter-10.c: New test.
	* gcc.dg/Wvla-parameter-11.c: New test.

diff --git a/gcc/attribs.c b/gcc/attribs.c
index ebc0783c439..70e0a2f188f 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -2126,14 +2126,14 @@  init_attr_rdwr_indices (rdwr_map *rwm, tree attrs)
 
       /* The (optional) list of VLA bounds.  */
       tree vblist = TREE_CHAIN (mode);
-      if (vblist)
-       vblist = TREE_VALUE (vblist);
-
       mode = TREE_VALUE (mode);
       if (TREE_CODE (mode) != STRING_CST)
 	continue;
       gcc_assert (TREE_CODE (mode) == STRING_CST);
 
+      if (vblist)
+	vblist = nreverse (copy_list (TREE_VALUE (vblist)));
+
       for (const char *m = TREE_STRING_POINTER (mode); *m; )
 	{
 	  attr_access acc = { };
@@ -2308,11 +2308,18 @@  attr_access::to_external_string () const
 unsigned
 attr_access::vla_bounds (unsigned *nunspec) const
 {
+  unsigned nbounds = 0;
   *nunspec = 0;
-  for (const char* p = strrchr (str, ']'); p && *p != '['; --p)
-    if (*p == '*')
-      ++*nunspec;
-  return list_length (size);
+  /* STR points to the beginning of the specified string for the current
+     argument that may be followed by the string for the next argument.  */
+  for (const char* p = strchr (str, ']'); p && *p != '['; --p)
+    {
+      if (*p == '*')
+	++*nunspec;
+      else if (*p == '$')
+	++nbounds;
+    }
+  return nbounds;
 }
 
 /* Reset front end-specific attribute access data from ATTRS.
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 2af2bc0a43f..f840f029f1c 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -3511,7 +3511,7 @@  warn_parm_array_mismatch (location_t origloc, tree fndecl, tree newparms)
 	  && newa->sizarg != UINT_MAX
 	  && newa->sizarg == cura->sizarg
 	  && newa->minsize == cura->minsize
-	  && !TREE_CHAIN (newa->size) && !TREE_CHAIN (cura->size))
+	  && !TREE_PURPOSE (newa->size) && !TREE_PURPOSE (cura->size))
 	continue;
 
       if (newa->size || cura->size)
diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-10.c b/gcc/testsuite/gcc.dg/Wvla-parameter-10.c
new file mode 100644
index 00000000000..68db3edfbc5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wvla-parameter-10.c
@@ -0,0 +1,68 @@ 
+/* PR c/100719 - missing -Wvla-parameter on a mismatch in second parameter
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+typedef struct A1 { int i; } A1;
+typedef struct A2 { int i; } A2;
+typedef struct A3 { int i; } A3;
+
+void f2 (int n, A1[n], A2[n]);
+void f2 (int n, A1[n], A2[n]);
+
+void f2_x1 (int n, A1[n],     A2[n]);   // { dg-note "previously declared as 'A1\\\[n]' with bound argument 1" }
+void f2_x1 (int n, A1[n + 1], A2[n]);   // { dg-warning "argument 2 of type 'A1\\\[n \\+ 1]' declared with mismatched bound 'n \\+ 1'" }
+
+void f2_x2 (int n, A1[n], A2[n]);       // { dg-note "previously declared as 'A2\\\[n]' with bound argument 1" }
+void f2_x2 (int n, A1[n], A2[n + 2]);   // { dg-warning "argument 3 of type 'A2\\\[n \\+ 2]' declared with mismatched bound 'n \\+ 2'" }
+
+
+void f3 (int n, A1[n], A2[n], A3[n]);
+void f3 (int n, A1[n], A2[n], A3[n]);
+
+void f3_x1 (int n, A1[n],     A2[n], A3[n]);
+// { dg-note "previously declared as 'A1\\\[n]' with bound argument 1" "note" { target *-*-* } .-1 }
+void f3_x1 (int n, A1[n + 1], A2[n], A3[n]);
+// { dg-warning "argument 2 of type 'A1\\\[n \\+ 1]' declared with mismatched bound 'n \\+ 1'" "" { target *-*-* } .-1 }
+
+void f3_x2 (int n, A1[n], A2[n],     A3[n]);
+// { dg-note "previously declared as 'A2\\\[n]' with bound argument 1" "note" { target *-*-* } .-1 }
+void f3_x2 (int n, A1[n], A2[n + 2], A3[n]);
+// { dg-warning "argument 3 of type 'A2\\\[n \\+ 2]' declared with mismatched bound 'n \\+ 2'" "" { target *-*-* } .-1 }
+
+void f3_x3 (int n, A1[n], A2[n], A3[n]);
+// { dg-note "previously declared as 'A3\\\[n]' with bound argument 1" "note" { target *-*-* } .-1 }
+void f3_x3 (int n, A1[n], A2[n], A3[n + 3]);
+// { dg-warning "argument 4 of type 'A3\\\[n \\+ 3]' declared with mismatched bound 'n \\+ 3'" "" { target *-*-* } .-1 }
+
+
+void g3_x1 (int n, A1[n],     A2[*], A3[n]);
+// { dg-note "previously declared as 'A1\\\[n]' with bound argument 1" "note" { target *-*-* } .-1 }
+void g3_x1 (int n, A1[n + 1], A2[*], A3[n]);
+// { dg-warning "argument 2 of type 'A1\\\[n \\+ 1]' declared with mismatched bound 'n \\+ 1'" "" { target *-*-* } .-1 }
+
+void g3_x2 (int n, A1[*], A2[n],     A3[n]);
+// { dg-note "previously declared as 'A2\\\[n]' with bound argument 1" "note" { target *-*-* } .-1 }
+void g3_x2 (int n, A1[*], A2[n + 2], A3[n]);
+// { dg-warning "argument 3 of type 'A2\\\[n \\+ 2]' declared with mismatched bound 'n \\+ 2'" "" { target *-*-* } .-1 }
+
+void g3_x3 (int n, A1[*], A2[*], A3[n]);
+// { dg-note "previously declared as 'A3\\\[n]' with bound argument 1" "note" { target *-*-* } .-1 }
+void g3_x3 (int n, A1[*], A2[*], A3[n + 3]);
+// { dg-warning "argument 4 of type 'A3\\\[n \\+ 3]' declared with mismatched bound 'n \\+ 3'" "" { target *-*-* } .-1 }
+
+
+void h3_x1 (int n, A1[n],     A2[ ], A3[n]);
+// { dg-note "previously declared as 'A1\\\[n]' with bound argument 1" "note" { target *-*-* } .-1 }
+void h3_x1 (int n, A1[n + 1], A2[ ], A3[n]);
+// { dg-warning "argument 2 of type 'A1\\\[n \\+ 1]' declared with mismatched bound 'n \\+ 1'" "" { target *-*-* } .-1 }
+
+void h3_x2 (int n, A1[ ], A2[n],     A3[n]);
+// { dg-note "previously declared as 'A2\\\[n]' with bound argument 1" "note" { target *-*-* } .-1 }
+void h3_x2 (int n, A1[ ], A2[n + 2], A3[n]);
+// { dg-warning "argument 3 of type 'A2\\\[n \\+ 2]' declared with mismatched bound 'n \\+ 2'" "" { target *-*-* } .-1 }
+
+void h3_x3 (int n, A1[ ], A2[ ], A3[n]);
+// { dg-note "previously declared as 'A3\\\[n]' with bound argument 1" "note" { target *-*-* } .-1 }
+void h3_x3 (int n, A1[ ], A2[ ], A3[n + 3]);
+// { dg-warning "argument 4 of type 'A3\\\[n \\+ 3]' declared with mismatched bound 'n \\+ 3'" "" { target *-*-* } .-1 }
+
diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-11.c b/gcc/testsuite/gcc.dg/Wvla-parameter-11.c
new file mode 100644
index 00000000000..39886a22d68
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wvla-parameter-11.c
@@ -0,0 +1,70 @@ 
+/* PR c/100719 - missing -Wvla-parameter on a mismatch in second parameter
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+typedef struct A1 { int i; } A1;
+typedef struct A2 { int i; } A2;
+typedef struct A3 { int i; } A3;
+
+extern int n, n1, n2, n3;
+
+void f2 (int, A1[n], A2[n]);
+void f2 (int, A1[n], A2[n]);
+
+void f2_x1 (int, A1[n],  A2[n]);        // { dg-note "previously declared as 'A1\\\[n]'" }
+void f2_x1 (int, A1[n1], A2[n]);        // { dg-warning "argument 2 of type 'A1\\\[n1]' declared with mismatched bound 'n1'" }
+
+void f2_x2 (int, A1[n], A2[n]);         // { dg-note "previously declared as 'A2\\\[n]'" }
+void f2_x2 (int, A1[n], A2[n2]);        // { dg-warning "argument 3 of type 'A2\\\[n2]' declared with mismatched bound 'n2'" }
+
+
+void f3 (int, A1[n], A2[n], A3[n]);
+void f3 (int, A1[n], A2[n], A3[n]);
+
+void f3_x1 (int, A1[n],  A2[n], A3[n]);
+// { dg-note "previously declared as 'A1\\\[n]'" "note" { target *-*-* } .-1 }
+void f3_x1 (int, A1[n1], A2[n], A3[n]);
+// { dg-warning "argument 2 of type 'A1\\\[n1]' declared with mismatched bound 'n1'" "" { target *-*-* } .-1 }
+
+void f3_x2 (int, A1[n], A2[n],  A3[n]);
+// { dg-note "previously declared as 'A2\\\[n]'" "note" { target *-*-* } .-1 }
+void f3_x2 (int, A1[n], A2[n2], A3[n]);
+// { dg-warning "argument 3 of type 'A2\\\[n2]' declared with mismatched bound 'n2'" "" { target *-*-* } .-1 }
+
+void f3_x3 (int, A1[n], A2[n], A3[n]);
+// { dg-note "previously declared as 'A3\\\[n]'" "note" { target *-*-* } .-1 }
+void f3_x3 (int, A1[n], A2[n], A3[n3]);
+// { dg-warning "argument 4 of type 'A3\\\[n3]' declared with mismatched bound 'n3'" "" { target *-*-* } .-1 }
+
+
+void g3_x1 (int, A1[n],  A2[*], A3[n]);
+// { dg-note "previously declared as 'A1\\\[n]'" "note" { target *-*-* } .-1 }
+void g3_x1 (int, A1[n1], A2[*], A3[n]);
+// { dg-warning "argument 2 of type 'A1\\\[n1]' declared with mismatched bound 'n1'" "" { target *-*-* } .-1 }
+
+void g3_x2 (int, A1[*], A2[n],  A3[n]);
+// { dg-note "previously declared as 'A2\\\[n]'" "note" { target *-*-* } .-1 }
+void g3_x2 (int, A1[*], A2[n2], A3[n]);
+// { dg-warning "argument 3 of type 'A2\\\[n2]' declared with mismatched bound 'n2'" "" { target *-*-* } .-1 }
+
+void g3_x3 (int, A1[*], A2[*], A3[n]);
+// { dg-note "previously declared as 'A3\\\[n]'" "note" { target *-*-* } .-1 }
+void g3_x3 (int, A1[*], A2[*], A3[n3]);
+// { dg-warning "argument 4 of type 'A3\\\[n3]' declared with mismatched bound 'n3'" "" { target *-*-* } .-1 }
+
+
+void h3_x1 (int, A1[n],  A2[ ], A3[n]);
+// { dg-note "previously declared as 'A1\\\[n]'" "note" { target *-*-* } .-1 }
+void h3_x1 (int, A1[n1], A2[ ], A3[n]);
+// { dg-warning "argument 2 of type 'A1\\\[n1]' declared with mismatched bound 'n1'" "" { target *-*-* } .-1 }
+
+void h3_x2 (int, A1[ ], A2[n],  A3[n]);
+// { dg-note "previously declared as 'A2\\\[n]'" "note" { target *-*-* } .-1 }
+void h3_x2 (int, A1[ ], A2[n2], A3[n]);
+// { dg-warning "argument 3 of type 'A2\\\[n2]' declared with mismatched bound 'n2'" "" { target *-*-* } .-1 }
+
+void h3_x3 (int, A1[ ], A2[ ], A3[n]);
+// { dg-note "previously declared as 'A3\\\[n]'" "note" { target *-*-* } .-1 }
+void h3_x3 (int, A1[ ], A2[ ], A3[n3]);
+// { dg-warning "argument 4 of type 'A3\\\[n3]' declared with mismatched bound 'n3'" "" { target *-*-* } .-1 }
+