re PR middle-end/79123 (incorrect -Walloca-larger-than: alloca may be too large due...
authorAldy Hernandez <aldyh@redhat.com>
Tue, 24 Jan 2017 09:50:33 +0000 (09:50 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Tue, 24 Jan 2017 09:50:33 +0000 (09:50 +0000)
PR middle-end/79123
* gimple-ssa-warn-alloca.c (alloca_call_type): Make sure
casts from signed to unsigned really don't have a range.

From-SVN: r244859

gcc/ChangeLog
gcc/gimple-ssa-warn-alloca.c
gcc/testsuite/gcc.dg/Walloca-13.c [new file with mode: 0644]

index 96def33bd56e5450c84fd0de9fd13ca61e9aeb14..e66fb836d68da4d4266411e64eae147f0bf95c1c 100644 (file)
@@ -1,3 +1,9 @@
+2017-01-24  Aldy Hernandez  <aldyh@redhat.com>
+
+       PR middle-end/79123
+       * gimple-ssa-warn-alloca.c (alloca_call_type): Make sure
+       casts from signed to unsigned really don't have a range.
+
 2017-01-24  Markus Trippelsdorf  <markus@trippelsdorf.de>
 
        * gimple-ssa-sprintf.c (format_floating): Change MPFR_RNDx to
index a27eea1fb4c16d4a236c50f5997f8b434ef80d82..d553a346bfee379dfe43d16e8a789111a9b21ad1 100644 (file)
@@ -272,6 +272,7 @@ static struct alloca_type_and_limit
 alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
 {
   gcc_assert (gimple_alloca_call_p (stmt));
+  bool tentative_cast_from_signed = false;
   tree len = gimple_call_arg (stmt, 0);
   tree len_casted = NULL;
   wide_int min, max;
@@ -352,8 +353,26 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
          // with this heuristic.  Hopefully, this VR_ANTI_RANGE
          // nonsense will go away, and we won't have to catch the
          // sign conversion problems with this crap.
+         //
+         // This is here to catch things like:
+         // void foo(signed int n) {
+         //   if (n < 100)
+         //     alloca(n);
+         //   ...
+         // }
          if (cast_from_signed_p (len, invalid_casted_type))
-           return alloca_type_and_limit (ALLOCA_CAST_FROM_SIGNED);
+           {
+             // Unfortunately this also triggers:
+             //
+             // __SIZE_TYPE__ n = (__SIZE_TYPE__)blah;
+             // if (n < 100)
+             //   alloca(n);
+             //
+             // ...which is clearly bounded.  So, double check that
+             // the paths leading up to the size definitely don't
+             // have a bound.
+             tentative_cast_from_signed = true;
+           }
        }
       // No easily determined range and try other things.
     }
@@ -371,10 +390,12 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
          ret = alloca_call_type_by_arg (len, len_casted,
                                         EDGE_PRED (bb, ix), max_size);
          if (ret.type != ALLOCA_OK)
-           return ret;
+           break;
        }
     }
 
+  if (tentative_cast_from_signed && ret.type != ALLOCA_OK)
+    return alloca_type_and_limit (ALLOCA_CAST_FROM_SIGNED);
   return ret;
 }
 
diff --git a/gcc/testsuite/gcc.dg/Walloca-13.c b/gcc/testsuite/gcc.dg/Walloca-13.c
new file mode 100644 (file)
index 0000000..f9bdcef
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-Walloca-larger-than=100 -O2" } */
+
+void f (void*);
+
+void g (int *p, int *q)
+{
+  __SIZE_TYPE__ n = (__SIZE_TYPE__)(p - q);
+  if (n < 100)
+    f (__builtin_alloca (n));
+}