Skip to content

Commit 77d0e0e

Browse files
committed
Simplify equal/not-equal over pointer_object expressions using value set
The value set can help us infer that, e.g., a particular pointer cannot be among the ones assigned to __CPROVER_dead_object, whereby we can simplify R_OK/W_OK expressions.
1 parent 6489c32 commit 77d0e0e

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed

src/goto-symex/simplify_expr_with_value_set.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,78 @@ simplify_exprt::resultt<> simplify_expr_with_value_sett::simplify_inequality(
155155
return unchanged(expr);
156156
}
157157

158+
simplify_exprt::resultt<>
159+
simplify_expr_with_value_sett::simplify_inequality_pointer_object(
160+
const binary_relation_exprt &expr)
161+
{
162+
PRECONDITION(expr.id() == ID_equal || expr.id() == ID_notequal);
163+
PRECONDITION(expr.is_boolean());
164+
165+
auto collect_objects = [this](const exprt &pointer)
166+
{
167+
std::set<exprt> objects;
168+
if(auto address_of = expr_try_dynamic_cast<address_of_exprt>(pointer))
169+
{
170+
objects.insert(
171+
object_descriptor_exprt::root_object(address_of->object()));
172+
}
173+
else if(auto ssa_expr = expr_try_dynamic_cast<ssa_exprt>(pointer))
174+
{
175+
ssa_exprt l1_expr{*ssa_expr};
176+
l1_expr.remove_level_2();
177+
const std::vector<exprt> value_set_elements =
178+
value_set.get_value_set(l1_expr, ns);
179+
180+
for(const auto &value_set_element : value_set_elements)
181+
{
182+
if(
183+
value_set_element.id() == ID_unknown ||
184+
value_set_element.id() == ID_invalid ||
185+
is_failed_symbol(
186+
to_object_descriptor_expr(value_set_element).root_object()))
187+
{
188+
objects.clear();
189+
break;
190+
}
191+
192+
objects.insert(
193+
to_object_descriptor_expr(value_set_element).root_object());
194+
}
195+
}
196+
return objects;
197+
};
198+
199+
auto lhs_objects =
200+
collect_objects(to_pointer_object_expr(expr.lhs()).pointer());
201+
auto rhs_objects =
202+
collect_objects(to_pointer_object_expr(expr.rhs()).pointer());
203+
204+
if(lhs_objects.size() == 1 && lhs_objects == rhs_objects)
205+
{
206+
// there is exactly one pointed-to object on both left-hand and right-hand
207+
// side, and that object is the same
208+
return expr.id() == ID_equal ? changed(static_cast<exprt>(true_exprt{}))
209+
: changed(static_cast<exprt>(false_exprt{}));
210+
}
211+
212+
std::list<exprt> intersection;
213+
std::set_intersection(
214+
lhs_objects.begin(),
215+
lhs_objects.end(),
216+
rhs_objects.begin(),
217+
rhs_objects.end(),
218+
std::back_inserter(intersection));
219+
if(!lhs_objects.empty() && !rhs_objects.empty() && intersection.empty())
220+
{
221+
// all pointed-to objects on the left-hand side are different from any of
222+
// the pointed-to objects on the right-hand side
223+
return expr.id() == ID_equal ? changed(static_cast<exprt>(false_exprt{}))
224+
: changed(static_cast<exprt>(true_exprt{}));
225+
}
226+
227+
return simplify_exprt::simplify_inequality_pointer_object(expr);
228+
}
229+
158230
simplify_exprt::resultt<>
159231
simplify_expr_with_value_sett::simplify_pointer_offset(
160232
const pointer_offset_exprt &expr)

src/goto-symex/simplify_expr_with_value_set.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class simplify_expr_with_value_sett : public simplify_exprt
2727
[[nodiscard]] resultt<>
2828
simplify_inequality(const binary_relation_exprt &) override;
2929
[[nodiscard]] resultt<>
30+
simplify_inequality_pointer_object(const binary_relation_exprt &) override;
31+
[[nodiscard]] resultt<>
3032
simplify_pointer_offset(const pointer_offset_exprt &) override;
3133

3234
protected:

src/util/simplify_expr_class.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ class simplify_exprt
273273
simplify_inequality_rhs_is_constant(const binary_relation_exprt &);
274274
[[nodiscard]] resultt<>
275275
simplify_inequality_address_of(const binary_relation_exprt &);
276-
[[nodiscard]] resultt<>
276+
[[nodiscard]] virtual resultt<>
277277
simplify_inequality_pointer_object(const binary_relation_exprt &);
278278

279279
// main recursion

0 commit comments

Comments
 (0)