summaryrefslogtreecommitdiff
path: root/gcc/gimple-ssa-warn-restrict.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2019-01-17 16:33:55 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2019-01-17 09:33:55 -0700
commit213694e56e6265044bc85dbf43bda9028f05dba7 (patch)
tree6e55de74c41ab1ba9949e3447f390dbb4c09b935 /gcc/gimple-ssa-warn-restrict.c
parent16d46c7bfda76b5b3e88a2d9a809aacdc3ed8e1a (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.c58
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 *