toolchain: gcc: backport v11.3.0 fix for false positive VLA params warnings
authorAndrey Erokhin <a.erokhin@inango-systems.com>
Wed, 22 Mar 2023 15:27:01 +0000 (16:27 +0100)
committerChristian Marangi <ansuelsmth@gmail.com>
Thu, 2 Nov 2023 17:45:50 +0000 (18:45 +0100)
If the vla parameter has a const specifier, the compiler will warn about
mismatched bounds:

 $ cat mwe.c
 extern void mwe(const int len, char buf[len]);
 void mwe(const int len, char buf[len]) {}

 $ make CFLAGS=-Wvla-parameter mwe.o
 cc -Wvla-parameter   -c -o mwe.o mwe.c
 mwe.c:2:30: warning: argument 2 of type ‘char[len]’ declared with mismatched bound ‘len’ [-Wvla-parameter]
     2 | void mwe(const int len, char buf[len]) {}
       |                         ~~~~~^~~~~~~~
 mwe.c:1:37: note: previously declared as ‘char[len]’ with bound ‘len’
     1 | extern void mwe(const int len, char buf[len]);
       |                                ~~~~~^~~~~~~~

On some code bases it might result in a lot of false positive warnings,
which can indeed be easily disabled, but on the other this workaround
might hide some real issues, so lets rather fix the compiler and make it
more reliable.

References: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101289
Signed-off-by: Andrey Erokhin <a.erokhin@inango-systems.com>
Signed-off-by: Petr Štetiar <ynezz@true.cz> [commit message]
toolchain/gcc/patches/11.2.0/400-v11.3.0-bogus-Wvla-parameter.patch [new file with mode: 0644]

diff --git a/toolchain/gcc/patches/11.2.0/400-v11.3.0-bogus-Wvla-parameter.patch b/toolchain/gcc/patches/11.2.0/400-v11.3.0-bogus-Wvla-parameter.patch
new file mode 100644 (file)
index 0000000..443839f
--- /dev/null
@@ -0,0 +1,192 @@
+From 7d3f53c595e1766ca0494e5f56f33b0ce49b3bb4 Mon Sep 17 00:00:00 2001
+From: Martin Sebor <msebor@redhat.com>
+Date: Thu, 15 Jul 2021 10:11:23 -0600
+Subject: [PATCH] Avoid -Wvla-parameter for nontrivial bounds [PR97548].
+
+Resolves:
+PR c/101289 - bogus -Wvla-paramater warning when using const for vla param
+PR c/97548 -  bogus -Wvla-parameter on a bound expression involving a parameter
+
+gcc/c-family/ChangeLog:
+
+       PR c/101289
+       PR c/97548
+       * c-warn.c (warn_parm_array_mismatch): Use OEP_DECL_NAME.
+
+gcc/c/ChangeLog:
+
+       PR c/101289
+       PR c/97548
+       * c-decl.c (get_parm_array_spec): Strip nops.
+
+gcc/ChangeLog:
+
+       PR c/101289
+       PR c/97548
+       * fold-const.c (operand_compare::operand_equal_p): Handle OEP_DECL_NAME.
+       (operand_compare::verify_hash_value): Same.
+       * tree-core.h (OEP_DECL_NAME): New.
+
+gcc/testsuite/ChangeLog:
+
+       * gcc.dg/Wvla-parameter-12.c: New test.
+---
+ gcc/c-family/c-warn.c                    |  3 +-
+ gcc/c/c-decl.c                           |  1 +
+ gcc/fold-const.c                         | 33 ++++++++++++++++------
+ gcc/testsuite/gcc.dg/Wvla-parameter-12.c | 36 ++++++++++++++++++++++++
+ gcc/tree-core.h                          |  7 ++++-
+ 5 files changed, 69 insertions(+), 11 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/Wvla-parameter-12.c
+
+diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
+index 7414063aa11..250da89a829 100644
+--- a/gcc/c-family/c-warn.c
++++ b/gcc/c-family/c-warn.c
+@@ -3646,7 +3646,8 @@ warn_parm_array_mismatch (location_t origloc, tree fndecl, tree newparms)
+             /* The VLA bounds don't refer to other function parameters.
+                Compare them lexicographically to detect gross mismatches
+                such as between T[foo()] and T[bar()].  */
+-            if (operand_equal_p (newbnd, curbnd, OEP_LEXICOGRAPHIC))
++            if (operand_equal_p (newbnd, curbnd,
++                                 OEP_DECL_NAME | OEP_LEXICOGRAPHIC))
+               continue;
+             if (warning_at (newloc, OPT_Wvla_parameter,
+diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
+index 53b2b5b637d..ddef9c68fb7 100644
+--- a/gcc/c/c-decl.c
++++ b/gcc/c/c-decl.c
+@@ -5862,6 +5862,7 @@ get_parm_array_spec (const struct c_parm *parm, tree 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/fold-const.c b/gcc/fold-const.c
+index a1d08c74025..f5c19a0cfd4 100644
+--- a/gcc/fold-const.c
++++ b/gcc/fold-const.c
+@@ -3506,11 +3506,26 @@ operand_compare::operand_equal_p (const_tree arg0, const_tree arg1,
+     case tcc_declaration:
+       /* Consider __builtin_sqrt equal to sqrt.  */
+-      return (TREE_CODE (arg0) == FUNCTION_DECL
+-            && fndecl_built_in_p (arg0) && fndecl_built_in_p (arg1)
+-            && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
+-            && (DECL_UNCHECKED_FUNCTION_CODE (arg0)
+-                == DECL_UNCHECKED_FUNCTION_CODE (arg1)));
++      if (TREE_CODE (arg0) == FUNCTION_DECL)
++      return (fndecl_built_in_p (arg0) && fndecl_built_in_p (arg1)
++              && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
++              && (DECL_UNCHECKED_FUNCTION_CODE (arg0)
++                  == DECL_UNCHECKED_FUNCTION_CODE (arg1)));
++
++      if (DECL_P (arg0)
++        && (flags & OEP_DECL_NAME)
++        && (flags & OEP_LEXICOGRAPHIC))
++      {
++        /* Consider decls with the same name equal.  The caller needs
++           to make sure they refer to the same entity (such as a function
++           formal parameter).  */
++        tree a0name = DECL_NAME (arg0);
++        tree a1name = DECL_NAME (arg1);
++        const char *a0ns = a0name ? IDENTIFIER_POINTER (a0name) : NULL;
++        const char *a1ns = a1name ? IDENTIFIER_POINTER (a1name) : NULL;
++        return a0ns && a1ns && strcmp (a0ns, a1ns) == 0;
++      }
++      return false;
+     case tcc_exceptional:
+       if (TREE_CODE (arg0) == CONSTRUCTOR)
+@@ -3921,14 +3936,14 @@ bool
+ operand_compare::verify_hash_value (const_tree arg0, const_tree arg1,
+                                   unsigned int flags, bool *ret)
+ {
+-  /* When checking, verify at the outermost operand_equal_p call that
+-     if operand_equal_p returns non-zero then ARG0 and ARG1 has the same
+-     hash value.  */
++  /* When checking and unless comparing DECL names, verify that if
++     the outermost operand_equal_p call returns non-zero then ARG0
++     and ARG1 have the same hash value.  */
+   if (flag_checking && !(flags & OEP_NO_HASH_CHECK))
+     {
+       if (operand_equal_p (arg0, arg1, flags | OEP_NO_HASH_CHECK))
+       {
+-        if (arg0 != arg1)
++        if (arg0 != arg1 && !(flags & OEP_DECL_NAME))
+           {
+             inchash::hash hstate0 (0), hstate1 (0);
+             hash_operand (arg0, hstate0, flags | OEP_HASH_CHECK);
+diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-12.c b/gcc/testsuite/gcc.dg/Wvla-parameter-12.c
+new file mode 100644
+index 00000000000..1be5e48203b
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/Wvla-parameter-12.c
+@@ -0,0 +1,36 @@
++/* PR c/101289 - bogus -Wvla-parameter warning when using const bound
++   { dg-do compile }
++   { dg-options "-Wall" } */
++
++void f1ci_can (const int n, char a[n]);
++void f1ci_can (const int n, char a[n]); // { dg-bogus "-Wvla-parameter" }
++
++void f2ci_can (const int m, char a[m]);
++void f2ci_can (int n,       char a[n]); // { dg-bogus "-Wvla-parameter" }
++
++void f3i_can (int n,       char a[n]);
++void f3i_can (const int n, char a[n]);  // { dg-bogus "-Wvla-parameter" }
++
++void f4i_can (int n,       char a[n]);
++void f4i_can (const int n, char a[(int)n]);   // { dg-bogus "-Wvla-parameter" }
++
++void f5i_can (int n,       char a[(char)n]);
++void f5i_can (const int n, char a[(char)n]);  // { dg-bogus "-Wvla-parameter" }
++
++void f6i_can (int m,       char a[(char)m]);
++void f6i_can (const int n, char a[(char)n]);  // { dg-bogus "-Wvla-parameter" "" { xfail *-*-* } }
++
++
++/* PR c/97548 - bogus -Wvla-parameter on a bound expression involving
++   a parameter */
++
++int n;
++
++void f7ianp1 (int, int[n + 1]);
++void f7ianp1 (int, int[n + 1]);
++void f7ianp1 (int, int[n + 2]);         // { dg-warning "-Wvla-parameter" }
++
++void f8iakp1 (int k, int [k + 1]);
++void f8iakp1 (int k, int [k + 1]);      // { dg-bogus "-Wvla-parameter" }
++void f8iakp1 (int k, int [1 + k]);      // { dg-bogus "-Wvla-parameter" }
++void f8iakp1 (int k, int [k + 2]);      // { dg-warning "-Wvla-parameter" }
+diff --git a/gcc/tree-core.h b/gcc/tree-core.h
+index 07ddf91a230..c31b8ebf249 100644
+--- a/gcc/tree-core.h
++++ b/gcc/tree-core.h
+@@ -885,6 +885,7 @@ enum size_type_kind {
+   stk_type_kind_last
+ };
++/* Flags controlling operand_equal_p() behavior.  */
+ enum operand_equal_flag {
+   OEP_ONLY_CONST = 1,
+   OEP_PURE_SAME = 2,
+@@ -899,7 +900,11 @@ enum operand_equal_flag {
+   OEP_BITWISE = 128,
+   /* For OEP_ADDRESS_OF of COMPONENT_REFs, only consider same fields as
+      equivalent rather than also different fields with the same offset.  */
+-  OEP_ADDRESS_OF_SAME_FIELD = 256
++  OEP_ADDRESS_OF_SAME_FIELD = 256,
++  /* In conjunction with OEP_LEXICOGRAPHIC considers names of declarations
++     of the same kind.  Used to compare VLA bounds involving parameters
++     across redeclarations of the same function.  */
++  OEP_DECL_NAME = 512
+ };
+ /* Enum and arrays used for tree allocation stats.
+-- 
+2.31.1
+