Go to the documentation of this file.
31 const std::unordered_map<irep_idt, smt_identifier_termt> &identifier_table)
33 solver_process.
send(command);
46 return "SMT solver returned an error message - " +
51 return {
"SMT solver does not support given command."};
70 std::vector<exprt> dependent_expressions;
78 dependent_expressions.push_back(expr_node);
81 return dependent_expressions;
89 const std::vector<exprt> &elements = array.
operands();
91 for(std::size_t i = 0; i < elements.size(); ++i)
112 {array_index_identifier},
119 template <
typename t_exprt>
121 const t_exprt &array)
126 "Converting array typed expression to SMT should result in a term of array "
138 const std::unique_ptr<smt_base_solver_processt> &solver_process,
139 std::unordered_map<exprt, smt_identifier_termt, irep_hash>
140 &expression_identifiers,
141 std::unordered_map<irep_idt, smt_identifier_termt> &identifier_table)
147 expression_identifiers.emplace(expr,
function.identifier());
148 identifier_table.emplace(symbol_identifier,
function.identifier());
149 solver_process->
send(
function);
157 std::unordered_set<exprt, irep_hash> seen_expressions =
159 .map([](
const std::pair<exprt, smt_identifier_termt> &expr_identifier) {
160 return expr_identifier.first;
162 std::stack<exprt> to_be_defined;
163 const auto push_dependencies_needed = [&](
const exprt &expr) {
167 if(!seen_expressions.insert(dependency).second)
170 to_be_defined.push(dependency);
174 push_dependencies_needed(expr);
175 while(!to_be_defined.empty())
177 const exprt current = to_be_defined.top();
178 if(push_dependencies_needed(current))
180 if(
const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(current))
182 const irep_idt &identifier = symbol_expr->get_identifier();
183 const symbolt *symbol =
nullptr;
188 symbol_expr->get_identifier(),
195 if(push_dependencies_needed(symbol->
value))
204 else if(
const auto array_expr = expr_try_dynamic_cast<array_exprt>(current))
207 const auto array_of_expr = expr_try_dynamic_cast<array_of_exprt>(current))
212 const auto nondet_symbol =
213 expr_try_dynamic_cast<nondet_symbol_exprt>(current))
217 nondet_symbol->get_identifier(),
230 const std::unordered_map<exprt, smt_identifier_termt, irep_hash>
231 &expression_identifiers)
234 auto find_result = expression_identifiers.find(node);
235 if(find_result == expression_identifiers.cend())
237 const auto type = find_result->first.type();
238 node =
symbol_exprt{find_result->second.identifier(), type};
245 std::unique_ptr<smt_base_solver_processt> _solver_process,
248 number_of_solver_calls{0},
249 solver_process(std::move(_solver_process)),
250 log{message_handler},
253 solver_process->send(
256 solver_process->send(object_size_function.declaration);
274 function.identifier().identifier(),
function.identifier());
284 if(
const auto with_expr = expr_try_dynamic_cast<with_exprt>(expr_node))
286 const auto index_expr = with_expr->where();
287 const auto index_term = convert_expr_to_smt(index_expr);
288 const auto index_identifier =
"index_" + std::to_string(index_sequence());
289 const auto index_definition =
290 smt_define_function_commandt{index_identifier, {}, index_term};
303 const exprt substituted =
322 debug <<
"`handle` -\n " << expr.pretty(2, 0) << messaget::eom;
330 const std::unordered_map<exprt, smt_identifier_termt, irep_hash>
331 &expression_handle_identifiers,
332 const std::unordered_map<exprt, smt_identifier_termt, irep_hash>
333 &expression_identifiers)
335 const auto handle_find_result = expression_handle_identifiers.find(expr);
336 if(handle_find_result != expression_handle_identifiers.cend())
337 return handle_find_result->second;
338 const auto expr_find_result = expression_identifiers.find(expr);
339 if(expr_find_result != expression_identifiers.cend())
340 return expr_find_result->second;
349 type.
is_complete(),
"Array size is required for getting array values.");
350 const auto size = numeric_cast<std::size_t>(
get(type.
size()));
353 "Size of array must be convertible to std::size_t for getting array value");
354 std::vector<exprt> elements;
356 elements.reserve(*size);
357 for(std::size_t index = 0; index < size; ++index)
374 const typet &type)
const
380 if(!get_value_response)
383 "Expected get-value response from solver, but received - " +
386 if(get_value_response->pairs().size() > 1)
389 "Expected single valuation pair in get-value response from solver, but "
390 "received multiple pairs - " +
394 get_value_response->pairs()[0].get().value(), type);
400 debug <<
"`get` - \n " + expr.pretty(2, 0) << messaget::eom;
403 if(
const auto index_expr = expr_try_dynamic_cast<index_exprt>(expr))
426 "Objects in expressions being read should already be tracked from "
427 "point of being set/handled.");
436 const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(expr);
438 symbol_expr,
"Unhandled expressions are expected to be symbols");
447 <<
"`get` attempted for unknown symbol, with identifier - \n"
452 if(
const auto array_type = type_try_dynamic_cast<array_typet>(expr.
type()))
454 if(array_type->is_incomplete())
456 return get_expr(*descriptor, *array_type);
462 std::ostream &out)
const
470 return "incremental SMT2 solving via " +
solver_process->description();
483 debug <<
"`set_to` (" << std::string{value ?
"true" :
"false"} <<
") -\n "
487 define_dependent_functions(expr);
488 auto converted_term = [&]() ->
smt_termt {
489 const auto expression_handle_identifier =
490 expression_handle_identifiers.
find(expr);
491 if(expression_handle_identifier != expression_handle_identifiers.cend())
492 return expression_handle_identifier->second;
502 const std::vector<exprt> &assumptions)
504 for(
const auto &assumption : assumptions)
507 "pushing of assumption:\n " + assumption.pretty(2, 0));
#define UNREACHABLE
This should be used to mark dead code.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
void define_dependent_functions(const exprt &expr)
Defines any functions which expr depends on, which have not yet been defined, along with their depend...
bool can_cast_expr< symbol_exprt >(const exprt &base)
make_applicationt make_application
std::unordered_map< irep_idt, smt_identifier_termt > identifier_table
This maps from the unsorted/untyped string/symbol for the identifiers which we have declared in SMT s...
void define_index_identifiers(const exprt &expr)
void send_function_definition(const exprt &expr, const irep_idt &symbol_identifier, const std::unique_ptr< smt_base_solver_processt > &solver_process, std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_identifiers, std::unordered_map< irep_idt, smt_identifier_termt > &identifier_table)
Stores identifiers in unescaped and unquoted form.
void track_expression_objects(const exprt &expression, const namespacet &ns, smt_object_mapt &object_map)
Finds all the object expressions in the given expression and adds them to the object map for cases wh...
#define UNIMPLEMENTED_FEATURE(FEATURE)
The type of an expression, extends irept.
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Information the decision procedure holds about each object.
const irept & find(const irep_idt &name) const
static smt_termt convert_expr_to_smt(const symbol_exprt &symbol_expr)
void push() override
Push a new context on the stack This context becomes a child context nested in the current context.
static smt_responset get_response_to_command(smt_base_solver_processt &solver_process, const smt_commandt &command, const std::unordered_map< irep_idt, smt_identifier_termt > &identifier_table)
Issues a command to the solving process which is expected to optionally return a success status follo...
std::string decision_procedure_text() const override
Return a textual description of the decision procedure.
Base class for all expressions.
static const smt_function_application_termt::factoryt< selectt > select
static const smt_function_application_termt::factoryt< nott > make_not
const sub_classt * cast() const &
const array_typet & type() const
resultt dec_solve() override
Run the decision procedure to solve the problem.
std::size_t get_number_of_solver_calls() const override
Return the number of incremental solver calls.
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Expression to hold a symbol (variable)
bool can_cast_expr< array_exprt >(const exprt &base)
bitvector_typet index_type()
static decision_proceduret::resultt lookup_decision_procedure_result(const smt_check_sat_response_kindt &response_kind)
smt_object_mapt object_map
This map is used to track object related state.
void print_assignment(std::ostream &out) const override
Print satisfying assignment to out.
const exprt & size() const
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
typet & type()
Return the type of the expression.
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
const array_typet & type() const
exprt get_expr(const smt_termt &descriptor, const typet &type) const
Gets the value of descriptor from the solver and returns the solver response expressed as an exprt of...
const std::string & id2string(const irep_idt &d)
static optionalt< smt_termt > get_identifier(const exprt &expr, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_handle_identifiers, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_identifiers)
class smt2_incremental_decision_proceduret::sequencet handle_sequence
static optionalt< std::string > get_problem_messages(const smt_responset &response)
#define PRECONDITION(CONDITION)
bool can_cast_expr< array_of_exprt >(const exprt &base)
type_size_mapt pointer_sizes_map
Precalculated type sizes used for pointer arithmetic.
Array constructor from single element.
bool can_cast_type< array_typet >(const typet &type)
Check whether a reference to a typet is a array_typet.
size_t number_of_solver_calls
The number of times dec_solve() has been called.
exprt construct_value_expr_from_smt(const smt_termt &value_term, const typet &type_to_construct)
Given a value_term and a type_to_construct, this function constructs a value exprt with a value based...
irep_idt identifier() const
smt_commandt make_definition(std::size_t unique_id, smt_termt size) const
Makes the command to define the resulting size of calling the object size function with unique_id.
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
exprt get(const exprt &expr) const override
Return expr with variables replaced by values from satisfying assignment if available.
nonstd::optional< T > optionalt
bool objects_are_already_tracked(const exprt &expression, const smt_object_mapt &object_map)
Finds whether all base object expressions in the given expression are already tracked in the given ob...
resultt
Result of running the decision procedure.
smt_object_sizet object_size_function
Implementation of the SMT formula for the object size function.
void ensure_handle_for_expr_defined(const exprt &expr)
exprt handle(const exprt &expr) override
Generate a handle, which is an expression that has the same value as the argument in any model that i...
bool can_cast_type< bool_typet >(const typet &base)
exprt value
Initial value of symbol.
smt2_incremental_decision_proceduret(const namespacet &_ns, std::unique_ptr< smt_base_solver_processt > solver_process, message_handlert &message_handler)
messaget log
For reporting errors, warnings and debugging information back to the user.
void pop() override
Pop whatever is on top of the stack.
const namespacet & ns
Namespace for looking up the expressions which symbol_exprts relate to.
const sub_classt * cast() const &
void conditional_output(mstreamt &mstream, const std::function< void(mstreamt &)> &output_generator) const
Generate output to message_stream using output_generator if the configured verbosity is at least as h...
void visit_pre(std::function< void(exprt &)>)
void define_array_function(const t_exprt &array)
Defines a function of array sort and asserts the element values from array_exprt or array_of_exprt.
bool can_cast_expr< nondet_symbol_exprt >(const exprt &base)
virtual void send(const smt_commandt &command)=0
Converts given SMT2 command to SMT2 string and sends it to the solver process.
void define_object_sizes()
Sends the solver the definitions of the object sizes.
static const smt_function_application_termt::factoryt< equalt > equal
void set_to(const exprt &expr, bool value) override
For a Boolean expression expr, add the constraint 'expr' if value is true, otherwise add 'not expr'.
smt_termt convert_expr_to_smt(const exprt &expr)
Add objects in expr to object_map if needed and convert to smt.
virtual smt_responset receive_response(const std::unordered_map< irep_idt, smt_identifier_termt > &identifier_table)=0
class smt2_incremental_decision_proceduret::sequencet array_sequence
std::unique_ptr< smt_base_solver_processt > solver_process
For handling the lifetime of and communication with the separate SMT solver process.
std::unordered_map< exprt, smt_identifier_termt, irep_hash > expression_handle_identifiers
When the handle(exprt) member function is called, the decision procedure commands the SMT solver to d...
static std::vector< exprt > gather_dependent_expressions(const exprt &expr)
Find all sub expressions of the given expr which need to be expressed as separate smt commands.
const sub_classt * cast() const &
mstreamt & warning() const
void associate_pointer_sizes(const exprt &expression, const namespacet &ns, type_size_mapt &type_size_map, const smt_object_mapt &object_map, const smt_object_sizet::make_applicationt &object_size)
This function populates the (pointer) type -> size map.
std::unordered_map< exprt, smt_identifier_termt, irep_hash > expression_identifiers
As part of the decision procedure's overall translation of CBMCs exprts into SMT terms,...
typet index_type() const
The type of the index expressions into any instance of this type.
static smt_sortt convert_type_to_smt_sort(const bool_typet &type)
Array constructor from list of elements.
ranget< iteratort > make_range(iteratort begin, iteratort end)
static exprt substitute_identifiers(exprt expr, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_identifiers)
Replaces the sub expressions of expr which have been defined as separate functions in the smt solver,...
irep_idt name
The unique identifier.
std::vector< bool > object_size_defined
The size of each object is separately defined as a pre-solving step.
smt_object_mapt initial_smt_object_map()
Constructs an initial object map containing the null object.
const typet & element_type() const
The type of the elements of the array.
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
void initialize_array_elements(const array_exprt &array, const smt_identifier_termt &array_identifier)
Generate and send to the SMT solver clauses asserting that each array element is as specified by arra...