diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c index 42c0ba1d87b..e9a24d4d1d0 100644 --- a/gcc/gimple-ssa-warn-alloca.c +++ b/gcc/gimple-ssa-warn-alloca.c @@ -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 index 00000000000..464ea242a7a --- /dev/null +++ b/gcc/testsuite/c-c++-common/Walloca-larger-than.C @@ -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 index 00000000000..9d4c4e8d062 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Walloca-larger-than-4.c @@ -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 index 00000000000..c131f837a1b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-larger-than-5.c @@ -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); +} diff --git a/gcc/testsuite/gcc.dg/pr79972.c b/gcc/testsuite/gcc.dg/pr79972.c index 1d2b8befb26..4d3064fb5d6 100644 --- a/gcc/testsuite/gcc.dg/pr79972.c +++ b/gcc/testsuite/gcc.dg/pr79972.c @@ -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));