CBMC
Loading...
Searching...
No Matches
smt2_incremental_decision_procedure.cpp
Go to the documentation of this file.
1// Author: Diffblue Ltd.
2
4
5#include <util/arith_tools.h>
8#include <util/c_types.h>
9#include <util/range.h>
10#include <util/simplify_expr.h>
11#include <util/std_expr.h>
13
26
27#include <stack>
28#include <unordered_set>
29
33 smt_base_solver_processt &solver_process,
34 const smt_commandt &command,
35 const std::unordered_map<irep_idt, smt_identifier_termt> &identifier_table)
36{
37 solver_process.send(command);
38 auto response = solver_process.receive_response(identifier_table);
40 return solver_process.receive_response(identifier_table);
41 else
42 return response;
43}
44
47static std::optional<std::string>
49{
50 if(const auto error = response.cast<smt_error_responset>())
51 {
52 return "SMT solver returned an error message - " +
53 id2string(error->message());
54 }
56 {
57 return {"SMT solver does not support given command."};
58 }
59 return {};
60}
61
74static std::vector<exprt> gather_dependent_expressions(const exprt &root_expr)
75{
76 std::vector<exprt> dependent_expressions;
77
78 std::stack<const exprt *> stack;
79 stack.push(&root_expr);
80
81 while(!stack.empty())
82 {
83 const exprt &expr_node = *stack.top();
84 stack.pop();
85 if(
91 {
93 }
94 // The decision procedure does not depend on the values inside address of
95 // code typed expressions. We can build the address without knowing the
96 // value at that memory location. In this case the hypothetical compiled
97 // machine instructions at the address are not relevant to solving, only
98 // representing *which* function a pointer points to is needed.
100 if(address_of && can_cast_type<code_typet>(address_of->object().type()))
101 continue;
102 for(auto &operand : expr_node.operands())
103 stack.push(&operand);
104 }
106}
107
109 const array_exprt &array,
111{
113 const std::vector<exprt> &elements = array.operands();
114 const typet &index_type = array.type().index_type();
115 for(std::size_t i = 0; i < elements.size(); ++i)
116 {
117 const smt_termt index = convert_expr_to_smt(from_integer(i, index_type));
120 convert_expr_to_smt(elements.at(i)))};
122 }
123}
124
142
149
150template <typename t_exprt>
152 const t_exprt &array)
153{
154 const smt_sortt array_sort = convert_type_to_smt_sort(array.type());
155 INVARIANT(
157 "Converting array typed expression to SMT should result in a term of array "
158 "sort.");
160 "array_" + std::to_string(array_sequence()), array_sort};
164}
165
167 const exprt &expr,
169 const std::unique_ptr<smt_base_solver_processt> &solver_process,
170 std::unordered_map<exprt, smt_identifier_termt, irep_hash>
171 &expression_identifiers,
172 std::unordered_map<irep_idt, smt_identifier_termt> &identifier_table)
173{
174 const smt_declare_function_commandt function{
177 {}};
178 expression_identifiers.emplace(expr, function.identifier());
179 identifier_table.emplace(symbol_identifier, function.identifier());
180 solver_process->send(function);
181}
182
186 const exprt &expr)
187{
188 std::unordered_set<exprt, irep_hash> seen_expressions =
190 .map([](const std::pair<exprt, smt_identifier_termt> &expr_identifier) {
191 return expr_identifier.first;
192 });
193 std::stack<exprt> to_be_defined;
194 const auto push_dependencies_needed = [&](const exprt &expr) {
195 bool result = false;
196 for(const auto &dependency : gather_dependent_expressions(expr))
197 {
198 if(!seen_expressions.insert(dependency).second)
199 continue;
200 result = true;
202 }
203 return result;
204 };
206 while(!to_be_defined.empty())
207 {
208 const exprt current = to_be_defined.top();
209 if(push_dependencies_needed(current))
210 continue;
211 if(const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(current))
212 {
214 *symbol_expr,
215 symbol_expr->identifier(),
219 }
220 else if(const auto array_expr = expr_try_dynamic_cast<array_exprt>(current))
222 else if(
224 {
226 }
227 else if(
228 const auto string = expr_try_dynamic_cast<string_constantt>(current))
229 {
230 define_array_function(*string);
231 }
232 else if(
233 const auto nondet_symbol =
235 {
238 nondet_symbol->get_identifier(),
242 }
243 to_be_defined.pop();
244 }
245}
246
250 exprt expr,
251 const std::unordered_map<exprt, smt_identifier_termt, irep_hash>
252 &expression_identifiers)
253{
254 expr.visit_pre([&](exprt &node) -> void {
255 auto find_result = expression_identifiers.find(node);
256 if(find_result == expression_identifiers.cend())
257 return;
258 const auto type = find_result->first.type();
259 node = symbol_exprt{find_result->second.identifier(), type};
260 });
261 return expr;
262}
263
265 const namespacet &_ns,
266 std::unique_ptr<smt_base_solver_processt> _solver_process,
267 message_handlert &message_handler)
268 : ns{_ns},
269 number_of_solver_calls{0},
270 solver_process(std::move(_solver_process)),
271 log{message_handler},
272 object_map{initial_smt_object_map()},
273 struct_encoding{_ns}
274{
275 solver_process->send(
280}
281
283{
284 expr.visit_pre([&ns](exprt &expr) {
285 if(
286 auto prophecy_r_or_w_ok =
288 {
289 expr = simplify_expr(prophecy_r_or_w_ok->lower(ns), ns);
290 }
291 else if(
294 {
295 expr = simplify_expr(prophecy_pointer_in_range->lower(ns), ns);
296 }
297 });
298 return expr;
299}
300
302{
303 expr.visit_pre([](exprt &expr) {
304 if(auto zero_extend = expr_try_dynamic_cast<zero_extend_exprt>(expr))
305 {
306 expr = zero_extend->lower();
307 }
308 });
309 return expr;
310}
311
314static bool has_floatbv_type(const exprt &expr)
315{
316 if(expr.type().id() == ID_floatbv)
317 return true;
318 for(const auto &op : expr.operands())
319 {
320 if(op.type().id() == ID_floatbv)
321 return true;
322 }
323 return false;
324}
325
331{
332 // Recurse into operands first (bottom-up)
333 for(auto &op : expr.operands())
334 op = lower_floatbv(op);
335
336 // Only attempt float_bv conversion on expressions involving floats
337 if(has_floatbv_type(expr))
338 {
339 const float_bvt float_bv;
340 const exprt converted = float_bv.convert(expr);
341 if(!converted.is_nil())
342 return converted;
343 }
344
345 return expr;
346}
347
349 const exprt &in_expr)
350{
351 if(
354 {
355 return;
356 }
357
359
362 "B" + std::to_string(handle_sequence()),
363 {},
365 expression_handle_identifiers.emplace(in_expr, function.identifier());
366 identifier_table.emplace(
367 function.identifier().identifier(), function.identifier());
368 solver_process->send(function);
369}
370
372 const exprt &expr)
373{
374 expr.visit_post(
375 [&](const exprt &expr_node)
376 {
378 return;
380 {
381 const auto index_expr = with_expr->where();
383 const auto index_identifier =
384 "index_" + std::to_string(index_sequence());
385 const auto index_definition =
388 index_expr, index_definition.identifier());
389 identifier_table.emplace(
390 index_identifier, index_definition.identifier());
391 solver_process->send(
393 }
394 });
395}
396
399{
400 root_expr.visit_pre([&](exprt &node) {
402 {
403 const auto instance = "padding_" + std::to_string(padding_sequence());
404 const auto term =
407 node = symbol_exprt{instance, node.type()};
408 }
409 });
410 return root_expr;
411}
412
434
436{
438 debug << "`handle` -\n " << expr.pretty(2, 0) << messaget::eom;
439 });
441 return expr;
442}
443
444std::optional<smt_termt>
446{
447 // Lookup the non-lowered form first.
450 return handle_find_result->second;
451 const auto expr_find_result = expression_identifiers.find(expr);
453 return expr_find_result->second;
454
455 // If that didn't yield any results, then try the lowered form.
456 const exprt lowered_expr = lower(expr);
457 const auto lowered_handle_find_result =
460 return lowered_handle_find_result->second;
461 const auto lowered_expr_find_result =
464 return lowered_expr_find_result->second;
465 return {};
466}
467
469 const smt_termt &array,
470 const array_typet &type) const
471{
472 INVARIANT(
473 type.is_complete(), "Array size is required for getting array values.");
474 const auto size = numeric_cast<std::size_t>(get(type.size()));
475 INVARIANT(
476 size,
477 "Size of array must be convertible to std::size_t for getting array value");
478 std::vector<exprt> elements;
479 const auto index_type = type.index_type();
480 elements.reserve(*size);
481 for(std::size_t index = 0; index < size; ++index)
482 {
484 from_integer(index, index_type),
489 auto element = get_expr(
491 if(!element)
492 return {};
493 elements.push_back(std::move(*element));
494 }
495 return array_exprt{elements, type};
496}
497
499 const smt_termt &struct_term,
500 const struct_tag_typet &type) const
501{
502 const auto encoded_result =
504 if(!encoded_result)
505 return {};
506 return {struct_encoding.decode(*encoded_result, type)};
507}
508
510 const smt_termt &union_term,
511 const union_tag_typet &type) const
512{
513 const auto encoded_result =
515 if(!encoded_result)
516 return {};
517 return {struct_encoding.decode(*encoded_result, type)};
518}
519
521 const smt_termt &descriptor,
522 const typet &type) const
523{
525 {
526 if(array_type->is_incomplete())
527 return {};
528 return get_expr(descriptor, *array_type);
529 }
531 {
532 return get_expr(descriptor, *struct_type);
533 }
535 {
536 return get_expr(descriptor, *union_type);
537 }
543 {
545 "Expected get-value response from solver, but received - " +
546 response.pretty()};
547 }
548 if(get_value_response->pairs().size() > 1)
549 {
551 "Expected single valuation pair in get-value response from solver, but "
552 "received multiple pairs - " +
553 response.pretty()};
554 }
556 get_value_response->pairs()[0].get().value(), type, ns);
557}
558
559// This is a fall back which builds resulting expression based on getting the
560// values of its operands. It is used during trace building in the case where
561// certain kinds of expression appear on the left hand side of an
562// assignment. For example in the following trace assignment -
563// `byte_extract_little_endian(x, offset) = 1`
564// `::get` will be called on `byte_extract_little_endian(x, offset)` and
565// we build a resulting expression where `x` and `offset` are substituted
566// with their values.
568 const exprt &expr,
569 const stack_decision_proceduret &decision_procedure)
570{
571 exprt copy = expr;
572 for(auto &op : copy.operands())
573 {
574 exprt eval_op = decision_procedure.get(op);
575 if(eval_op.is_nil())
576 return nil_exprt{};
577 op = std::move(eval_op);
578 }
579 return copy;
580}
581
583{
585 debug << "`get` - \n " + expr.pretty(2, 0) << messaget::eom;
586 });
587 auto descriptor = [&]() -> std::optional<smt_termt> {
589 {
590 const auto array = get_identifier(index_expr->array());
591 const auto index = get_identifier(index_expr->index());
592 if(!array || !index)
593 return {};
594 return smt_array_theoryt::select(*array, *index);
595 }
597 {
599 }
600 const exprt lowered = lower(expr);
602 {
603 INVARIANT(
605 "Objects in expressions being read should already be tracked from "
606 "point of being set/handled.");
607 return ::convert_expr_to_smt(
608 lowered,
613 }
614 return {};
615 }();
616 if(!descriptor)
617 {
620 "symbol expressions must have a known value",
622 return build_expr_based_on_getting_operands(expr, *this);
623 }
624 if(auto result = get_expr(*descriptor, expr.type()))
625 return std::move(*result);
626 return expr;
627}
628
630 std::ostream &out) const
631{
632 UNIMPLEMENTED_FEATURE("printing of assignments.");
633}
634
635std::string
637{
638 return "incremental SMT2 solving via " + solver_process->description();
639}
640
641std::size_t
646
648 const exprt &in_expr,
649 bool value)
650{
652 debug << "`set_to` (" << std::string{value ? "true" : "false"} << ") -\n "
653 << in_expr.pretty(2, 0) << messaget::eom;
654 });
655 const exprt lowered_expr = lower(in_expr);
657
658 define_dependent_functions(lowered_expr);
659 auto converted_term = [&]() -> smt_termt {
661 expression_handle_identifiers.find(lowered_expr);
662 if(expression_handle_identifier != expression_handle_identifiers.cend())
663 return expression_handle_identifier->second;
664 else
666 }();
667 if(!value)
669 solver_process->send(smt_assert_commandt{converted_term});
670}
671
673 const std::vector<exprt> &assumptions)
674{
675 for(const auto &assumption : assumptions)
676 {
678 "pushing of assumption:\n " + assumption.pretty(2, 0));
679 }
680 UNIMPLEMENTED_FEATURE("`push` of empty assumptions.");
681}
682
687
692
705
707{
709 for(const auto &key_value : object_map)
710 {
711 const decision_procedure_objectt &object = key_value.second;
712 if(object_properties_defined[object.unique_id])
713 continue;
714 else
715 object_properties_defined[object.unique_id] = true;
716 define_dependent_functions(object.size);
718 object.unique_id, convert_expr_to_smt(object.size)));
720 object.unique_id, object.is_dynamic));
721 }
722}
723
725{
730 ns),
731 ns));
733 if(lowered != expression)
734 debug << "lowered to -\n " << lowered.pretty(2, 0) << messaget::eom;
735 });
736 return lowered;
737}
738
741{
746 if(const auto check_sat_response = result.cast<smt_check_sat_responset>())
747 {
748 if(check_sat_response->kind().cast<smt_unknown_responset>())
749 log.error() << "SMT2 solver returned \"unknown\"" << messaget::eom;
751 }
752 if(const auto problem = get_problem_messages(result))
754 throw analysis_exceptiont{"Unexpected kind of response from SMT solver."};
755}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
API to expression classes for bitvectors.
Expression classes for byte-level operators.
exprt lower_byte_operators(const exprt &src, const namespacet &ns)
Rewrite an expression possibly containing byte-extract or -update expressions to more fundamental ope...
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
Array constructor from list of elements.
Definition std_expr.h:1570
const array_typet & type() const
Definition std_expr.h:1577
Array constructor from single element.
Definition std_expr.h:1512
const array_typet & type() const
Definition std_expr.h:1519
exprt & what()
Definition std_expr.h:1529
Arrays with given size.
Definition std_types.h:807
typet index_type() const
The type of the index expressions into any instance of this type.
Definition std_types.cpp:34
bool is_complete() const
Definition std_types.h:852
const exprt & size() const
Definition std_types.h:840
const typet & element_type() const
The type of the elements of the array.
Definition std_types.h:827
virtual exprt get(const exprt &) const =0
Return expr with variables replaced by values from satisfying assignment if available.
resultt
Result of running the decision procedure.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:57
void visit_pre(std::function< void(exprt &)>)
Definition expr.cpp:148
typet & type()
Return the type of the expression.
Definition expr.h:85
void visit_post(std::function< void(exprt &)>)
These are post-order traversal visitors, i.e., the visitor is executed on a node after its children h...
Definition expr.cpp:119
operandst & operands()
Definition expr.h:95
const irep_idt & id() const
Definition irep.h:388
bool is_nil() const
Definition irep.h:368
mstreamt & error() const
Definition message.h:391
mstreamt & debug() const
Definition message.h:421
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...
Definition message.cpp:139
static eomt eom
Definition message.h:289
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
The NIL expression.
Definition std_expr.h:3144
smt_object_sizet object_size_function
Implementation of the SMT formula for the object size function.
size_t number_of_solver_calls
The number of times dec_solve() has been called.
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,...
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...
exprt lower(exprt expression) const
Performs a combination of transformations which reduces the set of possible expression forms by expre...
exprt substitute_defined_padding(exprt expr)
In the case where lowering passes insert instances of the anonymous nondet_padding_exprt,...
std::optional< 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...
std::size_t get_number_of_solver_calls() const override
Return the number of incremental solver calls.
std::string decision_procedure_text() const override
Return a textual description of the decision procedure.
smt_is_dynamic_objectt is_dynamic_object_function
Implementation of the SMT formula for the dynamic object status lookup function.
void ensure_handle_for_expr_defined(const exprt &expr)
If a function has not been defined for handling expr, then a new function is defined.
void define_dependent_functions(const exprt &expr)
Defines any functions which expr depends on, which have not yet been defined, along with their depend...
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...
void print_assignment(std::ostream &out) const override
Print satisfying assignment to out.
resultt dec_solve(const exprt &) override
Implementation of the decision procedure.
void push() override
Push a new context on the stack This context becomes a child context nested in the current context.
messaget log
For reporting errors, warnings and debugging information back to the user.
void pop() override
Pop whatever is on top of the stack.
std::optional< smt_termt > get_identifier(const exprt &expr) const
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...
smt_object_mapt object_map
This map is used to track object related state.
std::vector< bool > object_properties_defined
The size of each object and the dynamic object stus is separately defined as a pre-solving step.
void define_object_properties()
Sends the solver the definitions of the object sizes and dynamic memory statuses.
smt_termt convert_expr_to_smt(const exprt &expr)
Add objects in expr to object_map if needed and convert to smt.
const namespacet & ns
Namespace for looking up the expressions which symbol_exprts relate to.
exprt get(const exprt &expr) const override
Return expr with variables replaced by values from satisfying assignment if available.
type_size_mapt pointer_sizes_map
Precalculated type sizes used for pointer arithmetic.
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...
std::unique_ptr< smt_base_solver_processt > solver_process
For handling the lifetime of and communication with the separate SMT solver process.
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'.
smt2_incremental_decision_proceduret(const namespacet &_ns, std::unique_ptr< smt_base_solver_processt > solver_process, message_handlert &message_handler)
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.
static const smt_function_application_termt::factoryt< selectt > select
virtual void send(const smt_commandt &command)=0
Converts given SMT2 command to SMT2 string and sends it to the solver process.
virtual smt_responset receive_response(const std::unordered_map< irep_idt, smt_identifier_termt > &identifier_table)=0
static const smt_function_application_termt::factoryt< equalt > equal
static const smt_function_application_termt::factoryt< nott > make_not
Stores identifiers in unescaped and unquoted form.
Definition smt_terms.h:93
const sub_classt * cast() const &
typet encode(typet type) const
exprt decode(const exprt &encoded, const struct_tag_typet &original_type) const
Reconstructs a struct expression of the original_type using the data from the bit vector encoded expr...
A struct tag type, i.e., struct_typet with an identifier.
Definition std_types.h:493
Expression to hold a symbol (variable)
Definition std_expr.h:132
The type of an expression, extends irept.
Definition type.h:29
A union tag type, i.e., union_typet with an identifier.
Definition c_types.h:199
exprt construct_value_expr_from_smt(const smt_termt &value_term, const typet &type_to_construct, const namespacet &ns)
Given a value_term and a type_to_construct, this function constructs a value exprt with a value based...
static smt_sortt convert_type_to_smt_sort(const bool_typet &type)
static smt_termt convert_expr_to_smt(const symbol_exprt &symbol_expr)
exprt lower_enum(exprt expr, const namespacet &ns)
Function to lower expr and its sub-expressions containing enum types.
exprt float_bv(const exprt &src)
Definition float_bv.h:202
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
double log(double x)
Definition math.c:2416
STL namespace.
Expressions for use in incremental SMT2 decision procedure.
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...
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...
smt_object_mapt initial_smt_object_map()
Constructs an initial object map containing the null object.
static struct_typet::componentst::iterator pad(struct_typet::componentst &components, struct_typet::componentst::iterator where, std::size_t pad_bits)
Definition padding.cpp:154
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition range.h:522
exprt simplify_expr(exprt src, const namespacet &ns)
static exprt lower_floatbv(exprt expr)
Lower floating-point operations to bitvector expressions.
static exprt lower_rw_ok_pointer_in_range(exprt expr, const namespacet &ns)
static bool has_floatbv_type(const exprt &expr)
Check whether an expression or any of its immediate operands has floating-point bitvector type.
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)
static std::optional< std::string > get_problem_messages(const smt_responset &response)
Returns a message string describing the problem in the case where the response from the solver is an ...
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,...
static decision_proceduret::resultt lookup_decision_procedure_result(const smt_check_sat_response_kindt &response_kind)
static exprt build_expr_based_on_getting_operands(const exprt &expr, const stack_decision_proceduret &decision_procedure)
static std::vector< exprt > gather_dependent_expressions(const exprt &root_expr)
Find all sub expressions of the given expr which need to be expressed as separate smt commands.
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...
static exprt lower_zero_extend(exprt expr, const namespacet &ns)
Decision procedure with incremental SMT2 solving.
#define UNIMPLEMENTED_FEATURE(FEATURE)
Definition invariant.h:549
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Same as invariant, with one or more diagnostics attached Diagnostics can be of any type that has a sp...
Definition invariant.h:437
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
API to expression classes.
const array_exprt & to_array_expr(const exprt &expr)
Cast an exprt to an array_exprt.
Definition std_expr.h:1614
Information the decision procedure holds about each object.
make_applicationt make_application
smt_declare_function_commandt declaration
The command for declaring the is_dynamic_object function.
smt_commandt make_definition(std::size_t unique_id, bool is_dynamic_object) const
Makes the command to define the resulting is_dynamic_object status for calls to the is_dynamic_object...
make_applicationt make_application
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.
smt_declare_function_commandt declaration
The command for declaring the object size function.
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, const smt_is_dynamic_objectt::make_applicationt &is_dynamic_object)
This function populates the (pointer) type -> size map.
Utilities for making a map of types to associated sizes.