ESBMC
Efficient SMT-based Context-Bounded Model Checker
Loading...
Searching...
No Matches
builder.h
Go to the documentation of this file.
1#pragma once
2
3#include <nlohmann/json.hpp>
4#include <util/irep/expr.h>
5
7class symbol_id;
8class symbolt;
9
11{
12public:
14 python_converter &converter,
15 const nlohmann::json &call);
16
17 exprt build() const;
18
19 /*
20 * Extracts information from the call to populate the function_id attribute.
21 */
23
24 /*
25 * Checks if assume (__ESBMC_assume or __VERIFIER_assume) function is being
26 * invoked.
27 */
28 bool is_assume_call(const symbol_id &function_id) const;
29
30 /*
31 * Checks if __ESBMC_assert function is being invoked.
32 */
33 bool is_assert_call(const symbol_id &function_id) const;
34
35 /*
36 * Checks if __ESBMC_cover function is being invoked.
37 */
38 bool is_cover_call(const symbol_id &function_id) const;
39
40 /*
41 * Checks if __ESBMC_unreachable function is being invoked.
42 */
43 bool is_unreachable_call(const symbol_id &function_id) const;
44
45 /*
46 * Checks if the Python len() function is being invoked.
47 */
48 bool is_len_call(const symbol_id &function_id) const;
49
50 /*
51 * len() of an operand that lowered to a bitvector: length 1 for a single
52 * character, TypeError for a number, which defines no __len__ (#6261).
53 */
54 exprt len_of_bitvector_operand(const nlohmann::json &arg) const;
55
56 /*
57 * Checks if a NumPy function is being invoked.
58 */
59 bool is_numpy_call(const symbol_id &function_id) const;
60
61private:
62 /*
63 * Validates a call to __ESBMC_requires / __ESBMC_ensures / __ESBMC_assigns;
64 * a no-op for any other callee.
65 */
66 void check_contract_call(const symbol_id &function_id) const;
67
70 bool receiver_is_bound_to_none() const;
71 bool nested_function_exists(const symbol_id &sid) const;
72 void use_imported_class_file(
73 symbol_id &function_id,
74 const symbolt &receiver,
75 const std::string &class_name) const;
76
79 void raise_if_none_receiver() const;
80
83 std::string instance_class_name(const nlohmann::json &node) const;
84
87 bool receiver_class_defines_method() const;
88
91 exprt build_method_call_on_receiver() const;
92
95 exprt str_method_on_number_error() const;
96
97 /*
98 * Rejects a contract clause that does not lower to a pure expression.
99 * Throws with a diagnostic naming the offending construct.
100 */
101 /*
102 * Rejects a name a clause may not mention: the return value in a
103 * precondition or in a None-returning function, or a value whose type
104 * could not be determined.
105 */
106 void check_clause_name(const nlohmann::json &node, const std::string &clause)
107 const;
108
109 const symbolt *clause_name_symbol(const std::string &name) const;
110
111 bool is_pure_list_query(const nlohmann::json &node) const;
112
113 void
114 check_clause_planted_nothing(const std::string &clause, size_t planted) const;
115
116 void check_contract_clause(
117 const nlohmann::json &node,
118 const std::string &clause) const;
119
120 /*
121 * Validates a contract-intrinsic call and, for the ones that denote a value,
122 * builds it. Registers the bodiless symbol the clause intrinsics need.
123 * Returns nullopt for any callee that is not one, or that denotes no value.
124 */
125 std::optional<exprt>
126 build_contract_intrinsic(const symbol_id &function_id) const;
127
128 /*
129 * __ESBMC_old(x) as the C macro spells it: the value x held before the body
130 * ran. Throws when x is not a scalar the frontend can snapshot.
131 */
132 exprt build_old_snapshot() const;
133
135 void check_assigns_targets() const;
136
138 exprt build_assigns_call() const;
139
140 /*
141 * Whether the name is a parameter of the function being converted, or a
142 * module-level global. Only those have a value from before the body ran.
143 */
144 bool names_enclosing_parameter(const std::string &name) const;
145 bool names_module_global(const std::string &name) const;
146
147 /*
148 * Return type of the function currently being converted; nil when there is
149 * no enclosing function.
150 */
151 typet enclosing_return_type() const;
152
153 /*
154 * The class of a method call's receiver that is not a plain name. For an
155 * item of a list of class instances (`xs[i].m()`) it is their class, so
156 * the call dispatches as `x = xs[i]; x.m()` does; otherwise "str". Throws
157 * when the list's items are not known to share one class, since no single
158 * method can then be chosen statically.
159 */
160 std::string subscript_receiver_class(const nlohmann::json &receiver) const;
161
169 std::string call_receiver_class(const nlohmann::json &inner_call) const;
170
171 python_converter &converter_;
172 const nlohmann::json &call_;
173};
Definition expr.h:34
bool is_unreachable_call(const symbol_id &function_id) const
Definition builder.cpp:666
function_call_builder(python_converter &converter, const nlohmann::json &call)
Definition builder.cpp:626
bool is_len_call(const symbol_id &function_id) const
Definition builder.cpp:672
exprt len_of_bitvector_operand(const nlohmann::json &arg) const
Definition builder.cpp:1608
bool is_cover_call(const symbol_id &function_id) const
Definition builder.cpp:633
bool is_assume_call(const symbol_id &function_id) const
Definition builder.cpp:655
symbol_id build_function_id() const
Definition builder.cpp:960
bool is_assert_call(const symbol_id &function_id) const
Definition builder.cpp:661
bool is_numpy_call(const symbol_id &function_id) const
Definition builder.cpp:639
exprt build() const
Definition builder.cpp:1850
Main converter for transforming Python AST into ESBMC's intermediate representation.
Definition python_converter.h:76
Definition symbol_id.h:6
Definition symbol.h:12
Definition type.h:9