CBMC
replace_symbol.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: 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 
17 {
18 }
19 
21 {
22 }
23 
25  const symbol_exprt &old_expr,
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>(
33  old_expr.get_identifier(), new_expr));
34 }
35 
36 void replace_symbolt::set(const symbol_exprt &old_expr, const exprt &new_expr)
37 {
38  PRECONDITION(old_expr.type() == new_expr.type());
39  expr_map[old_expr.get_identifier()] = new_expr;
40 }
41 
42 
44 {
45  expr_mapt::const_iterator it = expr_map.find(s.get_identifier());
46 
47  if(it == expr_map.end())
48  return true;
49 
51  s.type() == it->second.type(),
52  "types to be replaced should match. s.type:\n" + s.type().pretty() +
53  "\nit->second.type:\n" + it->second.type().pretty());
54  static_cast<exprt &>(s) = it->second;
55 
56  return false;
57 }
58 
60 {
61  bool result=true; // unchanged
62 
63  // first look at type
64 
65  const exprt &const_dest(dest);
66  if(have_to_replace(const_dest.type()))
67  if(!replace(dest.type()))
68  result=false;
69 
70  // now do expression itself
71 
72  if(!have_to_replace(dest))
73  return result;
74 
75  if(dest.id()==ID_member)
76  {
77  member_exprt &me=to_member_expr(dest);
78 
79  if(!replace(me.struct_op()))
80  result=false;
81  }
82  else if(dest.id()==ID_index)
83  {
84  index_exprt &ie=to_index_expr(dest);
85 
86  if(!replace(ie.array()))
87  result=false;
88 
89  if(!replace(ie.index()))
90  result=false;
91  }
92  else if(dest.id()==ID_address_of)
93  {
95 
96  if(!replace(aoe.object()))
97  result=false;
98  }
99  else if(dest.id()==ID_symbol)
100  {
102  return false;
103  }
104  else if(dest.id() == ID_let)
105  {
106  auto &let_expr = to_let_expr(dest);
107 
108  // first replace the assigned value expressions
109  for(auto &op : let_expr.values())
110  if(replace(op))
111  result = false;
112 
113  // now set up the binding
114  auto old_bindings = bindings;
115  for(auto &variable : let_expr.variables())
116  bindings.insert(variable.get_identifier());
117 
118  // now replace in the 'where' expression
119  if(!replace(let_expr.where()))
120  result = false;
121 
122  bindings = std::move(old_bindings);
123  }
124  else if(
125  dest.id() == ID_array_comprehension || dest.id() == ID_exists ||
126  dest.id() == ID_forall || dest.id() == ID_lambda)
127  {
128  auto &binding_expr = to_binding_expr(dest);
129 
130  auto old_bindings = bindings;
131  for(auto &binding : binding_expr.variables())
132  bindings.insert(binding.get_identifier());
133 
134  if(!replace(binding_expr.where()))
135  result = false;
136 
137  bindings = std::move(old_bindings);
138  }
139  else
140  {
141  Forall_operands(it, dest)
142  if(!replace(*it))
143  result=false;
144  }
145 
146  const typet &c_sizeof_type =
147  static_cast<const typet&>(dest.find(ID_C_c_sizeof_type));
148  if(c_sizeof_type.is_not_nil() && have_to_replace(c_sizeof_type))
149  result &= replace(static_cast<typet&>(dest.add(ID_C_c_sizeof_type)));
150 
151  const typet &va_arg_type =
152  static_cast<const typet&>(dest.find(ID_C_va_arg_type));
153  if(va_arg_type.is_not_nil() && have_to_replace(va_arg_type))
154  result &= replace(static_cast<typet&>(dest.add(ID_C_va_arg_type)));
155 
156  return result;
157 }
158 
160 {
161  if(empty())
162  return false;
163 
164  // first look at type
165 
166  if(have_to_replace(dest.type()))
167  return true;
168 
169  // now do expression itself
170 
171  if(dest.id()==ID_symbol)
172  {
173  const irep_idt &identifier = to_symbol_expr(dest).get_identifier();
174  if(bindings.find(identifier) != bindings.end())
175  return false;
176  else
177  return replaces_symbol(identifier);
178  }
179 
180  forall_operands(it, dest)
181  if(have_to_replace(*it))
182  return true;
183 
184  const irept &c_sizeof_type=dest.find(ID_C_c_sizeof_type);
185 
186  if(c_sizeof_type.is_not_nil())
187  if(have_to_replace(static_cast<const typet &>(c_sizeof_type)))
188  return true;
189 
190  const irept &va_arg_type=dest.find(ID_C_va_arg_type);
191 
192  if(va_arg_type.is_not_nil())
193  if(have_to_replace(static_cast<const typet &>(va_arg_type)))
194  return true;
195 
196  return false;
197 }
198 
200 {
201  if(!have_to_replace(dest))
202  return true;
203 
204  bool result=true;
205 
206  if(dest.has_subtype())
207  if(!replace(to_type_with_subtype(dest).subtype()))
208  result=false;
209 
210  for(typet &subtype : to_type_with_subtypes(dest).subtypes())
211  {
212  if(!replace(subtype))
213  result=false;
214  }
215 
216  if(dest.id()==ID_struct ||
217  dest.id()==ID_union)
218  {
219  struct_union_typet &struct_union_type=to_struct_union_type(dest);
220 
221  for(auto &c : struct_union_type.components())
222  if(!replace(c))
223  result=false;
224  }
225  else if(dest.id()==ID_code)
226  {
227  code_typet &code_type=to_code_type(dest);
228  if(!replace(code_type.return_type()))
229  result = false;
230 
231  for(auto &p : code_type.parameters())
232  if(!replace(p))
233  result=false;
234 
235  const exprt &spec_assigns =
236  static_cast<const exprt &>(dest.find(ID_C_spec_assigns));
237  if(spec_assigns.is_not_nil() && have_to_replace(spec_assigns))
238  result &= replace(static_cast<exprt &>(dest.add(ID_C_spec_assigns)));
239 
240  const exprt &spec_ensures =
241  static_cast<const exprt &>(dest.find(ID_C_spec_ensures));
242  if(spec_ensures.is_not_nil() && have_to_replace(spec_ensures))
243  result &= replace(static_cast<exprt &>(dest.add(ID_C_spec_ensures)));
244 
245  const exprt &spec_ensures_contract =
246  static_cast<const exprt &>(dest.find(ID_C_spec_ensures_contract));
247  if(
248  spec_ensures_contract.is_not_nil() &&
249  have_to_replace(spec_ensures_contract))
250  {
251  result &=
252  replace(static_cast<exprt &>(dest.add(ID_C_spec_ensures_contract)));
253  }
254 
255  const exprt &spec_requires =
256  static_cast<const exprt &>(dest.find(ID_C_spec_requires));
257  if(spec_requires.is_not_nil() && have_to_replace(spec_requires))
258  result &= replace(static_cast<exprt &>(dest.add(ID_C_spec_requires)));
259 
260  const exprt &spec_requires_contract =
261  static_cast<const exprt &>(dest.find(ID_C_spec_requires_contract));
262  if(
263  spec_requires_contract.is_not_nil() &&
264  have_to_replace(spec_requires_contract))
265  {
266  result &=
267  replace(static_cast<exprt &>(dest.add(ID_C_spec_requires_contract)));
268  }
269  }
270  else if(dest.id()==ID_array)
271  {
272  array_typet &array_type=to_array_type(dest);
273  if(!replace(array_type.size()))
274  result=false;
275  }
276 
277  return result;
278 }
279 
281 {
282  if(expr_map.empty())
283  return false;
284 
285  if(dest.has_subtype())
286  if(have_to_replace(to_type_with_subtype(dest).subtype()))
287  return true;
288 
289  for(const typet &subtype : to_type_with_subtypes(dest).subtypes())
290  {
291  if(have_to_replace(subtype))
292  return true;
293  }
294 
295  if(dest.id()==ID_struct ||
296  dest.id()==ID_union)
297  {
298  const struct_union_typet &struct_union_type=
299  to_struct_union_type(dest);
300 
301  for(const auto &c : struct_union_type.components())
302  if(have_to_replace(c))
303  return true;
304  }
305  else if(dest.id()==ID_code)
306  {
307  const code_typet &code_type=to_code_type(dest);
308  if(have_to_replace(code_type.return_type()))
309  return true;
310 
311  for(const auto &p : code_type.parameters())
312  if(have_to_replace(p))
313  return true;
314 
315  const exprt &spec_assigns =
316  static_cast<const exprt &>(dest.find(ID_C_spec_assigns));
317  if(spec_assigns.is_not_nil() && have_to_replace(spec_assigns))
318  return true;
319 
320  const exprt &spec_ensures =
321  static_cast<const exprt &>(dest.find(ID_C_spec_ensures));
322  if(spec_ensures.is_not_nil() && have_to_replace(spec_ensures))
323  return true;
324 
325  const exprt &spec_ensures_contract =
326  static_cast<const exprt &>(dest.find(ID_C_spec_ensures_contract));
327  if(
328  spec_ensures_contract.is_not_nil() &&
329  have_to_replace(spec_ensures_contract))
330  {
331  return true;
332  }
333 
334  const exprt &spec_requires =
335  static_cast<const exprt &>(dest.find(ID_C_spec_requires));
336  if(spec_requires.is_not_nil() && have_to_replace(spec_requires))
337  return true;
338 
339  const exprt &spec_requires_contract =
340  static_cast<const exprt &>(dest.find(ID_C_spec_requires_contract));
341  if(
342  spec_requires_contract.is_not_nil() &&
343  have_to_replace(spec_requires_contract))
344  {
345  return true;
346  }
347  }
348  else if(dest.id()==ID_array)
349  return have_to_replace(to_array_type(dest).size());
350 
351  return false;
352 }
353 
355  const symbol_exprt &old_expr,
356  const exprt &new_expr)
357 {
358  expr_map.emplace(old_expr.get_identifier(), new_expr);
359 }
360 
362 {
363  expr_mapt::const_iterator it = expr_map.find(s.get_identifier());
364 
365  if(it == expr_map.end())
366  return true;
367 
368  static_cast<exprt &>(s) = it->second;
369 
370  return false;
371 }
372 
374 {
375  const exprt &const_dest(dest);
376  if(!require_lvalue && const_dest.id() != ID_address_of)
378 
379  bool result = true; // unchanged
380 
381  // first look at type
382  if(have_to_replace(const_dest.type()))
383  {
384  const set_require_lvalue_and_backupt backup(require_lvalue, false);
386  result = false;
387  }
388 
389  // now do expression itself
390 
391  if(!have_to_replace(dest))
392  return result;
393 
394  if(dest.id() == ID_index)
395  {
396  index_exprt &ie = to_index_expr(dest);
397 
398  // Could yield non l-value.
399  if(!replace(ie.array()))
400  result = false;
401 
402  const set_require_lvalue_and_backupt backup(require_lvalue, false);
403  if(!replace(ie.index()))
404  result = false;
405  }
406  else if(dest.id() == ID_address_of)
407  {
409 
411  if(!replace(aoe.object()))
412  result = false;
413  }
414  else
415  {
417  return false;
418  }
419 
420  const set_require_lvalue_and_backupt backup(require_lvalue, false);
421 
422  const typet &c_sizeof_type =
423  static_cast<const typet &>(dest.find(ID_C_c_sizeof_type));
424  if(c_sizeof_type.is_not_nil() && have_to_replace(c_sizeof_type))
426  static_cast<typet &>(dest.add(ID_C_c_sizeof_type)));
427 
428  const typet &va_arg_type =
429  static_cast<const typet &>(dest.find(ID_C_va_arg_type));
430  if(va_arg_type.is_not_nil() && have_to_replace(va_arg_type))
432  static_cast<typet &>(dest.add(ID_C_va_arg_type)));
433 
434  return result;
435 }
436 
438  symbol_exprt &s) const
439 {
440  symbol_exprt s_copy = s;
442  return true;
443 
444  if(require_lvalue && !is_assignable(s_copy))
445  return true;
446 
447  // Note s_copy is no longer a symbol_exprt due to the replace operation,
448  // and after this line `s` won't be either
449  s = s_copy;
450 
451  return false;
452 }
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:147
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
replace_symbolt::~replace_symbolt
virtual ~replace_symbolt()
Definition: replace_symbol.cpp:20
is_assignable
bool is_assignable(const exprt &expr)
Returns true iff the argument is one of the following:
Definition: expr_util.cpp:22
replace_symbolt::have_to_replace
bool have_to_replace(const exprt &dest) const
Definition: replace_symbol.cpp:159
replace_symbolt::replaces_symbol
bool replaces_symbol(const irep_idt &id) const
Definition: replace_symbol.h:74
Forall_operands
#define Forall_operands(it, expr)
Definition: expr.h:27
address_of_exprt::object
exprt & object()
Definition: pointer_expr.h:380
to_struct_union_type
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition: std_types.h:214
typet
The type of an expression, extends irept.
Definition: type.h:28
irept::pretty
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:495
to_index_expr
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1478
irept::find
const irept & find(const irep_idt &name) const
Definition: irep.cpp:106
replace_symbolt::replace_symbolt
replace_symbolt()
Definition: replace_symbol.cpp:16
typet::has_subtype
bool has_subtype() const
Definition: type.h:82
struct_union_typet
Base type for structs and unions.
Definition: std_types.h:61
replace_symbol.h
invariant.h
to_type_with_subtype
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:193
to_type_with_subtypes
const type_with_subtypest & to_type_with_subtypes(const typet &type)
Definition: type.h:237
exprt
Base class for all expressions.
Definition: expr.h:55
replace_symbolt::expr_map
expr_mapt expr_map
Definition: replace_symbol.h:93
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
array_typet::size
const exprt & size() const
Definition: std_types.h:800
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
replace_symbolt::replace_symbol_expr
virtual bool replace_symbol_expr(symbol_exprt &dest) const
Definition: replace_symbol.cpp:43
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
DATA_INVARIANT
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:510
forall_operands
#define forall_operands(it, expr)
Definition: expr.h:20
member_exprt::struct_op
const exprt & struct_op() const
Definition: std_expr.h:2832
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
address_of_aware_replace_symbolt::replace
bool replace(exprt &dest) const override
Definition: replace_symbol.cpp:373
to_let_expr
const let_exprt & to_let_expr(const exprt &expr)
Cast an exprt to a let_exprt.
Definition: std_expr.h:3266
pointer_expr.h
replace_symbolt::replace
virtual bool replace(exprt &dest) const
Definition: replace_symbol.cpp:59
index_exprt::index
exprt & index()
Definition: std_expr.h:1450
index_exprt::array
exprt & array()
Definition: std_expr.h:1440
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:222
code_typet
Base type of functions.
Definition: std_types.h:538
irept::id
const irep_idt & id() const
Definition: irep.h:396
replace_symbolt::empty
bool empty() const
Definition: replace_symbol.h:59
replace_symbolt::insert
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...
Definition: replace_symbol.cpp:24
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:655
address_of_aware_replace_symbolt::require_lvalue
bool require_lvalue
Definition: replace_symbol.h:129
member_exprt
Extract member of struct or union.
Definition: std_expr.h:2793
expr_util.h
Deprecated expression utility functions.
replace_symbolt::bindings
std::set< irep_idt > bindings
Definition: replace_symbol.h:94
irept::add
irept & add(const irep_idt &name)
Definition: irep.cpp:116
array_typet
Arrays with given size.
Definition: std_types.h:762
unchecked_replace_symbolt::insert
void insert(const symbol_exprt &old_expr, const exprt &new_expr)
Definition: replace_symbol.cpp:354
PRECONDITION_WITH_DIAGNOSTICS
#define PRECONDITION_WITH_DIAGNOSTICS(CONDITION,...)
Definition: invariant.h:464
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
code_typet::return_type
const typet & return_type() const
Definition: std_types.h:645
to_member_expr
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2886
irept
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition: irep.h:359
address_of_aware_replace_symbolt::replace_symbol_expr
bool replace_symbol_expr(symbol_exprt &dest) const override
Definition: replace_symbol.cpp:437
to_address_of_expr
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:408
index_exprt
Array index operator.
Definition: std_expr.h:1409
address_of_exprt
Operator to return the address of an object.
Definition: pointer_expr.h:370
address_of_aware_replace_symbolt::set_require_lvalue_and_backupt
Definition: replace_symbol.h:131
to_binding_expr
const binding_exprt & to_binding_expr(const exprt &expr)
Cast an exprt to a binding_exprt.
Definition: std_expr.h:3114
std_expr.h
unchecked_replace_symbolt::replace_symbol_expr
bool replace_symbol_expr(symbol_exprt &dest) const override
Definition: replace_symbol.cpp:361
replace_symbolt::set
void set(const class symbol_exprt &old_expr, const exprt &new_expr)
Sets old_expr to be replaced by new_expr.
Definition: replace_symbol.cpp:36