Avoid -Walloca-larger-than and -Wvla-larger-than false postives and negatives.
authorMartin Sebor <msebor@redhat.com>
Mon, 10 May 2021 20:00:04 +0000 (14:00 -0600)
committerMartin Sebor <msebor@redhat.com>
Mon, 10 May 2021 20:02:35 +0000 (14:02 -0600)
Resolves:
PR middle-end/100425 - missing -Walloca-larger-than with -O0
PR middle-end/100510 - bogus -Wvla-large-than with -Walloca

gcc/ChangeLog:

PR middle-end/100425
PR middle-end/100510
* gimple-ssa-warn-alloca.c (pass_walloca::firast_time_p): Rename...
(pass_walloca::xlimit_certain_p): ...to this.
(pass_walloca::gate): Execute for any kind of handled warning.
(pass_walloca::execute): Avoid issuing "maybe" and "unbounded"
warnings when xlimit_certain_p is set.

gcc/testsuite/ChangeLog:

PR middle-end/100425
PR middle-end/100510
* c-c++-common/Walloca-larger-than.C: New test.
* gcc.dg/Walloca-larger-than-4.c: New test.
* gcc.dg/Wvla-larger-than-5.c: New test.
* gcc.dg/pr79972.c: Remove unexpected warning directive.

gcc/gimple-ssa-warn-alloca.c
gcc/testsuite/c-c++-common/Walloca-larger-than.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/Walloca-larger-than-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wvla-larger-than-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr79972.c

index 42c0ba1..e9a24d4 100644 (file)
@@ -56,31 +56,30 @@ class pass_walloca : public gimple_opt_pass
 {
 public:
   pass_walloca (gcc::context *ctxt)
-    : gimple_opt_pass(pass_data_walloca, ctxt), first_time_p (false)
+    : gimple_opt_pass(pass_data_walloca, ctxt), xlimit_certain_p (false)
   {}
   opt_pass *clone () { return new pass_walloca (m_ctxt); }
   void set_pass_param (unsigned int n, bool param)
     {
       gcc_assert (n == 0);
-      first_time_p = param;
+      // Set to true to enable only warnings for alloca calls that
+      // are certainly in excess of the limit.  This includes calls
+      // with constant arguments but excludes those in ranges (that
+      // can only be determined by range analysis) as well as
+      // the "may be too large" kind.
+      xlimit_certain_p = param;
     }
   virtual bool gate (function *);
   virtual unsigned int execute (function *);
 
  private:
   // Set to TRUE the first time we run this pass on a function.
-  bool first_time_p;
+  bool xlimit_certain_p;
 };
 
 bool
 pass_walloca::gate (function *fun ATTRIBUTE_UNUSED)
 {
-  // The first time this pass is called, it is called before
-  // optimizations have been run and range information is unavailable,
-  // so we can only perform strict alloca checking.
-  if (first_time_p)
-    return warn_alloca != 0;
-
   // Warning is disabled when its size limit is greater than PTRDIFF_MAX
   // for the target maximum, which makes the limit negative since when
   // represented in signed HOST_WIDE_INT.
@@ -317,6 +316,9 @@ pass_walloca::execute (function *fun)
              break;
            case ALLOCA_BOUND_MAYBE_LARGE:
              {
+               if (xlimit_certain_p)
+                 break;
+
                auto_diagnostic_group d;
                if (warning_at (loc, wcode,
                                (is_vla
@@ -354,6 +356,9 @@ pass_walloca::execute (function *fun)
              }
              break;
            case ALLOCA_UNBOUNDED:
+             if (xlimit_certain_p)
+               break;
+
              warning_at (loc, wcode,
                          (is_vla
                           ? G_("%Gunbounded use of variable-length array")
diff --git a/gcc/testsuite/c-c++-common/Walloca-larger-than.C b/gcc/testsuite/c-c++-common/Walloca-larger-than.C
new file mode 100644 (file)
index 0000000..464ea24
--- /dev/null
@@ -0,0 +1,21 @@
+/* PR middle-end/100425 - missing -Walloca-larger-than with -O0
+   { dg-do compile }
+   { dg-options "-O0 -Wall -Walloca-larger-than=128" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+#if __cplusplus
+extern "C"
+#endif
+
+void* alloca (size_t);
+
+void sink (void*);
+
+void warn_alloca_too_large (void)
+{
+  sink (alloca (1));
+  sink (alloca (128));
+  sink (alloca (129));    // { dh-warning "\\\[-Walloca-larger-than" }
+  sink (alloca (1024));   // { dh-warning "\\\[-Walloca-larger-than" }
+}
diff --git a/gcc/testsuite/gcc.dg/Walloca-larger-than-4.c b/gcc/testsuite/gcc.dg/Walloca-larger-than-4.c
new file mode 100644 (file)
index 0000000..9d4c4e8
--- /dev/null
@@ -0,0 +1,18 @@
+/* PR middle-end/100425 - missing -Walloca-larger-than with -O0
+   { dg-do compile }
+   { dg-options "-O0 -Wall -Walloca-larger-than=128" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* alloca (size_t);
+
+void sink (void*);
+
+void warn_alloca_too_large (void)
+{
+  sink (alloca (1));
+  sink (alloca (128));
+  sink (alloca (129));        // { dg-warning "\\\[-Walloca-larger-than" }
+  sink (alloca (128 + 2));    // { dg-warning "\\\[-Walloca-larger-than" }
+  sink (alloca (1024));       // { dg-warning "\\\[-Walloca-larger-than" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wvla-larger-than-5.c b/gcc/testsuite/gcc.dg/Wvla-larger-than-5.c
new file mode 100644 (file)
index 0000000..c131f83
--- /dev/null
@@ -0,0 +1,38 @@
+/* PR middle-end/100510 - bogus -Wvla-large-than with -Walloca
+   { dg-do compile }
+   { dg-options "-O0 -Walloca -Wvla-larger-than=1000" } */
+
+void f (void*);
+
+#pragma GCC optimize ("0")
+
+void nowarn_O0 (__SIZE_TYPE__ n)
+{
+  if (n > 32)
+    return;
+
+  char a[n];                  // { dg-bogus "\\\[-Wvla-larger-than=" }
+  f (a);
+}
+
+#pragma GCC optimize ("1")
+
+void nowarn_O1 (__SIZE_TYPE__ n)
+{
+  if (n > 33)
+    return;
+
+  char a[n];                  // { dg-bogus "\\\[-Wvla-larger-than=" }
+  f (a);
+}
+
+#pragma GCC optimize ("2")
+
+void nowarn_O2 (__SIZE_TYPE__ n)
+{
+  if (n > 34)
+    return;
+
+  char a[n];                  // { dg-bogus "\\\[-Wvla-larger-than=" }
+  f (a);
+}
index 1d2b8be..4d3064f 100644 (file)
@@ -6,7 +6,8 @@
 int
 f (int dim, int *b, int *c)
 {
-  int newcentroid[3][dim];     /* { dg-warning "unbounded use of variable-length array" } */
+  /* -Wvla-larger-than is only issued with optimization (see PR 100510).  */
+  int newcentroid[3][dim];
   int *a = newcentroid[2];
   int i, dist = 0;
   __builtin_memcpy (newcentroid, c, sizeof (newcentroid));