aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-ssa-warn-alloca.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-08-28 19:09:38 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2018-08-28 13:09:38 -0600
commit0aaafa5e95df44eed3ad67ea65c9afda2dbdd493 (patch)
treedbf4c33008642719c398d068222b45cd34a970c4 /gcc/gimple-ssa-warn-alloca.c
parentdd35da2cbef6d8bf9db86d7e66faeebb5022c881 (diff)
downloadgcc-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.c46
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);
}
}