Skip to content

Commit a831464

Browse files
tautschnigqinheping
authored andcommitted
Simplify inequality over pointers
When using pointers as iterators we may see less-than (or less-or-equal) comparison of pointers with some offsets. When the base pointers point to the same root object we can safely simplify this. Also avoid undefined behaviour (pointer below object bounds) in regression test.
1 parent f3fbe64 commit a831464

File tree

4 files changed

+37
-20
lines changed

4 files changed

+37
-20
lines changed

regression/cbmc-incr-smt2/pointers-relational-operators/pointers_stack_lessthan.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
int main()
44
{
5-
int i = 12;
6-
int *x = &i;
5+
int i[2] = {12, 13};
6+
int *x = &i[0] + 1;
77
int *y = x + 1;
88
int *z = x - 1;
99

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
int main()
2+
{
3+
int A[5] = {0, 1, 2, 3, 4};
4+
for(int *iter = &A[0]; iter < &A[5]; ++iter)
5+
__CPROVER_assert(*iter == iter - &A[0], "values match");
6+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
main.c
3+
--unwind 10 --unwinding-assertions
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
Unwinding loop .* iteration 6
9+
^warning: ignoring
10+
--
11+
Simplification and constant propagation should ensure that unwinding the loop
12+
stops when reaching the array bound.

src/util/simplify_expr_int.cpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,12 +1587,24 @@ simplify_exprt::resultt<> simplify_exprt::simplify_inequality_no_constant(
15871587
if(expr.op0().type().id() == ID_floatbv)
15881588
return unchanged(expr);
15891589

1590-
// simplifications below require same-object, which we don't check for
1591-
if(
1592-
expr.op0().type().id() == ID_pointer && expr.id() != ID_equal &&
1593-
expr.id() != ID_notequal)
1590+
if(expr.op0().type().id() == ID_pointer)
15941591
{
1595-
return unchanged(expr);
1592+
exprt ptr_op0 = simplify_object(expr.op0()).expr;
1593+
exprt ptr_op1 = simplify_object(expr.op1()).expr;
1594+
1595+
if(ptr_op0 == ptr_op1)
1596+
{
1597+
pointer_offset_exprt offset_op0{expr.op0(), size_type()};
1598+
pointer_offset_exprt offset_op1{expr.op1(), size_type()};
1599+
1600+
return changed(simplify_rec(binary_relation_exprt{
1601+
std::move(offset_op0), expr.id(), std::move(offset_op1)}));
1602+
}
1603+
// simplifications below require same-object, which we don't check for
1604+
else if(expr.id() != ID_equal && expr.id() != ID_notequal)
1605+
{
1606+
return unchanged(expr);
1607+
}
15961608
}
15971609

15981610
// eliminate strict inequalities
@@ -1651,19 +1663,6 @@ simplify_exprt::resultt<> simplify_exprt::simplify_inequality_no_constant(
16511663
new_expr.rhs() = simplify_node(new_expr.rhs());
16521664
return changed(simplify_inequality(new_expr)); // recursive call
16531665
}
1654-
else if(expr.op0().type().id() == ID_pointer)
1655-
{
1656-
exprt ptr_op0 = simplify_object(expr.op0()).expr;
1657-
exprt ptr_op1 = simplify_object(expr.op1()).expr;
1658-
1659-
if(ptr_op0 == ptr_op1)
1660-
{
1661-
pointer_offset_exprt offset_op0{expr.op0(), size_type()};
1662-
pointer_offset_exprt offset_op1{expr.op1(), size_type()};
1663-
1664-
return changed(simplify_rec(equal_exprt{offset_op0, offset_op1}));
1665-
}
1666-
}
16671666
}
16681667

16691668
return unchanged(expr);

0 commit comments

Comments
 (0)