From 0aaafa5e95df44eed3ad67ea65c9afda2dbdd493 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 28 Aug 2018 19:09:38 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 10 +++++++++ gcc/calls.c | 7 +++++-- gcc/gimple-ssa-warn-alloca.c | 46 ++++++++++++++++++++++++++++++++--------- gcc/stor-layout.c | 19 ++++++++++------- gcc/testsuite/g++.dg/Walloca1.C | 6 ++++-- 5 files changed, 67 insertions(+), 21 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3ff21c3..b4b56da 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2018-08-28 Martin Sebor + + 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. + 2018-08-28 David Malcolm * dumpfile.h (ATTRIBUTE_GCC_DUMP_PRINTF): Change version check on diff --git a/gcc/calls.c b/gcc/calls.c index 87e3f00..e9660b6 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1222,8 +1222,11 @@ alloc_max_size (void) if (alloc_object_size_limit) return alloc_object_size_limit; - alloc_object_size_limit - = build_int_cst (size_type_node, warn_alloc_size_limit); + HOST_WIDE_INT limit = warn_alloc_size_limit; + if (limit == HOST_WIDE_INT_MAX) + limit = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node)); + + alloc_object_size_limit = build_int_cst (size_type_node, limit); return alloc_object_size_limit; } 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); } } diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 85937d0..088f360 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -760,14 +760,19 @@ layout_decl (tree decl, unsigned int known_align) { tree size = DECL_SIZE_UNIT (decl); - if (size != 0 && TREE_CODE (size) == INTEGER_CST - && compare_tree_int (size, warn_larger_than_size) > 0) + if (size != 0 && TREE_CODE (size) == INTEGER_CST) { - unsigned HOST_WIDE_INT uhwisize = tree_to_uhwi (size); - - warning (OPT_Wlarger_than_, "size of %q+D %wu bytes exceeds " - "maximum object size %wu", - decl, uhwisize, warn_larger_than_size); + /* -Wlarger-than= argument of HOST_WIDE_INT_MAX is treated + as if PTRDIFF_MAX had been specified, with the value + being that on the target rather than the host. */ + unsigned HOST_WIDE_INT max_size = warn_larger_than_size; + if (max_size == HOST_WIDE_INT_MAX) + max_size = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node)); + + if (compare_tree_int (size, max_size) > 0) + warning (OPT_Wlarger_than_, "size of %q+D %E bytes exceeds " + "maximum object size %wu", + decl, size, max_size); } } diff --git a/gcc/testsuite/g++.dg/Walloca1.C b/gcc/testsuite/g++.dg/Walloca1.C index b860a42..2985ac9 100644 --- a/gcc/testsuite/g++.dg/Walloca1.C +++ b/gcc/testsuite/g++.dg/Walloca1.C @@ -1,7 +1,9 @@ -/* PR middle-end/79809 */ +/* PR middle-end/79809 - ICE in alloca_call_type, at gimple-ssa-warn-alloca.c */ /* { dg-do compile } */ /* { dg-options "-Walloca-larger-than=4207115063 -Wvla-larger-than=1233877270 -O2" } */ /* { dg-require-effective-target alloca } */ int a; -char *b = static_cast(__builtin_alloca (a)); // { dg-warning "argument to .alloca. may be too large|unbounded use of" } +char *b = static_cast(__builtin_alloca (a)); + +// { dg-prune-output "argument to .alloca." } -- 2.7.4