Skip to content

Commit b86dbcf

Browse files
committed
value_set index_range should flatten contained values into one range
A constant of, say, 5 has a index_range of 5. A value_set of { 5, 6, 9 } therefore has an index_range of 5,6,9. An interval of [1, 3] has an index_range of 1,2,3. A value_set containing that interval should have the same index_range. A value_set of multiple constants and intervals should have an index_range which is the union of its contents index_range.
1 parent cdf11c3 commit b86dbcf

File tree

4 files changed

+148
-36
lines changed

4 files changed

+148
-36
lines changed

src/analyses/variable-sensitivity/value_set_abstract_object.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,17 @@
1111

1212
#include <analyses/variable-sensitivity/constant_abstract_value.h>
1313
#include <analyses/variable-sensitivity/context_abstract_object.h>
14-
#include <analyses/variable-sensitivity/interval_abstract_value.h>
1514
#include <analyses/variable-sensitivity/two_value_array_abstract_object.h>
1615
#include <analyses/variable-sensitivity/value_set_abstract_object.h>
1716
#include <util/make_unique.h>
1817

1918
static index_range_implementation_ptrt
20-
make_value_set_index_range(const abstract_object_sett &vals);
19+
make_value_set_index_range(const std::set<exprt> &vals);
2120

2221
class value_set_index_ranget : public index_range_implementationt
2322
{
2423
public:
25-
explicit value_set_index_ranget(const abstract_object_sett &vals)
24+
explicit value_set_index_ranget(const std::set<exprt> &vals)
2625
: values(vals), cur(), next(values.begin())
2726
{
2827
PRECONDITION(!values.empty());
@@ -37,7 +36,7 @@ class value_set_index_ranget : public index_range_implementationt
3736
if(next == values.end())
3837
return false;
3938

40-
cur = (*next)->to_constant();
39+
cur = *next;
4140
++next;
4241
return true;
4342
}
@@ -47,13 +46,13 @@ class value_set_index_ranget : public index_range_implementationt
4746
}
4847

4948
private:
50-
const abstract_object_sett &values;
49+
std::set<exprt> values;
5150
exprt cur;
52-
abstract_object_sett::const_iterator next;
51+
std::set<exprt>::const_iterator next;
5352
};
5453

5554
static index_range_implementation_ptrt
56-
make_value_set_index_range(const abstract_object_sett &vals)
55+
make_value_set_index_range(const std::set<exprt> &vals)
5756
{
5857
return util_make_unique<value_set_index_ranget>(vals);
5958
}
@@ -146,7 +145,15 @@ value_set_abstract_objectt::index_range_implementation(
146145
if(values.empty())
147146
return make_indeterminate_index_range();
148147

149-
return make_value_set_index_range(values);
148+
std::set<exprt> flattened;
149+
for(const auto &o : values)
150+
{
151+
const auto &v = std::dynamic_pointer_cast<const abstract_value_objectt>(o);
152+
for(auto e : v->index_range(ns))
153+
flattened.insert(e);
154+
}
155+
156+
return make_value_set_index_range(flattened);
150157
}
151158

152159
value_range_implementation_ptrt

unit/analyses/variable-sensitivity/abstract_object/index_range.cpp

Lines changed: 103 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1+
#include "analyses/variable-sensitivity/variable_sensitivity_test_helpers.h"
12
#include <analyses/variable-sensitivity/abstract_environment.h>
2-
#include <analyses/variable-sensitivity/abstract_object.h>
33
#include <analyses/variable-sensitivity/constant_abstract_value.h>
44
#include <analyses/variable-sensitivity/value_set_abstract_object.h>
55
#include <analyses/variable-sensitivity/variable_sensitivity_object_factory.h>
66
#include <testing-utils/use_catch.h>
77
#include <util/arith_tools.h>
8-
#include <util/mathematical_types.h>
98
#include <util/namespace.h>
109
#include <util/symbol_table.h>
1110

1211
SCENARIO(
1312
"index_range for constant_abstract_values"
14-
"[core][analyses][variable-sensitivity][constant_abstract_value][index-"
13+
"[core][analyses][variable-sensitivity][constant_abstract_value][index_"
1514
"range]")
1615
{
1716
auto type = signedbv_typet(32);
@@ -26,8 +25,7 @@ SCENARIO(
2625
{
2726
auto int_value = 99;
2827
auto value_expr = from_integer(int_value, type);
29-
auto value =
30-
std::make_shared<constant_abstract_valuet>(value_expr, env, ns);
28+
auto value = make_constant(value_expr, env, ns);
3129

3230
auto range = value->index_range(ns);
3331

@@ -59,7 +57,7 @@ SCENARIO(
5957

6058
GIVEN("a top constant's range is has a single nil expression")
6159
{
62-
auto value = std::make_shared<constant_abstract_valuet>(type);
60+
auto value = make_top_constant();
6361

6462
auto range = value->index_range(ns);
6563

@@ -78,7 +76,7 @@ SCENARIO(
7876

7977
SCENARIO(
8078
"index_range for interval_abstract_values"
81-
"[core][analyses][variable-sensitivity][interval_abstract_value][index-"
79+
"[core][analyses][variable-sensitivity][interval_abstract_value][index_"
8280
"range]")
8381
{
8482
auto object_factory = variable_sensitivity_object_factoryt::configured_with(
@@ -91,7 +89,7 @@ SCENARIO(
9189

9290
GIVEN("a top intervals's range is empty")
9391
{
94-
auto value = std::make_shared<interval_abstract_valuet>(type, true, false);
92+
auto value = make_top_interval();
9593

9694
auto range = value->index_range(ns);
9795

@@ -105,8 +103,7 @@ SCENARIO(
105103
{
106104
auto int_value = 99;
107105
auto value_expr = from_integer(int_value, type);
108-
auto value =
109-
std::make_shared<interval_abstract_valuet>(value_expr, env, ns);
106+
auto value = make_interval(value_expr, value_expr, env, ns);
110107

111108
auto range = value->index_range(ns);
112109

@@ -127,12 +124,9 @@ SCENARIO(
127124
GIVEN("a [99,100] interval's index_range has two elements")
128125
{
129126
auto int_value = 99;
130-
auto value_expr = from_integer(int_value, type);
131-
auto value = std::make_shared<interval_abstract_valuet>(
132-
constant_interval_exprt(
133-
from_integer(int_value, type), from_integer(int_value + 1, type), type),
134-
env,
135-
ns);
127+
auto lower = from_integer(int_value, type);
128+
auto upper = from_integer(int_value + 1, type);
129+
auto value = make_interval(lower, upper, env, ns);
136130

137131
auto range = value->index_range(ns);
138132

@@ -159,12 +153,9 @@ SCENARIO(
159153
GIVEN("a [99,102] interval's index_range has four elements")
160154
{
161155
auto int_value = 99;
162-
auto value_expr = from_integer(int_value, type);
163-
auto value = std::make_shared<interval_abstract_valuet>(
164-
constant_interval_exprt(
165-
from_integer(int_value, type), from_integer(int_value + 3, type), type),
166-
env,
167-
ns);
156+
auto lower = from_integer(int_value, type);
157+
auto upper = from_integer(int_value + 3, type);
158+
auto value = make_interval(lower, upper, env, ns);
168159

169160
auto range = value->index_range(ns);
170161

@@ -186,7 +177,7 @@ SCENARIO(
186177

187178
SCENARIO(
188179
"index_range for value_set_abstract_values"
189-
"[core][analyses][variable-sensitivity][value_set_abstract_value][index-"
180+
"[core][analyses][variable-sensitivity][value_set_abstract_value][index_"
190181
"range]")
191182
{
192183
auto object_factory = variable_sensitivity_object_factoryt::configured_with(
@@ -197,10 +188,9 @@ SCENARIO(
197188
namespacet ns(symbol_table);
198189
auto type = signedbv_typet(32);
199190

200-
GIVEN("a value_set is empty")
191+
GIVEN("a TOP value_set is empty")
201192
{
202-
auto value =
203-
std::make_shared<value_set_abstract_objectt>(type, true, false);
193+
auto value = make_top_value_set();
204194
auto range = value->index_range(ns);
205195

206196
THEN("range should have a nil expr")
@@ -214,4 +204,91 @@ SCENARIO(
214204
REQUIRE(i == range.end());
215205
}
216206
}
207+
GIVEN("a value_set { 99, 100, 101, 102 } index_range has four elements")
208+
{
209+
auto int_value = 99;
210+
auto _99 = from_integer(int_value, type);
211+
auto _100 = from_integer(100, type);
212+
auto _101 = from_integer(101, type);
213+
auto _102 = from_integer(102, type);
214+
auto value = make_value_set({_99, _100, _101, _102}, env, ns);
215+
216+
auto range = value->index_range(ns);
217+
218+
THEN("range has four values")
219+
{
220+
auto values = std::vector<exprt>();
221+
for(const auto &e : range)
222+
values.push_back(to_constant_expr(e));
223+
224+
REQUIRE(values.size() == 4);
225+
EXPECT(values, {_99, _100, _101, _102});
226+
}
227+
}
228+
GIVEN("a value_set { [99, 102] } index_range has four elements")
229+
{
230+
auto int_value = 99;
231+
auto _99 = from_integer(int_value, type);
232+
auto _100 = from_integer(100, type);
233+
auto _101 = from_integer(101, type);
234+
auto _102 = from_integer(102, type);
235+
auto _99_102 = constant_interval_exprt(_99, _102);
236+
auto value = make_value_set({_99_102}, env, ns);
237+
238+
auto range = value->index_range(ns);
239+
240+
THEN("range has four values")
241+
{
242+
auto values = std::vector<exprt>();
243+
for(const auto &e : range)
244+
values.push_back(to_constant_expr(e));
245+
246+
REQUIRE(values.size() == 4);
247+
EXPECT(values, {_99, _100, _101, _102});
248+
}
249+
}
250+
GIVEN("a value_set { 99, 100, [101, 102] } index_range has four elements")
251+
{
252+
auto int_value = 99;
253+
auto _99 = from_integer(int_value, type);
254+
auto _100 = from_integer(100, type);
255+
auto _101 = from_integer(101, type);
256+
auto _102 = from_integer(102, type);
257+
auto _101_102 = constant_interval_exprt(_101, _102);
258+
auto value = make_value_set({_99, _101_102, _100}, env, ns);
259+
260+
auto range = value->index_range(ns);
261+
262+
THEN("range has four values")
263+
{
264+
auto values = std::vector<exprt>();
265+
for(const auto &e : range)
266+
values.push_back(to_constant_expr(e));
267+
268+
REQUIRE(values.size() == 4);
269+
EXPECT(values, {_99, _100, _101, _102});
270+
}
271+
}
272+
GIVEN("a value_set { [99, 102], 100, 101 } index_range has four elements")
273+
{
274+
auto int_value = 99;
275+
auto _99 = from_integer(int_value, type);
276+
auto _100 = from_integer(100, type);
277+
auto _101 = from_integer(101, type);
278+
auto _102 = from_integer(102, type);
279+
auto _99_102 = constant_interval_exprt(_99, _102);
280+
auto value = make_value_set({_99_102, _100, _101}, env, ns);
281+
282+
auto range = value->index_range(ns);
283+
284+
THEN("range has four values")
285+
{
286+
auto values = std::vector<exprt>();
287+
for(const auto &e : range)
288+
values.push_back(to_constant_expr(e));
289+
290+
REQUIRE(values.size() == 4);
291+
EXPECT(values, {_99, _100, _101, _102});
292+
}
293+
}
217294
}

unit/analyses/variable-sensitivity/variable_sensitivity_test_helpers.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ as_value_set(const abstract_object_pointert &aop)
104104
return std::dynamic_pointer_cast<const value_set_abstract_objectt>(aop);
105105
}
106106

107+
bool set_contains(const std::vector<exprt> &set, const exprt &val)
108+
{
109+
auto i = std::find_if(
110+
set.begin(), set.end(), [&val](const exprt &lhs) { return lhs == val; });
111+
return i != set.end();
112+
}
113+
107114
bool set_contains(const abstract_object_sett &set, const exprt &val)
108115
{
109116
auto i = std::find_if(
@@ -210,14 +217,31 @@ void EXPECT(
210217
REQUIRE_FALSE(result->is_bottom());
211218

212219
auto values = result->get_values();
220+
auto value_string = set_to_str(values);
221+
auto expected_string = exprs_to_str(expected_values);
222+
223+
INFO("Expect " + value_string + " to match " + expected_string);
213224
REQUIRE(values.size() == expected_values.size());
214225

215-
auto value_string = set_to_str(values);
226+
for(auto &ev : expected_values)
227+
{
228+
INFO("Expect " + value_string + " to match " + expected_string);
229+
REQUIRE(set_contains(values, ev));
230+
}
231+
}
232+
233+
void EXPECT(
234+
const std::vector<exprt> &values,
235+
const std::vector<exprt> &expected_values)
236+
{
237+
auto value_string = exprs_to_str(values);
216238
auto expected_string = exprs_to_str(expected_values);
239+
INFO("Expect " + value_string + " to match " + expected_string);
240+
REQUIRE(values.size() == expected_values.size());
217241

218242
for(auto &ev : expected_values)
219243
{
220-
INFO("Expect " + value_string + " to include " + expected_string);
244+
INFO("Expect " + value_string + " to match " + expected_string);
221245
REQUIRE(set_contains(values, ev));
222246
}
223247
}

unit/analyses/variable-sensitivity/variable_sensitivity_test_helpers.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ void EXPECT(
6161
std::shared_ptr<const value_set_abstract_objectt> &result,
6262
const std::vector<exprt> &expected_values);
6363

64+
void EXPECT(
65+
const std::vector<exprt> &values,
66+
const std::vector<exprt> &expected_values);
67+
6468
void EXPECT_TOP(std::shared_ptr<const abstract_objectt> result);
6569

6670
void EXPECT_TOP(std::shared_ptr<const value_set_abstract_objectt> &result);

0 commit comments

Comments
 (0)