aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2017-12-16 23:58:34 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2017-12-16 16:58:34 -0700
commitcc8bea0aeeeeb6ed8046ede1a577ee681da2ca6a (patch)
tree8ab48ffcd2c1abce152c9686d64db508a4f40a96 /gcc/calls.c
parentd43568222a4564e22a6ffd370481e11ba031b318 (diff)
downloadgcc-cc8bea0aeeeeb6ed8046ede1a577ee681da2ca6a.zip
gcc-cc8bea0aeeeeb6ed8046ede1a577ee681da2ca6a.tar.gz
gcc-cc8bea0aeeeeb6ed8046ede1a577ee681da2ca6a.tar.bz2
PR tree-optimization/78918 - missing -Wrestrict on memcpy copying over self
gcc/c-family/ChangeLog: PR tree-optimization/78918 * c-common.c (check_function_restrict): Avoid checking built-ins. * c.opt (-Wrestrict): Include in -Wall. gcc/ChangeLog: PR tree-optimization/78918 * Makefile.in (OBJS): Add gimple-ssa-warn-restrict.o. * builtins.c (check_sizes): Rename... (check_access): ...to this. Rename function arguments for clarity. (check_memop_sizes): Adjust names. (expand_builtin_memchr, expand_builtin_memcpy): Same. (expand_builtin_memmove, expand_builtin_mempcpy): Same. (expand_builtin_strcat, expand_builtin_stpncpy): Same. (check_strncat_sizes, expand_builtin_strncat): Same. (expand_builtin_strncpy, expand_builtin_memset): Same. (expand_builtin_bzero, expand_builtin_memcmp): Same. (expand_builtin_memory_chk, maybe_emit_chk_warning): Same. (maybe_emit_sprintf_chk_warning): Same. (expand_builtin_strcpy): Adjust. (expand_builtin_stpcpy): Same. (expand_builtin_with_bounds): Detect out-of-bounds accesses in pointer-checking forms of memcpy, memmove, and mempcpy. (gcall_to_tree_minimal, max_object_size): Define new functions. * builtins.h (max_object_size): Declare. * calls.c (alloc_max_size): Call max_object_size instead of hardcoding ssizetype limit. (get_size_range): Handle new argument. * calls.h (get_size_range): Add a new argument. * cfgexpand.c (expand_call_stmt): Propagate no-warning bit. * doc/invoke.texi (-Wrestrict): Adjust, add example. * gimple-fold.c (gimple_fold_builtin_memory_op): Detect overlapping operations. (gimple_fold_builtin_memory_chk): Same. (gimple_fold_builtin_stxcpy_chk): New function. * gimple-ssa-warn-restrict.c: New source. * gimple-ssa-warn-restrict.h: New header. * gimple.c (gimple_build_call_from_tree): Propagate location. * passes.def (pass_warn_restrict): Add new pass. * tree-pass.h (make_pass_warn_restrict): Declare. * tree-ssa-strlen.c (handle_builtin_strcpy): Detect overlapping operations. (handle_builtin_strcat): Same. (strlen_optimize_stmt): Rename... (strlen_check_and_optimize_stmt): ...to this. Handle strncat, stpncpy, strncpy, and their checking forms. gcc/testsuite/ChangeLog: PR tree-optimization/78918 * c-c++-common/Warray-bounds.c: New test. * c-c++-common/Warray-bounds-2.c: New test. * c-c++-common/Warray-bounds-3.c: New test. * c-c++-common/Warray-bounds-4.c: New test. * c-c++-common/Warray-bounds-5.c: New test. * c-c++-common/Wrestrict-2.c: New test. * c-c++-common/Wrestrict.c: New test. * c-c++-common/Wrestrict.s: New test. * c-c++-common/Wsizeof-pointer-memaccess1.c: Adjust * c-c++-common/Wsizeof-pointer-memaccess2.c: Same. * g++.dg/torture/Wsizeof-pointer-memaccess1.C: Same. * g++.dg/torture/Wsizeof-pointer-memaccess2.C: Same. * gcc.dg/range.h: New header. * gcc.dg/memcpy-6.c: New test. * gcc.dg/pr69172.c: Adjust. * gcc.dg/pr79223.c: Same. * gcc.dg/pr81345.c: Adjust. * gcc.dg/Wobjsize-1.c: Same. * gcc.dg/Wrestrict-2.c: New test. * gcc.dg/Wrestrict.c: New test. * gcc.dg/Wsizeof-pointer-memaccess1.c: Adjust. * gcc.dg/builtin-stpncpy.c: Same. * gcc.dg/builtin-stringop-chk-1.c: Same. * gcc.target/i386/chkp-stropt-17.c: New test. * gcc.dg/torture/Wsizeof-pointer-memaccess1.c: Adjust. From-SVN: r255755
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c58
1 files changed, 41 insertions, 17 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index 8ae9899..da6c96b 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h"
#include "stringpool.h"
#include "attribs.h"
+#include "builtins.h"
/* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */
#define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
@@ -1194,7 +1195,7 @@ alloc_max_size (void)
{
if (!alloc_object_size_limit)
{
- alloc_object_size_limit = TYPE_MAX_VALUE (ssizetype);
+ alloc_object_size_limit = max_object_size ();
if (warn_alloc_size_limit)
{
@@ -1245,7 +1246,8 @@ alloc_max_size (void)
{
widest_int w = wi::mul (limit, unit);
if (w < wi::to_widest (alloc_object_size_limit))
- alloc_object_size_limit = wide_int_to_tree (ssizetype, w);
+ alloc_object_size_limit
+ = wide_int_to_tree (ptrdiff_type_node, w);
}
}
}
@@ -1254,13 +1256,17 @@ alloc_max_size (void)
}
/* Return true when EXP's range can be determined and set RANGE[] to it
- after adjusting it if necessary to make EXP a valid size argument to
- an allocation function declared with attribute alloc_size (whose
- argument may be signed), or to a string manipulation function like
- memset. */
+ after adjusting it if necessary to make EXP a represents a valid size
+ of object, or a valid size argument to an allocation function declared
+ with attribute alloc_size (whose argument may be signed), or to a string
+ manipulation function like memset. When ALLOW_ZERO is true, allow
+ returning a range of [0, 0] for a size in an anti-range [1, N] where
+ N > PTRDIFF_MAX. A zero range is a (nearly) invalid argument to
+ allocation functions like malloc but it is a valid argument to
+ functions like memset. */
bool
-get_size_range (tree exp, tree range[2])
+get_size_range (tree exp, tree range[2], bool allow_zero /* = false */)
{
if (tree_fits_uhwi_p (exp))
{
@@ -1269,20 +1275,33 @@ get_size_range (tree exp, tree range[2])
return true;
}
+ tree exptype = TREE_TYPE (exp);
+ bool integral = INTEGRAL_TYPE_P (exptype);
+
wide_int min, max;
- enum value_range_type range_type
- = ((TREE_CODE (exp) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (exp)))
- ? get_range_info (exp, &min, &max) : VR_VARYING);
+ enum value_range_type range_type;
+
+ if (TREE_CODE (exp) == SSA_NAME && integral)
+ range_type = get_range_info (exp, &min, &max);
+ else
+ range_type = VR_VARYING;
if (range_type == VR_VARYING)
{
- /* No range information available. */
+ if (integral)
+ {
+ /* Use the full range of the type of the expression when
+ no value range information is available. */
+ range[0] = TYPE_MIN_VALUE (exptype);
+ range[1] = TYPE_MAX_VALUE (exptype);
+ return true;
+ }
+
range[0] = NULL_TREE;
range[1] = NULL_TREE;
return false;
}
- tree exptype = TREE_TYPE (exp);
unsigned expprec = TYPE_PRECISION (exptype);
bool signed_p = !TYPE_UNSIGNED (exptype);
@@ -1320,11 +1339,16 @@ get_size_range (tree exp, tree range[2])
{
/* EXP is unsigned and not in the range [1, MAX]. That means
it's either zero or greater than MAX. Even though 0 would
- normally be detected by -Walloc-zero set the range to
- [MAX, TYPE_MAX] so that when MAX is greater than the limit
- the whole range is diagnosed. */
- min = max + 1;
- max = wi::to_wide (TYPE_MAX_VALUE (exptype));
+ normally be detected by -Walloc-zero, unless ALLOW_ZERO
+ is true, set the range to [MAX, TYPE_MAX] so that when MAX
+ is greater than the limit the whole range is diagnosed. */
+ if (allow_zero)
+ min = max = wi::zero (expprec);
+ else
+ {
+ min = max + 1;
+ max = wi::to_wide (TYPE_MAX_VALUE (exptype));
+ }
}
else
{