Commit 0aaafa5e by Martin Sebor Committed by Martin Sebor

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
parent dd35da2c
2018-08-28 Martin Sebor <msebor@redhat.com>
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 <dmalcolm@redhat.com> 2018-08-28 David Malcolm <dmalcolm@redhat.com>
* dumpfile.h (ATTRIBUTE_GCC_DUMP_PRINTF): Change version check on * dumpfile.h (ATTRIBUTE_GCC_DUMP_PRINTF): Change version check on
......
...@@ -1222,8 +1222,11 @@ alloc_max_size (void) ...@@ -1222,8 +1222,11 @@ alloc_max_size (void)
if (alloc_object_size_limit) if (alloc_object_size_limit)
return alloc_object_size_limit; return alloc_object_size_limit;
alloc_object_size_limit HOST_WIDE_INT limit = warn_alloc_size_limit;
= build_int_cst (size_type_node, 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; return alloc_object_size_limit;
} }
......
...@@ -38,6 +38,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -38,6 +38,8 @@ along with GCC; see the file COPYING3. If not see
#include "cfgloop.h" #include "cfgloop.h"
#include "intl.h" #include "intl.h"
static unsigned HOST_WIDE_INT adjusted_warn_limit (bool);
const pass_data pass_data_walloca = { const pass_data pass_data_walloca = {
GIMPLE_PASS, GIMPLE_PASS,
"walloca", "walloca",
...@@ -82,7 +84,9 @@ pass_walloca::gate (function *fun ATTRIBUTE_UNUSED) ...@@ -82,7 +84,9 @@ pass_walloca::gate (function *fun ATTRIBUTE_UNUSED)
// Warning is disabled when its size limit is greater than PTRDIFF_MAX // Warning is disabled when its size limit is greater than PTRDIFF_MAX
// for the target maximum, which makes the limit negative since when // for the target maximum, which makes the limit negative since when
// represented in signed HOST_WIDE_INT. // 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. // Possible problematic uses of alloca.
...@@ -127,6 +131,30 @@ struct alloca_type_and_limit { ...@@ -127,6 +131,30 @@ struct alloca_type_and_limit {
alloca_type_and_limit (enum alloca_type type) : type(type) { } 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 // NOTE: When we get better range info, this entire function becomes
// irrelevant, as it should be possible to get range info for an SSA // irrelevant, as it should be possible to get range info for an SSA
// name at any point in the program. // name at any point in the program.
...@@ -309,11 +337,7 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type) ...@@ -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 // Adjust warn_alloca_max_size for VLAs, by taking the underlying
// type into account. // type into account.
unsigned HOST_WIDE_INT max_size; unsigned HOST_WIDE_INT max_size = adjusted_warn_limit (is_vla);
if (is_vla)
max_size = warn_vla_limit;
else
max_size = warn_alloca_limit;
// Check for the obviously bounded case. // Check for the obviously bounded case.
if (TREE_CODE (len) == INTEGER_CST) if (TREE_CODE (len) == INTEGER_CST)
...@@ -510,6 +534,8 @@ pass_walloca::execute (function *fun) ...@@ -510,6 +534,8 @@ pass_walloca::execute (function *fun)
struct alloca_type_and_limit t struct alloca_type_and_limit t
= alloca_call_type (stmt, is_vla, &invalid_casted_type); = 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 // 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 // loop, except for a VLA, since VLAs are guaranteed to be cleaned
// up when they go out of scope, including in a loop. // up when they go out of scope, including in a loop.
...@@ -519,8 +545,7 @@ pass_walloca::execute (function *fun) ...@@ -519,8 +545,7 @@ pass_walloca::execute (function *fun)
is less than the maximum valid object size. */ is less than the maximum valid object size. */
const offset_int maxobjsize const offset_int maxobjsize
= wi::to_offset (max_object_size ()); = wi::to_offset (max_object_size ());
if ((unsigned HOST_WIDE_INT) warn_alloca_limit if (adjusted_alloca_limit < maxobjsize.to_uhwi ())
< maxobjsize.to_uhwi ())
t = alloca_type_and_limit (ALLOCA_IN_LOOP); t = alloca_type_and_limit (ALLOCA_IN_LOOP);
} }
...@@ -544,7 +569,8 @@ pass_walloca::execute (function *fun) ...@@ -544,7 +569,8 @@ pass_walloca::execute (function *fun)
print_decu (t.limit, buff); print_decu (t.limit, buff);
inform (loc, G_("limit is %wu bytes, but argument " inform (loc, G_("limit is %wu bytes, but argument "
"may be as large as %s"), "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; break;
...@@ -559,7 +585,7 @@ pass_walloca::execute (function *fun) ...@@ -559,7 +585,7 @@ pass_walloca::execute (function *fun)
{ {
print_decu (t.limit, buff); print_decu (t.limit, buff);
inform (loc, G_("limit is %wu bytes, but argument is %s"), 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); buff);
} }
} }
......
...@@ -760,14 +760,19 @@ layout_decl (tree decl, unsigned int known_align) ...@@ -760,14 +760,19 @@ layout_decl (tree decl, unsigned int known_align)
{ {
tree size = DECL_SIZE_UNIT (decl); tree size = DECL_SIZE_UNIT (decl);
if (size != 0 && TREE_CODE (size) == INTEGER_CST if (size != 0 && TREE_CODE (size) == INTEGER_CST)
&& compare_tree_int (size, warn_larger_than_size) > 0)
{ {
unsigned HOST_WIDE_INT uhwisize = tree_to_uhwi (size); /* -Wlarger-than= argument of HOST_WIDE_INT_MAX is treated
as if PTRDIFF_MAX had been specified, with the value
warning (OPT_Wlarger_than_, "size of %q+D %wu bytes exceeds " being that on the target rather than the host. */
"maximum object size %wu", unsigned HOST_WIDE_INT max_size = warn_larger_than_size;
decl, uhwisize, 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);
} }
} }
......
/* PR middle-end/79809 */ /* PR middle-end/79809 - ICE in alloca_call_type, at gimple-ssa-warn-alloca.c */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-Walloca-larger-than=4207115063 -Wvla-larger-than=1233877270 -O2" } */ /* { dg-options "-Walloca-larger-than=4207115063 -Wvla-larger-than=1233877270 -O2" } */
/* { dg-require-effective-target alloca } */ /* { dg-require-effective-target alloca } */
int a; int a;
char *b = static_cast<char *>(__builtin_alloca (a)); // { dg-warning "argument to .alloca. may be too large|unbounded use of" } char *b = static_cast<char *>(__builtin_alloca (a));
// { dg-prune-output "argument to .alloca." }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment