From cc8bea0aeeeeb6ed8046ede1a577ee681da2ca6a Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Sat, 16 Dec 2017 23:58:34 +0000 Subject: 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 --- gcc/calls.c | 58 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 17 deletions(-) (limited to 'gcc/calls.c') 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 { -- cgit v1.1