Skip to content

Commit 5aa4b92

Browse files
committed
Enable mixed value-set and interval expression evaluation
rewrite_expression has, incorrectly, expected every term in the rewritten expression to be a constant. When there are intervals in play, this is clearly not the case. When we encounter an interval, don't attempt to coerce it to a constant expression, simply use the existing operand.
1 parent 4e67c0e commit 5aa4b92

File tree

3 files changed

+114
-4
lines changed

3 files changed

+114
-4
lines changed

src/analyses/variable-sensitivity/abstract_value_object.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -556,13 +556,25 @@ class value_set_evaluator
556556
rewrite_expression(const std::vector<abstract_object_pointert> &ops) const
557557
{
558558
auto operands_expr = exprt::operandst{};
559-
for(auto v : ops)
560-
operands_expr.push_back(v->to_constant());
559+
for(size_t i = 0; i != expression.operands().size(); ++i)
560+
{
561+
const auto &v = ops[i];
562+
if(is_constant_value(v))
563+
operands_expr.push_back(v->to_constant());
564+
else
565+
operands_expr.push_back(expression.operands()[i]);
566+
}
561567
auto rewritten_expr =
562568
exprt(expression.id(), expression.type(), std::move(operands_expr));
563569
return rewritten_expr;
564570
}
565571

572+
static bool is_constant_value(const abstract_object_pointert &v)
573+
{
574+
return std::dynamic_pointer_cast<const constant_abstract_valuet>(v) !=
575+
nullptr;
576+
}
577+
566578
std::vector<value_ranget> operands_as_ranges() const
567579
{
568580
auto unwrapped = std::vector<value_ranget>{};

unit/analyses/variable-sensitivity/value_expression_evaluation/expression_evaluation.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,46 @@ SCENARIO(
287287
}
288288
}
289289
}
290+
GIVEN("adding an interval and a value-set of constants")
291+
{
292+
WHEN("[2,2] + { 1 }")
293+
{
294+
auto op1 = make_interval(val2, val2, environment, ns);
295+
auto op2 = make_value_set(val1, environment, ns);
296+
auto result = add_as_value_set(op1, op2, environment, ns);
297+
298+
THEN("= {[3,3]}")
299+
{
300+
EXPECT(result, {constant_interval_exprt(val3, val3)});
301+
}
302+
}
303+
WHEN("[2,4] + { 1 }")
304+
{
305+
auto op1 = make_interval(val2, val4, environment, ns);
306+
auto op2 = make_value_set(val1, environment, ns);
307+
auto result = add_as_value_set(op1, op2, environment, ns);
308+
309+
THEN("= {[3,5]}")
310+
{
311+
EXPECT(result, {constant_interval_exprt(val3, val5)});
312+
}
313+
}
314+
WHEN("[1,2] + { 1, 2, 3 }")
315+
{
316+
auto op1 = make_interval(val1, val2, environment, ns);
317+
auto op2 = make_value_set({val1, val2, val3}, environment, ns);
318+
auto result = add_as_value_set(op1, op2, environment, ns);
319+
320+
THEN("= {[2,3], [3,4], [4,5]}")
321+
{
322+
EXPECT(
323+
result,
324+
{constant_interval_exprt(val2, val3),
325+
constant_interval_exprt(val3, val4),
326+
constant_interval_exprt(val4, val5)});
327+
}
328+
}
329+
}
290330

291331
GIVEN("adding two value_sets")
292332
{
@@ -371,6 +411,46 @@ SCENARIO(
371411
}
372412
}
373413
}
414+
GIVEN("adding a value-set of constants and an interval")
415+
{
416+
WHEN("{ 1 } + [2,2]")
417+
{
418+
auto op1 = make_value_set(val1, environment, ns);
419+
auto op2 = make_interval(val2, val2, environment, ns);
420+
auto result = add_as_value_set(op1, op2, environment, ns);
421+
422+
THEN("= {[3,3]}")
423+
{
424+
EXPECT(result, {constant_interval_exprt(val3, val3)});
425+
}
426+
}
427+
WHEN("{ 1 } + [2,4]")
428+
{
429+
auto op1 = make_value_set(val1, environment, ns);
430+
auto op2 = make_interval(val2, val4, environment, ns);
431+
auto result = add_as_value_set(op1, op2, environment, ns);
432+
433+
THEN("= {[3,5]}")
434+
{
435+
EXPECT(result, {constant_interval_exprt(val3, val5)});
436+
}
437+
}
438+
WHEN("{ 1, 2, 3 } + [1,2]")
439+
{
440+
auto op1 = make_value_set({val1, val2, val3}, environment, ns);
441+
auto op2 = make_interval(val1, val2, environment, ns);
442+
auto result = add_as_value_set(op1, op2, environment, ns);
443+
444+
THEN("= {[2,3], [3,4], [4,5]}")
445+
{
446+
EXPECT(
447+
result,
448+
{constant_interval_exprt(val2, val3),
449+
constant_interval_exprt(val3, val4),
450+
constant_interval_exprt(val4, val5)});
451+
}
452+
}
453+
}
374454
GIVEN("multiple operands")
375455
{
376456
WHEN("{ 1, 2, 3 } + 1 + 1")

unit/analyses/variable-sensitivity/variable_sensitivity_test_helpers.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,22 @@ bool set_contains(const abstract_object_sett &set, const exprt &val)
9393
auto i = std::find_if(
9494
set.begin(), set.end(), [&val](const abstract_object_pointert &lhs) {
9595
auto l = lhs->to_constant();
96+
auto interval =
97+
std::dynamic_pointer_cast<const interval_abstract_valuet>(lhs);
98+
if(interval)
99+
l = interval->to_interval();
96100
return l == val;
97101
});
98102
return i != set.end();
99103
}
100104

101-
std::string expr_to_str(const exprt &expr)
105+
static std::string interval_to_str(const constant_interval_exprt &expr);
106+
107+
static std::string expr_to_str(const exprt &expr)
102108
{
109+
if(expr.id() == ID_constant_interval)
110+
return interval_to_str(to_constant_interval_expr(expr));
111+
103112
auto st = symbol_tablet{};
104113
auto ns = namespacet{st};
105114
auto expr_str = std::string{};
@@ -110,6 +119,13 @@ std::string expr_to_str(const exprt &expr)
110119
return expr_str;
111120
}
112121

122+
static std::string interval_to_str(const constant_interval_exprt &expr)
123+
{
124+
auto lower = expr_to_str(expr.get_lower());
125+
auto upper = expr_to_str(expr.get_upper());
126+
return "[" + lower + "," + upper + "]";
127+
}
128+
113129
template <class Container, typename UnaryOp>
114130
std::string container_to_str(const Container &con, UnaryOp unaryOp)
115131
{
@@ -125,7 +141,9 @@ std::string container_to_str(const Container &con, UnaryOp unaryOp)
125141
std::string set_to_str(const abstract_object_sett &set)
126142
{
127143
return container_to_str(set, [](const abstract_object_pointert &lhs) {
128-
return expr_to_str(lhs->to_constant());
144+
auto i = std::dynamic_pointer_cast<const interval_abstract_valuet>(lhs);
145+
return i ? interval_to_str(i->to_interval())
146+
: expr_to_str(lhs->to_constant());
129147
});
130148
}
131149

0 commit comments

Comments
 (0)