aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-ssa-warn-restrict.c
diff options
context:
space:
mode:
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 6eb393d..42c87190 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 *