Skip to content

Commit a3d1b75

Browse files
committed
Add abstract_value_objectt::to_interval()
Analogous to to_constant, it returns a constant_interval_exprt that expresses the range of the value. For constants the interval is across whatever the constant is, for intervals it is their interval(!) and for value_sets it is the interval between the smallest and largest values in the set. Used to intervals to merge with any other value type. This commit includes unit tests for interval_abstract_objectt::merge.
1 parent 6d3c463 commit a3d1b75

15 files changed

+655
-84
lines changed

src/analyses/variable-sensitivity/abstract_object_set.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ void abstract_object_sett::output(
3737
join_strings(out, output_values.begin(), output_values.end(), ", ");
3838
}
3939

40-
abstract_object_pointert abstract_object_sett::to_interval()
40+
constant_interval_exprt abstract_object_sett::to_interval() const
4141
{
4242
PRECONDITION(!values.empty());
4343

@@ -49,6 +49,5 @@ abstract_object_pointert abstract_object_sett::to_interval()
4949
lower_expr = constant_interval_exprt::get_min(lower_expr, value_expr);
5050
upper_expr = constant_interval_exprt::get_max(upper_expr, value_expr);
5151
}
52-
return std::make_shared<interval_abstract_valuet>(
53-
constant_interval_exprt(lower_expr, upper_expr));
52+
return constant_interval_exprt(lower_expr, upper_expr);
5453
}

src/analyses/variable-sensitivity/abstract_object_set.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,9 @@ class abstract_object_sett
8080
void
8181
output(std::ostream &out, const ai_baset &ai, const namespacet &ns) const;
8282

83-
/// Cast the set of values \p other_values to an interval.
84-
/// \param other_values: the value-set to be abstracted into an interval
85-
/// \return the interval-abstract-object containing \p other_values
86-
abstract_object_pointert to_interval();
83+
/// Calculate the set of values as an interval.
84+
/// \return the constant_interval_exprt bounding the values
85+
constant_interval_exprt to_interval() const;
8786

8887
private:
8988
value_sett values;

src/analyses/variable-sensitivity/abstract_value_object.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,11 +631,17 @@ class value_set_evaluator
631631
auto unwrapped_values = unwrap_and_extract_values(new_values);
632632

633633
if(unwrapped_values.size() > value_set_abstract_objectt::max_value_set_size)
634-
return unwrapped_values.to_interval();
634+
return make_interval(unwrapped_values);
635635

636636
return make_value_set(unwrapped_values);
637637
}
638638

639+
static abstract_object_pointert
640+
make_interval(const abstract_object_sett &values)
641+
{
642+
return std::make_shared<interval_abstract_valuet>(values.to_interval());
643+
}
644+
639645
static abstract_object_pointert
640646
make_value_set(const abstract_object_sett &values)
641647
{

src/analyses/variable-sensitivity/abstract_value_object.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_VALUE_OBJECT_H
1414

1515
#include <analyses/variable-sensitivity/abstract_object.h>
16+
#include <util/interval.h>
1617

1718
class abstract_value_tag
1819
{
@@ -265,6 +266,8 @@ class abstract_value_objectt : public abstract_objectt,
265266
return value_ranget(value_range_implementation());
266267
}
267268

269+
virtual constant_interval_exprt to_interval() const = 0;
270+
268271
/// Interface for transforms
269272
///
270273
/// \param expr: the expression to evaluate and find the result of it.
@@ -293,4 +296,4 @@ class abstract_value_objectt : public abstract_objectt,
293296

294297
using abstract_value_pointert = sharing_ptrt<const abstract_value_objectt>;
295298

296-
#endif
299+
#endif

src/analyses/variable-sensitivity/constant_abstract_value.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ exprt constant_abstract_valuet::to_constant() const
9191
}
9292
}
9393

94+
constant_interval_exprt constant_abstract_valuet::to_interval() const
95+
{
96+
return constant_interval_exprt(value, value);
97+
}
98+
9499
void constant_abstract_valuet::output(
95100
std::ostream &out,
96101
const ai_baset &ai,

src/analyses/variable-sensitivity/constant_abstract_value.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class constant_abstract_valuet : public abstract_value_objectt
3636
value_range_implementation_ptrt value_range_implementation() const override;
3737

3838
exprt to_constant() const override;
39+
constant_interval_exprt to_interval() const override;
3940

4041
void output(
4142
std::ostream &out,

src/analyses/variable-sensitivity/interval_abstract_value.cpp

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,8 @@ void interval_abstract_valuet::output(
329329
abstract_object_pointert
330330
interval_abstract_valuet::merge(abstract_object_pointert other) const
331331
{
332-
interval_abstract_value_pointert cast_other =
333-
std::dynamic_pointer_cast<const interval_abstract_valuet>(other);
332+
abstract_value_pointert cast_other =
333+
std::dynamic_pointer_cast<const abstract_value_objectt>(other);
334334
if(cast_other)
335335
{
336336
return merge_intervals(cast_other);
@@ -342,31 +342,31 @@ interval_abstract_valuet::merge(abstract_object_pointert other) const
342342
}
343343

344344
/// Merge another interval abstract object with this one
345-
/// \param other The interval abstract object to merge with
345+
/// \param other The abstract value object to merge with
346346
/// \return This if the other interval is subsumed by this,
347347
/// other if this is subsumed by other.
348348
/// Otherwise, a new interval abstract object
349349
/// with the smallest interval that subsumes both
350350
/// this and other
351-
abstract_object_pointert interval_abstract_valuet::merge_intervals(
352-
interval_abstract_value_pointert other) const
351+
abstract_object_pointert
352+
interval_abstract_valuet::merge_intervals(abstract_value_pointert &other) const
353353
{
354-
if(is_bottom() || other->interval.contains(interval))
355-
{
356-
return other;
357-
}
358-
else if(other->is_bottom() || interval.contains(other->interval))
359-
{
354+
if(other->is_bottom())
360355
return shared_from_this();
361-
}
362-
else
363-
{
364-
return std::make_shared<interval_abstract_valuet>(constant_interval_exprt(
365-
constant_interval_exprt::get_min(
366-
interval.get_lower(), other->interval.get_lower()),
367-
constant_interval_exprt::get_max(
368-
interval.get_upper(), other->interval.get_upper())));
369-
}
356+
357+
auto other_interval = other->to_interval();
358+
359+
if(is_bottom())
360+
return std::make_shared<interval_abstract_valuet>(other_interval);
361+
362+
if(interval.contains(other_interval))
363+
return shared_from_this();
364+
365+
return std::make_shared<interval_abstract_valuet>(constant_interval_exprt(
366+
constant_interval_exprt::get_min(
367+
interval.get_lower(), other_interval.get_lower()),
368+
constant_interval_exprt::get_max(
369+
interval.get_upper(), other_interval.get_upper())));
370370
}
371371

372372
abstract_object_pointert

src/analyses/variable-sensitivity/interval_abstract_value.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class interval_abstract_valuet : public abstract_value_objectt
4141
value_range_implementation_ptrt value_range_implementation() const override;
4242

4343
exprt to_constant() const override;
44-
const constant_interval_exprt &to_interval() const
44+
constant_interval_exprt to_interval() const override
4545
{
4646
return interval;
4747
}
@@ -68,7 +68,7 @@ class interval_abstract_valuet : public abstract_value_objectt
6868
sharing_ptrt<interval_abstract_valuet>;
6969

7070
abstract_object_pointert
71-
merge_intervals(interval_abstract_value_pointert other) const;
71+
merge_intervals(abstract_value_pointert &other) const;
7272
abstract_object_pointert
7373
meet_intervals(interval_abstract_value_pointert other) const;
7474

src/analyses/variable-sensitivity/value_set_abstract_object.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/// \file
1010
/// Value Set Abstract Object
1111

12+
#include "interval_abstract_value.h"
1213
#include <analyses/variable-sensitivity/constant_abstract_value.h>
1314
#include <analyses/variable-sensitivity/context_abstract_object.h>
1415
#include <analyses/variable-sensitivity/two_value_array_abstract_object.h>
@@ -162,6 +163,18 @@ value_set_abstract_objectt::value_range_implementation() const
162163
return make_value_set_value_range(values);
163164
}
164165

166+
exprt value_set_abstract_objectt::to_constant() const
167+
{
168+
verify();
169+
return values.size() == 1 ? (*values.begin())->to_constant()
170+
: abstract_objectt::to_constant();
171+
}
172+
173+
constant_interval_exprt value_set_abstract_objectt::to_interval() const
174+
{
175+
return values.to_interval();
176+
}
177+
165178
abstract_object_pointert value_set_abstract_objectt::write(
166179
abstract_environmentt &environment,
167180
const namespacet &ns,
@@ -199,7 +212,8 @@ abstract_object_pointert value_set_abstract_objectt::resolve_values(
199212

200213
if(unwrapped_values.size() > max_value_set_size)
201214
{
202-
return unwrapped_values.to_interval();
215+
return std::make_shared<interval_abstract_valuet>(
216+
unwrapped_values.to_interval());
203217
}
204218
//if(unwrapped_values.size() == 1)
205219
//{

src/analyses/variable-sensitivity/value_set_abstract_object.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,8 @@ class value_set_abstract_objectt : public abstract_value_objectt,
3636
value_range_implementation_ptrt value_range_implementation() const override;
3737

3838
/// \copydoc abstract_objectt::to_constant
39-
exprt to_constant() const override
40-
{
41-
verify();
42-
return values.size() == 1 ? (*values.begin())->to_constant()
43-
: abstract_objectt::to_constant();
44-
}
39+
exprt to_constant() const override;
40+
constant_interval_exprt to_interval() const override;
4541

4642
/// Getter for the set of stored abstract objects.
4743
/// \return the values represented by this abstract object

0 commit comments

Comments
 (0)