diff options
author | Martin Sebor <msebor@redhat.com> | 2019-01-17 16:33:55 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2019-01-17 09:33:55 -0700 |
commit | 213694e56e6265044bc85dbf43bda9028f05dba7 (patch) | |
tree | 6e55de74c41ab1ba9949e3447f390dbb4c09b935 /gcc/gimple-ssa-warn-restrict.c | |
parent | 16d46c7bfda76b5b3e88a2d9a809aacdc3ed8e1a (diff) |
PR tree-optimization/88800 - Spurious -Werror=array-bounds for non-taken branch
gcc/ChangeLog:
PR tree-optimization/88800
* gimple-fold.c (gimple_fold_builtin_memory_op): Avoid checking
NO_WARNING bit here. Avoid folding out-of-bounds calls.
* gimple-ssa-warn-restrict.c (maybe_diag_offset_bounds): Remove
redundant argument. Add new argument and issue diagnostics under
its control. Detect out-of-bounds access even with warnings
disabled.
(check_bounds_or_overlap): Change return type. Add argument.
(wrestrict_dom_walker::check_call): Adjust.
* gimple-ssa-warn-restrict.h (check_bounds_or_overlap): Add argument.
* tree-ssa-strlen.c (handle_builtin_strcpy): Adjust to change in
check_bounds_or_overlap's return value.
(handle_builtin_stxncpy): Same.
(handle_builtin_strcat): Same.
gcc/testsuite/ChangeLog:
PR tree-optimization/88800
* c-c++-common/Wrestrict.c: Adjust.
* gcc.dg/Warray-bounds-37.c: New test.
* gcc.dg/builtin-memcpy-2.c: New test.
* gcc.dg/builtin-memcpy.c: New test.
From-SVN: r268037
Diffstat (limited to 'gcc/gimple-ssa-warn-restrict.c')
-rw-r--r-- | gcc/gimple-ssa-warn-restrict.c | 58 |
1 files changed, 35 insertions, 23 deletions
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index 6eb393dc8e1..42c87190dd8 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -1329,6 +1329,9 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) if (!acs.overlap ()) return false; + if (gimple_no_warning_p (call)) + return true; + /* For convenience. */ const builtin_memref &dstref = *acs.dstref; const builtin_memref &srcref = *acs.srcref; @@ -1568,7 +1571,7 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) return true; } -/* Validate REF offsets in an EXPRession passed as an argument to a CALL +/* Validate REF offsets in an expression passed as an argument to a CALL to a built-in function FUNC to make sure they are within the bounds of the referenced object if its size is known, or PTRDIFF_MAX otherwise. Both initial values of the offsets and their final value computed by @@ -1578,21 +1581,27 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) static bool maybe_diag_offset_bounds (location_t loc, gimple *call, tree func, int strict, - tree expr, const builtin_memref &ref) + const builtin_memref &ref, bool do_warn) { - if (!warn_array_bounds) + /* Check for out-bounds pointers regardless of warning options since + the result is used to make codegen decisions. */ + offset_int ooboff[] = { ref.offrange[0], ref.offrange[1] }; + tree oobref = ref.offset_out_of_bounds (strict, ooboff); + if (!oobref) return false; - if (ref.ref && TREE_NO_WARNING (ref.ref)) + /* Return true without issuing a warning. */ + if (!do_warn) + return true; + + if (!warn_array_bounds) return false; - offset_int ooboff[] = { ref.offrange[0], ref.offrange[1] }; - tree oobref = ref.offset_out_of_bounds (strict, ooboff); - if (!oobref) + if (ref.ref && TREE_NO_WARNING (ref.ref)) return false; - if (EXPR_HAS_LOCATION (expr)) - loc = EXPR_LOCATION (expr); + if (EXPR_HAS_LOCATION (ref.ptr)) + loc = EXPR_LOCATION (ref.ptr); loc = expansion_point_location_if_in_system_header (loc); @@ -1811,7 +1820,7 @@ wrestrict_dom_walker::check_call (gimple *call) || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr)))) return; - if (check_bounds_or_overlap (call, dst, src, dstwr, NULL_TREE)) + if (!check_bounds_or_overlap (call, dst, src, dstwr, NULL_TREE)) return; /* Avoid diagnosing the call again. */ @@ -1823,12 +1832,14 @@ wrestrict_dom_walker::check_call (gimple *call) /* Attempt to detect and diagnose invalid offset bounds and (except for memmove) overlapping copy in a call expression EXPR from SRC to DST and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and - SRCSIZE may be NULL. Return false when one or the other has been - detected and diagnosed, true otherwise. */ + SRCSIZE may be NULL. DO_WARN is false to detect either problem + without issue a warning. Return the OPT_Wxxx constant corresponding + to the warning if one has been detected and zero otherwise. */ -bool +int check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, - tree srcsize, bool bounds_only /* = false */) + tree srcsize, bool bounds_only /* = false */, + bool do_warn /* = true */) { location_t loc = gimple_nonartificial_location (call); loc = expansion_point_location_if_in_system_header (loc); @@ -1847,11 +1858,12 @@ check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, /* Validate offsets first to make sure they are within the bounds of the destination object if its size is known, or PTRDIFF_MAX otherwise. */ - if (maybe_diag_offset_bounds (loc, call, func, strict, dst, dstref) - || maybe_diag_offset_bounds (loc, call, func, strict, src, srcref)) + if (maybe_diag_offset_bounds (loc, call, func, strict, dstref, do_warn) + || maybe_diag_offset_bounds (loc, call, func, strict, srcref, do_warn)) { - gimple_set_no_warning (call, true); - return false; + if (do_warn) + gimple_set_no_warning (call, true); + return OPT_Warray_bounds; } bool check_overlap @@ -1861,7 +1873,7 @@ check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, && DECL_FUNCTION_CODE (func) != BUILT_IN_MEMMOVE_CHK))); if (!check_overlap) - return true; + return 0; if (operand_equal_p (dst, src, 0)) { @@ -1875,20 +1887,20 @@ check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, "%G%qD source argument is the same as destination", call, func); gimple_set_no_warning (call, true); - return false; + return OPT_Wrestrict; } - return true; + return 0; } /* Return false when overlap has been detected. */ if (maybe_diag_overlap (loc, call, acs)) { gimple_set_no_warning (call, true); - return false; + return OPT_Wrestrict; } - return true; + return 0; } gimple_opt_pass * |