CBMC
Loading...
Searching...
No Matches
replace_symbol.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include "replace_symbol.h"
10
11#include "expr_util.h"
12#include "invariant.h"
13#include "pointer_expr.h"
14#include "std_expr.h"
15
19
23
26 const exprt &new_expr)
27{
29 old_expr.type() == new_expr.type(),
30 "types to be replaced should match. old type:\n" +
31 old_expr.type().pretty() + "\nnew.type:\n" + new_expr.type().pretty());
32 expr_map.insert(std::pair<irep_idt, exprt>(old_expr.identifier(), new_expr));
33}
34
36{
37 PRECONDITION(old_expr.type() == new_expr.type());
38 expr_map[old_expr.identifier()] = new_expr;
39}
40
41
43{
44 expr_mapt::const_iterator it = expr_map.find(s.identifier());
45
46 if(it == expr_map.end())
47 return true;
48
50 s.type() == it->second.type(),
51 "types to be replaced should match. s.type:\n" + s.type().pretty() +
52 "\nit->second.type:\n" + it->second.type().pretty());
54 static_cast<exprt &>(s) = it->second;
55 // back-end generated or internal symbols (like rounding mode) might not have
56 // a source location
57 if(s.source_location().is_nil() && previous_source_location.is_not_nil())
59
60 return false;
61}
62
64{
65 bool result=true; // unchanged
66
67 // first look at type
68
69 const exprt &const_dest(dest);
70 if(have_to_replace(const_dest.type()))
71 if(!replace(dest.type()))
72 result=false;
73
74 // now do expression itself
75
76 if(!have_to_replace(dest))
77 return result;
78
79 if(dest.id()==ID_member)
80 {
82
83 if(!replace(me.struct_op()))
84 result=false;
85 }
86 else if(dest.id()==ID_index)
87 {
89
90 if(!replace(ie.array()))
91 result=false;
92
93 if(!replace(ie.index()))
94 result=false;
95 }
96 else if(dest.id()==ID_address_of)
97 {
99
100 if(!replace(aoe.object()))
101 result=false;
102 }
103 else if(dest.id()==ID_symbol)
104 {
106 return false;
107 }
108 else if(dest.id() == ID_let)
109 {
110 auto &let_expr = to_let_expr(dest);
111
112 // first replace the assigned value expressions
113 for(auto &op : let_expr.values())
114 if(replace(op))
115 result = false;
116
117 // now set up the binding
118 auto old_bindings = bindings;
119 for(auto &variable : let_expr.variables())
120 bindings.insert(variable.identifier());
121
122 // now replace in the 'where' expression
123 if(!replace(let_expr.where()))
124 result = false;
125
126 bindings = std::move(old_bindings);
127 }
128 else if(
129 dest.id() == ID_array_comprehension || dest.id() == ID_exists ||
130 dest.id() == ID_forall || dest.id() == ID_lambda)
131 {
132 auto &binding_expr = to_binding_expr(dest);
133
134 auto old_bindings = bindings;
135 for(auto &binding : binding_expr.variables())
136 bindings.insert(binding.identifier());
137
138 if(!replace(binding_expr.where()))
139 result = false;
140
141 bindings = std::move(old_bindings);
142 }
143 else
144 {
145 Forall_operands(it, dest)
146 if(!replace(*it))
147 result=false;
148 }
149
150 const typet &c_sizeof_type =
151 static_cast<const typet&>(dest.find(ID_C_c_sizeof_type));
152 if(c_sizeof_type.is_not_nil() && have_to_replace(c_sizeof_type))
153 result &= replace(static_cast<typet&>(dest.add(ID_C_c_sizeof_type)));
154
155 const typet &va_arg_type =
156 static_cast<const typet&>(dest.find(ID_C_va_arg_type));
157 if(va_arg_type.is_not_nil() && have_to_replace(va_arg_type))
158 result &= replace(static_cast<typet&>(dest.add(ID_C_va_arg_type)));
159
160 return result;
161}
162
164{
165 if(empty())
166 return false;
167
168 // first look at type
169
170 if(have_to_replace(dest.type()))
171 return true;
172
173 // now do expression itself
174
175 if(dest.id()==ID_symbol)
176 {
177 const irep_idt &identifier = to_symbol_expr(dest).identifier();
178 if(bindings.find(identifier) != bindings.end())
179 return false;
180 else
181 return replaces_symbol(identifier);
182 }
183
184 for(const auto &op : dest.operands())
185 {
186 if(have_to_replace(op))
187 return true;
188 }
189
191
192 if(c_sizeof_type.is_not_nil())
193 if(have_to_replace(static_cast<const typet &>(c_sizeof_type)))
194 return true;
195
197
198 if(va_arg_type.is_not_nil())
199 if(have_to_replace(static_cast<const typet &>(va_arg_type)))
200 return true;
201
202 return false;
203}
204
206{
207 if(!have_to_replace(dest))
208 return true;
209
210 bool result=true;
211
212 if(dest.has_subtype())
213 if(!replace(to_type_with_subtype(dest).subtype()))
214 result=false;
215
216 for(typet &subtype : to_type_with_subtypes(dest).subtypes())
217 {
218 if(!replace(subtype))
219 result=false;
220 }
221
222 if(dest.id()==ID_struct ||
223 dest.id()==ID_union)
224 {
226
227 for(auto &c : struct_union_type.components())
228 if(!replace(c))
229 result=false;
230 }
231 else if(dest.id()==ID_code)
232 {
234 if(!replace(code_type.return_type()))
235 result = false;
236
237 for(auto &p : code_type.parameters())
238 if(!replace(p))
239 result=false;
240
241 const exprt &spec_assigns =
242 static_cast<const exprt &>(dest.find(ID_C_spec_assigns));
243 if(spec_assigns.is_not_nil() && have_to_replace(spec_assigns))
244 result &= replace(static_cast<exprt &>(dest.add(ID_C_spec_assigns)));
245
246 const exprt &spec_frees =
247 static_cast<const exprt &>(dest.find(ID_C_spec_frees));
248 if(spec_frees.is_not_nil() && have_to_replace(spec_frees))
249 result &= replace(static_cast<exprt &>(dest.add(ID_C_spec_frees)));
250
251 const exprt &spec_ensures =
252 static_cast<const exprt &>(dest.find(ID_C_spec_ensures));
253 if(spec_ensures.is_not_nil() && have_to_replace(spec_ensures))
254 result &= replace(static_cast<exprt &>(dest.add(ID_C_spec_ensures)));
255
256 const exprt &spec_requires =
257 static_cast<const exprt &>(dest.find(ID_C_spec_requires));
258 if(spec_requires.is_not_nil() && have_to_replace(spec_requires))
259 result &= replace(static_cast<exprt &>(dest.add(ID_C_spec_requires)));
260 }
261 else if(dest.id()==ID_array)
262 {
264 if(!replace(array_type.size()))
265 result=false;
266 }
267
268 return result;
269}
270
272{
273 if(expr_map.empty())
274 return false;
275
276 if(dest.has_subtype())
277 if(have_to_replace(to_type_with_subtype(dest).subtype()))
278 return true;
279
280 for(const typet &subtype : to_type_with_subtypes(dest).subtypes())
281 {
282 if(have_to_replace(subtype))
283 return true;
284 }
285
286 if(dest.id()==ID_struct ||
287 dest.id()==ID_union)
288 {
291
292 for(const auto &c : struct_union_type.components())
293 if(have_to_replace(c))
294 return true;
295 }
296 else if(dest.id()==ID_code)
297 {
298 const code_typet &code_type=to_code_type(dest);
299 if(have_to_replace(code_type.return_type()))
300 return true;
301
302 for(const auto &p : code_type.parameters())
303 if(have_to_replace(p))
304 return true;
305
306 const exprt &spec_assigns =
307 static_cast<const exprt &>(dest.find(ID_C_spec_assigns));
308 if(spec_assigns.is_not_nil() && have_to_replace(spec_assigns))
309 return true;
310
311 const exprt &spec_ensures =
312 static_cast<const exprt &>(dest.find(ID_C_spec_ensures));
313 if(spec_ensures.is_not_nil() && have_to_replace(spec_ensures))
314 return true;
315
316 const exprt &spec_requires =
317 static_cast<const exprt &>(dest.find(ID_C_spec_requires));
318 if(spec_requires.is_not_nil() && have_to_replace(spec_requires))
319 return true;
320 }
321 else if(dest.id()==ID_array)
322 return have_to_replace(to_array_type(dest).size());
323
324 return false;
325}
326
328 const symbol_exprt &old_expr,
329 const exprt &new_expr)
330{
331 expr_map.emplace(old_expr.identifier(), new_expr);
332}
333
335{
336 expr_mapt::const_iterator it = expr_map.find(s.identifier());
337
338 if(it == expr_map.end())
339 return true;
340
342 static_cast<exprt &>(s) = it->second;
343 // back-end generated or internal symbols (like rounding mode) might not have
344 // a source location
345 if(s.source_location().is_nil() && previous_source_location.is_not_nil())
347
348 return false;
349}
350
352{
353 const exprt &const_dest(dest);
356
357 bool result = true; // unchanged
358
359 // first look at type
360 if(have_to_replace(const_dest.type()))
361 {
364 result = false;
365 }
366
367 // now do expression itself
368
369 if(!have_to_replace(dest))
370 return result;
371
372 if(dest.id() == ID_index)
373 {
375
376 // Could yield non l-value.
377 if(!replace(ie.array()))
378 result = false;
379
381 if(!replace(ie.index()))
382 result = false;
383 }
384 else if(dest.id() == ID_address_of)
385 {
387
389 if(!replace(aoe.object()))
390 result = false;
391 }
392 else
393 {
395 return false;
396 }
397
399
400 const typet &c_sizeof_type =
401 static_cast<const typet &>(dest.find(ID_C_c_sizeof_type));
402 if(c_sizeof_type.is_not_nil() && have_to_replace(c_sizeof_type))
404 static_cast<typet &>(dest.add(ID_C_c_sizeof_type)));
405
406 const typet &va_arg_type =
407 static_cast<const typet &>(dest.find(ID_C_va_arg_type));
408 if(va_arg_type.is_not_nil() && have_to_replace(va_arg_type))
410 static_cast<typet &>(dest.add(ID_C_va_arg_type)));
411
412 return result;
413}
414
416 symbol_exprt &s) const
417{
420 return true;
421
423 return true;
424
425 // Note s_copy is no longer a symbol_exprt due to the replace operation,
426 // and after this line `s` won't be either
428 s = s_copy;
429 // back-end generated or internal symbols (like rounding mode) might not have
430 // a source location
431 if(s.source_location().is_nil() && previous_source_location.is_not_nil())
433
434 return false;
435}
bool replace_symbol_expr(symbol_exprt &dest) const override
bool replace(exprt &dest) const override
Operator to return the address of an object.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
Arrays with given size.
Definition std_types.h:807
Base type of functions.
Definition std_types.h:583
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
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
const source_locationt & source_location() const
Definition expr.h:236
source_locationt & add_source_location()
Definition expr.h:241
Array index operator.
Definition std_expr.h:1431
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const irept & find(const irep_idt &name) const
Definition irep.cpp:93
const irep_idt & id() const
Definition irep.h:388
irept & add(const irep_idt &name)
Definition irep.cpp:103
Extract member of struct or union.
Definition std_expr.h:2866
virtual bool replace(exprt &dest) const
bool empty() const
bool have_to_replace(const exprt &dest) const
void set(const class symbol_exprt &old_expr, const exprt &new_expr)
Sets old_expr to be replaced by new_expr.
std::set< irep_idt > bindings
virtual ~replace_symbolt()
virtual bool replace_symbol_expr(symbol_exprt &dest) const
void insert(const class symbol_exprt &old_expr, const exprt &new_expr)
Sets old_expr to be replaced by new_expr if we don't already have a replacement; otherwise does nothi...
bool replaces_symbol(const irep_idt &id) const
Base type for structs and unions.
Definition std_types.h:62
Expression to hold a symbol (variable)
Definition std_expr.h:132
void identifier(const irep_idt &identifier)
Definition std_expr.h:160
The type of an expression, extends irept.
Definition type.h:29
bool has_subtype() const
Definition type.h:64
bool replace_symbol_expr(symbol_exprt &dest) const override
void insert(const symbol_exprt &old_expr, const exprt &new_expr)
#define Forall_operands(it, expr)
Definition expr.h:28
bool is_assignable(const exprt &expr)
Returns true iff the argument is one of the following:
Definition expr_util.cpp:24
Deprecated expression utility functions.
API to expression classes for Pointers.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
#define PRECONDITION_WITH_DIAGNOSTICS(CONDITION,...)
Definition invariant.h:464
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define PRECONDITION(CONDITION)
Definition invariant.h:463
API to expression classes.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1494
const let_exprt & to_let_expr(const exprt &expr)
Cast an exprt to a let_exprt.
Definition std_expr.h:3383
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:2953
const binding_exprt & to_binding_expr(const exprt &expr)
Cast an exprt to a binding_exprt.
Definition std_expr.h:3233
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:221
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:214
const type_with_subtypest & to_type_with_subtypes(const typet &type)
Definition type.h:252
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition type.h:208