Skip to content

Commit b60259a

Browse files
authored
Merge pull request #6267 from jezhiggins/vsd-to-predicate
VSD - to predicate
2 parents b829c54 + 7af8e92 commit b60259a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1449
-362
lines changed

src/analyses/variable-sensitivity/abstract_environment.cpp

+27-12
Original file line numberDiff line numberDiff line change
@@ -408,22 +408,41 @@ void abstract_environmentt::output(
408408
{
409409
out << "{\n";
410410

411-
decltype(map)::viewt view;
412-
map.get_view(view);
413-
for(const auto &entry : view)
411+
for(const auto &entry : map.get_view())
414412
{
415413
out << entry.first << " () -> ";
416414
entry.second->output(out, ai, ns);
417415
out << "\n";
418416
}
417+
419418
out << "}\n";
420419
}
421420

421+
exprt abstract_environmentt::to_predicate() const
422+
{
423+
if(is_bottom())
424+
return false_exprt();
425+
if(is_top())
426+
return true_exprt();
427+
428+
auto predicates = std::vector<exprt>{};
429+
for(const auto &entry : map.get_view())
430+
{
431+
auto sym = entry.first;
432+
auto val = entry.second;
433+
auto pred = val->to_predicate(symbol_exprt(sym, val->type()));
434+
435+
predicates.push_back(pred);
436+
}
437+
438+
if(predicates.size() == 1)
439+
return predicates.front();
440+
return and_exprt(predicates);
441+
}
442+
422443
bool abstract_environmentt::verify() const
423444
{
424-
decltype(map)::viewt view;
425-
map.get_view(view);
426-
for(const auto &entry : view)
445+
for(const auto &entry : map.get_view())
427446
{
428447
if(entry.second == nullptr)
429448
{
@@ -460,9 +479,7 @@ abstract_environmentt::modified_symbols(
460479
{
461480
// Find all symbols who have different write locations in each map
462481
std::vector<abstract_environmentt::map_keyt> symbols_diff;
463-
decltype(first.map)::viewt view;
464-
first.map.get_view(view);
465-
for(const auto &entry : view)
482+
for(const auto &entry : first.map.get_view())
466483
{
467484
const auto &second_entry = second.map.find(entry.first);
468485
if(second_entry.has_value())
@@ -505,10 +522,8 @@ abstract_environmentt::gather_statistics(const namespacet &ns) const
505522
{
506523
abstract_object_statisticst statistics = {};
507524
statistics.number_of_globals = count_globals(ns);
508-
decltype(map)::viewt view;
509-
map.get_view(view);
510525
abstract_object_visitedt visited;
511-
for(auto const &object : view)
526+
for(auto const &object : map.get_view())
512527
{
513528
if(visited.find(object.second) == visited.end())
514529
{

src/analyses/variable-sensitivity/abstract_environment.h

+6
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ class abstract_environmentt
224224
void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns)
225225
const;
226226

227+
/// Gives a boolean condition that is true for all values represented by the
228+
/// environment.
229+
///
230+
/// \return An exprt describing the environment
231+
exprt to_predicate() const;
232+
227233
/// Check the structural invariants are maintained.
228234
/// In this case this is checking there aren't any null pointer mapped values
229235
bool verify() const;

src/analyses/variable-sensitivity/abstract_object.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,21 @@ exprt abstract_objectt::to_constant() const
172172
return nil_exprt();
173173
}
174174

175+
exprt abstract_objectt::to_predicate(const exprt &name) const
176+
{
177+
if(is_top())
178+
return true_exprt();
179+
if(is_bottom())
180+
return false_exprt();
181+
return to_predicate_internal(name);
182+
}
183+
184+
exprt abstract_objectt::to_predicate_internal(const exprt &name) const
185+
{
186+
UNREACHABLE;
187+
return nil_exprt();
188+
}
189+
175190
void abstract_objectt::output(
176191
std::ostream &out,
177192
const ai_baset &ai,

src/analyses/variable-sensitivity/abstract_object.h

+16
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,17 @@ class abstract_objectt : public std::enable_shared_from_this<abstract_objectt>
171171
/// that allows an object to be built from a value.
172172
virtual exprt to_constant() const;
173173

174+
/// Converts to an invariant expression
175+
///
176+
/// \param name - the variable name to substitute into the expression
177+
/// \return Returns an exprt representing the object as an invariant.
178+
///
179+
/// The the abstract element represents a single value the expression will
180+
/// have the form _name = value_, if the value is an interval it will have the
181+
/// the form _lower <= name <= upper_, etc.
182+
/// If the value is bottom returns false, if top returns true.
183+
exprt to_predicate(const exprt &name) const;
184+
174185
/**
175186
* A helper function to evaluate writing to a component of an
176187
* abstract object. More precise abstractions may override this to
@@ -352,6 +363,11 @@ class abstract_objectt : public std::enable_shared_from_this<abstract_objectt>
352363
return shared_from_this() == other;
353364
}
354365

366+
/// to_predicate implementation - derived classes will override
367+
/// \param name - the variable name to substitute into the expression
368+
/// \return Returns an exprt representing the object as an invariant.
369+
virtual exprt to_predicate_internal(const exprt &name) const;
370+
355371
private:
356372
/// To enforce copy-on-write these are private and have read-only accessors
357373
typet t;

src/analyses/variable-sensitivity/constant_abstract_value.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ abstract_value_pointert constant_abstract_valuet::constrain(
144144
return as_value(mutable_clone());
145145
}
146146

147+
exprt constant_abstract_valuet::to_predicate_internal(const exprt &name) const
148+
{
149+
return equal_exprt(name, value);
150+
}
151+
147152
void constant_abstract_valuet::get_statistics(
148153
abstract_object_statisticst &statistics,
149154
abstract_object_visitedt &visited,

src/analyses/variable-sensitivity/constant_abstract_value.h

+2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class constant_abstract_valuet : public abstract_value_objectt
8181
abstract_object_pointert
8282
meet_with_value(const abstract_value_pointert &other) const override;
8383

84+
exprt to_predicate_internal(const exprt &name) const override;
85+
8486
private:
8587
exprt value;
8688
};

src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -388,3 +388,9 @@ exprt constant_pointer_abstract_objectt::ptr_comparison_expr(
388388
return true_exprt();
389389
return nil_exprt();
390390
}
391+
392+
exprt constant_pointer_abstract_objectt::to_predicate_internal(
393+
const exprt &name) const
394+
{
395+
return equal_exprt(name, value_stack.to_expression());
396+
}

src/analyses/variable-sensitivity/constant_pointer_abstract_object.h

+2
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ class constant_pointer_abstract_objectt : public abstract_pointer_objectt
145145

146146
CLONE
147147

148+
exprt to_predicate_internal(const exprt &name) const override;
149+
148150
private:
149151
bool same_target(abstract_object_pointert other) const;
150152
exprt offset() const;

src/analyses/variable-sensitivity/context_abstract_object.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ abstract_object_pointert context_abstract_objectt::unwrap_context() const
160160
return child_abstract_object->unwrap_context();
161161
}
162162

163+
exprt context_abstract_objectt::to_predicate_internal(const exprt &name) const
164+
{
165+
return child_abstract_object->to_predicate(name);
166+
}
167+
163168
void context_abstract_objectt::get_statistics(
164169
abstract_object_statisticst &statistics,
165170
abstract_object_visitedt &visited,

src/analyses/variable-sensitivity/context_abstract_object.h

+2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ class context_abstract_objectt : public abstract_objectt
117117
bool merging_write) const override;
118118

119119
bool has_been_modified(const abstract_object_pointert &before) const override;
120+
121+
exprt to_predicate_internal(const exprt &name) const override;
120122
};
121123

122124
#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONTEXT_ABSTRACT_OBJECT_H

src/analyses/variable-sensitivity/full_array_abstract_object.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <analyses/variable-sensitivity/abstract_environment.h>
1212
#include <util/arith_tools.h>
13+
#include <util/mathematical_types.h>
1314
#include <util/std_expr.h>
1415

1516
#include "abstract_value_object.h"
@@ -401,6 +402,28 @@ abstract_object_pointert full_array_abstract_objectt::visit_sub_elements(
401402
}
402403
}
403404

405+
exprt full_array_abstract_objectt::to_predicate_internal(
406+
const exprt &name) const
407+
{
408+
auto all_predicates = exprt::operandst{};
409+
410+
for(auto field : map.get_sorted_view())
411+
{
412+
auto ii = from_integer(field.first.to_long(), integer_typet());
413+
auto index = index_exprt(name, ii);
414+
auto field_expr = field.second->to_predicate(index);
415+
416+
if(!field_expr.is_true())
417+
all_predicates.push_back(field_expr);
418+
}
419+
420+
if(all_predicates.empty())
421+
return true_exprt();
422+
if(all_predicates.size() == 1)
423+
return all_predicates.front();
424+
return and_exprt(all_predicates);
425+
}
426+
404427
void full_array_abstract_objectt::statistics(
405428
abstract_object_statisticst &statistics,
406429
abstract_object_visitedt &visited,

src/analyses/variable-sensitivity/full_array_abstract_object.h

+2
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ class full_array_abstract_objectt : public abstract_aggregate_objectt<
212212
abstract_object_pointert full_array_merge(
213213
const full_array_pointert &other,
214214
const widen_modet &widen_mode) const;
215+
216+
exprt to_predicate_internal(const exprt &name) const override;
215217
};
216218

217219
#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_ARRAY_ABSTRACT_OBJECT_H

src/analyses/variable-sensitivity/full_struct_abstract_object.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,27 @@ abstract_object_pointert full_struct_abstract_objectt::visit_sub_elements(
307307
}
308308
}
309309

310+
exprt full_struct_abstract_objectt::to_predicate_internal(
311+
const exprt &name) const
312+
{
313+
auto all_predicates = exprt::operandst{};
314+
315+
for(auto field : map.get_sorted_view())
316+
{
317+
auto field_name = member_exprt(name, field.first, name.type());
318+
auto field_expr = field.second->to_predicate(field_name);
319+
320+
if(!field_expr.is_true())
321+
all_predicates.push_back(field_expr);
322+
}
323+
324+
if(all_predicates.empty())
325+
return true_exprt();
326+
if(all_predicates.size() == 1)
327+
return all_predicates.front();
328+
return and_exprt(all_predicates);
329+
}
330+
310331
void full_struct_abstract_objectt::statistics(
311332
abstract_object_statisticst &statistics,
312333
abstract_object_visitedt &visited,

src/analyses/variable-sensitivity/full_struct_abstract_object.h

+2
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ class full_struct_abstract_objectt : public abstract_aggregate_objectt<
169169
abstract_object_pointert merge(
170170
const abstract_object_pointert &other,
171171
const widen_modet &widen_mode) const override;
172+
173+
exprt to_predicate_internal(const exprt &name) const override;
172174
};
173175

174176
#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H

src/analyses/variable-sensitivity/interval_abstract_value.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,17 @@ abstract_value_pointert interval_abstract_valuet::constrain(
463463
make_interval(constant_interval_exprt(lower_bound, upper_bound)));
464464
}
465465

466+
exprt interval_abstract_valuet::to_predicate_internal(const exprt &name) const
467+
{
468+
if(interval.is_single_value_interval())
469+
return equal_exprt(name, interval.get_lower());
470+
471+
auto lower_bound = binary_relation_exprt(interval.get_lower(), ID_le, name);
472+
auto upper_bound = binary_relation_exprt(name, ID_le, interval.get_upper());
473+
474+
return and_exprt(lower_bound, upper_bound);
475+
}
476+
466477
void interval_abstract_valuet::get_statistics(
467478
abstract_object_statisticst &statistics,
468479
abstract_object_visitedt &visited,

src/analyses/variable-sensitivity/interval_abstract_value.h

+2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ class interval_abstract_valuet : public abstract_value_objectt
9494
abstract_object_pointert
9595
meet_with_value(const abstract_value_pointert &other) const override;
9696

97+
exprt to_predicate_internal(const exprt &name) const override;
98+
9799
private:
98100
constant_interval_exprt interval;
99101

src/analyses/variable-sensitivity/value_set_abstract_object.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ static bool are_any_top(const abstract_object_sett &set);
119119
static bool is_set_extreme(const typet &type, const abstract_object_sett &set);
120120

121121
static abstract_object_sett compact_values(const abstract_object_sett &values);
122+
static abstract_object_sett
123+
non_destructive_compact(const abstract_object_sett &values);
122124
static abstract_object_sett widen_value_set(
123125
const abstract_object_sett &values,
124126
const constant_interval_exprt &lhs,
@@ -334,6 +336,25 @@ abstract_value_pointert value_set_abstract_objectt::constrain(
334336
return as_value(resolve_values(constrained_values));
335337
}
336338

339+
exprt value_set_abstract_objectt::to_predicate_internal(const exprt &name) const
340+
{
341+
auto compacted = non_destructive_compact(values);
342+
if(compacted.size() == 1)
343+
return compacted.first()->to_predicate(name);
344+
345+
auto all_predicates = exprt::operandst{};
346+
std::transform(
347+
compacted.begin(),
348+
compacted.end(),
349+
std::back_inserter(all_predicates),
350+
[&name](const abstract_object_pointert &value) {
351+
return value->to_predicate(name);
352+
});
353+
std::sort(all_predicates.begin(), all_predicates.end());
354+
355+
return or_exprt(all_predicates);
356+
}
357+
337358
void value_set_abstract_objectt::output(
338359
std::ostream &out,
339360
const ai_baset &ai,

src/analyses/variable-sensitivity/value_set_abstract_object.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class value_set_abstract_objectt : public abstract_value_objectt,
6969
abstract_object_pointert
7070
meet_with_value(const abstract_value_pointert &other) const override;
7171

72+
exprt to_predicate_internal(const exprt &name) const override;
73+
7274
private:
7375
/// Setter for updating the stored values
7476
/// \param other_values: the new (non-empty) set of values
@@ -82,10 +84,10 @@ class value_set_abstract_objectt : public abstract_value_objectt,
8284
abstract_object_pointert
8385
resolve_values(const abstract_object_sett &new_values) const;
8486

87+
void set_top_internal() override;
88+
8589
// data
8690
abstract_object_sett values;
87-
88-
void set_top_internal() override;
8991
};
9092

9193
#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_ABSTRACT_OBJECT_H

src/analyses/variable-sensitivity/value_set_pointer_abstract_object.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,25 @@ abstract_object_pointert value_set_pointer_abstract_objectt::merge(
229229
return abstract_objectt::merge(other, widen_mode);
230230
}
231231

232+
exprt value_set_pointer_abstract_objectt::to_predicate_internal(
233+
const exprt &name) const
234+
{
235+
if(values.size() == 1)
236+
return values.first()->to_predicate(name);
237+
238+
auto all_predicates = exprt::operandst{};
239+
std::transform(
240+
values.begin(),
241+
values.end(),
242+
std::back_inserter(all_predicates),
243+
[&name](const abstract_object_pointert &value) {
244+
return value->to_predicate(name);
245+
});
246+
std::sort(all_predicates.begin(), all_predicates.end());
247+
248+
return or_exprt(all_predicates);
249+
}
250+
232251
void value_set_pointer_abstract_objectt::set_values(
233252
const abstract_object_sett &other_values)
234253
{

src/analyses/variable-sensitivity/value_set_pointer_abstract_object.h

+2
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ class value_set_pointer_abstract_objectt : public abstract_pointer_objectt,
9898
const abstract_object_pointert &other,
9999
const widen_modet &widen_mode) const override;
100100

101+
exprt to_predicate_internal(const exprt &name) const override;
102+
101103
private:
102104
/// Update the set of stored values to \p new_values. Build a new abstract
103105
/// object of the right type if necessary.

0 commit comments

Comments
 (0)