Skip to content

Commit b4e2353

Browse files
committed
Domain pruning for < and <= assumptions.
Implemented for intervals and value-sets which are not top.
1 parent 546e705 commit b4e2353

File tree

14 files changed

+431
-17
lines changed

14 files changed

+431
-17
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
int main()
2+
{
3+
int x = 0;
4+
if(nondet())
5+
{
6+
x = 30;
7+
}
8+
9+
if(x < 10)
10+
{
11+
assert(x < 20);
12+
}
13+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--variable-sensitivity --vsd-values constants --verify
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
\[main\.assertion\.1\] line .* assertion x < 20: UNKNOWN
7+
8+
--
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.c
3+
--variable-sensitivity --vsd-values intervals --verify
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
\[main\.assertion\.1\] line .* assertion x < 20: SUCCESS
7+
--
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.c
3+
--variable-sensitivity --vsd-values set-of-constants --verify
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
\[main\.assertion\.1\] line .* assertion x < 20: SUCCESS
7+
--

src/analyses/variable-sensitivity/abstract_environment.cpp

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,19 @@ exprt invert_expr(const exprt &expr)
553553
relation_expr.lhs(), inverse_op, relation_expr.rhs());
554554
}
555555

556+
void prune_assign(
557+
abstract_environmentt &env,
558+
const exprt &destination,
559+
abstract_object_pointert obj,
560+
const namespacet &ns)
561+
{
562+
auto context_value =
563+
std::dynamic_pointer_cast<const context_abstract_objectt>(obj);
564+
if(context_value == nullptr)
565+
obj = env.add_object_context(obj);
566+
env.assign(destination, obj, ns);
567+
}
568+
556569
exprt assume_not(
557570
abstract_environmentt &env,
558571
const exprt &expr,
@@ -623,9 +636,9 @@ exprt assume_eq(
623636
return false_exprt();
624637

625638
if(is_lvalue(equal_expr.lhs()))
626-
env.assign(equal_expr.lhs(), meet, ns);
639+
prune_assign(env, equal_expr.lhs(), meet, ns);
627640
if(is_lvalue(equal_expr.rhs()))
628-
env.assign(equal_expr.rhs(), meet, ns);
641+
prune_assign(env, equal_expr.rhs(), meet, ns);
629642
return true_exprt();
630643
}
631644

@@ -654,6 +667,8 @@ exprt assume_noteq(
654667

655668
struct left_and_right_valuest
656669
{
670+
exprt lhs;
671+
exprt rhs;
657672
abstract_value_pointert left;
658673
abstract_value_pointert right;
659674

@@ -679,13 +694,15 @@ left_and_right_valuest eval_operands_as_values(
679694
{
680695
auto const &relationship_expr = to_binary_expr(expr);
681696

682-
auto left = env.eval(relationship_expr.lhs(), ns);
683-
auto right = env.eval(relationship_expr.rhs(), ns);
697+
auto lhs = relationship_expr.lhs();
698+
auto rhs = relationship_expr.rhs();
699+
auto left = env.eval(lhs, ns);
700+
auto right = env.eval(rhs, ns);
684701

685702
if(left->is_top() || right->is_top())
686703
return {};
687704

688-
return {as_value(left), as_value(right)};
705+
return {lhs, rhs, as_value(left), as_value(right)};
689706
}
690707

691708
exprt assume_less_than(
@@ -697,12 +714,33 @@ exprt assume_less_than(
697714
if(!operands.are_good())
698715
return nil_exprt();
699716

700-
auto left_lower = operands.left_interval().get_lower();
701-
auto right_upper = operands.right_interval().get_upper();
717+
auto left_interval = operands.left_interval();
718+
auto right_interval = operands.right_interval();
719+
720+
const auto &left_lower = left_interval.get_lower();
721+
const auto &right_upper = right_interval.get_upper();
702722

703723
auto reduced_le_expr =
704724
binary_relation_exprt(left_lower, expr.id(), right_upper);
705-
return env.eval(reduced_le_expr, ns)->to_constant();
725+
auto result = env.eval(reduced_le_expr, ns)->to_constant();
726+
if(result.is_true())
727+
{
728+
if(is_lvalue(operands.lhs))
729+
{
730+
auto pruned_upper = constant_interval_exprt::get_min(
731+
left_interval.get_upper(), right_upper);
732+
auto constrained = operands.left->constrain(left_lower, pruned_upper);
733+
prune_assign(env, operands.lhs, constrained, ns);
734+
}
735+
if(is_lvalue(operands.rhs))
736+
{
737+
auto pruned_lower = constant_interval_exprt::get_max(
738+
left_lower, right_interval.get_lower());
739+
auto constrained = operands.right->constrain(pruned_lower, right_upper);
740+
prune_assign(env, operands.rhs, constrained, ns);
741+
}
742+
}
743+
return result;
706744
}
707745

708746
exprt assume_greater_than(

src/analyses/variable-sensitivity/abstract_value_object.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,3 +694,9 @@ static abstract_object_pointert value_set_expression_transform(
694694
auto evaluator = value_set_evaluator(expr, operands, environment, ns);
695695
return evaluator();
696696
}
697+
698+
abstract_value_pointert
699+
abstract_value_objectt::as_value(const abstract_object_pointert &obj) const
700+
{
701+
return std::dynamic_pointer_cast<const abstract_value_objectt>(obj);
702+
}

src/analyses/variable-sensitivity/abstract_value_object.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,18 @@ class abstract_value_objectt : public abstract_objectt,
287287
const abstract_environmentt &environment,
288288
const namespacet &ns) const final;
289289

290+
virtual sharing_ptrt<const abstract_value_objectt>
291+
constrain(const exprt &lower, const exprt &upper) const = 0;
292+
290293
protected:
291294
virtual index_range_implementation_ptrt
292295
index_range_implementation(const namespacet &ns) const = 0;
293296

294297
virtual value_range_implementation_ptrt
295298
value_range_implementation() const = 0;
299+
300+
sharing_ptrt<const abstract_value_objectt>
301+
as_value(const abstract_object_pointert &obj) const;
296302
};
297303

298304
using abstract_value_pointert = sharing_ptrt<const abstract_value_objectt>;

src/analyses/variable-sensitivity/constant_abstract_value.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,13 @@ abstract_object_pointert constant_abstract_valuet::meet_with_value(
158158
return abstract_objectt::meet(other);
159159
}
160160

161+
abstract_value_pointert constant_abstract_valuet::constrain(
162+
const exprt &lower,
163+
const exprt &upper) const
164+
{
165+
return as_value(mutable_clone());
166+
}
167+
161168
void constant_abstract_valuet::get_statistics(
162169
abstract_object_statisticst &statistics,
163170
abstract_object_visitedt &visited,

src/analyses/variable-sensitivity/constant_abstract_value.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ class constant_abstract_valuet : public abstract_value_objectt
3737
exprt to_constant() const override;
3838
constant_interval_exprt to_interval() const override;
3939

40+
abstract_value_pointert
41+
constrain(const exprt &lower, const exprt &upper) const override;
42+
4043
void output(
4144
std::ostream &out,
4245
const class ai_baset &ai,

src/analyses/variable-sensitivity/interval_abstract_value.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,19 @@ interval_abstract_valuet::value_range_implementation() const
446446
return make_single_value_range(shared_from_this());
447447
}
448448

449+
abstract_value_pointert interval_abstract_valuet::constrain(
450+
const exprt &lower,
451+
const exprt &upper) const
452+
{
453+
auto lower_bound =
454+
constant_interval_exprt::get_max(lower, interval.get_lower());
455+
auto upper_bound =
456+
constant_interval_exprt::get_min(upper, interval.get_upper());
457+
458+
return as_value(
459+
make_interval(constant_interval_exprt(lower_bound, upper_bound)));
460+
}
461+
449462
void interval_abstract_valuet::get_statistics(
450463
abstract_object_statisticst &statistics,
451464
abstract_object_visitedt &visited,

0 commit comments

Comments
 (0)