aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2021-07-07 14:05:25 -0600
committerMartin Sebor <msebor@redhat.com>2021-07-07 14:06:59 -0600
commita110855667782dac7b674d3e328b253b3b3c919b (patch)
tree4d7212fdc8b29304d8defd03eefdb6ca842daa2f /gcc/builtins.c
parent6278065af07634278ba30029d92a82b089969baa (diff)
downloadgcc-a110855667782dac7b674d3e328b253b3b3c919b.zip
gcc-a110855667782dac7b674d3e328b253b3b3c919b.tar.gz
gcc-a110855667782dac7b674d3e328b253b3b3c919b.tar.bz2
Correct handling of variable offset minus constant in -Warray-bounds [PR100137]
Resolves: PR tree-optimization/100137 - -Warray-bounds false positive on varying offset plus negative PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional PR tree-optimization/97027 - missing warning on buffer overflow storing a larger scalar into a smaller array gcc/ChangeLog: PR tree-optimization/100137 PR tree-optimization/99121 PR tree-optimization/97027 * builtins.c (access_ref::access_ref): Also set offmax. (access_ref::offset_in_range): Define new function. (access_ref::add_offset): Set offmax. (access_ref::inform_access): Handle access_none. (handle_mem_ref): Clear ostype. (compute_objsize_r): Handle ASSERT_EXPR. * builtins.h (struct access_ref): Add offmax member. * gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): Use compute_objsize() and simplify. gcc/testsuite/ChangeLog: PR tree-optimization/100137 PR tree-optimization/99121 PR tree-optimization/97027 * c-c++-common/Warray-bounds-3.c: Remove xfail * c-c++-common/Warray-bounds-4.c: Add an expected warning. * c-c++-common/Warray-bounds-9.c: New test. * c-c++-common/Warray-bounds-10.c: New test. * g++.dg/asan/asan_test.C: Suppress expected warnings. * g++.dg/pr95768.C: Same. * g++.dg/warn/Warray-bounds-10.C: Adjust text of expected messages. * g++.dg/warn/Warray-bounds-11.C: Same. * g++.dg/warn/Warray-bounds-12.C: Same. * g++.dg/warn/Warray-bounds-13.C: Same. * g++.dg/warn/Warray-bounds-17.C: Same. * g++.dg/warn/Warray-bounds-20.C: Same. * gcc.dg/Warray-bounds-29.c: Same. * gcc.dg/Warray-bounds-30.c: Add xfail. * gcc.dg/Warray-bounds-31.c: Adjust text of expected messages. * gcc.dg/Warray-bounds-32.c: Same. * gcc.dg/Warray-bounds-52.c: Same. * gcc.dg/Warray-bounds-53.c: Same. * gcc.dg/Warray-bounds-58.c: Remove xfail. * gcc.dg/Warray-bounds-63.c: Adjust text of expected messages. * gcc.dg/Warray-bounds-66.c: Same. * gcc.dg/Warray-bounds-69.c: Same. * gcc.dg/Wstringop-overflow-34.c: Same. * gcc.dg/Wstringop-overflow-47.c: Same. * gcc.dg/Wstringop-overflow-61.c: Same. * gcc.dg/Warray-bounds-77.c: New test. * gcc.dg/Warray-bounds-78.c: New test. * gcc.dg/Warray-bounds-79.c: New test.
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c69
1 files changed, 61 insertions, 8 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index e52fe42..39ab139 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -206,6 +206,7 @@ access_ref::access_ref (tree bound /* = NULL_TREE */,
{
/* Set to valid. */
offrng[0] = offrng[1] = 0;
+ offmax[0] = offmax[1] = 0;
/* Invalidate. */
sizrng[0] = sizrng[1] = -1;
@@ -457,6 +458,21 @@ access_ref::size_remaining (offset_int *pmin /* = NULL */) const
return sizrng[1] - or0;
}
+/* Return true if the offset and object size are in range for SIZE. */
+
+bool
+access_ref::offset_in_range (const offset_int &size) const
+{
+ if (size_remaining () < size)
+ return false;
+
+ if (base0)
+ return offmax[0] >= 0 && offmax[1] <= sizrng[1];
+
+ offset_int maxoff = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
+ return offmax[0] > -maxoff && offmax[1] < maxoff;
+}
+
/* Add the range [MIN, MAX] to the offset range. For known objects (with
zero-based offsets) at least one of whose offset's bounds is in range,
constrain the other (or both) to the bounds of the object (i.e., zero
@@ -493,6 +509,8 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max)
if (max >= 0)
{
offrng[0] = 0;
+ if (offmax[0] > 0)
+ offmax[0] = 0;
return;
}
@@ -509,6 +527,12 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max)
offrng[0] = 0;
}
+ /* Set the minimum and maximmum computed so far. */
+ if (offrng[1] < 0 && offrng[1] < offmax[0])
+ offmax[0] = offrng[1];
+ if (offrng[0] > 0 && offrng[0] > offmax[1])
+ offmax[1] = offrng[0];
+
if (!base0)
return;
@@ -4571,23 +4595,46 @@ access_ref::inform_access (access_mode mode) const
return;
}
+ if (mode == access_read_only)
+ {
+ if (allocfn == NULL_TREE)
+ {
+ if (*offstr)
+ inform (loc, "at offset %s into source object %qE of size %s",
+ offstr, ref, sizestr);
+ else
+ inform (loc, "source object %qE of size %s", ref, sizestr);
+
+ return;
+ }
+
+ if (*offstr)
+ inform (loc,
+ "at offset %s into source object of size %s allocated by %qE",
+ offstr, sizestr, allocfn);
+ else
+ inform (loc, "source object of size %s allocated by %qE",
+ sizestr, allocfn);
+ return;
+ }
+
if (allocfn == NULL_TREE)
{
if (*offstr)
- inform (loc, "at offset %s into source object %qE of size %s",
+ inform (loc, "at offset %s into object %qE of size %s",
offstr, ref, sizestr);
else
- inform (loc, "source object %qE of size %s", ref, sizestr);
+ inform (loc, "object %qE of size %s", ref, sizestr);
return;
}
if (*offstr)
inform (loc,
- "at offset %s into source object of size %s allocated by %qE",
+ "at offset %s into object of size %s allocated by %qE",
offstr, sizestr, allocfn);
else
- inform (loc, "source object of size %s allocated by %qE",
+ inform (loc, "object of size %s allocated by %qE",
sizestr, allocfn);
}
@@ -5433,16 +5480,16 @@ handle_mem_ref (tree mref, int ostype, access_ref *pref,
if (VECTOR_TYPE_P (TREE_TYPE (mref)))
{
- /* Hack: Give up for MEM_REFs of vector types; those may be
- synthesized from multiple assignments to consecutive data
- members (see PR 93200 and 96963).
+ /* Hack: Handle MEM_REFs of vector types as those to complete
+ objects; those may be synthesized from multiple assignments
+ to consecutive data members (see PR 93200 and 96963).
FIXME: Vectorized assignments should only be present after
vectorization so this hack is only necessary after it has
run and could be avoided in calls from prior passes (e.g.,
tree-ssa-strlen.c).
FIXME: Deal with this more generally, e.g., by marking up
such MEM_REFs at the time they're created. */
- return false;
+ ostype = 0;
}
tree mrefop = TREE_OPERAND (mref, 0);
@@ -5796,6 +5843,12 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref,
tree rhs = gimple_assign_rhs1 (stmt);
+ if (code == ASSERT_EXPR)
+ {
+ rhs = TREE_OPERAND (rhs, 0);
+ return compute_objsize_r (rhs, ostype, pref, snlim, qry);
+ }
+
if (code == POINTER_PLUS_EXPR
&& TREE_CODE (TREE_TYPE (rhs)) == POINTER_TYPE)
{