CBMC
simplify_expr.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 "simplify_expr.h"
10 
11 #include <algorithm>
12 
13 #include "bitvector_expr.h"
14 #include "byte_operators.h"
15 #include "c_types.h"
16 #include "config.h"
17 #include "expr_util.h"
18 #include "fixedbv.h"
19 #include "floatbv_expr.h"
20 #include "invariant.h"
21 #include "mathematical_expr.h"
22 #include "namespace.h"
23 #include "pointer_expr.h"
24 #include "pointer_offset_size.h"
25 #include "pointer_offset_sum.h"
26 #include "rational.h"
27 #include "rational_tools.h"
28 #include "simplify_utils.h"
29 #include "std_expr.h"
30 #include "string_expr.h"
31 
32 // #define DEBUGX
33 
34 #ifdef DEBUGX
35 #include "format_expr.h"
36 #include <iostream>
37 #endif
38 
39 #include "simplify_expr_class.h"
40 
41 // #define USE_CACHE
42 
43 #ifdef USE_CACHE
44 struct simplify_expr_cachet
45 {
46 public:
47  #if 1
48  typedef std::unordered_map<
49  exprt, exprt, irep_full_hash, irep_full_eq> containert;
50  #else
51  typedef std::unordered_map<exprt, exprt, irep_hash> containert;
52  #endif
53 
54  containert container_normal;
55 
56  containert &container()
57  {
58  return container_normal;
59  }
60 };
61 
62 simplify_expr_cachet simplify_expr_cache;
63 #endif
64 
66 {
67  if(expr.op().is_constant())
68  {
69  const typet &type = to_unary_expr(expr).op().type();
70 
71  if(type.id()==ID_floatbv)
72  {
73  ieee_floatt value(to_constant_expr(to_unary_expr(expr).op()));
74  value.set_sign(false);
75  return value.to_expr();
76  }
77  else if(type.id()==ID_signedbv ||
78  type.id()==ID_unsignedbv)
79  {
80  auto value = numeric_cast<mp_integer>(to_unary_expr(expr).op());
81  if(value.has_value())
82  {
83  if(*value >= 0)
84  {
85  return to_unary_expr(expr).op();
86  }
87  else
88  {
89  value->negate();
90  return from_integer(*value, type);
91  }
92  }
93  }
94  }
95 
96  return unchanged(expr);
97 }
98 
100 {
101  if(expr.op().is_constant())
102  {
103  const typet &type = expr.op().type();
104 
105  if(type.id()==ID_floatbv)
106  {
107  ieee_floatt value(to_constant_expr(expr.op()));
108  return make_boolean_expr(value.get_sign());
109  }
110  else if(type.id()==ID_signedbv ||
111  type.id()==ID_unsignedbv)
112  {
113  const auto value = numeric_cast<mp_integer>(expr.op());
114  if(value.has_value())
115  {
116  return make_boolean_expr(*value >= 0);
117  }
118  }
119  }
120 
121  return unchanged(expr);
122 }
123 
126 {
127  const exprt &op = expr.op();
128 
129  if(op.is_constant())
130  {
131  const typet &op_type = op.type();
132 
133  if(op_type.id() == ID_signedbv || op_type.id() == ID_unsignedbv)
134  {
135  const auto width = to_bitvector_type(op_type).get_width();
136  const auto &value = to_constant_expr(op).get_value();
137  std::size_t result = 0;
138 
139  for(std::size_t i = 0; i < width; i++)
140  if(get_bvrep_bit(value, width, i))
141  result++;
142 
143  return from_integer(result, expr.type());
144  }
145  }
146 
147  return unchanged(expr);
148 }
149 
152 {
153  const auto const_bits_opt = expr2bits(
154  expr.op(),
156  ns);
157 
158  if(!const_bits_opt.has_value())
159  return unchanged(expr);
160 
161  // expr2bits generates a bit string starting with the least-significant bit
162  std::size_t n_leading_zeros = const_bits_opt->rfind('1');
163  if(n_leading_zeros == std::string::npos)
164  {
165  if(!expr.zero_permitted())
166  return unchanged(expr);
167 
168  n_leading_zeros = const_bits_opt->size();
169  }
170  else
171  n_leading_zeros = const_bits_opt->size() - n_leading_zeros - 1;
172 
173  return from_integer(n_leading_zeros, expr.type());
174 }
175 
178 {
179  const auto const_bits_opt = expr2bits(
180  expr.op(),
182  ns);
183 
184  if(!const_bits_opt.has_value())
185  return unchanged(expr);
186 
187  // expr2bits generates a bit string starting with the least-significant bit
188  std::size_t n_trailing_zeros = const_bits_opt->find('1');
189  if(n_trailing_zeros == std::string::npos)
190  {
191  if(!expr.zero_permitted())
192  return unchanged(expr);
193 
194  n_trailing_zeros = const_bits_opt->size();
195  }
196 
197  return from_integer(n_trailing_zeros, expr.type());
198 }
199 
202 {
203  const auto const_bits_opt = expr2bits(
204  expr.op(),
206  ns);
207 
208  if(!const_bits_opt.has_value())
209  return unchanged(expr);
210 
211  // expr2bits generates a bit string starting with the least-significant bit
212  std::size_t first_one_bit = const_bits_opt->find('1');
213  if(first_one_bit == std::string::npos)
214  first_one_bit = 0;
215  else
216  ++first_one_bit;
217 
218  return from_integer(first_one_bit, expr.type());
219 }
220 
226  const function_application_exprt &expr,
227  const namespacet &ns)
228 {
229  const refined_string_exprt &s1 = to_string_expr(expr.arguments().at(0));
230  const auto s1_data_opt = try_get_string_data_array(s1.content(), ns);
231 
232  if(!s1_data_opt)
233  return simplify_exprt::unchanged(expr);
234 
235  const array_exprt &s1_data = s1_data_opt->get();
236  const refined_string_exprt &s2 = to_string_expr(expr.arguments().at(1));
237  const auto s2_data_opt = try_get_string_data_array(s2.content(), ns);
238 
239  if(!s2_data_opt)
240  return simplify_exprt::unchanged(expr);
241 
242  const array_exprt &s2_data = s2_data_opt->get();
243  const bool res = s2_data.operands().size() <= s1_data.operands().size() &&
244  std::equal(
245  s2_data.operands().rbegin(),
246  s2_data.operands().rend(),
247  s1_data.operands().rbegin());
248 
249  return from_integer(res ? 1 : 0, expr.type());
250 }
251 
254  const function_application_exprt &expr,
255  const namespacet &ns)
256 {
257  // We want to get both arguments of any starts-with comparison, and
258  // trace them back to the actual string instance. All variables on the
259  // way must be constant for us to be sure this will work.
260  auto &first_argument = to_string_expr(expr.arguments().at(0));
261  auto &second_argument = to_string_expr(expr.arguments().at(1));
262 
263  const auto first_value_opt =
264  try_get_string_data_array(first_argument.content(), ns);
265 
266  if(!first_value_opt)
267  {
268  return simplify_exprt::unchanged(expr);
269  }
270 
271  const array_exprt &first_value = first_value_opt->get();
272 
273  const auto second_value_opt =
274  try_get_string_data_array(second_argument.content(), ns);
275 
276  if(!second_value_opt)
277  {
278  return simplify_exprt::unchanged(expr);
279  }
280 
281  const array_exprt &second_value = second_value_opt->get();
282 
283  // Is our 'contains' array directly contained in our target.
284  const bool includes =
285  std::search(
286  first_value.operands().begin(),
287  first_value.operands().end(),
288  second_value.operands().begin(),
289  second_value.operands().end()) != first_value.operands().end();
290 
291  return from_integer(includes ? 1 : 0, expr.type());
292 }
293 
299  const function_application_exprt &expr,
300  const namespacet &ns)
301 {
302  const function_application_exprt &function_app =
304  const refined_string_exprt &s =
305  to_string_expr(function_app.arguments().at(0));
306 
307  if(s.length().id() != ID_constant)
308  return simplify_exprt::unchanged(expr);
309 
310  const auto numeric_length =
311  numeric_cast_v<mp_integer>(to_constant_expr(s.length()));
312 
313  return from_integer(numeric_length == 0 ? 1 : 0, expr.type());
314 }
315 
324  const function_application_exprt &expr,
325  const namespacet &ns)
326 {
327  const refined_string_exprt &s1 = to_string_expr(expr.arguments().at(0));
328  const auto s1_data_opt = try_get_string_data_array(s1.content(), ns);
329 
330  if(!s1_data_opt)
331  return simplify_exprt::unchanged(expr);
332 
333  const refined_string_exprt &s2 = to_string_expr(expr.arguments().at(1));
334  const auto s2_data_opt = try_get_string_data_array(s2.content(), ns);
335 
336  if(!s2_data_opt)
337  return simplify_exprt::unchanged(expr);
338 
339  const array_exprt &s1_data = s1_data_opt->get();
340  const array_exprt &s2_data = s2_data_opt->get();
341 
342  if(s1_data.operands() == s2_data.operands())
343  return from_integer(0, expr.type());
344 
345  const mp_integer s1_size = s1_data.operands().size();
346  const mp_integer s2_size = s2_data.operands().size();
347  const bool first_shorter = s1_size < s2_size;
348  const exprt::operandst &ops1 =
349  first_shorter ? s1_data.operands() : s2_data.operands();
350  const exprt::operandst &ops2 =
351  first_shorter ? s2_data.operands() : s1_data.operands();
352  auto it_pair = std::mismatch(ops1.begin(), ops1.end(), ops2.begin());
353 
354  if(it_pair.first == ops1.end())
355  return from_integer(s1_size - s2_size, expr.type());
356 
357  const mp_integer char1 =
358  numeric_cast_v<mp_integer>(to_constant_expr(*it_pair.first));
359  const mp_integer char2 =
360  numeric_cast_v<mp_integer>(to_constant_expr(*it_pair.second));
361 
362  return from_integer(
363  first_shorter ? char1 - char2 : char2 - char1, expr.type());
364 }
365 
373  const function_application_exprt &expr,
374  const namespacet &ns,
375  const bool search_from_end)
376 {
377  std::size_t starting_index = 0;
378 
379  // Determine starting index for the comparison (if given)
380  if(expr.arguments().size() == 3)
381  {
382  auto &starting_index_expr = expr.arguments().at(2);
383 
384  if(starting_index_expr.id() != ID_constant)
385  {
386  return simplify_exprt::unchanged(expr);
387  }
388 
389  const mp_integer idx =
390  numeric_cast_v<mp_integer>(to_constant_expr(starting_index_expr));
391 
392  // Negative indices are treated like 0
393  if(idx > 0)
394  {
395  starting_index = numeric_cast_v<std::size_t>(idx);
396  }
397  }
398 
399  const refined_string_exprt &s1 = to_string_expr(expr.arguments().at(0));
400 
401  const auto s1_data_opt = try_get_string_data_array(s1.content(), ns);
402 
403  if(!s1_data_opt)
404  {
405  return simplify_exprt::unchanged(expr);
406  }
407 
408  const array_exprt &s1_data = s1_data_opt->get();
409 
410  const auto search_string_size = s1_data.operands().size();
411  if(starting_index >= search_string_size)
412  {
413  return from_integer(-1, expr.type());
414  }
415 
416  unsigned long starting_offset =
417  starting_index > 0 ? (search_string_size - 1) - starting_index : 0;
419  {
420  // Second argument is a string
421 
422  const refined_string_exprt &s2 = to_string_expr(expr.arguments().at(1));
423 
424  const auto s2_data_opt = try_get_string_data_array(s2.content(), ns);
425 
426  if(!s2_data_opt)
427  {
428  return simplify_exprt::unchanged(expr);
429  }
430 
431  const array_exprt &s2_data = s2_data_opt->get();
432 
433  // Searching for empty string is a special case and is simply the
434  // "always found at the first searched position. This needs to take into
435  // account starting position and if you're starting from the beginning or
436  // end.
437  if(s2_data.operands().empty())
438  return from_integer(
439  search_from_end
440  ? starting_index > 0 ? starting_index : search_string_size
441  : 0,
442  expr.type());
443 
444  if(search_from_end)
445  {
446  auto end = std::prev(s1_data.operands().end(), starting_offset);
447  auto it = std::find_end(
448  s1_data.operands().begin(),
449  end,
450  s2_data.operands().begin(),
451  s2_data.operands().end());
452  if(it != end)
453  return from_integer(
454  std::distance(s1_data.operands().begin(), it), expr.type());
455  }
456  else
457  {
458  auto it = std::search(
459  std::next(s1_data.operands().begin(), starting_index),
460  s1_data.operands().end(),
461  s2_data.operands().begin(),
462  s2_data.operands().end());
463 
464  if(it != s1_data.operands().end())
465  return from_integer(
466  std::distance(s1_data.operands().begin(), it), expr.type());
467  }
468  }
469  else if(expr.arguments().at(1).id() == ID_constant)
470  {
471  // Second argument is a constant character
472 
473  const constant_exprt &c1 = to_constant_expr(expr.arguments().at(1));
474  const auto c1_val = numeric_cast_v<mp_integer>(c1);
475 
476  auto pred = [&](const exprt &c2) {
477  const auto c2_val = numeric_cast_v<mp_integer>(to_constant_expr(c2));
478 
479  return c1_val == c2_val;
480  };
481 
482  if(search_from_end)
483  {
484  auto it = std::find_if(
485  std::next(s1_data.operands().rbegin(), starting_offset),
486  s1_data.operands().rend(),
487  pred);
488  if(it != s1_data.operands().rend())
489  return from_integer(
490  std::distance(s1_data.operands().begin(), it.base() - 1),
491  expr.type());
492  }
493  else
494  {
495  auto it = std::find_if(
496  std::next(s1_data.operands().begin(), starting_index),
497  s1_data.operands().end(),
498  pred);
499  if(it != s1_data.operands().end())
500  return from_integer(
501  std::distance(s1_data.operands().begin(), it), expr.type());
502  }
503  }
504  else
505  {
506  return simplify_exprt::unchanged(expr);
507  }
508 
509  return from_integer(-1, expr.type());
510 }
511 
518  const function_application_exprt &expr,
519  const namespacet &ns)
520 {
521  if(expr.arguments().at(1).id() != ID_constant)
522  {
523  return simplify_exprt::unchanged(expr);
524  }
525 
526  const auto &index = to_constant_expr(expr.arguments().at(1));
527 
528  const refined_string_exprt &s = to_string_expr(expr.arguments().at(0));
529 
530  const auto char_seq_opt = try_get_string_data_array(s.content(), ns);
531 
532  if(!char_seq_opt)
533  {
534  return simplify_exprt::unchanged(expr);
535  }
536 
537  const array_exprt &char_seq = char_seq_opt->get();
538 
539  const auto i_opt = numeric_cast<std::size_t>(index);
540 
541  if(!i_opt || *i_opt >= char_seq.operands().size())
542  {
543  return simplify_exprt::unchanged(expr);
544  }
545 
546  const auto &c = to_constant_expr(char_seq.operands().at(*i_opt));
547 
548  if(c.type() != expr.type())
549  {
550  return simplify_exprt::unchanged(expr);
551  }
552 
553  return c;
554 }
555 
557 static bool lower_case_string_expression(array_exprt &string_data)
558 {
559  auto &operands = string_data.operands();
560  for(auto &operand : operands)
561  {
562  auto &constant_value = to_constant_expr(operand);
563  auto character = numeric_cast_v<unsigned int>(constant_value);
564 
565  // Can't guarantee matches against non-ASCII characters.
566  if(character >= 128)
567  return false;
568 
569  if(isalpha(character))
570  {
571  if(isupper(character))
572  constant_value =
573  from_integer(tolower(character), constant_value.type());
574  }
575  }
576 
577  return true;
578 }
579 
586  const function_application_exprt &expr,
587  const namespacet &ns)
588 {
589  // We want to get both arguments of any starts-with comparison, and
590  // trace them back to the actual string instance. All variables on the
591  // way must be constant for us to be sure this will work.
592  auto &first_argument = to_string_expr(expr.arguments().at(0));
593  auto &second_argument = to_string_expr(expr.arguments().at(1));
594 
595  const auto first_value_opt =
596  try_get_string_data_array(first_argument.content(), ns);
597 
598  if(!first_value_opt)
599  {
600  return simplify_exprt::unchanged(expr);
601  }
602 
603  array_exprt first_value = first_value_opt->get();
604 
605  const auto second_value_opt =
606  try_get_string_data_array(second_argument.content(), ns);
607 
608  if(!second_value_opt)
609  {
610  return simplify_exprt::unchanged(expr);
611  }
612 
613  array_exprt second_value = second_value_opt->get();
614 
615  // Just lower-case both expressions.
616  if(
617  !lower_case_string_expression(first_value) ||
618  !lower_case_string_expression(second_value))
619  return simplify_exprt::unchanged(expr);
620 
621  bool is_equal = first_value == second_value;
622  return from_integer(is_equal ? 1 : 0, expr.type());
623 }
624 
631  const function_application_exprt &expr,
632  const namespacet &ns)
633 {
634  // We want to get both arguments of any starts-with comparison, and
635  // trace them back to the actual string instance. All variables on the
636  // way must be constant for us to be sure this will work.
637  auto &first_argument = to_string_expr(expr.arguments().at(0));
638  auto &second_argument = to_string_expr(expr.arguments().at(1));
639 
640  const auto first_value_opt =
641  try_get_string_data_array(first_argument.content(), ns);
642 
643  if(!first_value_opt)
644  {
645  return simplify_exprt::unchanged(expr);
646  }
647 
648  const array_exprt &first_value = first_value_opt->get();
649 
650  const auto second_value_opt =
651  try_get_string_data_array(second_argument.content(), ns);
652 
653  if(!second_value_opt)
654  {
655  return simplify_exprt::unchanged(expr);
656  }
657 
658  const array_exprt &second_value = second_value_opt->get();
659 
660  mp_integer offset_int = 0;
661  if(expr.arguments().size() == 3)
662  {
663  auto &offset = expr.arguments()[2];
664  if(offset.id() != ID_constant)
665  return simplify_exprt::unchanged(expr);
666  offset_int = numeric_cast_v<mp_integer>(to_constant_expr(offset));
667  }
668 
669  // test whether second_value is a prefix of first_value
670  bool is_prefix =
671  offset_int >= 0 && mp_integer(first_value.operands().size()) >=
672  offset_int + second_value.operands().size();
673  if(is_prefix)
674  {
675  exprt::operandst::const_iterator second_it =
676  second_value.operands().begin();
677  for(const auto &first_op : first_value.operands())
678  {
679  if(offset_int > 0)
680  --offset_int;
681  else if(second_it == second_value.operands().end())
682  break;
683  else if(first_op != *second_it)
684  {
685  is_prefix = false;
686  break;
687  }
688  else
689  ++second_it;
690  }
691  }
692 
693  return from_integer(is_prefix ? 1 : 0, expr.type());
694 }
695 
697  const function_application_exprt &expr)
698 {
699  if(expr.function().id() == ID_lambda)
700  {
701  // expand the function application
702  return to_lambda_expr(expr.function()).application(expr.arguments());
703  }
704 
705  if(expr.function().id() != ID_symbol)
706  return unchanged(expr);
707 
708  const irep_idt &func_id = to_symbol_expr(expr.function()).get_identifier();
709 
710  // String.startsWith() is used to implement String.equals() in the models
711  // library
712  if(func_id == ID_cprover_string_startswith_func)
713  {
714  return simplify_string_startswith(expr, ns);
715  }
716  else if(func_id == ID_cprover_string_endswith_func)
717  {
718  return simplify_string_endswith(expr, ns);
719  }
720  else if(func_id == ID_cprover_string_is_empty_func)
721  {
722  return simplify_string_is_empty(expr, ns);
723  }
724  else if(func_id == ID_cprover_string_compare_to_func)
725  {
726  return simplify_string_compare_to(expr, ns);
727  }
728  else if(func_id == ID_cprover_string_index_of_func)
729  {
730  return simplify_string_index_of(expr, ns, false);
731  }
732  else if(func_id == ID_cprover_string_char_at_func)
733  {
734  return simplify_string_char_at(expr, ns);
735  }
736  else if(func_id == ID_cprover_string_contains_func)
737  {
738  return simplify_string_contains(expr, ns);
739  }
740  else if(func_id == ID_cprover_string_last_index_of_func)
741  {
742  return simplify_string_index_of(expr, ns, true);
743  }
744  else if(func_id == ID_cprover_string_equals_ignore_case_func)
745  {
747  }
748 
749  return unchanged(expr);
750 }
751 
754 {
755  const typet &expr_type = expr.type();
756  const typet &op_type = expr.op().type();
757 
758  // eliminate casts of infinity
759  if(expr.op().id() == ID_infinity)
760  {
761  typet new_type=expr.type();
762  exprt tmp = expr.op();
763  tmp.type()=new_type;
764  return std::move(tmp);
765  }
766 
767  // casts from NULL to any integer
768  if(
769  op_type.id() == ID_pointer && expr.op().is_constant() &&
770  to_constant_expr(expr.op()).get_value() == ID_NULL &&
771  (expr_type.id() == ID_unsignedbv || expr_type.id() == ID_signedbv) &&
773  {
774  return from_integer(0, expr_type);
775  }
776 
777  // casts from pointer to integer
778  // where width of integer >= width of pointer
779  // (void*)(intX)expr -> (void*)expr
780  if(
781  expr_type.id() == ID_pointer && expr.op().id() == ID_typecast &&
782  (op_type.id() == ID_signedbv || op_type.id() == ID_unsignedbv) &&
783  to_bitvector_type(op_type).get_width() >=
784  to_bitvector_type(expr_type).get_width())
785  {
786  auto new_expr = expr;
787  new_expr.op() = to_typecast_expr(expr.op()).op();
788  return changed(simplify_typecast(new_expr)); // rec. call
789  }
790 
791  // eliminate redundant typecasts
792  if(expr.type() == expr.op().type())
793  {
794  return expr.op();
795  }
796 
797  // eliminate casts to proper bool
798  if(expr_type.id()==ID_bool)
799  {
800  // rewrite (bool)x to x!=0
801  binary_relation_exprt inequality(
802  expr.op(),
803  op_type.id() == ID_floatbv ? ID_ieee_float_notequal : ID_notequal,
804  from_integer(0, op_type));
805  inequality.add_source_location()=expr.source_location();
806  return changed(simplify_node(inequality));
807  }
808 
809  // eliminate casts from proper bool
810  if(
811  op_type.id() == ID_bool &&
812  (expr_type.id() == ID_signedbv || expr_type.id() == ID_unsignedbv ||
813  expr_type.id() == ID_c_bool || expr_type.id() == ID_c_bit_field))
814  {
815  // rewrite (T)(bool) to bool?1:0
816  auto one = from_integer(1, expr_type);
817  auto zero = from_integer(0, expr_type);
818  exprt new_expr = if_exprt(expr.op(), std::move(one), std::move(zero));
819  simplify_if_preorder(to_if_expr(new_expr));
820  return new_expr;
821  }
822 
823  // circular casts through types shorter than `int`
824  if(op_type == signedbv_typet(32) && expr.op().id() == ID_typecast)
825  {
826  if(expr_type==c_bool_typet(8) ||
827  expr_type==signedbv_typet(8) ||
828  expr_type==signedbv_typet(16) ||
829  expr_type==unsignedbv_typet(16))
830  {
831  // We checked that the id was ID_typecast in the enclosing `if`
832  const auto &typecast = expr_checked_cast<typecast_exprt>(expr.op());
833  if(typecast.op().type()==expr_type)
834  {
835  return typecast.op();
836  }
837  }
838  }
839 
840  // eliminate casts to _Bool
841  if(expr_type.id()==ID_c_bool &&
842  op_type.id()!=ID_bool)
843  {
844  // rewrite (_Bool)x to (_Bool)(x!=0)
845  exprt inequality = is_not_zero(expr.op(), ns);
846  auto new_expr = expr;
847  new_expr.op() = simplify_node(std::move(inequality));
848  return changed(simplify_typecast(new_expr)); // recursive call
849  }
850 
851  // eliminate typecasts from NULL
852  if(
853  expr_type.id() == ID_pointer && expr.op().is_constant() &&
854  (to_constant_expr(expr.op()).get_value() == ID_NULL ||
855  (expr.op().is_zero() && config.ansi_c.NULL_is_zero)))
856  {
857  exprt tmp = expr.op();
858  tmp.type()=expr.type();
859  to_constant_expr(tmp).set_value(ID_NULL);
860  return std::move(tmp);
861  }
862 
863  // eliminate duplicate pointer typecasts
864  // (T1 *)(T2 *)x -> (T1 *)x
865  if(
866  expr_type.id() == ID_pointer && expr.op().id() == ID_typecast &&
867  op_type.id() == ID_pointer)
868  {
869  auto new_expr = expr;
870  new_expr.op() = to_typecast_expr(expr.op()).op();
871  return changed(simplify_typecast(new_expr)); // recursive call
872  }
873 
874  // casts from integer to pointer and back:
875  // (int)(void *)int -> (int)(size_t)int
876  if(
877  (expr_type.id() == ID_signedbv || expr_type.id() == ID_unsignedbv) &&
878  expr.op().id() == ID_typecast && expr.op().operands().size() == 1 &&
879  op_type.id() == ID_pointer)
880  {
881  auto inner_cast = to_typecast_expr(expr.op());
882  inner_cast.type() = size_type();
883 
884  auto outer_cast = expr;
885  outer_cast.op() = simplify_typecast(inner_cast); // rec. call
886  return changed(simplify_typecast(outer_cast)); // rec. call
887  }
888 
889  // mildly more elaborate version of the above:
890  // (int)((T*)0 + int) -> (int)(sizeof(T)*(size_t)int) if NULL is zero
891  if(
893  (expr_type.id() == ID_signedbv || expr_type.id() == ID_unsignedbv) &&
894  op_type.id() == ID_pointer && expr.op().id() == ID_plus &&
895  expr.op().operands().size() == 2)
896  {
897  const auto &op_plus_expr = to_plus_expr(expr.op());
898 
899  if(
900  (op_plus_expr.op0().id() == ID_typecast &&
901  to_typecast_expr(op_plus_expr.op0()).op().is_zero()) ||
902  (op_plus_expr.op0().is_constant() &&
903  is_null_pointer(to_constant_expr(op_plus_expr.op0()))))
904  {
905  auto sub_size =
906  pointer_offset_size(to_pointer_type(op_type).base_type(), ns);
907  if(sub_size.has_value())
908  {
909  auto new_expr = expr;
910  exprt offset_expr =
911  simplify_typecast(typecast_exprt(op_plus_expr.op1(), size_type()));
912 
913  // void*
914  if(*sub_size == 0 || *sub_size == 1)
915  new_expr.op() = offset_expr;
916  else
917  {
918  new_expr.op() = simplify_mult(
919  mult_exprt(from_integer(*sub_size, size_type()), offset_expr));
920  }
921 
922  return changed(simplify_typecast(new_expr)); // rec. call
923  }
924  }
925  }
926 
927  // Push a numerical typecast into various integer operations, i.e.,
928  // (T)(x OP y) ---> (T)x OP (T)y
929  //
930  // Doesn't work for many, e.g., pointer difference, floating-point,
931  // division, modulo.
932  // Many operations fail if the width of T
933  // is bigger than that of (x OP y). This includes ID_bitnot and
934  // anything that might overflow, e.g., ID_plus.
935  //
936  if((expr_type.id()==ID_signedbv || expr_type.id()==ID_unsignedbv) &&
937  (op_type.id()==ID_signedbv || op_type.id()==ID_unsignedbv))
938  {
939  bool enlarge=
940  to_bitvector_type(expr_type).get_width()>
941  to_bitvector_type(op_type).get_width();
942 
943  if(!enlarge)
944  {
945  irep_idt op_id = expr.op().id();
946 
947  if(op_id==ID_plus || op_id==ID_minus || op_id==ID_mult ||
948  op_id==ID_unary_minus ||
949  op_id==ID_bitxor || op_id==ID_bitor || op_id==ID_bitand)
950  {
951  exprt result = expr.op();
952 
953  if(
954  result.operands().size() >= 1 &&
955  to_multi_ary_expr(result).op0().type() == result.type())
956  {
957  result.type()=expr.type();
958 
959  Forall_operands(it, result)
960  {
961  auto new_operand = typecast_exprt(*it, expr.type());
962  *it = simplify_typecast(new_operand); // recursive call
963  }
964 
965  return changed(simplify_node(result)); // possibly recursive call
966  }
967  }
968  else if(op_id==ID_ashr || op_id==ID_lshr || op_id==ID_shl)
969  {
970  }
971  }
972  }
973 
974  // Push a numerical typecast into pointer arithmetic
975  // (T)(ptr + int) ---> (T)((size_t)ptr + sizeof(subtype)*(size_t)int)
976  //
977  if(
978  (expr_type.id() == ID_signedbv || expr_type.id() == ID_unsignedbv) &&
979  op_type.id() == ID_pointer && expr.op().id() == ID_plus)
980  {
981  const auto step =
982  pointer_offset_size(to_pointer_type(op_type).base_type(), ns);
983 
984  if(step.has_value() && *step != 0)
985  {
986  const typet size_t_type(size_type());
987  auto new_expr = expr;
988 
989  new_expr.op().type() = size_t_type;
990 
991  for(auto &op : new_expr.op().operands())
992  {
993  exprt new_op = simplify_typecast(typecast_exprt(op, size_t_type));
994  if(op.type().id() != ID_pointer && *step > 1)
995  {
996  new_op =
997  simplify_mult(mult_exprt(from_integer(*step, size_t_type), new_op));
998  }
999  op = std::move(new_op);
1000  }
1001 
1002  new_expr.op() = simplify_plus(to_plus_expr(new_expr.op()));
1003 
1004  return changed(simplify_typecast(new_expr)); // recursive call
1005  }
1006  }
1007 
1008  #if 0
1009  // (T)(a?b:c) --> a?(T)b:(T)c
1010  if(expr.op().id()==ID_if &&
1011  expr.op().operands().size()==3)
1012  {
1013  typecast_exprt tmp_op1(expr.op().op1(), expr_type);
1014  typecast_exprt tmp_op2(expr.op().op2(), expr_type);
1015  simplify_typecast(tmp_op1);
1016  simplify_typecast(tmp_op2);
1017  auto new_expr=if_exprt(expr.op().op0(), tmp_op1, tmp_op2, expr_type);
1018  simplify_if(new_expr);
1019  return std::move(new_expr);
1020  }
1021  #endif
1022 
1023  const irep_idt &expr_type_id=expr_type.id();
1024  const exprt &operand = expr.op();
1025  const irep_idt &op_type_id=op_type.id();
1026 
1027  if(operand.is_constant())
1028  {
1029  const irep_idt &value=to_constant_expr(operand).get_value();
1030 
1031  // preserve the sizeof type annotation
1032  typet c_sizeof_type=
1033  static_cast<const typet &>(operand.find(ID_C_c_sizeof_type));
1034 
1035  if(op_type_id==ID_integer ||
1036  op_type_id==ID_natural)
1037  {
1038  // from integer to ...
1039 
1040  mp_integer int_value=string2integer(id2string(value));
1041 
1042  if(expr_type_id==ID_bool)
1043  {
1044  return make_boolean_expr(int_value != 0);
1045  }
1046 
1047  if(expr_type_id==ID_unsignedbv ||
1048  expr_type_id==ID_signedbv ||
1049  expr_type_id==ID_c_enum ||
1050  expr_type_id==ID_c_bit_field ||
1051  expr_type_id==ID_integer)
1052  {
1053  return from_integer(int_value, expr_type);
1054  }
1055  else if(expr_type_id == ID_c_enum_tag)
1056  {
1057  const auto &c_enum_type = ns.follow_tag(to_c_enum_tag_type(expr_type));
1058  if(!c_enum_type.is_incomplete()) // possibly incomplete
1059  {
1060  exprt tmp = from_integer(int_value, c_enum_type);
1061  tmp.type() = expr_type; // we maintain the tag type
1062  return std::move(tmp);
1063  }
1064  }
1065  }
1066  else if(op_type_id==ID_rational)
1067  {
1068  }
1069  else if(op_type_id==ID_real)
1070  {
1071  }
1072  else if(op_type_id==ID_bool)
1073  {
1074  if(expr_type_id==ID_unsignedbv ||
1075  expr_type_id==ID_signedbv ||
1076  expr_type_id==ID_integer ||
1077  expr_type_id==ID_natural ||
1078  expr_type_id==ID_rational ||
1079  expr_type_id==ID_c_bool ||
1080  expr_type_id==ID_c_enum ||
1081  expr_type_id==ID_c_bit_field)
1082  {
1083  if(operand.is_true())
1084  {
1085  return from_integer(1, expr_type);
1086  }
1087  else if(operand.is_false())
1088  {
1089  return from_integer(0, expr_type);
1090  }
1091  }
1092  else if(expr_type_id==ID_c_enum_tag)
1093  {
1094  const auto &c_enum_type = ns.follow_tag(to_c_enum_tag_type(expr_type));
1095  if(!c_enum_type.is_incomplete()) // possibly incomplete
1096  {
1097  unsigned int_value = operand.is_true() ? 1u : 0u;
1098  exprt tmp=from_integer(int_value, c_enum_type);
1099  tmp.type()=expr_type; // we maintain the tag type
1100  return std::move(tmp);
1101  }
1102  }
1103  else if(expr_type_id==ID_pointer &&
1104  operand.is_false() &&
1106  {
1107  return null_pointer_exprt(to_pointer_type(expr_type));
1108  }
1109  }
1110  else if(op_type_id==ID_unsignedbv ||
1111  op_type_id==ID_signedbv ||
1112  op_type_id==ID_c_bit_field ||
1113  op_type_id==ID_c_bool)
1114  {
1115  mp_integer int_value;
1116 
1117  if(to_integer(to_constant_expr(operand), int_value))
1118  return unchanged(expr);
1119 
1120  if(expr_type_id==ID_bool)
1121  {
1122  return make_boolean_expr(int_value != 0);
1123  }
1124 
1125  if(expr_type_id==ID_c_bool)
1126  {
1127  return from_integer(int_value != 0, expr_type);
1128  }
1129 
1130  if(expr_type_id==ID_integer)
1131  {
1132  return from_integer(int_value, expr_type);
1133  }
1134 
1135  if(expr_type_id==ID_natural)
1136  {
1137  if(int_value>=0)
1138  {
1139  return from_integer(int_value, expr_type);
1140  }
1141  }
1142 
1143  if(expr_type_id==ID_unsignedbv ||
1144  expr_type_id==ID_signedbv ||
1145  expr_type_id==ID_bv ||
1146  expr_type_id==ID_c_bit_field)
1147  {
1148  auto result = from_integer(int_value, expr_type);
1149 
1150  if(c_sizeof_type.is_not_nil())
1151  result.set(ID_C_c_sizeof_type, c_sizeof_type);
1152 
1153  return std::move(result);
1154  }
1155 
1156  if(expr_type_id==ID_c_enum_tag)
1157  {
1158  const auto &c_enum_type = ns.follow_tag(to_c_enum_tag_type(expr_type));
1159  if(!c_enum_type.is_incomplete()) // possibly incomplete
1160  {
1161  exprt tmp=from_integer(int_value, c_enum_type);
1162  tmp.type()=expr_type; // we maintain the tag type
1163  return std::move(tmp);
1164  }
1165  }
1166 
1167  if(expr_type_id==ID_c_enum)
1168  {
1169  return from_integer(int_value, expr_type);
1170  }
1171 
1172  if(expr_type_id==ID_fixedbv)
1173  {
1174  // int to float
1175  const fixedbv_typet &f_expr_type=
1176  to_fixedbv_type(expr_type);
1177 
1178  fixedbvt f;
1179  f.spec=fixedbv_spect(f_expr_type);
1180  f.from_integer(int_value);
1181  return f.to_expr();
1182  }
1183 
1184  if(expr_type_id==ID_floatbv)
1185  {
1186  // int to float
1187  const floatbv_typet &f_expr_type=
1188  to_floatbv_type(expr_type);
1189 
1190  ieee_floatt f(f_expr_type);
1191  f.from_integer(int_value);
1192 
1193  return f.to_expr();
1194  }
1195 
1196  if(expr_type_id==ID_rational)
1197  {
1198  rationalt r(int_value);
1199  return from_rational(r);
1200  }
1201  }
1202  else if(op_type_id==ID_fixedbv)
1203  {
1204  if(expr_type_id==ID_unsignedbv ||
1205  expr_type_id==ID_signedbv)
1206  {
1207  // cast from fixedbv to int
1208  fixedbvt f(to_constant_expr(expr.op()));
1209  return from_integer(f.to_integer(), expr_type);
1210  }
1211  else if(expr_type_id==ID_fixedbv)
1212  {
1213  // fixedbv to fixedbv
1214  fixedbvt f(to_constant_expr(expr.op()));
1215  f.round(fixedbv_spect(to_fixedbv_type(expr_type)));
1216  return f.to_expr();
1217  }
1218  else if(expr_type_id == ID_bv)
1219  {
1220  fixedbvt f{to_constant_expr(expr.op())};
1221  return from_integer(f.get_value(), expr_type);
1222  }
1223  }
1224  else if(op_type_id==ID_floatbv)
1225  {
1226  ieee_floatt f(to_constant_expr(expr.op()));
1227 
1228  if(expr_type_id==ID_unsignedbv ||
1229  expr_type_id==ID_signedbv)
1230  {
1231  // cast from float to int
1232  return from_integer(f.to_integer(), expr_type);
1233  }
1234  else if(expr_type_id==ID_floatbv)
1235  {
1236  // float to double or double to float
1238  return f.to_expr();
1239  }
1240  else if(expr_type_id==ID_fixedbv)
1241  {
1242  fixedbvt fixedbv;
1243  fixedbv.spec=fixedbv_spect(to_fixedbv_type(expr_type));
1244  ieee_floatt factor(f.spec);
1245  factor.from_integer(power(2, fixedbv.spec.get_fraction_bits()));
1246  f*=factor;
1247  fixedbv.set_value(f.to_integer());
1248  return fixedbv.to_expr();
1249  }
1250  else if(expr_type_id == ID_bv)
1251  {
1252  return from_integer(f.pack(), expr_type);
1253  }
1254  }
1255  else if(op_type_id==ID_bv)
1256  {
1257  if(
1258  expr_type_id == ID_unsignedbv || expr_type_id == ID_signedbv ||
1259  expr_type_id == ID_c_enum || expr_type_id == ID_c_enum_tag ||
1260  expr_type_id == ID_c_bit_field)
1261  {
1262  const auto width = to_bv_type(op_type).get_width();
1263  const auto int_value = bvrep2integer(value, width, false);
1264  if(expr_type_id != ID_c_enum_tag)
1265  return from_integer(int_value, expr_type);
1266  else
1267  {
1268  c_enum_tag_typet tag_type = to_c_enum_tag_type(expr_type);
1269  auto result = from_integer(int_value, ns.follow_tag(tag_type));
1270  result.type() = tag_type;
1271  return std::move(result);
1272  }
1273  }
1274  else if(expr_type_id == ID_floatbv)
1275  {
1276  const auto width = to_bv_type(op_type).get_width();
1277  const auto int_value = bvrep2integer(value, width, false);
1278  ieee_floatt ieee_float{to_floatbv_type(expr_type)};
1279  ieee_float.unpack(int_value);
1280  return ieee_float.to_expr();
1281  }
1282  else if(expr_type_id == ID_fixedbv)
1283  {
1284  const auto width = to_bv_type(op_type).get_width();
1285  const auto int_value = bvrep2integer(value, width, false);
1286  fixedbvt fixedbv{fixedbv_spect{to_fixedbv_type(expr_type)}};
1287  fixedbv.set_value(int_value);
1288  return fixedbv.to_expr();
1289  }
1290  }
1291  else if(op_type_id==ID_c_enum_tag) // enum to int
1292  {
1293  const typet &base_type =
1294  ns.follow_tag(to_c_enum_tag_type(op_type)).underlying_type();
1295  if(base_type.id()==ID_signedbv || base_type.id()==ID_unsignedbv)
1296  {
1297  // enum constants use the representation of their base type
1298  auto new_expr = expr;
1299  new_expr.op().type() = base_type;
1300  return changed(simplify_typecast(new_expr)); // recursive call
1301  }
1302  }
1303  else if(op_type_id==ID_c_enum) // enum to int
1304  {
1305  const typet &base_type = to_c_enum_type(op_type).underlying_type();
1306  if(base_type.id()==ID_signedbv || base_type.id()==ID_unsignedbv)
1307  {
1308  // enum constants use the representation of their base type
1309  auto new_expr = expr;
1310  new_expr.op().type() = base_type;
1311  return changed(simplify_typecast(new_expr)); // recursive call
1312  }
1313  }
1314  }
1315  else if(operand.id()==ID_typecast) // typecast of typecast
1316  {
1317  // (T1)(T2)x ---> (T1)
1318  // where T1 has fewer bits than T2
1319  if(
1320  op_type_id == expr_type_id &&
1321  (expr_type_id == ID_unsignedbv || expr_type_id == ID_signedbv) &&
1322  to_bitvector_type(expr_type).get_width() <=
1323  to_bitvector_type(operand.type()).get_width())
1324  {
1325  auto new_expr = expr;
1326  new_expr.op() = to_typecast_expr(operand).op();
1327  // might enable further simplification
1328  return changed(simplify_typecast(new_expr)); // recursive call
1329  }
1330  }
1331  else if(operand.id()==ID_address_of)
1332  {
1333  const exprt &o=to_address_of_expr(operand).object();
1334 
1335  // turn &array into &array[0] when casting to pointer-to-element-type
1336  if(
1337  o.type().id() == ID_array &&
1338  expr_type == pointer_type(to_array_type(o.type()).element_type()))
1339  {
1340  auto result =
1342 
1343  return changed(simplify_address_of(result)); // recursive call
1344  }
1345  }
1346 
1347  return unchanged(expr);
1348 }
1349 
1352 {
1353  const exprt &pointer = expr.pointer();
1354 
1355  if(pointer.type().id()!=ID_pointer)
1356  return unchanged(expr);
1357 
1358  if(pointer.id()==ID_if && pointer.operands().size()==3)
1359  {
1360  const if_exprt &if_expr=to_if_expr(pointer);
1361 
1362  auto tmp_op1 = expr;
1363  tmp_op1.op() = if_expr.true_case();
1364  exprt tmp_op1_result = simplify_dereference(tmp_op1);
1365 
1366  auto tmp_op2 = expr;
1367  tmp_op2.op() = if_expr.false_case();
1368  exprt tmp_op2_result = simplify_dereference(tmp_op2);
1369 
1370  if_exprt tmp{if_expr.cond(), tmp_op1_result, tmp_op2_result};
1371 
1372  return changed(simplify_if(tmp));
1373  }
1374 
1375  if(pointer.id()==ID_address_of)
1376  {
1377  exprt tmp=to_address_of_expr(pointer).object();
1378  // one address_of is gone, try again
1379  return changed(simplify_rec(tmp));
1380  }
1381  // rewrite *(&a[0] + x) to a[x]
1382  else if(
1383  pointer.id() == ID_plus && pointer.operands().size() == 2 &&
1384  to_plus_expr(pointer).op0().id() == ID_address_of)
1385  {
1386  const auto &pointer_plus_expr = to_plus_expr(pointer);
1387 
1388  const address_of_exprt &address_of =
1389  to_address_of_expr(pointer_plus_expr.op0());
1390 
1391  if(address_of.object().id()==ID_index)
1392  {
1393  const index_exprt &old=to_index_expr(address_of.object());
1394  if(old.array().type().id() == ID_array)
1395  {
1396  index_exprt idx(
1397  old.array(),
1398  pointer_offset_sum(old.index(), pointer_plus_expr.op1()),
1399  to_array_type(old.array().type()).element_type());
1400  return changed(simplify_rec(idx));
1401  }
1402  }
1403  }
1404 
1405  return unchanged(expr);
1406 }
1407 
1410 {
1411  return unchanged(expr);
1412 }
1413 
1415 {
1416  bool no_change = true;
1417 
1418  if((expr.operands().size()%2)!=1)
1419  return unchanged(expr);
1420 
1421  // copy
1422  auto with_expr = expr;
1423 
1424  const typet old_type_followed = ns.follow(with_expr.old().type());
1425 
1426  // now look at first operand
1427 
1428  if(old_type_followed.id() == ID_struct)
1429  {
1430  if(with_expr.old().id() == ID_struct || with_expr.old().id() == ID_constant)
1431  {
1432  while(with_expr.operands().size() > 1)
1433  {
1434  const irep_idt &component_name =
1435  with_expr.where().get(ID_component_name);
1436 
1437  if(!to_struct_type(old_type_followed).has_component(component_name))
1438  return unchanged(expr);
1439 
1440  std::size_t number =
1441  to_struct_type(old_type_followed).component_number(component_name);
1442 
1443  if(number >= with_expr.old().operands().size())
1444  return unchanged(expr);
1445 
1446  with_expr.old().operands()[number].swap(with_expr.new_value());
1447 
1448  with_expr.operands().erase(++with_expr.operands().begin());
1449  with_expr.operands().erase(++with_expr.operands().begin());
1450 
1451  no_change = false;
1452  }
1453  }
1454  }
1455  else if(
1456  with_expr.old().type().id() == ID_array ||
1457  with_expr.old().type().id() == ID_vector)
1458  {
1459  if(
1460  with_expr.old().id() == ID_array || with_expr.old().id() == ID_constant ||
1461  with_expr.old().id() == ID_vector)
1462  {
1463  while(with_expr.operands().size() > 1)
1464  {
1465  const auto i = numeric_cast<mp_integer>(with_expr.where());
1466 
1467  if(!i.has_value())
1468  break;
1469 
1470  if(*i < 0 || *i >= with_expr.old().operands().size())
1471  break;
1472 
1473  with_expr.old().operands()[numeric_cast_v<std::size_t>(*i)].swap(
1474  with_expr.new_value());
1475 
1476  with_expr.operands().erase(++with_expr.operands().begin());
1477  with_expr.operands().erase(++with_expr.operands().begin());
1478 
1479  no_change = false;
1480  }
1481  }
1482  }
1483 
1484  if(with_expr.operands().size() == 1)
1485  return with_expr.old();
1486 
1487  if(no_change)
1488  return unchanged(expr);
1489  else
1490  return std::move(with_expr);
1491 }
1492 
1495 {
1496  // this is to push updates into (possibly nested) constants
1497 
1498  const exprt::operandst &designator = expr.designator();
1499 
1500  exprt updated_value = expr.old();
1501  exprt *value_ptr=&updated_value;
1502 
1503  for(const auto &e : designator)
1504  {
1505  const typet &value_ptr_type=ns.follow(value_ptr->type());
1506 
1507  if(e.id()==ID_index_designator &&
1508  value_ptr->id()==ID_array)
1509  {
1510  const auto i = numeric_cast<mp_integer>(to_index_designator(e).index());
1511 
1512  if(!i.has_value())
1513  return unchanged(expr);
1514 
1515  if(*i < 0 || *i >= value_ptr->operands().size())
1516  return unchanged(expr);
1517 
1518  value_ptr = &value_ptr->operands()[numeric_cast_v<std::size_t>(*i)];
1519  }
1520  else if(e.id()==ID_member_designator &&
1521  value_ptr->id()==ID_struct)
1522  {
1523  const irep_idt &component_name=
1524  e.get(ID_component_name);
1525  const struct_typet &value_ptr_struct_type =
1526  to_struct_type(value_ptr_type);
1527  if(!value_ptr_struct_type.has_component(component_name))
1528  return unchanged(expr);
1529  auto &designator_as_struct_expr = to_struct_expr(*value_ptr);
1530  value_ptr = &designator_as_struct_expr.component(component_name, ns);
1531  CHECK_RETURN(value_ptr->is_not_nil());
1532  }
1533  else
1534  return unchanged(expr); // give up, unknown designator
1535  }
1536 
1537  // found, done
1538  *value_ptr = expr.new_value();
1539  return updated_value;
1540 }
1541 
1543 {
1544  if(expr.id()==ID_plus)
1545  {
1546  if(expr.type().id()==ID_pointer)
1547  {
1548  // kill integers from sum
1549  for(auto &op : expr.operands())
1550  if(op.type().id() == ID_pointer)
1551  return changed(simplify_object(op)); // recursive call
1552  }
1553  }
1554  else if(expr.id()==ID_typecast)
1555  {
1556  auto const &typecast_expr = to_typecast_expr(expr);
1557  const typet &op_type = typecast_expr.op().type();
1558 
1559  if(op_type.id()==ID_pointer)
1560  {
1561  // cast from pointer to pointer
1562  return changed(simplify_object(typecast_expr.op())); // recursive call
1563  }
1564  else if(op_type.id()==ID_signedbv || op_type.id()==ID_unsignedbv)
1565  {
1566  // cast from integer to pointer
1567 
1568  // We do a bit of special treatment for (TYPE *)(a+(int)&o) and
1569  // (TYPE *)(a+(int)((T*)&o+x)), which are re-written to '&o'.
1570 
1571  const exprt &casted_expr = typecast_expr.op();
1572  if(casted_expr.id() == ID_plus && casted_expr.operands().size() == 2)
1573  {
1574  const auto &plus_expr = to_plus_expr(casted_expr);
1575 
1576  const exprt &cand = plus_expr.op0().id() == ID_typecast
1577  ? plus_expr.op0()
1578  : plus_expr.op1();
1579 
1580  if(cand.id() == ID_typecast)
1581  {
1582  const auto &typecast_op = to_typecast_expr(cand).op();
1583 
1584  if(typecast_op.id() == ID_address_of)
1585  {
1586  return typecast_op;
1587  }
1588  else if(
1589  typecast_op.id() == ID_plus && typecast_op.operands().size() == 2 &&
1590  to_plus_expr(typecast_op).op0().id() == ID_typecast &&
1591  to_typecast_expr(to_plus_expr(typecast_op).op0()).op().id() ==
1592  ID_address_of)
1593  {
1594  return to_typecast_expr(to_plus_expr(typecast_op).op0()).op();
1595  }
1596  }
1597  }
1598  }
1599  }
1600  else if(expr.id()==ID_address_of)
1601  {
1602  const auto &object = to_address_of_expr(expr).object();
1603 
1604  if(object.id() == ID_index)
1605  {
1606  // &some[i] -> &some
1607  address_of_exprt new_expr(to_index_expr(object).array());
1608  return changed(simplify_object(new_expr)); // recursion
1609  }
1610  else if(object.id() == ID_member)
1611  {
1612  // &some.f -> &some
1613  address_of_exprt new_expr(to_member_expr(object).compound());
1614  return changed(simplify_object(new_expr)); // recursion
1615  }
1616  }
1617 
1618  return unchanged(expr);
1619 }
1620 
1623 {
1624  // lift up any ID_if on the object
1625  if(expr.op().id()==ID_if)
1626  {
1627  if_exprt if_expr=lift_if(expr, 0);
1628  if_expr.true_case() =
1630  if_expr.false_case() =
1632  return changed(simplify_if(if_expr));
1633  }
1634 
1635  const auto el_size = pointer_offset_bits(expr.type(), ns);
1636  if(el_size.has_value() && *el_size < 0)
1637  return unchanged(expr);
1638 
1639  // byte_extract(byte_extract(root, offset1), offset2) =>
1640  // byte_extract(root, offset1+offset2)
1641  if(expr.op().id()==expr.id())
1642  {
1643  auto tmp = expr;
1644 
1645  tmp.offset() = simplify_plus(
1646  plus_exprt(to_byte_extract_expr(expr.op()).offset(), expr.offset()));
1647  tmp.op() = to_byte_extract_expr(expr.op()).op();
1648 
1649  return changed(simplify_byte_extract(tmp)); // recursive call
1650  }
1651 
1652  // byte_extract(byte_update(root, offset, value), offset) =>
1653  // value
1654  if(
1655  ((expr.id() == ID_byte_extract_big_endian &&
1656  expr.op().id() == ID_byte_update_big_endian) ||
1657  (expr.id() == ID_byte_extract_little_endian &&
1658  expr.op().id() == ID_byte_update_little_endian)) &&
1659  expr.offset() == to_byte_update_expr(as_const(expr).op()).offset())
1660  {
1661  const auto &op_byte_update = to_byte_update_expr(expr.op());
1662 
1663  if(expr.type() == op_byte_update.value().type())
1664  {
1665  return op_byte_update.value();
1666  }
1667  else if(
1668  el_size.has_value() &&
1669  *el_size <= pointer_offset_bits(op_byte_update.value().type(), ns))
1670  {
1671  auto tmp = expr;
1672  tmp.op() = op_byte_update.value();
1673  tmp.offset() = from_integer(0, expr.offset().type());
1674 
1675  return changed(simplify_byte_extract(tmp)); // recursive call
1676  }
1677  }
1678 
1679  // the following require a constant offset
1680  auto offset = numeric_cast<mp_integer>(expr.offset());
1681  if(!offset.has_value() || *offset < 0)
1682  return unchanged(expr);
1683 
1684  // don't do any of the following if endianness doesn't match, as
1685  // bytes need to be swapped
1686  if(
1687  *offset == 0 && ((expr.id() == ID_byte_extract_little_endian &&
1690  (expr.id() == ID_byte_extract_big_endian &&
1693  {
1694  // byte extract of full object is object
1695  if(expr.type() == expr.op().type())
1696  {
1697  return expr.op();
1698  }
1699  else if(
1700  expr.type().id() == ID_pointer && expr.op().type().id() == ID_pointer)
1701  {
1702  return typecast_exprt(expr.op(), expr.type());
1703  }
1704  }
1705 
1706  // no proper simplification for expr.type()==void
1707  // or types of unknown size
1708  if(!el_size.has_value() || *el_size == 0)
1709  return unchanged(expr);
1710 
1711  if(expr.op().id()==ID_array_of &&
1712  to_array_of_expr(expr.op()).op().id()==ID_constant)
1713  {
1714  const auto const_bits_opt = expr2bits(
1715  to_array_of_expr(expr.op()).op(),
1718  ns);
1719 
1720  if(!const_bits_opt.has_value())
1721  return unchanged(expr);
1722 
1723  std::string const_bits=const_bits_opt.value();
1724 
1725  DATA_INVARIANT(!const_bits.empty(), "bit representation must be non-empty");
1726 
1727  // double the string until we have sufficiently many bits
1728  while(mp_integer(const_bits.size()) < *offset * 8 + *el_size)
1729  const_bits+=const_bits;
1730 
1731  std::string el_bits = std::string(
1732  const_bits,
1733  numeric_cast_v<std::size_t>(*offset * 8),
1734  numeric_cast_v<std::size_t>(*el_size));
1735 
1736  auto tmp = bits2expr(
1737  el_bits, expr.type(), expr.id() == ID_byte_extract_little_endian, ns);
1738 
1739  if(tmp.has_value())
1740  return std::move(*tmp);
1741  }
1742 
1743  // in some cases we even handle non-const array_of
1744  if(
1745  expr.op().id() == ID_array_of && (*offset * 8) % (*el_size) == 0 &&
1746  *el_size <=
1748  {
1749  auto tmp = expr;
1750  tmp.op() = simplify_index(index_exprt(expr.op(), expr.offset()));
1751  tmp.offset() = from_integer(0, expr.offset().type());
1752  return changed(simplify_byte_extract(tmp));
1753  }
1754 
1755  // extract bits of a constant
1756  const auto bits =
1757  expr2bits(expr.op(), expr.id() == ID_byte_extract_little_endian, ns);
1758 
1759  // make sure we don't lose bits with structs containing flexible array members
1760  const bool struct_has_flexible_array_member = has_subtype(
1761  expr.type(),
1762  [&](const typet &type) {
1763  if(type.id() != ID_struct && type.id() != ID_struct_tag)
1764  return false;
1765 
1766  const struct_typet &st = to_struct_type(ns.follow(type));
1767  const auto &comps = st.components();
1768  if(comps.empty() || comps.back().type().id() != ID_array)
1769  return false;
1770 
1771  if(comps.back().type().get_bool(ID_C_flexible_array_member))
1772  return true;
1773 
1774  const auto size =
1775  numeric_cast<mp_integer>(to_array_type(comps.back().type()).size());
1776  return !size.has_value() || *size <= 1;
1777  },
1778  ns);
1779  if(
1780  bits.has_value() && mp_integer(bits->size()) >= *el_size + *offset * 8 &&
1781  !struct_has_flexible_array_member)
1782  {
1783  std::string bits_cut = std::string(
1784  bits.value(),
1785  numeric_cast_v<std::size_t>(*offset * 8),
1786  numeric_cast_v<std::size_t>(*el_size));
1787 
1788  auto tmp = bits2expr(
1789  bits_cut, expr.type(), expr.id() == ID_byte_extract_little_endian, ns);
1790 
1791  if(tmp.has_value())
1792  return std::move(*tmp);
1793  }
1794 
1795  // push byte extracts into struct or union expressions, just like
1796  // lower_byte_extract does (this is the same code, except recursive calls use
1797  // simplify rather than lower_byte_extract)
1798  if(expr.op().id() == ID_struct || expr.op().id() == ID_union)
1799  {
1800  if(expr.type().id() == ID_struct || expr.type().id() == ID_struct_tag)
1801  {
1802  const struct_typet &struct_type = to_struct_type(ns.follow(expr.type()));
1803  const struct_typet::componentst &components = struct_type.components();
1804 
1805  bool failed = false;
1806  struct_exprt s({}, expr.type());
1807 
1808  for(const auto &comp : components)
1809  {
1810  auto component_bits = pointer_offset_bits(comp.type(), ns);
1811 
1812  // the next member would be misaligned, abort
1813  if(
1814  !component_bits.has_value() || *component_bits == 0 ||
1815  *component_bits % 8 != 0)
1816  {
1817  failed = true;
1818  break;
1819  }
1820 
1821  auto member_offset_opt =
1822  member_offset_expr(struct_type, comp.get_name(), ns);
1823 
1824  if(!member_offset_opt.has_value())
1825  {
1826  failed = true;
1827  break;
1828  }
1829 
1830  exprt new_offset = simplify_rec(
1831  plus_exprt{expr.offset(),
1833  member_offset_opt.value(), expr.offset().type())});
1834 
1835  byte_extract_exprt tmp = expr;
1836  tmp.type() = comp.type();
1837  tmp.offset() = new_offset;
1838 
1840  }
1841 
1842  if(!failed)
1843  return s;
1844  }
1845  else if(expr.type().id() == ID_union || expr.type().id() == ID_union_tag)
1846  {
1847  const union_typet &union_type = to_union_type(ns.follow(expr.type()));
1848  auto widest_member_opt = union_type.find_widest_union_component(ns);
1849  if(widest_member_opt.has_value())
1850  {
1851  byte_extract_exprt be = expr;
1852  be.type() = widest_member_opt->first.type();
1853  return union_exprt{widest_member_opt->first.get_name(),
1855  expr.type()};
1856  }
1857  }
1858  }
1859  else if(expr.op().id() == ID_array)
1860  {
1861  const array_typet &array_type = to_array_type(expr.op().type());
1862  const auto &element_bit_width =
1863  pointer_offset_bits(array_type.element_type(), ns);
1864  if(element_bit_width.has_value() && *element_bit_width > 0)
1865  {
1866  if(*offset > 0 && *offset * 8 % *element_bit_width == 0)
1867  {
1868  const auto elements_to_erase =
1869  numeric_cast_v<std::size_t>((*offset * 8) / *element_bit_width);
1870  array_exprt slice = to_array_expr(expr.op());
1871  slice.operands().erase(
1872  slice.operands().begin(),
1873  slice.operands().begin() +
1874  std::min(elements_to_erase, slice.operands().size()));
1875  slice.type().size() =
1876  from_integer(slice.operands().size(), slice.type().size().type());
1877  byte_extract_exprt be = expr;
1878  be.op() = slice;
1879  be.offset() = from_integer(0, expr.offset().type());
1880  return changed(simplify_byte_extract(be));
1881  }
1882  else if(*offset == 0 && *el_size % *element_bit_width == 0)
1883  {
1884  const auto elements_to_keep =
1885  numeric_cast_v<std::size_t>(*el_size / *element_bit_width);
1886  array_exprt slice = to_array_expr(expr.op());
1887  if(slice.operands().size() > elements_to_keep)
1888  {
1889  slice.operands().resize(elements_to_keep);
1890  slice.type().size() =
1891  from_integer(slice.operands().size(), slice.type().size().type());
1892  byte_extract_exprt be = expr;
1893  be.op() = slice;
1894  return changed(simplify_byte_extract(be));
1895  }
1896  }
1897  }
1898  }
1899 
1900  // try to refine it down to extracting from a member or an index in an array
1901  auto subexpr =
1902  get_subexpression_at_offset(expr.op(), *offset, expr.type(), ns);
1903  if(!subexpr.has_value() || subexpr.value() == expr)
1904  return unchanged(expr);
1905 
1906  return changed(simplify_rec(subexpr.value())); // recursive call
1907 }
1908 
1911 {
1912  // byte_update(byte_update(root, offset, value), offset, value2) =>
1913  // byte_update(root, offset, value2)
1914  if(
1915  expr.id() == expr.op().id() &&
1916  expr.offset() == to_byte_update_expr(expr.op()).offset() &&
1917  expr.value().type() == to_byte_update_expr(expr.op()).value().type())
1918  {
1919  auto tmp = expr;
1920  tmp.set_op(to_byte_update_expr(expr.op()).op());
1921  return std::move(tmp);
1922  }
1923 
1924  const exprt &root = expr.op();
1925  const exprt &offset = expr.offset();
1926  const exprt &value = expr.value();
1927  const auto val_size = pointer_offset_bits(value.type(), ns);
1928  const auto root_size = pointer_offset_bits(root.type(), ns);
1929 
1930  // byte update of full object is byte_extract(new value)
1931  if(
1932  offset.is_zero() && val_size.has_value() && *val_size > 0 &&
1933  root_size.has_value() && *root_size > 0 && *val_size >= *root_size)
1934  {
1935  byte_extract_exprt be(
1936  expr.id()==ID_byte_update_little_endian ?
1937  ID_byte_extract_little_endian :
1938  ID_byte_extract_big_endian,
1939  value, offset, expr.type());
1940 
1941  return changed(simplify_byte_extract(be));
1942  }
1943 
1944  // update bits in a constant
1945  const auto offset_int = numeric_cast<mp_integer>(offset);
1946  if(
1947  root_size.has_value() && *root_size >= 0 && val_size.has_value() &&
1948  *val_size >= 0 && offset_int.has_value() && *offset_int >= 0 &&
1949  *offset_int * 8 + *val_size <= *root_size)
1950  {
1951  auto root_bits =
1952  expr2bits(root, expr.id() == ID_byte_update_little_endian, ns);
1953 
1954  if(root_bits.has_value())
1955  {
1956  const auto val_bits =
1957  expr2bits(value, expr.id() == ID_byte_update_little_endian, ns);
1958 
1959  if(val_bits.has_value())
1960  {
1961  root_bits->replace(
1962  numeric_cast_v<std::size_t>(*offset_int * 8),
1963  numeric_cast_v<std::size_t>(*val_size),
1964  *val_bits);
1965 
1966  auto tmp = bits2expr(
1967  *root_bits,
1968  expr.type(),
1969  expr.id() == ID_byte_update_little_endian,
1970  ns);
1971 
1972  if(tmp.has_value())
1973  return std::move(*tmp);
1974  }
1975  }
1976  }
1977 
1978  /*
1979  * byte_update(root, offset,
1980  * extract(root, offset) WITH component:=value)
1981  * =>
1982  * byte_update(root, offset + component offset,
1983  * value)
1984  */
1985 
1986  if(expr.id()!=ID_byte_update_little_endian)
1987  return unchanged(expr);
1988 
1989  if(value.id()==ID_with)
1990  {
1991  const with_exprt &with=to_with_expr(value);
1992 
1993  if(with.old().id()==ID_byte_extract_little_endian)
1994  {
1995  const byte_extract_exprt &extract=to_byte_extract_expr(with.old());
1996 
1997  /* the simplification can be used only if
1998  root and offset of update and extract
1999  are the same */
2000  if(!(root==extract.op()))
2001  return unchanged(expr);
2002  if(!(offset==extract.offset()))
2003  return unchanged(expr);
2004 
2005  const typet &tp=ns.follow(with.type());
2006  if(tp.id()==ID_struct)
2007  {
2008  const struct_typet &struct_type=to_struct_type(tp);
2009  const irep_idt &component_name=with.where().get(ID_component_name);
2010  const typet &c_type = struct_type.get_component(component_name).type();
2011 
2012  // is this a bit field?
2013  if(c_type.id() == ID_c_bit_field || c_type.id() == ID_bool)
2014  {
2015  // don't touch -- might not be byte-aligned
2016  }
2017  else
2018  {
2019  // new offset = offset + component offset
2020  auto i = member_offset(struct_type, component_name, ns);
2021  if(i.has_value())
2022  {
2023  exprt compo_offset = from_integer(*i, offset.type());
2024  plus_exprt new_offset(offset, compo_offset);
2025  exprt new_value(with.new_value());
2026  auto tmp = expr;
2027  tmp.set_offset(simplify_node(std::move(new_offset)));
2028  tmp.set_value(std::move(new_value));
2029  return changed(simplify_byte_update(tmp)); // recursive call
2030  }
2031  }
2032  }
2033  else if(tp.id()==ID_array)
2034  {
2035  auto i = pointer_offset_size(to_array_type(tp).element_type(), ns);
2036  if(i.has_value())
2037  {
2038  const exprt &index=with.where();
2039  exprt index_offset =
2040  simplify_mult(mult_exprt(index, from_integer(*i, index.type())));
2041 
2042  // index_offset may need a typecast
2043  if(offset.type() != index.type())
2044  {
2045  index_offset =
2046  simplify_typecast(typecast_exprt(index_offset, offset.type()));
2047  }
2048 
2049  plus_exprt new_offset(offset, index_offset);
2050  exprt new_value(with.new_value());
2051  auto tmp = expr;
2052  tmp.set_offset(simplify_plus(std::move(new_offset)));
2053  tmp.set_value(std::move(new_value));
2054  return changed(simplify_byte_update(tmp)); // recursive call
2055  }
2056  }
2057  }
2058  }
2059 
2060  // the following require a constant offset
2061  if(!offset_int.has_value() || *offset_int < 0)
2062  return unchanged(expr);
2063 
2064  const typet &op_type=ns.follow(root.type());
2065 
2066  // size must be known
2067  if(!val_size.has_value() || *val_size == 0)
2068  return unchanged(expr);
2069 
2070  // Are we updating (parts of) a struct? Do individual member updates
2071  // instead, unless there are non-byte-sized bit fields
2072  if(op_type.id()==ID_struct)
2073  {
2074  exprt result_expr;
2075  result_expr.make_nil();
2076 
2077  auto update_size = pointer_offset_size(value.type(), ns);
2078 
2079  const struct_typet &struct_type=
2080  to_struct_type(op_type);
2081  const struct_typet::componentst &components=
2082  struct_type.components();
2083 
2084  for(const auto &component : components)
2085  {
2086  auto m_offset = member_offset(struct_type, component.get_name(), ns);
2087 
2088  auto m_size_bits = pointer_offset_bits(component.type(), ns);
2089 
2090  // can we determine the current offset?
2091  if(!m_offset.has_value())
2092  {
2093  result_expr.make_nil();
2094  break;
2095  }
2096 
2097  // is it a byte-sized member?
2098  if(!m_size_bits.has_value() || *m_size_bits == 0 || (*m_size_bits) % 8 != 0)
2099  {
2100  result_expr.make_nil();
2101  break;
2102  }
2103 
2104  mp_integer m_size_bytes = (*m_size_bits) / 8;
2105 
2106  // is that member part of the update?
2107  if(*m_offset + m_size_bytes <= *offset_int)
2108  continue;
2109  // are we done updating?
2110  else if(
2111  update_size.has_value() && *update_size > 0 &&
2112  *m_offset >= *offset_int + *update_size)
2113  {
2114  break;
2115  }
2116 
2117  if(result_expr.is_nil())
2118  result_expr = as_const(expr).op();
2119 
2120  exprt member_name(ID_member_name);
2121  member_name.set(ID_component_name, component.get_name());
2122  result_expr=with_exprt(result_expr, member_name, nil_exprt());
2123 
2124  // are we updating on member boundaries?
2125  if(
2126  *m_offset < *offset_int ||
2127  (*m_offset == *offset_int && update_size.has_value() &&
2128  *update_size > 0 && m_size_bytes > *update_size))
2129  {
2131  ID_byte_update_little_endian,
2132  member_exprt(root, component.get_name(), component.type()),
2133  from_integer(*offset_int - *m_offset, offset.type()),
2134  value);
2135 
2136  to_with_expr(result_expr).new_value().swap(v);
2137  }
2138  else if(
2139  update_size.has_value() && *update_size > 0 &&
2140  *m_offset + m_size_bytes > *offset_int + *update_size)
2141  {
2142  // we don't handle this for the moment
2143  result_expr.make_nil();
2144  break;
2145  }
2146  else
2147  {
2149  ID_byte_extract_little_endian,
2150  value,
2151  from_integer(*m_offset - *offset_int, offset.type()),
2152  component.type());
2153 
2154  to_with_expr(result_expr).new_value().swap(v);
2155  }
2156  }
2157 
2158  if(result_expr.is_not_nil())
2159  return changed(simplify_rec(result_expr));
2160  }
2161 
2162  // replace elements of array or struct expressions, possibly using
2163  // byte_extract
2164  if(root.id()==ID_array)
2165  {
2166  auto el_size =
2167  pointer_offset_bits(to_type_with_subtype(op_type).subtype(), ns);
2168 
2169  if(!el_size.has_value() || *el_size == 0 ||
2170  (*el_size) % 8 != 0 || (*val_size) % 8 != 0)
2171  {
2172  return unchanged(expr);
2173  }
2174 
2175  exprt result=root;
2176 
2177  mp_integer m_offset_bits=0, val_offset=0;
2178  Forall_operands(it, result)
2179  {
2180  if(*offset_int * 8 + (*val_size) <= m_offset_bits)
2181  break;
2182 
2183  if(*offset_int * 8 < m_offset_bits + *el_size)
2184  {
2185  mp_integer bytes_req = (m_offset_bits + *el_size) / 8 - *offset_int;
2186  bytes_req-=val_offset;
2187  if(val_offset + bytes_req > (*val_size) / 8)
2188  bytes_req = (*val_size) / 8 - val_offset;
2189 
2190  byte_extract_exprt new_val(
2191  ID_byte_extract_little_endian,
2192  value,
2193  from_integer(val_offset, offset.type()),
2194  array_typet(
2195  unsignedbv_typet(8), from_integer(bytes_req, offset.type())));
2196 
2197  *it = byte_update_exprt(
2198  expr.id(),
2199  *it,
2200  from_integer(
2201  *offset_int + val_offset - m_offset_bits / 8, offset.type()),
2202  new_val);
2203 
2204  *it = simplify_rec(*it); // recursive call
2205 
2206  val_offset+=bytes_req;
2207  }
2208 
2209  m_offset_bits += *el_size;
2210  }
2211 
2212  return std::move(result);
2213  }
2214 
2215  return unchanged(expr);
2216 }
2217 
2220 {
2221  if(expr.id() == ID_complex_real)
2222  {
2223  auto &complex_real_expr = to_complex_real_expr(expr);
2224 
2225  if(complex_real_expr.op().id() == ID_complex)
2226  return to_complex_expr(complex_real_expr.op()).real();
2227  }
2228  else if(expr.id() == ID_complex_imag)
2229  {
2230  auto &complex_imag_expr = to_complex_imag_expr(expr);
2231 
2232  if(complex_imag_expr.op().id() == ID_complex)
2233  return to_complex_expr(complex_imag_expr.op()).imag();
2234  }
2235 
2236  return unchanged(expr);
2237 }
2238 
2241 {
2242  // When one operand is zero, an overflow can only occur for a subtraction from
2243  // zero.
2244  if(
2245  expr.op1().is_zero() ||
2246  (expr.op0().is_zero() && !can_cast_expr<minus_overflow_exprt>(expr)))
2247  {
2248  return false_exprt{};
2249  }
2250 
2251  // One is neutral element for multiplication
2252  if(
2254  (expr.op0().is_one() || expr.op1().is_one()))
2255  {
2256  return false_exprt{};
2257  }
2258 
2259  // we only handle the case of same operand types
2260  if(expr.op0().type() != expr.op1().type())
2261  return unchanged(expr);
2262 
2263  // catch some cases over mathematical types
2264  const irep_idt &op_type_id = expr.op0().type().id();
2265  if(
2266  op_type_id == ID_integer || op_type_id == ID_rational ||
2267  op_type_id == ID_real)
2268  {
2269  return false_exprt{};
2270  }
2271 
2272  if(op_type_id == ID_natural && !can_cast_expr<minus_overflow_exprt>(expr))
2273  return false_exprt{};
2274 
2275  // we only handle constants over signedbv/unsignedbv for the remaining cases
2276  if(op_type_id != ID_signedbv && op_type_id != ID_unsignedbv)
2277  return unchanged(expr);
2278 
2279  if(!expr.op0().is_constant() || !expr.op1().is_constant())
2280  return unchanged(expr);
2281 
2282  const auto op0_value = numeric_cast<mp_integer>(expr.op0());
2283  const auto op1_value = numeric_cast<mp_integer>(expr.op1());
2284  if(!op0_value.has_value() || !op1_value.has_value())
2285  return unchanged(expr);
2286 
2287  mp_integer no_overflow_result;
2289  no_overflow_result = *op0_value + *op1_value;
2291  no_overflow_result = *op0_value - *op1_value;
2292  else if(can_cast_expr<mult_overflow_exprt>(expr))
2293  no_overflow_result = *op0_value * *op1_value;
2294  else if(can_cast_expr<shl_overflow_exprt>(expr))
2295  no_overflow_result = *op0_value << *op1_value;
2296  else
2297  UNREACHABLE;
2298 
2299  const std::size_t width = to_bitvector_type(expr.op0().type()).get_width();
2300  const integer_bitvector_typet bv_type{op_type_id, width};
2301  if(
2302  no_overflow_result < bv_type.smallest() ||
2303  no_overflow_result > bv_type.largest())
2304  {
2305  return true_exprt{};
2306  }
2307  else
2308  return false_exprt{};
2309 }
2310 
2313 {
2314  // zero is a neutral element for all operations supported here
2315  if(expr.op().is_zero())
2316  return false_exprt{};
2317 
2318  // catch some cases over mathematical types
2319  const irep_idt &op_type_id = expr.op().type().id();
2320  if(
2321  op_type_id == ID_integer || op_type_id == ID_rational ||
2322  op_type_id == ID_real)
2323  {
2324  return false_exprt{};
2325  }
2326 
2327  if(op_type_id == ID_natural)
2328  return true_exprt{};
2329 
2330  // we only handle constants over signedbv/unsignedbv for the remaining cases
2331  if(op_type_id != ID_signedbv && op_type_id != ID_unsignedbv)
2332  return unchanged(expr);
2333 
2334  if(!expr.op().is_constant())
2335  return unchanged(expr);
2336 
2337  const auto op_value = numeric_cast<mp_integer>(expr.op());
2338  if(!op_value.has_value())
2339  return unchanged(expr);
2340 
2341  mp_integer no_overflow_result;
2343  no_overflow_result = -*op_value;
2344  else
2345  UNREACHABLE;
2346 
2347  const std::size_t width = to_bitvector_type(expr.op().type()).get_width();
2348  const integer_bitvector_typet bv_type{op_type_id, width};
2349  if(
2350  no_overflow_result < bv_type.smallest() ||
2351  no_overflow_result > bv_type.largest())
2352  {
2353  return true_exprt{};
2354  }
2355  else
2356  return false_exprt{};
2357 }
2358 
2361 {
2362  if(expr.id() == ID_overflow_result_unary_minus)
2363  {
2364  // zero is a neutral element
2365  if(expr.op0().is_zero())
2366  return struct_exprt{{expr.op0(), false_exprt{}}, expr.type()};
2367 
2368  // catch some cases over mathematical types
2369  const irep_idt &op_type_id = expr.op0().type().id();
2370  if(
2371  op_type_id == ID_integer || op_type_id == ID_rational ||
2372  op_type_id == ID_real)
2373  {
2374  return struct_exprt{{expr.op0(), false_exprt{}}, expr.type()};
2375  }
2376 
2377  // always an overflow for natural numbers, but the result is not
2378  // representable
2379  if(op_type_id == ID_natural)
2380  return unchanged(expr);
2381 
2382  // we only handle constants over signedbv/unsignedbv for the remaining cases
2383  if(op_type_id != ID_signedbv && op_type_id != ID_unsignedbv)
2384  return unchanged(expr);
2385 
2386  if(!expr.op0().is_constant())
2387  return unchanged(expr);
2388 
2389  const auto op_value = numeric_cast<mp_integer>(expr.op0());
2390  if(!op_value.has_value())
2391  return unchanged(expr);
2392 
2393  mp_integer no_overflow_result = -*op_value;
2394 
2395  const std::size_t width = to_bitvector_type(expr.op0().type()).get_width();
2396  const integer_bitvector_typet bv_type{op_type_id, width};
2397  if(
2398  no_overflow_result < bv_type.smallest() ||
2399  no_overflow_result > bv_type.largest())
2400  {
2401  return struct_exprt{
2402  {from_integer(no_overflow_result, expr.op0().type()), true_exprt{}},
2403  expr.type()};
2404  }
2405  else
2406  {
2407  return struct_exprt{
2408  {from_integer(no_overflow_result, expr.op0().type()), false_exprt{}},
2409  expr.type()};
2410  }
2411  }
2412  else
2413  {
2414  // When one operand is zero, an overflow can only occur for a subtraction
2415  // from zero.
2416  if(expr.op0().is_zero())
2417  {
2418  if(
2419  expr.id() == ID_overflow_result_plus ||
2420  expr.id() == ID_overflow_result_shl)
2421  {
2422  return struct_exprt{{expr.op1(), false_exprt{}}, expr.type()};
2423  }
2424  else if(expr.id() == ID_overflow_result_mult)
2425  {
2426  return struct_exprt{
2427  {from_integer(0, expr.op0().type()), false_exprt{}}, expr.type()};
2428  }
2429  }
2430  else if(expr.op1().is_zero())
2431  {
2432  if(
2433  expr.id() == ID_overflow_result_plus ||
2434  expr.id() == ID_overflow_result_minus ||
2435  expr.id() == ID_overflow_result_shl)
2436  {
2437  return struct_exprt{{expr.op0(), false_exprt{}}, expr.type()};
2438  }
2439  else
2440  {
2441  return struct_exprt{
2442  {from_integer(0, expr.op0().type()), false_exprt{}}, expr.type()};
2443  }
2444  }
2445 
2446  // One is neutral element for multiplication
2447  if(
2448  expr.id() == ID_overflow_result_mult &&
2449  (expr.op0().is_one() || expr.op1().is_one()))
2450  {
2451  return struct_exprt{
2452  {expr.op0().is_one() ? expr.op1() : expr.op0(), false_exprt{}},
2453  expr.type()};
2454  }
2455 
2456  // we only handle the case of same operand types
2457  if(
2458  expr.id() != ID_overflow_result_shl &&
2459  expr.op0().type() != expr.op1().type())
2460  {
2461  return unchanged(expr);
2462  }
2463 
2464  // catch some cases over mathematical types
2465  const irep_idt &op_type_id = expr.op0().type().id();
2466  if(
2467  expr.id() != ID_overflow_result_shl &&
2468  (op_type_id == ID_integer || op_type_id == ID_rational ||
2469  op_type_id == ID_real))
2470  {
2471  irep_idt id =
2472  expr.id() == ID_overflow_result_plus
2473  ? ID_plus
2474  : expr.id() == ID_overflow_result_minus ? ID_minus : ID_mult;
2475  return struct_exprt{
2476  {simplify_node(binary_exprt{expr.op0(), id, expr.op1()}),
2477  false_exprt{}},
2478  expr.type()};
2479  }
2480 
2481  if(
2482  (expr.id() == ID_overflow_result_plus ||
2483  expr.id() == ID_overflow_result_mult) &&
2484  op_type_id == ID_natural)
2485  {
2486  return struct_exprt{
2488  expr.op0(),
2489  expr.id() == ID_overflow_result_plus ? ID_plus : ID_mult,
2490  expr.op1()}),
2491  false_exprt{}},
2492  expr.type()};
2493  }
2494 
2495  // we only handle constants over signedbv/unsignedbv for the remaining cases
2496  if(op_type_id != ID_signedbv && op_type_id != ID_unsignedbv)
2497  return unchanged(expr);
2498 
2499  if(!expr.op0().is_constant() || !expr.op1().is_constant())
2500  return unchanged(expr);
2501 
2502  const auto op0_value = numeric_cast<mp_integer>(expr.op0());
2503  const auto op1_value = numeric_cast<mp_integer>(expr.op1());
2504  if(!op0_value.has_value() || !op1_value.has_value())
2505  return unchanged(expr);
2506 
2507  mp_integer no_overflow_result;
2508  if(expr.id() == ID_overflow_result_plus)
2509  no_overflow_result = *op0_value + *op1_value;
2510  else if(expr.id() == ID_overflow_result_minus)
2511  no_overflow_result = *op0_value - *op1_value;
2512  else if(expr.id() == ID_overflow_result_mult)
2513  no_overflow_result = *op0_value * *op1_value;
2514  else if(expr.id() == ID_overflow_result_shl)
2515  no_overflow_result = *op0_value << *op1_value;
2516  else
2517  UNREACHABLE;
2518 
2519  const std::size_t width = to_bitvector_type(expr.op0().type()).get_width();
2520  const integer_bitvector_typet bv_type{op_type_id, width};
2521  if(
2522  no_overflow_result < bv_type.smallest() ||
2523  no_overflow_result > bv_type.largest())
2524  {
2525  return struct_exprt{
2526  {from_integer(no_overflow_result, expr.op0().type()), true_exprt{}},
2527  expr.type()};
2528  }
2529  else
2530  {
2531  return struct_exprt{
2532  {from_integer(no_overflow_result, expr.op0().type()), false_exprt{}},
2533  expr.type()};
2534  }
2535  }
2536 }
2537 
2539 {
2540  bool result=true;
2541 
2542  // The ifs below could one day be replaced by a switch()
2543 
2544  if(expr.id()==ID_address_of)
2545  {
2546  // the argument of this expression needs special treatment
2547  }
2548  else if(expr.id()==ID_if)
2549  result=simplify_if_preorder(to_if_expr(expr));
2550  else
2551  {
2552  if(expr.has_operands())
2553  {
2554  Forall_operands(it, expr)
2555  {
2556  auto r_it = simplify_rec(*it); // recursive call
2557  if(r_it.has_changed())
2558  {
2559  *it = r_it.expr;
2560  result=false;
2561  }
2562  }
2563  }
2564  }
2565 
2566  return result;
2567 }
2568 
2570 {
2571  if(!node.has_operands())
2572  return unchanged(node); // no change
2573 
2574  // #define DEBUGX
2575 
2576 #ifdef DEBUGX
2577  exprt old(node);
2578 #endif
2579 
2580  exprt expr = node;
2581  bool no_change_join_operands = join_operands(expr);
2582 
2583  resultt<> r = unchanged(expr);
2584 
2585  if(expr.id()==ID_typecast)
2586  {
2588  }
2589  else if(expr.id()==ID_equal || expr.id()==ID_notequal ||
2590  expr.id()==ID_gt || expr.id()==ID_lt ||
2591  expr.id()==ID_ge || expr.id()==ID_le)
2592  {
2594  }
2595  else if(expr.id()==ID_if)
2596  {
2597  r = simplify_if(to_if_expr(expr));
2598  }
2599  else if(expr.id()==ID_lambda)
2600  {
2601  r = simplify_lambda(to_lambda_expr(expr));
2602  }
2603  else if(expr.id()==ID_with)
2604  {
2605  r = simplify_with(to_with_expr(expr));
2606  }
2607  else if(expr.id()==ID_update)
2608  {
2609  r = simplify_update(to_update_expr(expr));
2610  }
2611  else if(expr.id()==ID_index)
2612  {
2613  r = simplify_index(to_index_expr(expr));
2614  }
2615  else if(expr.id()==ID_member)
2616  {
2617  r = simplify_member(to_member_expr(expr));
2618  }
2619  else if(expr.id()==ID_byte_update_little_endian ||
2620  expr.id()==ID_byte_update_big_endian)
2621  {
2623  }
2624  else if(expr.id()==ID_byte_extract_little_endian ||
2625  expr.id()==ID_byte_extract_big_endian)
2626  {
2628  }
2629  else if(expr.id()==ID_pointer_object)
2630  {
2632  }
2633  else if(expr.id() == ID_is_dynamic_object)
2634  {
2636  }
2637  else if(expr.id() == ID_is_invalid_pointer)
2638  {
2640  }
2641  else if(
2642  const auto object_size = expr_try_dynamic_cast<object_size_exprt>(expr))
2643  {
2645  }
2646  else if(expr.id()==ID_good_pointer)
2647  {
2649  }
2650  else if(expr.id()==ID_div)
2651  {
2652  r = simplify_div(to_div_expr(expr));
2653  }
2654  else if(expr.id()==ID_mod)
2655  {
2656  r = simplify_mod(to_mod_expr(expr));
2657  }
2658  else if(expr.id()==ID_bitnot)
2659  {
2660  r = simplify_bitnot(to_bitnot_expr(expr));
2661  }
2662  else if(expr.id()==ID_bitand ||
2663  expr.id()==ID_bitor ||
2664  expr.id()==ID_bitxor)
2665  {
2667  }
2668  else if(expr.id()==ID_ashr || expr.id()==ID_lshr || expr.id()==ID_shl)
2669  {
2670  r = simplify_shifts(to_shift_expr(expr));
2671  }
2672  else if(expr.id()==ID_power)
2673  {
2674  r = simplify_power(to_binary_expr(expr));
2675  }
2676  else if(expr.id()==ID_plus)
2677  {
2678  r = simplify_plus(to_plus_expr(expr));
2679  }
2680  else if(expr.id()==ID_minus)
2681  {
2682  r = simplify_minus(to_minus_expr(expr));
2683  }
2684  else if(expr.id()==ID_mult)
2685  {
2686  r = simplify_mult(to_mult_expr(expr));
2687  }
2688  else if(expr.id()==ID_floatbv_plus ||
2689  expr.id()==ID_floatbv_minus ||
2690  expr.id()==ID_floatbv_mult ||
2691  expr.id()==ID_floatbv_div)
2692  {
2694  }
2695  else if(expr.id()==ID_floatbv_typecast)
2696  {
2698  }
2699  else if(expr.id()==ID_unary_minus)
2700  {
2702  }
2703  else if(expr.id()==ID_unary_plus)
2704  {
2706  }
2707  else if(expr.id()==ID_not)
2708  {
2709  r = simplify_not(to_not_expr(expr));
2710  }
2711  else if(expr.id()==ID_implies ||
2712  expr.id()==ID_or || expr.id()==ID_xor ||
2713  expr.id()==ID_and)
2714  {
2715  r = simplify_boolean(expr);
2716  }
2717  else if(expr.id()==ID_dereference)
2718  {
2720  }
2721  else if(expr.id()==ID_address_of)
2722  {
2724  }
2725  else if(expr.id()==ID_pointer_offset)
2726  {
2728  }
2729  else if(expr.id()==ID_extractbit)
2730  {
2732  }
2733  else if(expr.id()==ID_concatenation)
2734  {
2736  }
2737  else if(expr.id()==ID_extractbits)
2738  {
2740  }
2741  else if(expr.id()==ID_ieee_float_equal ||
2742  expr.id()==ID_ieee_float_notequal)
2743  {
2745  }
2746  else if(expr.id() == ID_bswap)
2747  {
2748  r = simplify_bswap(to_bswap_expr(expr));
2749  }
2750  else if(expr.id()==ID_isinf)
2751  {
2752  r = simplify_isinf(to_unary_expr(expr));
2753  }
2754  else if(expr.id()==ID_isnan)
2755  {
2756  r = simplify_isnan(to_unary_expr(expr));
2757  }
2758  else if(expr.id()==ID_isnormal)
2759  {
2761  }
2762  else if(expr.id()==ID_abs)
2763  {
2764  r = simplify_abs(to_abs_expr(expr));
2765  }
2766  else if(expr.id()==ID_sign)
2767  {
2768  r = simplify_sign(to_sign_expr(expr));
2769  }
2770  else if(expr.id() == ID_popcount)
2771  {
2773  }
2774  else if(expr.id() == ID_count_leading_zeros)
2775  {
2777  }
2778  else if(expr.id() == ID_count_trailing_zeros)
2779  {
2781  }
2782  else if(expr.id() == ID_find_first_set)
2783  {
2785  }
2786  else if(expr.id() == ID_function_application)
2787  {
2789  }
2790  else if(expr.id() == ID_complex_real || expr.id() == ID_complex_imag)
2791  {
2792  r = simplify_complex(to_unary_expr(expr));
2793  }
2794  else if(
2795  const auto binary_overflow =
2796  expr_try_dynamic_cast<binary_overflow_exprt>(expr))
2797  {
2798  r = simplify_overflow_binary(*binary_overflow);
2799  }
2800  else if(
2801  const auto unary_overflow =
2802  expr_try_dynamic_cast<unary_overflow_exprt>(expr))
2803  {
2804  r = simplify_overflow_unary(*unary_overflow);
2805  }
2806  else if(
2807  const auto overflow_result =
2808  expr_try_dynamic_cast<overflow_result_exprt>(expr))
2809  {
2810  r = simplify_overflow_result(*overflow_result);
2811  }
2812  else if(expr.id() == ID_bitreverse)
2813  {
2815  }
2816 
2817  if(!no_change_join_operands)
2818  r = changed(r);
2819 
2820 #ifdef DEBUGX
2821  if(
2822  r.has_changed()
2823 # ifdef DEBUG_ON_DEMAND
2824  && debug_on
2825 # endif
2826  )
2827  {
2828  std::cout << "===== " << node.id() << ": " << format(node) << '\n'
2829  << " ---> " << format(r.expr) << '\n';
2830  }
2831 #endif
2832 
2833  return r;
2834 }
2835 
2837 {
2838  // look up in cache
2839 
2840  #ifdef USE_CACHE
2841  std::pair<simplify_expr_cachet::containert::iterator, bool>
2842  cache_result=simplify_expr_cache.container().
2843  insert(std::pair<exprt, exprt>(expr, exprt()));
2844 
2845  if(!cache_result.second) // found!
2846  {
2847  const exprt &new_expr=cache_result.first->second;
2848 
2849  if(new_expr.id().empty())
2850  return true; // no change
2851 
2852  expr=new_expr;
2853  return false;
2854  }
2855  #endif
2856 
2857  // We work on a copy to prevent unnecessary destruction of sharing.
2858  exprt tmp=expr;
2859  bool no_change = simplify_node_preorder(tmp);
2860 
2861  auto simplify_node_result = simplify_node(tmp);
2862 
2863  if(simplify_node_result.has_changed())
2864  {
2865  no_change = false;
2866  tmp = simplify_node_result.expr;
2867  }
2868 
2869 #ifdef USE_LOCAL_REPLACE_MAP
2870  #if 1
2871  replace_mapt::const_iterator it=local_replace_map.find(tmp);
2872  if(it!=local_replace_map.end())
2873  {
2874  tmp=it->second;
2875  no_change = false;
2876  }
2877  #else
2878  if(!local_replace_map.empty() &&
2879  !replace_expr(local_replace_map, tmp))
2880  {
2881  simplify_rec(tmp);
2882  no_change = false;
2883  }
2884  #endif
2885 #endif
2886 
2887  if(no_change) // no change
2888  {
2889  return unchanged(expr);
2890  }
2891  else // change, new expression is 'tmp'
2892  {
2893  POSTCONDITION(as_const(tmp).type() == expr.type());
2894 
2895 #ifdef USE_CACHE
2896  // save in cache
2897  cache_result.first->second = tmp;
2898 #endif
2899 
2900  return std::move(tmp);
2901  }
2902 }
2903 
2906 {
2907 #ifdef DEBUG_ON_DEMAND
2908  if(debug_on)
2909  std::cout << "TO-SIMP " << format(expr) << "\n";
2910 #endif
2911  auto result = simplify_rec(expr);
2912 #ifdef DEBUG_ON_DEMAND
2913  if(debug_on)
2914  std::cout << "FULLSIMP " << format(result.expr) << "\n";
2915 #endif
2916  if(result.has_changed())
2917  {
2918  expr = result.expr;
2919  return false; // change
2920  }
2921  else
2922  return true; // no change
2923 }
2924 
2926 bool simplify(exprt &expr, const namespacet &ns)
2927 {
2928  return simplify_exprt(ns).simplify(expr);
2929 }
2930 
2932 {
2933  simplify_exprt(ns).simplify(src);
2934  return src;
2935 }
with_exprt
Operator to update elements in structs and arrays.
Definition: std_expr.h:2423
simplify_exprt::simplify_rec
resultt simplify_rec(const exprt &)
Definition: simplify_expr.cpp:2836
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
exprt::op2
exprt & op2()
Definition: expr.h:131
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:147
simplify_exprt::simplify_object_size
resultt simplify_object_size(const object_size_exprt &)
Definition: simplify_expr_pointer.cpp:650
simplify_exprt::simplify_is_invalid_pointer
resultt simplify_is_invalid_pointer(const unary_exprt &)
Definition: simplify_expr_pointer.cpp:617
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
pointer_offset_size.h
to_union_type
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition: c_types.h:162
function_application_exprt::arguments
argumentst & arguments()
Definition: mathematical_expr.h:218
simplify_exprt::simplify_isnormal
resultt simplify_isnormal(const unary_exprt &)
Definition: simplify_expr_floatbv.cpp:51
ieee_floatt
Definition: ieee_float.h:116
format
static format_containert< T > format(const T &o)
Definition: format.h:37
to_update_expr
const update_exprt & to_update_expr(const exprt &expr)
Cast an exprt to an update_exprt.
Definition: std_expr.h:2688
typecast_exprt::conditional_cast
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2025
to_extractbit_expr
const extractbit_exprt & to_extractbit_expr(const exprt &expr)
Cast an exprt to an extractbit_exprt.
Definition: bitvector_expr.h:429
to_unary_expr
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:361
configt::ansi_ct::NULL_is_zero
bool NULL_is_zero
Definition: config.h:209
simplify_exprt::simplify_shifts
resultt simplify_shifts(const shift_exprt &)
Definition: simplify_expr_int.cpp:915
simplify_string_index_of
static simplify_exprt::resultt simplify_string_index_of(const function_application_exprt &expr, const namespacet &ns, const bool search_from_end)
Simplify String.indexOf function when arguments are constant.
Definition: simplify_expr.cpp:372
simplify_exprt::simplify_dereference
resultt simplify_dereference(const dereference_exprt &)
Definition: simplify_expr.cpp:1351
simplify_exprt::simplify_concatenation
resultt simplify_concatenation(const concatenation_exprt &)
Definition: simplify_expr_int.cpp:813
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
to_lambda_expr
const lambda_exprt & to_lambda_expr(const exprt &expr)
Cast an exprt to a lambda_exprt.
Definition: mathematical_expr.h:461
to_div_expr
const div_exprt & to_div_expr(const exprt &expr)
Cast an exprt to a div_exprt.
Definition: std_expr.h:1146
simplify_expr_class.h
simplify_exprt::simplify_pointer_offset
resultt simplify_pointer_offset(const pointer_offset_exprt &)
Definition: simplify_expr_pointer.cpp:248
fixedbvt::from_integer
void from_integer(const mp_integer &i)
Definition: fixedbv.cpp:32
byte_update_exprt
Expression corresponding to op() where the bytes starting at position offset (given in number of byte...
Definition: byte_operators.h:77
Forall_operands
#define Forall_operands(it, expr)
Definition: expr.h:27
count_trailing_zeros_exprt
The count trailing zeros (counting the number of zero bits starting from the least-significant bit) e...
Definition: bitvector_expr.h:1067
simplify_exprt::simplify_address_of
resultt simplify_address_of(const address_of_exprt &)
Definition: simplify_expr_pointer.cpp:210
to_array_expr
const array_exprt & to_array_expr(const exprt &expr)
Cast an exprt to an array_exprt.
Definition: std_expr.h:1603
struct_union_typet::get_component
const componentt & get_component(const irep_idt &component_name) const
Get the reference to a component with given name.
Definition: std_types.cpp:63
rational.h
simplify_exprt::simplify_unary_plus
resultt simplify_unary_plus(const unary_plus_exprt &)
Definition: simplify_expr_int.cpp:1120
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
simplify_exprt::simplify_bitwise
resultt simplify_bitwise(const multi_ary_exprt &)
Definition: simplify_expr_int.cpp:608
rational_tools.h
address_of_exprt::object
exprt & object()
Definition: pointer_expr.h:380
ieee_floatt::set_sign
void set_sign(bool _sign)
Definition: ieee_float.h:184
simplify_exprt::simplify_if_preorder
bool simplify_if_preorder(if_exprt &expr)
Definition: simplify_expr_if.cpp:214
to_dereference_expr
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:716
array_of_exprt::what
exprt & what()
Definition: std_expr.h:1515
irept::make_nil
void make_nil()
Definition: irep.h:454
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
simplify_exprt::simplify_bitnot
resultt simplify_bitnot(const bitnot_exprt &)
Definition: simplify_expr_int.cpp:1187
to_string_expr
refined_string_exprt & to_string_expr(exprt &expr)
Definition: string_expr.h:150
typet
The type of an expression, extends irept.
Definition: type.h:28
update_exprt::old
exprt & old()
Definition: std_expr.h:2620
simplify_exprt::simplify_overflow_binary
resultt simplify_overflow_binary(const binary_overflow_exprt &)
Try to simplify overflow-+, overflow-*, overflow–, overflow-shl.
Definition: simplify_expr.cpp:2240
to_byte_extract_expr
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
Definition: byte_operators.h:57
fixedbvt::to_integer
mp_integer to_integer() const
Definition: fixedbv.cpp:37
union_typet::find_widest_union_component
optionalt< std::pair< struct_union_typet::componentt, mp_integer > > find_widest_union_component(const namespacet &ns) const
Determine the member of maximum bit width in a union type.
Definition: c_types.cpp:318
to_floatbv_type
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
Definition: bitvector_types.h:367
to_index_expr
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1478
to_if_expr
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition: std_expr.h:2403
bits2expr
optionalt< exprt > bits2expr(const std::string &bits, const typet &type, bool little_endian, const namespacet &ns)
Definition: simplify_utils.cpp:194
irept::find
const irept & find(const irep_idt &name) const
Definition: irep.cpp:106
simplify_string_endswith
static simplify_exprt::resultt simplify_string_endswith(const function_application_exprt &expr, const namespacet &ns)
Simplify String.endsWith function when arguments are constant.
Definition: simplify_expr.cpp:225
dereference_exprt
Operator to dereference a pointer.
Definition: pointer_expr.h:659
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:2322
byte_update_exprt::offset
const exprt & offset() const
Definition: byte_operators.h:106
simplify_exprt::simplify_popcount
resultt simplify_popcount(const popcount_exprt &)
Definition: simplify_expr.cpp:125
floatbv_typet
Fixed-width bit-vector with IEEE floating-point interpretation.
Definition: bitvector_types.h:321
string2integer
const mp_integer string2integer(const std::string &n, unsigned base)
Definition: mp_arith.cpp:54
simplify_exprt::simplify
virtual bool simplify(exprt &expr)
Definition: simplify_expr.cpp:2905
to_c_enum_type
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition: c_types.h:302
simplify_exprt::simplify_is_dynamic_object
resultt simplify_is_dynamic_object(const unary_exprt &)
Definition: simplify_expr_pointer.cpp:558
fixedbv_spect::get_fraction_bits
std::size_t get_fraction_bits() const
Definition: fixedbv.h:35
with_exprt::new_value
exprt & new_value()
Definition: std_expr.h:2454
fixedbv.h
simplify_string_char_at
static simplify_exprt::resultt simplify_string_char_at(const function_application_exprt &expr, const namespacet &ns)
Simplify String.charAt function when arguments are constant.
Definition: simplify_expr.cpp:517
invariant.h
s1
int8_t s1
Definition: bytecode_info.h:59
simplify_exprt::simplify_clz
resultt simplify_clz(const count_leading_zeros_exprt &)
Try to simplify count-leading-zeros to a constant expression.
Definition: simplify_expr.cpp:151
union_exprt
Union constructor from single element.
Definition: std_expr.h:1707
simplify_exprt::simplify_update
resultt simplify_update(const update_exprt &)
Definition: simplify_expr.cpp:1494
to_array_of_expr
const array_of_exprt & to_array_of_expr(const exprt &expr)
Cast an exprt to an array_of_exprt.
Definition: std_expr.h:1543
to_type_with_subtype
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:193
plus_exprt
The plus expression Associativity is not specified.
Definition: std_expr.h:946
simplify_exprt::simplify_boolean
resultt simplify_boolean(const exprt &)
Definition: simplify_expr_boolean.cpp:20
ieee_floatt::change_spec
void change_spec(const ieee_float_spect &dest_spec)
Definition: ieee_float.cpp:1048
simplify_exprt::simplify_overflow_unary
resultt simplify_overflow_unary(const unary_overflow_exprt &)
Try to simplify overflow-unary-.
Definition: simplify_expr.cpp:2312
simplify_string_compare_to
static simplify_exprt::resultt simplify_string_compare_to(const function_application_exprt &expr, const namespacet &ns)
Simplify String.compareTo function when arguments are constant.
Definition: simplify_expr.cpp:323
count_trailing_zeros_exprt::zero_permitted
bool zero_permitted() const
Definition: bitvector_expr.h:1081
simplify_string_equals_ignore_case
static simplify_exprt::resultt simplify_string_equals_ignore_case(const function_application_exprt &expr, const namespacet &ns)
Simplify String.equalsIgnorecase function when arguments are constant.
Definition: simplify_expr.cpp:585
exprt
Base class for all expressions.
Definition: expr.h:55
simplify_exprt::simplify_ctz
resultt simplify_ctz(const count_trailing_zeros_exprt &)
Try to simplify count-trailing-zeros to a constant expression.
Definition: simplify_expr.cpp:177
to_complex_expr
const complex_exprt & to_complex_expr(const exprt &expr)
Cast an exprt to a complex_exprt.
Definition: std_expr.h:1907
struct_union_typet::componentst
std::vector< componentt > componentst
Definition: std_types.h:140
unary_exprt
Generic base class for unary expressions.
Definition: std_expr.h:313
simplify_exprt::simplify_extractbit
resultt simplify_extractbit(const extractbit_exprt &)
Definition: simplify_expr_int.cpp:784
binary_exprt
A base class for binary expressions.
Definition: std_expr.h:582
to_bv_type
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
Definition: bitvector_types.h:82
overflow_result_exprt
An expression returning both the result of the arithmetic operation under wrap-around semantics as we...
Definition: bitvector_expr.h:1304
namespace_baset::follow_tag
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
byte_update_exprt::set_op
void set_op(exprt e)
Definition: byte_operators.h:92
sign_exprt
Sign of an expression Predicate is true if _op is negative, false otherwise.
Definition: std_expr.h:538
exprt::op0
exprt & op0()
Definition: expr.h:125
component
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:76
to_integer
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
Definition: arith_tools.cpp:20
to_bitnot_expr
const bitnot_exprt & to_bitnot_expr(const exprt &expr)
Cast an exprt to a bitnot_exprt.
Definition: bitvector_expr.h:106
lift_if
if_exprt lift_if(const exprt &src, std::size_t operand_number)
lift up an if_exprt one level
Definition: expr_util.cpp:201
can_cast_expr< refined_string_exprt >
bool can_cast_expr< refined_string_exprt >(const exprt &base)
Definition: string_expr.h:165
ieee_floatt::to_integer
mp_integer to_integer() const
Definition: ieee_float.cpp:1073
exprt::is_true
bool is_true() const
Return whether the expression is a constant representing true.
Definition: expr.cpp:34
simplify_exprt::simplify_complex
resultt simplify_complex(const unary_exprt &)
Definition: simplify_expr.cpp:2219
configt::ansi_c
struct configt::ansi_ct ansi_c
to_bitvector_type
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
Definition: bitvector_types.h:32
try_get_string_data_array
optionalt< std::reference_wrapper< const array_exprt > > try_get_string_data_array(const exprt &content, const namespacet &ns)
Get char sequence from content field of a refined string expression.
Definition: simplify_utils.cpp:484
simplify_exprt::simplify_plus
resultt simplify_plus(const plus_exprt &)
Definition: simplify_expr_int.cpp:402
namespace.h
struct_union_typet::component_number
std::size_t component_number(const irep_idt &component_name) const
Return the sequence number of the component with given name.
Definition: std_types.cpp:46
from_rational
constant_exprt from_rational(const rationalt &a)
Definition: rational_tools.cpp:81
fixedbvt::to_expr
constant_exprt to_expr() const
Definition: fixedbv.cpp:43
to_popcount_expr
const popcount_exprt & to_popcount_expr(const exprt &expr)
Cast an exprt to a popcount_exprt.
Definition: bitvector_expr.h:685
simplify_exprt::simplify_byte_extract
resultt simplify_byte_extract(const byte_extract_exprt &)
Definition: simplify_expr.cpp:1622
simplify_exprt::simplify_not
resultt simplify_not(const not_exprt &)
Definition: simplify_expr_boolean.cpp:230
to_minus_expr
const minus_exprt & to_minus_expr(const exprt &expr)
Cast an exprt to a minus_exprt.
Definition: std_expr.h:1031
simplify_exprt::unchanged
static resultt unchanged(exprt expr)
Definition: simplify_expr_class.h:136
to_find_first_set_expr
const find_first_set_exprt & to_find_first_set_expr(const exprt &expr)
Cast an exprt to a find_first_set_exprt.
Definition: bitvector_expr.h:1489
if_exprt::false_case
exprt & false_case()
Definition: std_expr.h:2360
simplify_exprt::simplify_node
resultt simplify_node(exprt)
Definition: simplify_expr.cpp:2569
exprt::is_false
bool is_false() const
Return whether the expression is a constant representing false.
Definition: expr.cpp:43
unsignedbv_typet
Fixed-width bit-vector with unsigned binary interpretation.
Definition: bitvector_types.h:158
refined_string_exprt
Definition: string_expr.h:108
refined_string_exprt::length
const exprt & length() const
Definition: string_expr.h:128
to_floatbv_typecast_expr
const floatbv_typecast_exprt & to_floatbv_typecast_expr(const exprt &expr)
Cast an exprt to a floatbv_typecast_exprt.
Definition: floatbv_expr.h:68
to_fixedbv_type
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
Definition: bitvector_types.h:305
irept::get
const irep_idt & get(const irep_idt &name) const
Definition: irep.cpp:45
ieee_float_spect
Definition: ieee_float.h:22
to_unary_plus_expr
const unary_plus_exprt & to_unary_plus_expr(const exprt &expr)
Cast an exprt to a unary_plus_exprt.
Definition: std_expr.h:497
to_complex_real_expr
const complex_real_exprt & to_complex_real_expr(const exprt &expr)
Cast an exprt to a complex_real_exprt.
Definition: std_expr.h:1952
to_binary_expr
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:660
to_bswap_expr
const bswap_exprt & to_bswap_expr(const exprt &expr)
Cast an exprt to a bswap_exprt.
Definition: bitvector_expr.h:63
simplify_exprt::simplify_if
resultt simplify_if(const if_exprt &)
Definition: simplify_expr_if.cpp:330
struct_exprt
Struct constructor from list of elements.
Definition: std_expr.h:1818
c_bool_typet
The C/C++ Booleans.
Definition: c_types.h:74
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
complex_exprt::imag
exprt imag()
Definition: std_expr.h:1879
simplify_string_startswith
static simplify_exprt::resultt simplify_string_startswith(const function_application_exprt &expr, const namespacet &ns)
Simplify String.startsWith function when arguments are constant.
Definition: simplify_expr.cpp:630
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
simplify_exprt::simplify_minus
resultt simplify_minus(const minus_exprt &)
Definition: simplify_expr_int.cpp:566
to_pointer_object_expr
const pointer_object_exprt & to_pointer_object_expr(const exprt &expr)
Cast an exprt to a pointer_object_exprt.
Definition: pointer_expr.h:986
count_leading_zeros_exprt::zero_permitted
bool zero_permitted() const
Definition: bitvector_expr.h:988
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
configt::ansi_ct::endiannesst::IS_LITTLE_ENDIAN
@ IS_LITTLE_ENDIAN
with_exprt::old
exprt & old()
Definition: std_expr.h:2434
byte_operators.h
Expression classes for byte-level operators.
simplify_exprt::simplify_power
resultt simplify_power(const binary_exprt &)
Definition: simplify_expr_int.cpp:1023
simplify_exprt::simplify_div
resultt simplify_div(const div_exprt &)
Definition: simplify_expr_int.cpp:271
as_const
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
Definition: as_const.h:14
can_cast_expr< unary_minus_overflow_exprt >
bool can_cast_expr< unary_minus_overflow_exprt >(const exprt &base)
Definition: bitvector_expr.h:934
simplify_exprt::simplify_typecast
resultt simplify_typecast(const typecast_exprt &)
Definition: simplify_expr.cpp:753
to_mod_expr
const mod_exprt & to_mod_expr(const exprt &expr)
Cast an exprt to a mod_exprt.
Definition: std_expr.h:1217
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
to_mult_expr
const mult_exprt & to_mult_expr(const exprt &expr)
Cast an exprt to a mult_exprt.
Definition: std_expr.h:1077
exprt::has_operands
bool has_operands() const
Return true if there is at least one operand.
Definition: expr.h:91
simplify_exprt::simplify_bitreverse
resultt simplify_bitreverse(const bitreverse_exprt &)
Try to simplify bit-reversing to a constant expression.
Definition: simplify_expr_int.cpp:1838
null_pointer_exprt
The null pointer constant.
Definition: pointer_expr.h:734
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
simplify_exprt::simplify_mod
resultt simplify_mod(const mod_exprt &)
Definition: simplify_expr_int.cpp:365
byte_extract_exprt::op
exprt & op()
Definition: byte_operators.h:43
overflow_result_exprt::op1
exprt & op1()
Definition: expr.h:128
failed
static bool failed(bool error_indicator)
Definition: symtab2gb_parse_options.cpp:39
simplify_exprt::simplify_isnan
resultt simplify_isnan(const unary_exprt &)
Definition: simplify_expr_floatbv.cpp:37
to_c_enum_tag_type
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
Definition: c_types.h:344
to_byte_update_expr
const byte_update_exprt & to_byte_update_expr(const exprt &expr)
Definition: byte_operators.h:117
irept::set
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:420
binary_overflow_exprt
A Boolean expression returning true, iff operation kind would result in an overflow when applied to o...
Definition: bitvector_expr.h:704
simplify_exprt::changed
static resultt changed(resultt<> result)
Definition: simplify_expr_class.h:141
overflow_result_exprt::op0
exprt & op0()
Definition: expr.h:125
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
has_subtype
bool has_subtype(const typet &type, const std::function< bool(const typet &)> &pred, const namespacet &ns)
returns true if any of the contained types satisfies pred
Definition: expr_util.cpp:153
nil_exprt
The NIL expression.
Definition: std_expr.h:3025
can_cast_expr< plus_overflow_exprt >
bool can_cast_expr< plus_overflow_exprt >(const exprt &base)
Definition: bitvector_expr.h:811
dereference_exprt::pointer
exprt & pointer()
Definition: pointer_expr.h:673
pointer_offset_bits
optionalt< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
Definition: pointer_offset_size.cpp:101
signedbv_typet
Fixed-width bit-vector with two's complement interpretation.
Definition: bitvector_types.h:207
pointer_offset_sum
exprt pointer_offset_sum(const exprt &a, const exprt &b)
Definition: pointer_offset_sum.cpp:16
slice
void slice(symex_bmct &symex, symex_target_equationt &symex_target_equation, const namespacet &ns, const optionst &options, ui_message_handlert &ui_message_handler)
Definition: bmc_util.cpp:199
join_operands
bool join_operands(exprt &expr)
Definition: simplify_utils.cpp:189
simplify_exprt::simplify_bswap
resultt simplify_bswap(const bswap_exprt &)
Definition: simplify_expr_int.cpp:29
to_plus_expr
const plus_exprt & to_plus_expr(const exprt &expr)
Cast an exprt to a plus_exprt.
Definition: std_expr.h:986
pointer_expr.h
simplify_exprt::simplify_node_preorder
bool simplify_node_preorder(exprt &expr)
Definition: simplify_expr.cpp:2538
integer_bitvector_typet
Fixed-width bit-vector representing a signed or unsigned integer.
Definition: bitvector_types.h:98
simplify
bool simplify(exprt &expr, const namespacet &ns)
Definition: simplify_expr.cpp:2926
exprt::op1
exprt & op1()
Definition: expr.h:128
function_application_exprt
Application of (mathematical) function.
Definition: mathematical_expr.h:196
mult_exprt
Binary multiplication Associativity is not specified.
Definition: std_expr.h:1051
to_pointer_type
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:79
simplify_expr
exprt simplify_expr(exprt src, const namespacet &ns)
Definition: simplify_expr.cpp:2931
simplify_exprt::simplify_inequality
resultt simplify_inequality(const binary_relation_exprt &)
simplifies inequalities !=, <=, <, >=, >, and also ==
Definition: simplify_expr_int.cpp:1218
index_exprt::index
exprt & index()
Definition: std_expr.h:1450
to_unary_minus_expr
const unary_minus_exprt & to_unary_minus_expr(const exprt &expr)
Cast an exprt to a unary_minus_exprt.
Definition: std_expr.h:453
ieee_floatt::pack
mp_integer pack() const
Definition: ieee_float.cpp:374
pointer_type
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:253
simplify_exprt
Definition: simplify_expr_class.h:79
index_exprt::array
exprt & array()
Definition: std_expr.h:1440
irept::swap
void swap(irept &irep)
Definition: irep.h:442
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:222
struct_union_typet::has_component
bool has_component(const irep_idt &component_name) const
Definition: std_types.h:157
object_size
exprt object_size(const exprt &pointer)
Definition: pointer_predicates.cpp:33
simplify_exprt::simplify_good_pointer
resultt simplify_good_pointer(const unary_exprt &)
Definition: simplify_expr_pointer.cpp:698
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
dstringt::empty
bool empty() const
Definition: dstring.h:88
abs_exprt
Absolute value.
Definition: std_expr.h:378
simplify_string_contains
static simplify_exprt::resultt simplify_string_contains(const function_application_exprt &expr, const namespacet &ns)
Simplify String.contains function when arguments are constant.
Definition: simplify_expr.cpp:253
to_count_trailing_zeros_expr
const count_trailing_zeros_exprt & to_count_trailing_zeros_expr(const exprt &expr)
Cast an exprt to a count_trailing_zeros_exprt.
Definition: bitvector_expr.h:1136
false_exprt
The Boolean constant false.
Definition: std_expr.h:3016
floatbv_expr.h
union_typet
The union type.
Definition: c_types.h:124
simplify_exprt::simplify_mult
resultt simplify_mult(const mult_exprt &)
Definition: simplify_expr_int.cpp:159
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
fixedbvt::set_value
void set_value(const mp_integer &_v)
Definition: fixedbv.h:96
simplify_exprt::simplify_with
resultt simplify_with(const with_exprt &)
Definition: simplify_expr.cpp:1414
simplify_exprt::resultt
Definition: simplify_expr_class.h:102
simplify_exprt::simplify_unary_minus
resultt simplify_unary_minus(const unary_minus_exprt &)
Definition: simplify_expr_int.cpp:1127
ieee_floatt::from_integer
void from_integer(const mp_integer &i)
Definition: ieee_float.cpp:515
to_complex_imag_expr
const complex_imag_exprt & to_complex_imag_expr(const exprt &expr)
Cast an exprt to a complex_imag_exprt.
Definition: std_expr.h:1997
simplify_exprt::simplify_function_application
resultt simplify_function_application(const function_application_exprt &)
Attempt to simplify mathematical function applications if we have enough information to do so.
Definition: simplify_expr.cpp:696
simplify_exprt::simplify_pointer_object
resultt simplify_pointer_object(const pointer_object_exprt &)
Definition: simplify_expr_pointer.cpp:526
to_shift_expr
const shift_exprt & to_shift_expr(const exprt &expr)
Cast an exprt to a shift_exprt.
Definition: bitvector_expr.h:278
fixedbv_spect
Definition: fixedbv.h:19
to_with_expr
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
Definition: std_expr.h:2486
update_exprt
Operator to update elements in structs and arrays.
Definition: std_expr.h:2607
update_exprt::designator
exprt::operandst & designator()
Definition: std_expr.h:2634
simplify_exprt::simplify_index
resultt simplify_index(const index_exprt &)
Definition: simplify_expr_array.cpp:19
config
configt config
Definition: config.cpp:25
ieee_floatt::spec
ieee_float_spect spec
Definition: ieee_float.h:135
expr2bits
optionalt< std::string > expr2bits(const exprt &expr, bool little_endian, const namespacet &ns)
Definition: simplify_utils.cpp:409
fixedbv_typet
Fixed-width bit-vector with signed fixed-point interpretation.
Definition: bitvector_types.h:260
simplify_expr.h
bitvector_typet::get_width
std::size_t get_width() const
Definition: std_types.h:876
to_ieee_float_op_expr
const ieee_float_op_exprt & to_ieee_float_op_expr(const exprt &expr)
Cast an exprt to an ieee_float_op_exprt.
Definition: floatbv_expr.h:425
byte_extract_exprt::offset
exprt & offset()
Definition: byte_operators.h:44
to_concatenation_expr
const concatenation_exprt & to_concatenation_expr(const exprt &expr)
Cast an exprt to a concatenation_exprt.
Definition: bitvector_expr.h:636
exprt::is_zero
bool is_zero() const
Return whether the expression is a constant representing 0.
Definition: expr.cpp:65
member_exprt
Extract member of struct or union.
Definition: std_expr.h:2793
simplify_exprt::simplify_member
resultt simplify_member(const member_exprt &)
Definition: simplify_expr_struct.cpp:21
expr_util.h
Deprecated expression utility functions.
bvrep2integer
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
Definition: arith_tools.cpp:402
unary_overflow_exprt
A Boolean expression returning true, iff operation kind would result in an overflow when applied to t...
Definition: bitvector_expr.h:871
refined_string_exprt::content
const exprt & content() const
Definition: string_expr.h:138
format_expr.h
POSTCONDITION
#define POSTCONDITION(CONDITION)
Definition: invariant.h:479
simplify_exprt::simplify_object
resultt simplify_object(const exprt &)
Definition: simplify_expr.cpp:1542
struct_typet
Structure type, corresponds to C style structs.
Definition: std_types.h:230
byte_update_exprt::value
const exprt & value() const
Definition: byte_operators.h:107
c_enum_tag_typet
C enum tag type, i.e., c_enum_typet with an identifier.
Definition: c_types.h:318
pointer_offset_size
optionalt< mp_integer > pointer_offset_size(const typet &type, const namespacet &ns)
Compute the size of a type in bytes, rounding up to full bytes.
Definition: pointer_offset_size.cpp:90
array_typet
Arrays with given size.
Definition: std_types.h:762
if_exprt::true_case
exprt & true_case()
Definition: std_expr.h:2350
configt::ansi_ct::endiannesst::IS_BIG_ENDIAN
@ IS_BIG_ENDIAN
namespace_baset::follow
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:49
to_sign_expr
const sign_exprt & to_sign_expr(const exprt &expr)
Cast an exprt to a sign_exprt.
Definition: std_expr.h:564
to_not_expr
const not_exprt & to_not_expr(const exprt &expr)
Cast an exprt to an not_exprt.
Definition: std_expr.h:2303
to_bitreverse_expr
const bitreverse_exprt & to_bitreverse_expr(const exprt &expr)
Cast an exprt to a bitreverse_exprt.
Definition: bitvector_expr.h:1186
is_not_zero
exprt is_not_zero(const exprt &src, const namespacet &ns)
converts a scalar/float expression to C/C++ Booleans
Definition: expr_util.cpp:98
update_exprt::new_value
exprt & new_value()
Definition: std_expr.h:2644
function_application_exprt::function
exprt & function()
Definition: mathematical_expr.h:205
lambda_exprt
A (mathematical) lambda expression.
Definition: mathematical_expr.h:421
simplify_exprt::simplify_sign
resultt simplify_sign(const sign_exprt &)
Definition: simplify_expr.cpp:99
replace_expr
bool replace_expr(const exprt &what, const exprt &by, exprt &dest)
Definition: replace_expr.cpp:12
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
to_typecast_expr
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2051
get_subexpression_at_offset
optionalt< exprt > get_subexpression_at_offset(const exprt &expr, const mp_integer &offset_bytes, const typet &target_type_raw, const namespacet &ns)
Definition: pointer_offset_size.cpp:568
exprt::is_constant
bool is_constant() const
Return whether the expression is a constant.
Definition: expr.cpp:27
if_exprt::cond
exprt & cond()
Definition: std_expr.h:2340
binary_relation_exprt
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition: std_expr.h:706
fixedbvt::round
void round(const fixedbv_spect &dest_spec)
Definition: fixedbv.cpp:52
byte_extract_exprt
Expression of type type extracted from some object op starting at position offset (given in number of...
Definition: byte_operators.h:28
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
power
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
Definition: arith_tools.cpp:195
exprt::add_to_operands
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:162
fixedbvt::spec
fixedbv_spect spec
Definition: fixedbv.h:44
simplify_exprt::simplify_lambda
resultt simplify_lambda(const lambda_exprt &)
Definition: simplify_expr.cpp:1409
can_cast_expr< mult_overflow_exprt >
bool can_cast_expr< mult_overflow_exprt >(const exprt &base)
Definition: bitvector_expr.h:849
config.h
to_pointer_offset_expr
const pointer_offset_exprt & to_pointer_offset_expr(const exprt &expr)
Cast an exprt to a pointer_offset_exprt.
Definition: pointer_expr.h:928
fixedbvt
Definition: fixedbv.h:41
to_extractbits_expr
const extractbits_exprt & to_extractbits_expr(const exprt &expr)
Cast an exprt to an extractbits_exprt.
Definition: bitvector_expr.h:517
simplify_exprt::simplify_extractbits
resultt simplify_extractbits(const extractbits_exprt &)
Simplifies extracting of bits from a constant.
Definition: simplify_expr_int.cpp:1044
exprt::is_one
bool is_one() const
Return whether the expression is a constant representing 1.
Definition: expr.cpp:114
simplify_exprt::ns
const namespacet & ns
Definition: simplify_expr_class.h:266
to_member_expr
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2886
irep_full_eq
Definition: irep.h:494
ieee_floatt::to_expr
constant_exprt to_expr() const
Definition: ieee_float.cpp:702
make_boolean_expr
constant_exprt make_boolean_expr(bool value)
returns true_exprt if given true and false_exprt otherwise
Definition: expr_util.cpp:284
ieee_floatt::get_sign
bool get_sign() const
Definition: ieee_float.h:248
find_first_set_exprt
Returns one plus the index of the least-significant one bit, or zero if the operand is zero.
Definition: bitvector_expr.h:1432
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
exprt::operands
operandst & operands()
Definition: expr.h:94
simplify_exprt::simplify_byte_update
resultt simplify_byte_update(const byte_update_exprt &)
Definition: simplify_expr.cpp:1910
r
static int8_t r
Definition: irep_hash.h:60
is_null_pointer
bool is_null_pointer(const constant_exprt &expr)
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition: expr_util.cpp:315
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
c_enum_typet::underlying_type
const typet & underlying_type() const
Definition: c_types.h:274
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:216
popcount_exprt
The popcount (counting the number of bits set to 1) expression.
Definition: bitvector_expr.h:650
s2
int16_t s2
Definition: bytecode_info.h:60
typecast_exprt
Semantic type conversion.
Definition: std_expr.h:2016
size_type
unsignedbv_typet size_type()
Definition: c_types.cpp:68
true_exprt
The Boolean constant true.
Definition: std_expr.h:3007
constant_exprt
A constant literal expression.
Definition: std_expr.h:2941
pointer_offset_sum.h
simplify_exprt::simplify_abs
resultt simplify_abs(const abs_exprt &)
Definition: simplify_expr.cpp:65
member_offset_expr
optionalt< exprt > member_offset_expr(const member_exprt &member_expr, const namespacet &ns)
Definition: pointer_offset_size.cpp:221
binary_exprt::op1
exprt & op1()
Definition: expr.h:128
simplify_utils.h
to_multi_ary_expr
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition: std_expr.h:932
can_cast_expr< shl_overflow_exprt >
bool can_cast_expr< shl_overflow_exprt >(const exprt &base)
Definition: bitvector_expr.h:864
std_expr.h
string_expr.h
to_binary_relation_expr
const binary_relation_exprt & to_binary_relation_expr(const exprt &expr)
Cast an exprt to a binary_relation_exprt.
Definition: std_expr.h:840
constant_exprt::set_value
void set_value(const irep_idt &value)
Definition: std_expr.h:2955
constant_exprt::get_value
const irep_idt & get_value() const
Definition: std_expr.h:2950
exprt::source_location
const source_locationt & source_location() const
Definition: expr.h:211
with_exprt::where
exprt & where()
Definition: std_expr.h:2444
lambda_exprt::application
exprt application(const operandst &arguments) const
Definition: mathematical_expr.h:438
member_offset
optionalt< mp_integer > member_offset(const struct_typet &type, const irep_idt &member, const namespacet &ns)
Definition: pointer_offset_size.cpp:24
byte_update_exprt::op
const exprt & op() const
Definition: byte_operators.h:105
array_exprt
Array constructor from list of elements.
Definition: std_expr.h:1562
simplify_exprt::simplify_ieee_float_relation
resultt simplify_ieee_float_relation(const binary_relation_exprt &)
Definition: simplify_expr_floatbv.cpp:338
c_types.h
rationalt
Definition: rational.h:15
to_function_application_expr
const function_application_exprt & to_function_application_expr(const exprt &expr)
Cast an exprt to a function_application_exprt.
Definition: mathematical_expr.h:247
simplify_exprt::simplify_ffs
resultt simplify_ffs(const find_first_set_exprt &)
Try to simplify find-first-set to a constant expression.
Definition: simplify_expr.cpp:201
irep_full_hash
Definition: irep.h:485
configt::ansi_ct::endianness
endiannesst endianness
Definition: config.h:192
complex_exprt::real
exprt real()
Definition: std_expr.h:1869
to_count_leading_zeros_expr
const count_leading_zeros_exprt & to_count_leading_zeros_expr(const exprt &expr)
Cast an exprt to a count_leading_zeros_exprt.
Definition: bitvector_expr.h:1043
bitvector_expr.h
binary_exprt::op0
exprt & op0()
Definition: expr.h:125
to_struct_expr
const struct_exprt & to_struct_expr(const exprt &expr)
Cast an exprt to a struct_exprt.
Definition: std_expr.h:1842
simplify_exprt::simplify_floatbv_typecast
resultt simplify_floatbv_typecast(const floatbv_typecast_exprt &)
Definition: simplify_expr_floatbv.cpp:139
to_abs_expr
const abs_exprt & to_abs_expr(const exprt &expr)
Cast an exprt to a abs_exprt.
Definition: std_expr.h:403
get_bvrep_bit
bool get_bvrep_bit(const irep_idt &src, std::size_t width, std::size_t bit_index)
Get a bit with given index from bit-vector representation.
Definition: arith_tools.cpp:262
count_leading_zeros_exprt
The count leading zeros (counting the number of zero bits starting from the most-significant bit) exp...
Definition: bitvector_expr.h:974
byte_update_exprt::set_offset
void set_offset(exprt e)
Definition: byte_operators.h:96
lower_case_string_expression
static bool lower_case_string_expression(array_exprt &string_data)
Take the passed-in constant string array and lower-case every character.
Definition: simplify_expr.cpp:557
simplify_exprt::simplify_floatbv_op
resultt simplify_floatbv_op(const ieee_float_op_exprt &)
Definition: simplify_expr_floatbv.cpp:273
simplify_exprt::simplify_overflow_result
resultt simplify_overflow_result(const overflow_result_exprt &)
Try to simplify overflow_result-+, overflow_result-*, overflow_result–, overflow_result-shl,...
Definition: simplify_expr.cpp:2360
array_typet::element_type
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:785
to_index_designator
const index_designatort & to_index_designator(const exprt &expr)
Cast an exprt to an index_designatort.
Definition: std_expr.h:2539
simplify_string_is_empty
static simplify_exprt::resultt simplify_string_is_empty(const function_application_exprt &expr, const namespacet &ns)
Simplify String.isEmpty function when arguments are constant.
Definition: simplify_expr.cpp:298
can_cast_expr< minus_overflow_exprt >
bool can_cast_expr< minus_overflow_exprt >(const exprt &base)
Definition: bitvector_expr.h:830
mathematical_expr.h
to_constant_expr
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:2992
simplify_exprt::simplify_isinf
resultt simplify_isinf(const unary_exprt &)
Definition: simplify_expr_floatbv.cpp:23