Skip to content

Commit c2a516a

Browse files
committed
Fix simplification of pointer-object comparison
1) pointer_object((T1 *)NULL) equals pointer_object((T2 *)NULL) for any types T1, T2. Previously, this would return false, unless T1==T2. 2) Do not restrict the above to NULL, but instead let the existing logic in simplify_inequality fully simplify this. 3) Add a unit test of this code, which highlighted further bugs and limitations: the unit test previously did not set the instance of the desired dynamic object, and address-of inequalities over dynamic objects can also be simplified.
1 parent 3b384ed commit c2a516a

File tree

2 files changed

+60
-13
lines changed

2 files changed

+60
-13
lines changed

src/util/simplify_expr_pointer.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,25 @@ bool simplify_exprt::simplify_inequality_address_of(exprt &expr)
447447

448448
return false;
449449
}
450+
else if(
451+
tmp0.op0().id() == ID_dynamic_object &&
452+
tmp1.op0().id() == ID_dynamic_object)
453+
{
454+
bool equal = to_dynamic_object_expr(tmp0.op0()).get_instance() ==
455+
to_dynamic_object_expr(tmp1.op0()).get_instance();
456+
457+
expr.make_bool(expr.id() == ID_equal ? equal : !equal);
458+
459+
return false;
460+
}
461+
else if(
462+
(tmp0.op0().id() == ID_symbol && tmp1.op0().id() == ID_dynamic_object) ||
463+
(tmp0.op0().id() == ID_dynamic_object && tmp1.op0().id() == ID_symbol))
464+
{
465+
expr.make_bool(expr.id() != ID_equal);
466+
467+
return false;
468+
}
450469

451470
return true;
452471
}
@@ -458,6 +477,7 @@ bool simplify_exprt::simplify_inequality_pointer_object(exprt &expr)
458477
DATA_INVARIANT(
459478
expr.operands().size() == 2, "(in)equalities have two operands");
460479

480+
exprt::operandst new_inequality_ops;
461481
forall_operands(it, expr)
462482
{
463483
PRECONDITION(it->id() == ID_pointer_object);
@@ -474,16 +494,23 @@ bool simplify_exprt::simplify_inequality_pointer_object(exprt &expr)
474494
return true;
475495
}
476496
}
477-
else if(op.id() != ID_constant || op.get(ID_value) != ID_NULL)
497+
else if(op.id() != ID_constant || !op.is_zero())
478498
{
479499
return true;
480500
}
481-
}
482501

483-
bool equal=expr.op0().op0()==expr.op1().op0();
484-
485-
expr.make_bool(expr.id()==ID_equal?equal:!equal);
502+
if(new_inequality_ops.empty())
503+
new_inequality_ops.push_back(op);
504+
else
505+
{
506+
new_inequality_ops.push_back(typecast_exprt::conditional_cast(
507+
op, new_inequality_ops.front().type()));
508+
simplify_node(new_inequality_ops.back());
509+
}
510+
}
486511

512+
expr.operands() = std::move(new_inequality_ops);
513+
simplify_inequality(expr);
487514
return false;
488515
}
489516

unit/util/simplify_expr.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Author: Michael Tautschnig
2020
#include <util/std_expr.h>
2121
#include <util/symbol_table.h>
2222

23-
TEST_CASE("Simplify pointer_offset(address of array index)")
23+
TEST_CASE("Simplify pointer_offset(address of array index)", "[core][util]")
2424
{
2525
config.set_arch("none");
2626

@@ -42,7 +42,7 @@ TEST_CASE("Simplify pointer_offset(address of array index)")
4242
REQUIRE(offset_value==1);
4343
}
4444

45-
TEST_CASE("Simplify const pointer offset")
45+
TEST_CASE("Simplify const pointer offset", "[core][util]")
4646
{
4747
config.set_arch("none");
4848

@@ -63,7 +63,7 @@ TEST_CASE("Simplify const pointer offset")
6363
REQUIRE(offset_value==1234);
6464
}
6565

66-
TEST_CASE("Simplify byte extract")
66+
TEST_CASE("Simplify byte extract", "[core][util]")
6767
{
6868
// this test does require a proper architecture to be set so that byte extract
6969
// uses adequate endianness
@@ -84,7 +84,7 @@ TEST_CASE("Simplify byte extract")
8484
REQUIRE(simp == s);
8585
}
8686

87-
TEST_CASE("expr2bits and bits2expr respect bit order")
87+
TEST_CASE("expr2bits and bits2expr respect bit order", "[core][util]")
8888
{
8989
symbol_tablet symbol_table;
9090
namespacet ns(symbol_table);
@@ -109,7 +109,7 @@ TEST_CASE("expr2bits and bits2expr respect bit order")
109109
REQUIRE(deadbeef == *should_be_deadbeef2);
110110
}
111111

112-
TEST_CASE("Simplify extractbit")
112+
TEST_CASE("Simplify extractbit", "[core][util]")
113113
{
114114
// this test does require a proper architecture to be set so that byte extract
115115
// uses adequate endianness
@@ -139,7 +139,7 @@ TEST_CASE("Simplify extractbit")
139139
REQUIRE(eb2 == true_exprt());
140140
}
141141

142-
TEST_CASE("Simplify extractbits")
142+
TEST_CASE("Simplify extractbits", "[core][util]")
143143
{
144144
// this test does require a proper architecture to be set so that byte extract
145145
// uses adequate endianness
@@ -158,7 +158,7 @@ TEST_CASE("Simplify extractbits")
158158
REQUIRE(eb == from_integer(0xbe, unsignedbv_typet(8)));
159159
}
160160

161-
TEST_CASE("Simplify shift")
161+
TEST_CASE("Simplify shift", "[core][util]")
162162
{
163163
const symbol_tablet symbol_table;
164164
const namespacet ns(symbol_table);
@@ -207,7 +207,7 @@ TEST_CASE("Simplify dynamic object comparison", "[core][util]")
207207
REQUIRE(simplify_expr(compare_null_through_cast, ns) == false_exprt());
208208

209209
dynamic_object_exprt other_dynamic_object(signedbv_typet(8));
210-
dynamic_object.set_instance(2);
210+
other_dynamic_object.set_instance(2);
211211
address_of_exprt address_of_other_dynamic_object(other_dynamic_object);
212212

213213
equal_exprt compare_pointer_objects(
@@ -216,3 +216,23 @@ TEST_CASE("Simplify dynamic object comparison", "[core][util]")
216216

217217
REQUIRE(simplify_expr(compare_pointer_objects, ns) == false_exprt());
218218
}
219+
220+
TEST_CASE("Simplify pointer_object equality", "[core][util]")
221+
{
222+
// this test requires a proper architecture to be set up so that pointers have
223+
// a width
224+
const cmdlinet cmdline;
225+
config.set(cmdline);
226+
227+
symbol_tablet symbol_table;
228+
namespacet ns(symbol_table);
229+
230+
exprt p_o_void =
231+
pointer_object(null_pointer_exprt{pointer_type(empty_typet{})});
232+
exprt p_o_int =
233+
pointer_object(null_pointer_exprt{pointer_type(signedbv_typet(32))});
234+
235+
exprt simp = simplify_expr(equal_exprt{p_o_void, p_o_int}, ns);
236+
237+
REQUIRE(simp.is_true());
238+
}

0 commit comments

Comments
 (0)