diff options
author | Martin Sebor <msebor@redhat.com> | 2018-08-28 19:09:38 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2018-08-28 13:09:38 -0600 |
commit | 0aaafa5e95df44eed3ad67ea65c9afda2dbdd493 (patch) | |
tree | dbf4c33008642719c398d068222b45cd34a970c4 /gcc/gimple-ssa-warn-alloca.c | |
parent | dd35da2cbef6d8bf9db86d7e66faeebb5022c881 (diff) | |
download | gcc-0aaafa5e95df44eed3ad67ea65c9afda2dbdd493.zip gcc-0aaafa5e95df44eed3ad67ea65c9afda2dbdd493.tar.gz gcc-0aaafa5e95df44eed3ad67ea65c9afda2dbdd493.tar.bz2 |
PR middle-end/86631 - missing -Walloc-size-larger-than on ILP32 hosts
gcc/ChangeLog:
PR middle-end/86631
* calls.c (alloc_max_size): Treat HOST_WIDE_INT special.
* gimple-ssa-warn-alloca.c (adjusted_warn_limit): New function.
(pass_walloca::gate): Use it.
(alloca_call_type): Same.
(pass_walloca::execute): Same.
* stor-layout.c (layout_decl): Treat HOST_WIDE_INT special.
gcc/testsuite/ChangeLog:
PR middle-end/86631
* g++.dg/Walloca1.C: Adjust.
From-SVN: r263928
Diffstat (limited to 'gcc/gimple-ssa-warn-alloca.c')
-rw-r--r-- | gcc/gimple-ssa-warn-alloca.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c index 4347707..4d5aed8 100644 --- a/gcc/gimple-ssa-warn-alloca.c +++ b/gcc/gimple-ssa-warn-alloca.c @@ -38,6 +38,8 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "intl.h" +static unsigned HOST_WIDE_INT adjusted_warn_limit (bool); + const pass_data pass_data_walloca = { GIMPLE_PASS, "walloca", @@ -82,7 +84,9 @@ pass_walloca::gate (function *fun ATTRIBUTE_UNUSED) // 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. - return warn_alloca_limit >= 0 || warn_vla_limit >= 0; + unsigned HOST_WIDE_INT max = tree_to_uhwi (TYPE_MAX_VALUE (ptrdiff_type_node)); + return (adjusted_warn_limit (false) <= max + || adjusted_warn_limit (true) <= max); } // Possible problematic uses of alloca. @@ -127,6 +131,30 @@ struct alloca_type_and_limit { alloca_type_and_limit (enum alloca_type type) : type(type) { } }; +/* Return the value of the argument N to -Walloca-larger-than= or + -Wvla-larger-than= adjusted for the target data model so that + when N == HOST_WIDE_INT_MAX, the adjusted value is set to + PTRDIFF_MAX on the target. This is done to prevent warnings + for unknown/unbounded allocations in the "permissive mode" + while still diagnosing excessive and necessarily invalid + allocations. */ + +static unsigned HOST_WIDE_INT +adjusted_warn_limit (bool idx) +{ + static HOST_WIDE_INT limits[2]; + if (limits[idx]) + return limits[idx]; + + limits[idx] = idx ? warn_vla_limit : warn_alloca_limit; + if (limits[idx] != HOST_WIDE_INT_MAX) + return limits[idx]; + + limits[idx] = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node)); + return limits[idx]; +} + + // NOTE: When we get better range info, this entire function becomes // irrelevant, as it should be possible to get range info for an SSA // name at any point in the program. @@ -309,11 +337,7 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type) // Adjust warn_alloca_max_size for VLAs, by taking the underlying // type into account. - unsigned HOST_WIDE_INT max_size; - if (is_vla) - max_size = warn_vla_limit; - else - max_size = warn_alloca_limit; + unsigned HOST_WIDE_INT max_size = adjusted_warn_limit (is_vla); // Check for the obviously bounded case. if (TREE_CODE (len) == INTEGER_CST) @@ -510,6 +534,8 @@ pass_walloca::execute (function *fun) struct alloca_type_and_limit t = alloca_call_type (stmt, is_vla, &invalid_casted_type); + unsigned HOST_WIDE_INT adjusted_alloca_limit + = adjusted_warn_limit (false); // Even if we think the alloca call is OK, make sure it's not in a // loop, except for a VLA, since VLAs are guaranteed to be cleaned // up when they go out of scope, including in a loop. @@ -519,8 +545,7 @@ pass_walloca::execute (function *fun) is less than the maximum valid object size. */ const offset_int maxobjsize = wi::to_offset (max_object_size ()); - if ((unsigned HOST_WIDE_INT) warn_alloca_limit - < maxobjsize.to_uhwi ()) + if (adjusted_alloca_limit < maxobjsize.to_uhwi ()) t = alloca_type_and_limit (ALLOCA_IN_LOOP); } @@ -544,7 +569,8 @@ pass_walloca::execute (function *fun) print_decu (t.limit, buff); inform (loc, G_("limit is %wu bytes, but argument " "may be as large as %s"), - is_vla ? warn_vla_limit : warn_alloca_limit, buff); + is_vla ? warn_vla_limit : adjusted_alloca_limit, + buff); } } break; @@ -559,7 +585,7 @@ pass_walloca::execute (function *fun) { print_decu (t.limit, buff); inform (loc, G_("limit is %wu bytes, but argument is %s"), - is_vla ? warn_vla_limit : warn_alloca_limit, + is_vla ? warn_vla_limit : adjusted_alloca_limit, buff); } } |