CBMC
c_typecheck_expr.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: ANSI-C Language Type Checking
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "c_typecheck_base.h"
13 
14 #include <sstream>
15 
16 #include <util/arith_tools.h>
17 #include <util/bitvector_expr.h>
18 #include <util/c_types.h>
19 #include <util/config.h>
20 #include <util/cprover_prefix.h>
21 #include <util/expr_util.h>
22 #include <util/floatbv_expr.h>
23 #include <util/ieee_float.h>
24 #include <util/mathematical_expr.h>
26 #include <util/pointer_expr.h>
29 #include <util/prefix.h>
30 #include <util/range.h>
31 #include <util/simplify_expr.h>
32 #include <util/string_constant.h>
33 #include <util/suffix.h>
34 
36 
37 #include "anonymous_member.h"
38 #include "ansi_c_declaration.h"
39 #include "builtin_factory.h"
40 #include "c_expr.h"
41 #include "c_qualifiers.h"
42 #include "expr2c.h"
43 #include "padding.h"
44 #include "type2name.h"
45 
47 {
48  if(expr.id()==ID_already_typechecked)
49  {
50  expr.swap(to_already_typechecked_expr(expr).get_expr());
51  return;
52  }
53 
54  // first do sub-nodes
56 
57  // now do case-split
58  typecheck_expr_main(expr);
59 }
60 
62 {
63  for(auto &op : expr.operands())
65 
66  if(expr.id()==ID_div ||
67  expr.id()==ID_mult ||
68  expr.id()==ID_plus ||
69  expr.id()==ID_minus)
70  {
71  if(expr.type().id()==ID_floatbv &&
72  expr.operands().size()==2)
73  {
74  // The rounding mode to be used at compile time is non-obvious.
75  // We'll simply use round to even (0), which is suggested
76  // by Sec. F.7.2 Translation, ISO-9899:1999.
77  expr.operands().resize(3);
78 
79  if(expr.id()==ID_div)
80  expr.id(ID_floatbv_div);
81  else if(expr.id()==ID_mult)
82  expr.id(ID_floatbv_mult);
83  else if(expr.id()==ID_plus)
84  expr.id(ID_floatbv_plus);
85  else if(expr.id()==ID_minus)
86  expr.id(ID_floatbv_minus);
87  else
89 
92  }
93  }
94 }
95 
97  const typet &type1,
98  const typet &type2)
99 {
100  // read
101  // http://gcc.gnu.org/onlinedocs/gcc-3.3.6/gcc/Other-Builtins.html
102 
103  // check qualifiers first
104  if(c_qualifierst(type1)!=c_qualifierst(type2))
105  return false;
106 
107  if(type1.id()==ID_c_enum_tag)
109  else if(type2.id()==ID_c_enum_tag)
111 
112  if(type1.id()==ID_c_enum)
113  {
114  if(type2.id()==ID_c_enum) // both are enums
115  return type1==type2; // compares the tag
116  else if(type2 == to_c_enum_type(type1).underlying_type())
117  return true;
118  }
119  else if(type2.id()==ID_c_enum)
120  {
121  if(type1 == to_c_enum_type(type2).underlying_type())
122  return true;
123  }
124  else if(type1.id()==ID_pointer &&
125  type2.id()==ID_pointer)
126  {
127  return gcc_types_compatible_p(
128  to_pointer_type(type1).base_type(), to_pointer_type(type2).base_type());
129  }
130  else if(type1.id()==ID_array &&
131  type2.id()==ID_array)
132  {
133  return gcc_types_compatible_p(
134  to_array_type(type1).element_type(),
135  to_array_type(type2).element_type()); // ignore size
136  }
137  else if(type1.id()==ID_code &&
138  type2.id()==ID_code)
139  {
140  const code_typet &c_type1=to_code_type(type1);
141  const code_typet &c_type2=to_code_type(type2);
142 
144  c_type1.return_type(),
145  c_type2.return_type()))
146  return false;
147 
148  if(c_type1.parameters().size()!=c_type2.parameters().size())
149  return false;
150 
151  for(std::size_t i=0; i<c_type1.parameters().size(); i++)
153  c_type1.parameters()[i].type(),
154  c_type2.parameters()[i].type()))
155  return false;
156 
157  return true;
158  }
159  else
160  {
161  if(type1==type2)
162  {
163  // Need to distinguish e.g. long int from int or
164  // long long int from long int.
165  // The rules appear to match those of C++.
166 
167  if(type1.get(ID_C_c_type)==type2.get(ID_C_c_type))
168  return true;
169  }
170  }
171 
172  return false;
173 }
174 
176 {
177  if(expr.id()==ID_side_effect)
179  else if(expr.id()==ID_constant)
181  else if(expr.id()==ID_infinity)
182  {
183  // ignore
184  }
185  else if(expr.id()==ID_symbol)
186  typecheck_expr_symbol(expr);
187  else if(expr.id()==ID_unary_plus ||
188  expr.id()==ID_unary_minus ||
189  expr.id()==ID_bitnot)
191  else if(expr.id()==ID_not)
193  else if(
194  expr.id() == ID_and || expr.id() == ID_or || expr.id() == ID_implies ||
195  expr.id() == ID_xor)
197  else if(expr.id()==ID_address_of)
199  else if(expr.id()==ID_dereference)
201  else if(expr.id()==ID_member)
202  typecheck_expr_member(expr);
203  else if(expr.id()==ID_ptrmember)
205  else if(expr.id()==ID_equal ||
206  expr.id()==ID_notequal ||
207  expr.id()==ID_lt ||
208  expr.id()==ID_le ||
209  expr.id()==ID_gt ||
210  expr.id()==ID_ge)
212  else if(expr.id()==ID_index)
213  typecheck_expr_index(expr);
214  else if(expr.id()==ID_typecast)
216  else if(expr.id()==ID_sizeof)
217  typecheck_expr_sizeof(expr);
218  else if(expr.id()==ID_alignof)
220  else if(
221  expr.id() == ID_plus || expr.id() == ID_minus || expr.id() == ID_mult ||
222  expr.id() == ID_div || expr.id() == ID_mod || expr.id() == ID_bitand ||
223  expr.id() == ID_bitxor || expr.id() == ID_bitor || expr.id() == ID_bitnand)
224  {
226  }
227  else if(expr.id()==ID_shl || expr.id()==ID_shr)
229  else if(expr.id()==ID_comma)
230  typecheck_expr_comma(expr);
231  else if(expr.id()==ID_if)
233  else if(expr.id()==ID_code)
234  {
236  error() << "typecheck_expr_main got code: " << expr.pretty() << eom;
237  throw 0;
238  }
239  else if(expr.id()==ID_gcc_builtin_va_arg)
241  else if(expr.id()==ID_cw_va_arg_typeof)
243  else if(expr.id()==ID_gcc_builtin_types_compatible_p)
244  {
245  expr.type()=bool_typet();
246  auto &subtypes =
247  (static_cast<type_with_subtypest &>(expr.add(ID_type_arg))).subtypes();
248  assert(subtypes.size()==2);
249  typecheck_type(subtypes[0]);
250  typecheck_type(subtypes[1]);
251  source_locationt source_location=expr.source_location();
252 
253  // ignores top-level qualifiers
254  subtypes[0].remove(ID_C_constant);
255  subtypes[0].remove(ID_C_volatile);
256  subtypes[0].remove(ID_C_restricted);
257  subtypes[1].remove(ID_C_constant);
258  subtypes[1].remove(ID_C_volatile);
259  subtypes[1].remove(ID_C_restricted);
260 
261  expr = make_boolean_expr(gcc_types_compatible_p(subtypes[0], subtypes[1]));
262  expr.add_source_location()=source_location;
263  }
264  else if(expr.id()==ID_clang_builtin_convertvector)
265  {
266  // This has one operand and a type, and acts like a typecast
267  DATA_INVARIANT(expr.operands().size()==1, "clang_builtin_convertvector has one operand");
268  typecheck_type(expr.type());
269  typecast_exprt tmp(to_unary_expr(expr).op(), expr.type());
271  expr.swap(tmp);
272  }
273  else if(expr.id()==ID_builtin_offsetof)
275  else if(expr.id()==ID_string_constant)
276  {
277  // already fine -- mark as lvalue
278  expr.set(ID_C_lvalue, true);
279  }
280  else if(expr.id()==ID_arguments)
281  {
282  // already fine
283  }
284  else if(expr.id()==ID_designated_initializer)
285  {
286  exprt &designator=static_cast<exprt &>(expr.add(ID_designator));
287 
288  Forall_operands(it, designator)
289  {
290  if(it->id()==ID_index)
291  typecheck_expr(to_unary_expr(*it).op()); // still needs typechecking
292  }
293  }
294  else if(expr.id()==ID_initializer_list)
295  {
296  // already fine, just set some type
297  expr.type()=void_type();
298  }
299  else if(
300  expr.id() == ID_forall || expr.id() == ID_exists || expr.id() == ID_lambda)
301  {
302  // These have two operands.
303  // op0 is a tuple with declarations,
304  // op1 is the bound expression
305  auto &binary_expr = to_binary_expr(expr);
306  auto &bindings = binary_expr.op0().operands();
307  auto &where = binary_expr.op1();
308 
309  for(const auto &binding : bindings)
310  {
311  if(binding.get(ID_statement) != ID_decl)
312  {
314  error() << "expected declaration as operand of quantifier" << eom;
315  throw 0;
316  }
317  }
318 
319  if(has_subexpr(where, ID_side_effect))
320  {
322  error() << "quantifier must not contain side effects" << eom;
323  throw 0;
324  }
325 
326  // replace declarations by symbol expressions
327  for(auto &binding : bindings)
328  binding = to_code_frontend_decl(to_code(binding)).symbol();
329 
330  if(expr.id() == ID_lambda)
331  {
333 
334  for(auto &binding : bindings)
335  domain.push_back(binding.type());
336 
337  expr.type() = mathematical_function_typet(domain, where.type());
338  }
339  else
340  {
341  expr.type() = bool_typet();
342  implicit_typecast_bool(where);
343  }
344  }
345  else if(expr.id()==ID_label)
346  {
347  expr.type()=void_type();
348  }
349  else if(expr.id()==ID_array)
350  {
351  // these pop up as string constants, and are already typed
352  }
353  else if(expr.id()==ID_complex)
354  {
355  // these should only exist as constants,
356  // and should already be typed
357  }
358  else if(expr.id() == ID_complex_real)
359  {
360  const exprt &op = to_unary_expr(expr).op();
361 
362  if(op.type().id() != ID_complex)
363  {
364  if(!is_number(op.type()))
365  {
367  error() << "real part retrieval expects numerical operand, "
368  << "but got '" << to_string(op.type()) << "'" << eom;
369  throw 0;
370  }
371 
372  typecast_exprt typecast_expr(op, complex_typet(op.type()));
373  complex_real_exprt complex_real_expr(typecast_expr);
374 
375  expr.swap(complex_real_expr);
376  }
377  else
378  {
379  complex_real_exprt complex_real_expr(op);
380 
381  // these are lvalues if the operand is one
382  if(op.get_bool(ID_C_lvalue))
383  complex_real_expr.set(ID_C_lvalue, true);
384 
385  if(op.type().get_bool(ID_C_constant))
386  complex_real_expr.type().set(ID_C_constant, true);
387 
388  expr.swap(complex_real_expr);
389  }
390  }
391  else if(expr.id() == ID_complex_imag)
392  {
393  const exprt &op = to_unary_expr(expr).op();
394 
395  if(op.type().id() != ID_complex)
396  {
397  if(!is_number(op.type()))
398  {
400  error() << "real part retrieval expects numerical operand, "
401  << "but got '" << to_string(op.type()) << "'" << eom;
402  throw 0;
403  }
404 
405  typecast_exprt typecast_expr(op, complex_typet(op.type()));
406  complex_imag_exprt complex_imag_expr(typecast_expr);
407 
408  expr.swap(complex_imag_expr);
409  }
410  else
411  {
412  complex_imag_exprt complex_imag_expr(op);
413 
414  // these are lvalues if the operand is one
415  if(op.get_bool(ID_C_lvalue))
416  complex_imag_expr.set(ID_C_lvalue, true);
417 
418  if(op.type().get_bool(ID_C_constant))
419  complex_imag_expr.type().set(ID_C_constant, true);
420 
421  expr.swap(complex_imag_expr);
422  }
423  }
424  else if(expr.id()==ID_generic_selection)
425  {
426  // This is C11.
427  // The operand is already typechecked. Depending
428  // on its type, we return one of the generic associations.
429  auto &op = to_unary_expr(expr).op();
430 
431  // This is one of the few places where it's detectable
432  // that we are using "bool" for boolean operators instead
433  // of "int". We convert for this reason.
434  if(op.type().id() == ID_bool)
435  op = typecast_exprt(op, signed_int_type());
436 
437  irept::subt &generic_associations=
438  expr.add(ID_generic_associations).get_sub();
439 
440  // first typecheck all types
441  for(auto &irep : generic_associations)
442  {
443  if(irep.get(ID_type_arg) != ID_default)
444  {
445  typet &type = static_cast<typet &>(irep.add(ID_type_arg));
446  typecheck_type(type);
447  }
448  }
449 
450  // first try non-default match
451  exprt default_match=nil_exprt();
452  exprt assoc_match=nil_exprt();
453 
454  const typet &op_type = follow(op.type());
455 
456  for(const auto &irep : generic_associations)
457  {
458  if(irep.get(ID_type_arg) == ID_default)
459  default_match = static_cast<const exprt &>(irep.find(ID_value));
460  else if(
461  op_type == follow(static_cast<const typet &>(irep.find(ID_type_arg))))
462  {
463  assoc_match = static_cast<const exprt &>(irep.find(ID_value));
464  }
465  }
466 
467  if(assoc_match.is_nil())
468  {
469  if(default_match.is_not_nil())
470  expr.swap(default_match);
471  else
472  {
474  error() << "unmatched generic selection: " << to_string(op.type())
475  << eom;
476  throw 0;
477  }
478  }
479  else
480  expr.swap(assoc_match);
481 
482  // still need to typecheck the result
483  typecheck_expr(expr);
484  }
485  else if(expr.id()==ID_gcc_asm_input ||
486  expr.id()==ID_gcc_asm_output ||
487  expr.id()==ID_gcc_asm_clobbered_register)
488  {
489  }
490  else if(expr.id()==ID_lshr || expr.id()==ID_ashr ||
491  expr.id()==ID_assign_lshr || expr.id()==ID_assign_ashr)
492  {
493  // already type checked
494  }
495  else if(expr.id() == ID_C_spec_assigns || expr.id() == ID_target_list)
496  {
497  // already type checked
498  }
499  else
500  {
502  error() << "unexpected expression: " << expr.pretty() << eom;
503  throw 0;
504  }
505 }
506 
508 {
509  expr.type() = to_binary_expr(expr).op1().type();
510 
511  // make this an l-value if the last operand is one
512  if(to_binary_expr(expr).op1().get_bool(ID_C_lvalue))
513  expr.set(ID_C_lvalue, true);
514 }
515 
517 {
518  // The first parameter is the va_list, and the second
519  // is the type, which will need to be fixed and checked.
520  // The type is given by the parser as type of the expression.
521 
522  typet arg_type=expr.type();
523  typecheck_type(arg_type);
524 
525  const code_typet new_type(
526  {code_typet::parametert(pointer_type(void_type()))}, std::move(arg_type));
527 
528  exprt arg = to_unary_expr(expr).op();
529 
531 
532  symbol_exprt function(ID_gcc_builtin_va_arg, new_type);
533  function.add_source_location() = expr.source_location();
534 
535  // turn into function call
537  function, {arg}, new_type.return_type(), expr.source_location());
538 
539  expr.swap(result);
540 
541  // Make sure symbol exists, but we have it return void
542  // to avoid collisions of the same symbol with different
543  // types.
544 
545  code_typet symbol_type=new_type;
546  symbol_type.return_type()=void_type();
547 
548  symbolt symbol;
549  symbol.base_name=ID_gcc_builtin_va_arg;
550  symbol.name=ID_gcc_builtin_va_arg;
551  symbol.type=symbol_type;
552  symbol.mode = ID_C;
553 
554  symbol_table.insert(std::move(symbol));
555 }
556 
558 {
559  // used in Code Warrior via
560  //
561  // __va_arg( <Symbol>, _var_arg_typeof( <Typ> ) )
562  //
563  // where __va_arg is declared as
564  //
565  // extern void* __va_arg(void*, int);
566 
567  typet &type=static_cast<typet &>(expr.add(ID_type_arg));
568  typecheck_type(type);
569 
570  // these return an integer
571  expr.type()=signed_int_type();
572 }
573 
575 {
576  // these need not be constant, due to array indices!
577 
578  if(!expr.operands().empty())
579  {
581  error() << "builtin_offsetof expects no operands" << eom;
582  throw 0;
583  }
584 
585  typet &type=static_cast<typet &>(expr.add(ID_type_arg));
586  typecheck_type(type);
587 
588  exprt &member=static_cast<exprt &>(expr.add(ID_designator));
589 
591 
592  forall_operands(m_it, member)
593  {
594  type = follow(type);
595 
596  if(m_it->id()==ID_member)
597  {
598  if(type.id()!=ID_union && type.id()!=ID_struct)
599  {
601  error() << "offsetof of member expects struct/union type, "
602  << "but got '" << to_string(type) << "'" << eom;
603  throw 0;
604  }
605 
606  bool found=false;
607  irep_idt component_name=m_it->get(ID_component_name);
608 
609  while(!found)
610  {
611  assert(type.id()==ID_union || type.id()==ID_struct);
612 
613  const struct_union_typet &struct_union_type=
614  to_struct_union_type(type);
615 
616  // direct member?
617  if(struct_union_type.has_component(component_name))
618  {
619  found=true;
620 
621  if(type.id()==ID_struct)
622  {
623  auto o_opt =
624  member_offset_expr(to_struct_type(type), component_name, *this);
625 
626  if(!o_opt.has_value())
627  {
629  error() << "offsetof failed to determine offset of '"
630  << component_name << "'" << eom;
631  throw 0;
632  }
633 
634  result = plus_exprt(
635  result,
636  typecast_exprt::conditional_cast(o_opt.value(), size_type()));
637  }
638 
639  type=struct_union_type.get_component(component_name).type();
640  }
641  else
642  {
643  // maybe anonymous?
644  bool found2=false;
645 
646  for(const auto &c : struct_union_type.components())
647  {
648  if(
649  c.get_anonymous() &&
650  (c.type().id() == ID_struct_tag || c.type().id() == ID_union_tag))
651  {
652  if(has_component_rec(c.type(), component_name, *this))
653  {
654  if(type.id()==ID_struct)
655  {
656  auto o_opt = member_offset_expr(
657  to_struct_type(type), c.get_name(), *this);
658 
659  if(!o_opt.has_value())
660  {
662  error() << "offsetof failed to determine offset of '"
663  << component_name << "'" << eom;
664  throw 0;
665  }
666 
667  result = plus_exprt(
668  result,
670  o_opt.value(), size_type()));
671  }
672 
673  typet tmp = follow(c.type());
674  type=tmp;
675  assert(type.id()==ID_union || type.id()==ID_struct);
676  found2=true;
677  break; // we run into another iteration of the outer loop
678  }
679  }
680  }
681 
682  if(!found2)
683  {
685  error() << "offset-of of member failed to find component '"
686  << component_name << "' in '" << to_string(type) << "'"
687  << eom;
688  throw 0;
689  }
690  }
691  }
692  }
693  else if(m_it->id()==ID_index)
694  {
695  if(type.id()!=ID_array)
696  {
698  error() << "offsetof of index expects array type" << eom;
699  throw 0;
700  }
701 
702  exprt index = to_unary_expr(*m_it).op();
703 
704  // still need to typecheck index
705  typecheck_expr(index);
706 
707  auto element_size_opt =
708  size_of_expr(to_array_type(type).element_type(), *this);
709 
710  if(!element_size_opt.has_value())
711  {
713  error() << "offsetof failed to determine array element size" << eom;
714  throw 0;
715  }
716 
718 
719  result = plus_exprt(result, mult_exprt(element_size_opt.value(), index));
720 
721  typet tmp = to_array_type(type).element_type();
722  type=tmp;
723  }
724  }
725 
726  // We make an effort to produce a constant,
727  // but this may depend on variables
728  simplify(result, *this);
729  result.add_source_location()=expr.source_location();
730 
731  expr.swap(result);
732 }
733 
735 {
736  if(expr.id()==ID_side_effect &&
737  expr.get(ID_statement)==ID_function_call)
738  {
739  // don't do function operand
740  typecheck_expr(to_binary_expr(expr).op1()); // arguments
741  }
742  else if(expr.id()==ID_side_effect &&
743  expr.get(ID_statement)==ID_statement_expression)
744  {
746  }
747  else if(
748  expr.id() == ID_forall || expr.id() == ID_exists || expr.id() == ID_lambda)
749  {
750  // These introduce new symbols, which need to be added to the symbol table
751  // before the second operand is typechecked.
752 
753  auto &binary_expr = to_binary_expr(expr);
754  auto &bindings = binary_expr.op0().operands();
755 
756  for(auto &binding : bindings)
757  {
758  ansi_c_declarationt &declaration = to_ansi_c_declaration(binding);
759 
760  typecheck_declaration(declaration);
761 
762  if(declaration.declarators().size() != 1)
763  {
765  error() << "forall/exists expects one declarator exactly" << eom;
766  throw 0;
767  }
768 
769  irep_idt identifier = declaration.declarators().front().get_name();
770 
771  // look it up
772  symbol_tablet::symbolst::const_iterator s_it =
773  symbol_table.symbols.find(identifier);
774 
775  if(s_it == symbol_table.symbols.end())
776  {
778  error() << "failed to find bound symbol `" << identifier
779  << "' in symbol table" << eom;
780  throw 0;
781  }
782 
783  const symbolt &symbol = s_it->second;
784 
785  if(
786  symbol.is_type || symbol.is_extern || symbol.is_static_lifetime ||
787  !is_complete_type(symbol.type) || symbol.type.id() == ID_code)
788  {
790  error() << "unexpected quantified symbol" << eom;
791  throw 0;
792  }
793 
794  code_frontend_declt decl(symbol.symbol_expr());
795  decl.add_source_location() = declaration.source_location();
796 
797  binding = decl;
798  }
799 
800  typecheck_expr(binary_expr.op1());
801  }
802  else
803  {
804  Forall_operands(it, expr)
805  typecheck_expr(*it);
806  }
807 }
808 
810 {
811  irep_idt identifier=to_symbol_expr(expr).get_identifier();
812 
813  // Is it a parameter? We do this while checking parameter lists.
814  id_type_mapt::const_iterator p_it=parameter_map.find(identifier);
815  if(p_it!=parameter_map.end())
816  {
817  // yes
818  expr.type()=p_it->second;
819  expr.set(ID_C_lvalue, true);
820  return;
821  }
822 
823  // renaming via GCC asm label
824  asm_label_mapt::const_iterator entry=
825  asm_label_map.find(identifier);
826  if(entry!=asm_label_map.end())
827  {
828  identifier=entry->second;
829  to_symbol_expr(expr).set_identifier(identifier);
830  }
831 
832  // look it up
833  const symbolt *symbol_ptr;
834  if(lookup(identifier, symbol_ptr))
835  {
837  error() << "failed to find symbol '" << identifier << "'" << eom;
838  throw 0;
839  }
840 
841  const symbolt &symbol=*symbol_ptr;
842 
843  if(symbol.is_type)
844  {
846  error() << "did not expect a type symbol here, but got '"
847  << symbol.display_name() << "'" << eom;
848  throw 0;
849  }
850 
851  // save the source location
852  source_locationt source_location=expr.source_location();
853 
854  if(symbol.is_macro)
855  {
856  // preserve enum key
857  #if 0
858  irep_idt base_name=expr.get(ID_C_base_name);
859  #endif
860 
861  follow_macros(expr);
862 
863  #if 0
864  if(expr.id()==ID_constant &&
865  !base_name.empty())
866  expr.set(ID_C_cformat, base_name);
867  else
868  #endif
869  typecheck_expr(expr);
870 
871  // preserve location
872  expr.add_source_location()=source_location;
873  }
874  else if(has_prefix(id2string(identifier), CPROVER_PREFIX "constant_infinity"))
875  {
876  expr=infinity_exprt(symbol.type);
877 
878  // put it back
879  expr.add_source_location()=source_location;
880  }
881  else if(identifier=="__func__" ||
882  identifier=="__FUNCTION__" ||
883  identifier=="__PRETTY_FUNCTION__")
884  {
885  // __func__ is an ANSI-C standard compliant hack to get the function name
886  // __FUNCTION__ and __PRETTY_FUNCTION__ are GCC-specific
887  string_constantt s(source_location.get_function());
888  s.add_source_location()=source_location;
889  s.set(ID_C_lvalue, true);
890  expr.swap(s);
891  }
892  else
893  {
894  expr=symbol.symbol_expr();
895 
896  // put it back
897  expr.add_source_location()=source_location;
898 
899  if(symbol.is_lvalue)
900  expr.set(ID_C_lvalue, true);
901 
902  if(expr.type().id()==ID_code) // function designator
903  { // special case: this is sugar for &f
904  address_of_exprt tmp(expr, pointer_type(expr.type()));
905  tmp.set(ID_C_implicit, true);
907  expr=tmp;
908  }
909  }
910 }
911 
913  side_effect_exprt &expr)
914 {
915  codet &code = to_code(to_unary_expr(expr).op());
916 
917  // the type is the type of the last statement in the
918  // block, but do worry about labels!
919 
921 
922  irep_idt last_statement=last.get_statement();
923 
924  if(last_statement==ID_expression)
925  {
926  assert(last.operands().size()==1);
927  exprt &op=last.op0();
928 
929  // arrays here turn into pointers (array decay)
930  if(op.type().id()==ID_array)
933 
934  expr.type()=op.type();
935  }
936  else
937  {
938  // we used to do this, but don't expect it any longer
939  PRECONDITION(last_statement != ID_function_call);
940 
941  expr.type()=typet(ID_empty);
942  }
943 }
944 
946 {
947  typet type;
948 
949  // these come in two flavors: with zero operands, for a type,
950  // and with one operand, for an expression.
951  PRECONDITION(expr.operands().size() <= 1);
952 
953  if(expr.operands().empty())
954  {
955  type.swap(static_cast<typet &>(expr.add(ID_type_arg)));
956  typecheck_type(type);
957  }
958  else
959  {
960  const exprt &op = to_unary_expr(as_const(expr)).op();
961  // This is one of the few places where it's detectable
962  // that we are using "bool" for boolean operators instead
963  // of "int". We convert for this reason.
964  if(op.type().id() == ID_bool)
965  type = signed_int_type();
966  else
967  type = op.type();
968  }
969 
970  exprt new_expr;
971 
972  if(type.id()==ID_c_bit_field)
973  {
975  error() << "sizeof cannot be applied to bit fields" << eom;
976  throw 0;
977  }
978  else if(type.id() == ID_bool)
979  {
981  error() << "sizeof cannot be applied to single bits" << eom;
982  throw 0;
983  }
984  else if(type.id() == ID_empty)
985  {
986  // This is a gcc extension.
987  // https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Pointer-Arith.html
988  new_expr = from_integer(1, size_type());
989  }
990  else
991  {
992  if(
993  (type.id() == ID_struct_tag &&
994  follow_tag(to_struct_tag_type(type)).is_incomplete()) ||
995  (type.id() == ID_union_tag &&
996  follow_tag(to_union_tag_type(type)).is_incomplete()) ||
997  (type.id() == ID_c_enum_tag &&
998  follow_tag(to_c_enum_tag_type(type)).is_incomplete()) ||
999  (type.id() == ID_array && to_array_type(type).is_incomplete()))
1000  {
1002  error() << "invalid application of \'sizeof\' to an incomplete type\n\t\'"
1003  << to_string(type) << "\'" << eom;
1004  throw 0;
1005  }
1006 
1007  auto size_of_opt = size_of_expr(type, *this);
1008 
1009  if(!size_of_opt.has_value())
1010  {
1012  error() << "type has no size: " << to_string(type) << eom;
1013  throw 0;
1014  }
1015 
1016  new_expr = size_of_opt.value();
1017  }
1018 
1019  new_expr.swap(expr);
1020 
1021  expr.add(ID_C_c_sizeof_type)=type;
1022 
1023  // The type may contain side-effects.
1024  if(!clean_code.empty())
1025  {
1026  side_effect_exprt side_effect_expr(
1027  ID_statement_expression, void_type(), expr.source_location());
1028  auto decl_block=code_blockt::from_list(clean_code);
1029  decl_block.set_statement(ID_decl_block);
1030  side_effect_expr.copy_to_operands(decl_block);
1031  clean_code.clear();
1032 
1033  // We merge the side-effect into the operand of the typecast,
1034  // using a comma-expression.
1035  // I.e., (type)e becomes (type)(side-effect, e)
1036  // It is not obvious whether the type or 'e' should be evaluated
1037  // first.
1038 
1039  binary_exprt comma_expr{
1040  std::move(side_effect_expr), ID_comma, expr, expr.type()};
1041  expr.swap(comma_expr);
1042  }
1043 }
1044 
1046 {
1047  typet argument_type;
1048 
1049  if(expr.operands().size()==1)
1050  argument_type = to_unary_expr(expr).op().type();
1051  else
1052  {
1053  typet &op_type=static_cast<typet &>(expr.add(ID_type_arg));
1054  typecheck_type(op_type);
1055  argument_type=op_type;
1056  }
1057 
1058  // we only care about the type
1059  mp_integer a=alignment(argument_type, *this);
1060 
1061  exprt tmp=from_integer(a, size_type());
1062  tmp.add_source_location()=expr.source_location();
1063 
1064  expr.swap(tmp);
1065 }
1066 
1068 {
1069  exprt &op = to_unary_expr(expr).op();
1070 
1071  typecheck_type(expr.type());
1072 
1073  // The type may contain side-effects.
1074  if(!clean_code.empty())
1075  {
1076  side_effect_exprt side_effect_expr(
1077  ID_statement_expression, void_type(), expr.source_location());
1078  auto decl_block=code_blockt::from_list(clean_code);
1079  decl_block.set_statement(ID_decl_block);
1080  side_effect_expr.copy_to_operands(decl_block);
1081  clean_code.clear();
1082 
1083  // We merge the side-effect into the operand of the typecast,
1084  // using a comma-expression.
1085  // I.e., (type)e becomes (type)(side-effect, e)
1086  // It is not obvious whether the type or 'e' should be evaluated
1087  // first.
1088 
1089  binary_exprt comma_expr{
1090  std::move(side_effect_expr), ID_comma, op, op.type()};
1091  op.swap(comma_expr);
1092  }
1093 
1094  const typet expr_type = expr.type();
1095 
1096  if(
1097  expr_type.id() == ID_union_tag && expr_type != op.type() &&
1098  op.id() != ID_initializer_list)
1099  {
1100  // This is a GCC extension. It's either a 'temporary union',
1101  // where the argument is one of the member types.
1102 
1103  // This is one of the few places where it's detectable
1104  // that we are using "bool" for boolean operators instead
1105  // of "int". We convert for this reason.
1106  if(op.type().id() == ID_bool)
1107  op = typecast_exprt(op, signed_int_type());
1108 
1109  // we need to find a member with the right type
1110  const auto &union_type = follow_tag(to_union_tag_type(expr_type));
1111  for(const auto &c : union_type.components())
1112  {
1113  if(c.type() == op.type())
1114  {
1115  // found! build union constructor
1116  union_exprt union_expr(c.get_name(), op, expr.type());
1117  union_expr.add_source_location()=expr.source_location();
1118  expr=union_expr;
1119  expr.set(ID_C_lvalue, true);
1120  return;
1121  }
1122  }
1123 
1124  // not found, complain
1126  error() << "type cast to union: type '" << to_string(op.type())
1127  << "' not found in union" << eom;
1128  throw 0;
1129  }
1130 
1131  // We allow (TYPE){ initializer_list }
1132  // This is called "compound literal", and is syntactic
1133  // sugar for a (possibly local) declaration.
1134  if(op.id()==ID_initializer_list)
1135  {
1136  // just do a normal initialization
1137  do_initializer(op, expr.type(), false);
1138 
1139  // This produces a struct-expression,
1140  // union-expression, array-expression,
1141  // or an expression for a pointer or scalar.
1142  // We produce a compound_literal expression.
1143  exprt tmp(ID_compound_literal, expr.type());
1144  tmp.copy_to_operands(op);
1145 
1146  // handle the case of TYPE being an array with unspecified size
1147  if(op.id()==ID_array &&
1148  expr.type().id()==ID_array &&
1149  to_array_type(expr.type()).size().is_nil())
1150  tmp.type()=op.type();
1151 
1152  expr=tmp;
1153  expr.set(ID_C_lvalue, true); // these are l-values
1154  return;
1155  }
1156 
1157  // a cast to void is always fine
1158  if(expr_type.id()==ID_empty)
1159  return;
1160 
1161  const typet op_type = op.type();
1162 
1163  // cast to same type?
1164  if(expr_type == op_type)
1165  return; // it's ok
1166 
1167  // vectors?
1168 
1169  if(expr_type.id()==ID_vector)
1170  {
1171  // we are generous -- any vector to vector is fine
1172  if(op_type.id()==ID_vector)
1173  return;
1174  else if(op_type.id()==ID_signedbv ||
1175  op_type.id()==ID_unsignedbv)
1176  return;
1177  }
1178 
1179  if(!is_numeric_type(expr_type) && expr_type.id()!=ID_pointer)
1180  {
1182  error() << "type cast to '" << to_string(expr_type) << "' is not permitted"
1183  << eom;
1184  throw 0;
1185  }
1186 
1187  if(is_numeric_type(op_type) || op_type.id()==ID_pointer)
1188  {
1189  }
1190  else if(op_type.id()==ID_array)
1191  {
1192  index_exprt index(op, from_integer(0, c_index_type()));
1193  op=address_of_exprt(index);
1194  }
1195  else if(op_type.id()==ID_empty)
1196  {
1197  if(expr_type.id()!=ID_empty)
1198  {
1200  error() << "type cast from void only permitted to void, but got '"
1201  << to_string(expr.type()) << "'" << eom;
1202  throw 0;
1203  }
1204  }
1205  else if(op_type.id()==ID_vector)
1206  {
1207  const vector_typet &op_vector_type=
1208  to_vector_type(op_type);
1209 
1210  // gcc allows conversion of a vector of size 1 to
1211  // an integer/float of the same size
1212  if((expr_type.id()==ID_signedbv ||
1213  expr_type.id()==ID_unsignedbv) &&
1214  pointer_offset_bits(expr_type, *this)==
1215  pointer_offset_bits(op_vector_type, *this))
1216  {
1217  }
1218  else
1219  {
1221  error() << "type cast from vector to '" << to_string(expr.type())
1222  << "' not permitted" << eom;
1223  throw 0;
1224  }
1225  }
1226  else
1227  {
1229  error() << "type cast from '" << to_string(op_type) << "' not permitted"
1230  << eom;
1231  throw 0;
1232  }
1233 
1234  // The new thing is an lvalue if the previous one is
1235  // an lvalue and it's just a pointer type cast.
1236  // This isn't really standard conformant!
1237  // Note that gcc says "warning: target of assignment not really an lvalue;
1238  // this will be a hard error in the future", i.e., we
1239  // can hope that the code below will one day simply go away.
1240 
1241  // Current versions of gcc in fact refuse to do this! Yay!
1242 
1243  if(op.get_bool(ID_C_lvalue))
1244  {
1245  if(expr_type.id()==ID_pointer)
1246  expr.set(ID_C_lvalue, true);
1247  }
1248 }
1249 
1251 {
1253 }
1254 
1256 {
1257  exprt &array_expr = to_binary_expr(expr).op0();
1258  exprt &index_expr = to_binary_expr(expr).op1();
1259 
1260  // we might have to swap them
1261 
1262  {
1263  const typet &array_type = array_expr.type();
1264  const typet &index_type = index_expr.type();
1265 
1266  if(
1267  array_type.id() != ID_array && array_type.id() != ID_pointer &&
1268  array_type.id() != ID_vector &&
1269  (index_type.id() == ID_array || index_type.id() == ID_pointer ||
1270  index_type.id() == ID_vector))
1271  std::swap(array_expr, index_expr);
1272  }
1273 
1274  make_index_type(index_expr);
1275 
1276  // array_expr is a reference to one of expr.operands(), when that vector is
1277  // swapped below the reference is no longer valid. final_array_type exists
1278  // beyond that point so can't be a reference
1279  const typet final_array_type = array_expr.type();
1280 
1281  if(final_array_type.id()==ID_array ||
1282  final_array_type.id()==ID_vector)
1283  {
1284  expr.type() = to_type_with_subtype(final_array_type).subtype();
1285 
1286  if(array_expr.get_bool(ID_C_lvalue))
1287  expr.set(ID_C_lvalue, true);
1288 
1289  if(final_array_type.get_bool(ID_C_constant))
1290  expr.type().set(ID_C_constant, true);
1291  }
1292  else if(final_array_type.id()==ID_pointer)
1293  {
1294  // p[i] is syntactic sugar for *(p+i)
1295 
1297  exprt::operandst summands;
1298  std::swap(summands, expr.operands());
1299  expr.add_to_operands(plus_exprt(std::move(summands), array_expr.type()));
1300  expr.id(ID_dereference);
1301  expr.set(ID_C_lvalue, true);
1302  expr.type() = to_pointer_type(final_array_type).base_type();
1303  }
1304  else
1305  {
1307  error() << "operator [] must take array/vector or pointer but got '"
1308  << to_string(array_expr.type()) << "'" << eom;
1309  throw 0;
1310  }
1311 }
1312 
1314 {
1315  // equality and disequality on float is not mathematical equality!
1316  if(expr.op0().type().id() == ID_floatbv)
1317  {
1318  if(expr.id()==ID_equal)
1319  expr.id(ID_ieee_float_equal);
1320  else if(expr.id()==ID_notequal)
1321  expr.id(ID_ieee_float_notequal);
1322  }
1323 }
1324 
1326  binary_relation_exprt &expr)
1327 {
1328  exprt &op0=expr.op0();
1329  exprt &op1=expr.op1();
1330 
1331  const typet o_type0=op0.type();
1332  const typet o_type1=op1.type();
1333 
1334  if(o_type0.id() == ID_vector || o_type1.id() == ID_vector)
1335  {
1337  return;
1338  }
1339 
1340  expr.type()=bool_typet();
1341 
1342  if(expr.id()==ID_equal || expr.id()==ID_notequal)
1343  {
1344  if(follow(o_type0)==follow(o_type1))
1345  {
1346  if(o_type0.id() != ID_array)
1347  {
1348  adjust_float_rel(expr);
1349  return; // no promotion necessary
1350  }
1351  }
1352  }
1353 
1354  implicit_typecast_arithmetic(op0, op1);
1355 
1356  const typet &type0=op0.type();
1357  const typet &type1=op1.type();
1358 
1359  if(type0==type1)
1360  {
1361  if(is_number(type0))
1362  {
1363  adjust_float_rel(expr);
1364  return;
1365  }
1366 
1367  if(type0.id()==ID_pointer)
1368  {
1369  if(expr.id()==ID_equal || expr.id()==ID_notequal)
1370  return;
1371 
1372  if(expr.id()==ID_le || expr.id()==ID_lt ||
1373  expr.id()==ID_ge || expr.id()==ID_gt)
1374  return;
1375  }
1376 
1377  if(type0.id()==ID_string_constant)
1378  {
1379  if(expr.id()==ID_equal || expr.id()==ID_notequal)
1380  return;
1381  }
1382  }
1383  else
1384  {
1385  // pointer and zero
1386  if(type0.id()==ID_pointer &&
1387  simplify_expr(op1, *this).is_zero())
1388  {
1389  op1 = null_pointer_exprt{to_pointer_type(type0)};
1390  return;
1391  }
1392 
1393  if(type1.id()==ID_pointer &&
1394  simplify_expr(op0, *this).is_zero())
1395  {
1396  op0 = null_pointer_exprt{to_pointer_type(type1)};
1397  return;
1398  }
1399 
1400  // pointer and integer
1401  if(type0.id()==ID_pointer && is_number(type1))
1402  {
1403  op1 = typecast_exprt(op1, type0);
1404  return;
1405  }
1406 
1407  if(type1.id()==ID_pointer && is_number(type0))
1408  {
1409  op0 = typecast_exprt(op0, type1);
1410  return;
1411  }
1412 
1413  if(type0.id()==ID_pointer && type1.id()==ID_pointer)
1414  {
1415  op1 = typecast_exprt(op1, type0);
1416  return;
1417  }
1418  }
1419 
1421  error() << "operator '" << expr.id() << "' not defined for types '"
1422  << to_string(o_type0) << "' and '" << to_string(o_type1) << "'"
1423  << eom;
1424  throw 0;
1425 }
1426 
1428 {
1429  const typet &o_type0 = as_const(expr).op0().type();
1430  const typet &o_type1 = as_const(expr).op1().type();
1431 
1432  if(o_type0.id() != ID_vector || o_type0 != o_type1)
1433  {
1435  error() << "vector operator '" << expr.id() << "' not defined for types '"
1436  << to_string(o_type0) << "' and '" << to_string(o_type1) << "'"
1437  << eom;
1438  throw 0;
1439  }
1440 
1441  // Comparisons between vectors produce a vector of integers of the same width
1442  // with the same dimension.
1443  auto subtype_width =
1444  to_bitvector_type(to_vector_type(o_type0).element_type()).get_width();
1445  expr.type() = vector_typet{
1446  to_vector_type(o_type0).index_type(),
1447  signedbv_typet{subtype_width},
1448  to_vector_type(o_type0).size()};
1449 
1450  // Replace the id as the semantics of these are point-wise application (and
1451  // the result is not of bool type).
1452  if(expr.id() == ID_notequal)
1453  expr.id(ID_vector_notequal);
1454  else
1455  expr.id("vector-" + id2string(expr.id()));
1456 }
1457 
1459 {
1460  auto &op = to_unary_expr(expr).op();
1461  const typet &op0_type = op.type();
1462 
1463  if(op0_type.id() == ID_array)
1464  {
1465  // a->f is the same as a[0].f
1466  exprt zero = from_integer(0, c_index_type());
1467  index_exprt index_expr(op, zero, to_array_type(op0_type).element_type());
1468  index_expr.set(ID_C_lvalue, true);
1469  op.swap(index_expr);
1470  }
1471  else if(op0_type.id() == ID_pointer)
1472  {
1473  // turn x->y into (*x).y
1474  dereference_exprt deref_expr(op);
1475  deref_expr.add_source_location()=expr.source_location();
1476  typecheck_expr_dereference(deref_expr);
1477  op.swap(deref_expr);
1478  }
1479  else
1480  {
1482  error() << "ptrmember operator requires pointer or array type "
1483  "on left hand side, but got '"
1484  << to_string(op0_type) << "'" << eom;
1485  throw 0;
1486  }
1487 
1488  expr.id(ID_member);
1489  typecheck_expr_member(expr);
1490 }
1491 
1493 {
1494  exprt &op0 = to_unary_expr(expr).op();
1495  typet type=op0.type();
1496 
1497  type = follow(type);
1498 
1499  if(type.id()!=ID_struct &&
1500  type.id()!=ID_union)
1501  {
1503  error() << "member operator requires structure type "
1504  "on left hand side but got '"
1505  << to_string(type) << "'" << eom;
1506  throw 0;
1507  }
1508 
1509  const struct_union_typet &struct_union_type=
1510  to_struct_union_type(type);
1511 
1512  if(struct_union_type.is_incomplete())
1513  {
1515  error() << "member operator got incomplete " << type.id()
1516  << " type on left hand side" << eom;
1517  throw 0;
1518  }
1519 
1520  const irep_idt &component_name=
1521  expr.get(ID_component_name);
1522 
1523  // first try to find directly
1525  struct_union_type.get_component(component_name);
1526 
1527  // if that fails, search the anonymous members
1528 
1529  if(component.is_nil())
1530  {
1531  exprt tmp=get_component_rec(op0, component_name, *this);
1532 
1533  if(tmp.is_nil())
1534  {
1535  // give up
1537  error() << "member '" << component_name << "' not found in '"
1538  << to_string(type) << "'" << eom;
1539  throw 0;
1540  }
1541 
1542  // done!
1543  expr.swap(tmp);
1544  return;
1545  }
1546 
1547  expr.type()=component.type();
1548 
1549  if(op0.get_bool(ID_C_lvalue))
1550  expr.set(ID_C_lvalue, true);
1551 
1552  if(op0.type().get_bool(ID_C_constant) || type.get_bool(ID_C_constant))
1553  expr.type().set(ID_C_constant, true);
1554 
1555  // copy method identifier
1556  const irep_idt &identifier=component.get(ID_C_identifier);
1557 
1558  if(!identifier.empty())
1559  expr.set(ID_C_identifier, identifier);
1560 
1561  const irep_idt &access=component.get_access();
1562 
1563  if(access==ID_private)
1564  {
1566  error() << "member '" << component_name << "' is " << access << eom;
1567  throw 0;
1568  }
1569 }
1570 
1572 {
1573  exprt::operandst &operands=expr.operands();
1574 
1575  assert(operands.size()==3);
1576 
1577  // copy (save) original types
1578  const typet o_type0=operands[0].type();
1579  const typet o_type1=operands[1].type();
1580  const typet o_type2=operands[2].type();
1581 
1582  implicit_typecast_bool(operands[0]);
1583 
1584  if(o_type1.id() == ID_empty || o_type2.id() == ID_empty)
1585  {
1586  operands[1] = typecast_exprt::conditional_cast(operands[1], void_type());
1587  operands[2] = typecast_exprt::conditional_cast(operands[2], void_type());
1588  expr.type() = void_type();
1589  return;
1590  }
1591 
1592  if(operands[1].type().id()==ID_pointer &&
1593  operands[2].type().id()!=ID_pointer)
1594  implicit_typecast(operands[2], operands[1].type());
1595  else if(operands[2].type().id()==ID_pointer &&
1596  operands[1].type().id()!=ID_pointer)
1597  implicit_typecast(operands[1], operands[2].type());
1598 
1599  if(operands[1].type().id()==ID_pointer &&
1600  operands[2].type().id()==ID_pointer &&
1601  operands[1].type()!=operands[2].type())
1602  {
1603  exprt tmp1=simplify_expr(operands[1], *this);
1604  exprt tmp2=simplify_expr(operands[2], *this);
1605 
1606  // is one of them void * AND null? Convert that to the other.
1607  // (at least that's how GCC behaves)
1608  if(
1609  to_pointer_type(operands[1].type()).base_type().id() == ID_empty &&
1610  tmp1.is_constant() && is_null_pointer(to_constant_expr(tmp1)))
1611  {
1612  implicit_typecast(operands[1], operands[2].type());
1613  }
1614  else if(
1615  to_pointer_type(operands[2].type()).base_type().id() == ID_empty &&
1616  tmp2.is_constant() && is_null_pointer(to_constant_expr(tmp2)))
1617  {
1618  implicit_typecast(operands[2], operands[1].type());
1619  }
1620  else if(
1621  to_pointer_type(operands[1].type()).base_type().id() != ID_code ||
1622  to_pointer_type(operands[2].type()).base_type().id() != ID_code)
1623  {
1624  // Make it void *.
1625  // gcc and clang issue a warning for this.
1626  expr.type() = pointer_type(void_type());
1627  implicit_typecast(operands[1], expr.type());
1628  implicit_typecast(operands[2], expr.type());
1629  }
1630  else
1631  {
1632  // maybe functions without parameter lists
1633  const code_typet &c_type1 =
1634  to_code_type(to_pointer_type(operands[1].type()).base_type());
1635  const code_typet &c_type2 =
1636  to_code_type(to_pointer_type(operands[2].type()).base_type());
1637 
1638  if(c_type1.return_type()==c_type2.return_type())
1639  {
1640  if(c_type1.parameters().empty() && c_type1.has_ellipsis())
1641  implicit_typecast(operands[1], operands[2].type());
1642  else if(c_type2.parameters().empty() && c_type2.has_ellipsis())
1643  implicit_typecast(operands[2], operands[1].type());
1644  }
1645  }
1646  }
1647 
1648  if(operands[1].type().id()==ID_empty ||
1649  operands[2].type().id()==ID_empty)
1650  {
1651  expr.type()=void_type();
1652  return;
1653  }
1654 
1655  if(
1656  operands[1].type() != operands[2].type() ||
1657  operands[1].type().id() == ID_array)
1658  {
1659  implicit_typecast_arithmetic(operands[1], operands[2]);
1660  }
1661 
1662  if(operands[1].type() == operands[2].type())
1663  {
1664  expr.type()=operands[1].type();
1665 
1666  // GCC says: "A conditional expression is a valid lvalue
1667  // if its type is not void and the true and false branches
1668  // are both valid lvalues."
1669 
1670  if(operands[1].get_bool(ID_C_lvalue) &&
1671  operands[2].get_bool(ID_C_lvalue))
1672  expr.set(ID_C_lvalue, true);
1673 
1674  return;
1675  }
1676 
1678  error() << "operator ?: not defined for types '" << to_string(o_type1)
1679  << "' and '" << to_string(o_type2) << "'" << eom;
1680  throw 0;
1681 }
1682 
1684  side_effect_exprt &expr)
1685 {
1686  // x ? : y is almost the same as x ? x : y,
1687  // but not quite, as x is evaluated only once
1688 
1689  exprt::operandst &operands=expr.operands();
1690 
1691  if(operands.size()!=2)
1692  {
1694  error() << "gcc conditional_expr expects two operands" << eom;
1695  throw 0;
1696  }
1697 
1698  // use typechecking code for "if"
1699 
1700  if_exprt if_expr(operands[0], operands[0], operands[1]);
1701  if_expr.add_source_location()=expr.source_location();
1702 
1703  typecheck_expr_trinary(if_expr);
1704 
1705  // copy the result
1706  operands[0] = if_expr.true_case();
1707  operands[1] = if_expr.false_case();
1708  expr.type()=if_expr.type();
1709 }
1710 
1712 {
1713  exprt &op = to_unary_expr(expr).op();
1714 
1715  if(op.type().id()==ID_c_bit_field)
1716  {
1718  error() << "cannot take address of a bit field" << eom;
1719  throw 0;
1720  }
1721 
1722  if(op.type().id() == ID_bool)
1723  {
1725  error() << "cannot take address of a single bit" << eom;
1726  throw 0;
1727  }
1728 
1729  // special case: address of label
1730  if(op.id()==ID_label)
1731  {
1732  expr.type()=pointer_type(void_type());
1733 
1734  // remember the label
1735  labels_used[op.get(ID_identifier)]=op.source_location();
1736  return;
1737  }
1738 
1739  // special case: address of function designator
1740  // ANSI-C 99 section 6.3.2.1 paragraph 4
1741 
1742  if(
1743  op.id() == ID_address_of && op.get_bool(ID_C_implicit) &&
1744  to_address_of_expr(op).object().type().id() == ID_code)
1745  {
1746  // make the implicit address_of an explicit address_of
1747  exprt tmp;
1748  tmp.swap(op);
1749  tmp.set(ID_C_implicit, false);
1750  expr.swap(tmp);
1751  return;
1752  }
1753 
1754  if(op.id()==ID_struct ||
1755  op.id()==ID_union ||
1756  op.id()==ID_array ||
1757  op.id()==ID_string_constant)
1758  {
1759  // these are really objects
1760  }
1761  else if(op.get_bool(ID_C_lvalue))
1762  {
1763  // ok
1764  }
1765  else if(op.type().id()==ID_code)
1766  {
1767  // ok
1768  }
1769  else
1770  {
1772  error() << "address_of error: '" << to_string(op) << "' not an lvalue"
1773  << eom;
1774  throw 0;
1775  }
1776 
1777  expr.type()=pointer_type(op.type());
1778 }
1779 
1781 {
1782  exprt &op = to_unary_expr(expr).op();
1783 
1784  const typet op_type = op.type();
1785 
1786  if(op_type.id()==ID_array)
1787  {
1788  // *a is the same as a[0]
1789  expr.id(ID_index);
1790  expr.type() = to_array_type(op_type).element_type();
1792  assert(expr.operands().size()==2);
1793  }
1794  else if(op_type.id()==ID_pointer)
1795  {
1796  expr.type() = to_pointer_type(op_type).base_type();
1797 
1798  if(
1799  expr.type().id() == ID_empty &&
1801  {
1803  error() << "dereferencing void pointer" << eom;
1804  throw 0;
1805  }
1806  }
1807  else
1808  {
1810  error() << "operand of unary * '" << to_string(op)
1811  << "' is not a pointer, but got '" << to_string(op_type) << "'"
1812  << eom;
1813  throw 0;
1814  }
1815 
1816  expr.set(ID_C_lvalue, true);
1817 
1818  // if you dereference a pointer pointing to
1819  // a function, you get a pointer again
1820  // allowing ******...*p
1821 
1823 }
1824 
1826 {
1827  if(expr.type().id()==ID_code)
1828  {
1829  address_of_exprt tmp(expr, pointer_type(expr.type()));
1830  tmp.set(ID_C_implicit, true);
1831  tmp.add_source_location()=expr.source_location();
1832  expr=tmp;
1833  }
1834 }
1835 
1837 {
1838  const irep_idt &statement=expr.get_statement();
1839 
1840  if(statement==ID_preincrement ||
1841  statement==ID_predecrement ||
1842  statement==ID_postincrement ||
1843  statement==ID_postdecrement)
1844  {
1845  const exprt &op0 = to_unary_expr(expr).op();
1846  const typet &type0=op0.type();
1847 
1848  if(!op0.get_bool(ID_C_lvalue))
1849  {
1851  error() << "prefix operator error: '" << to_string(op0)
1852  << "' not an lvalue" << eom;
1853  throw 0;
1854  }
1855 
1856  if(type0.get_bool(ID_C_constant))
1857  {
1859  error() << "error: '" << to_string(op0) << "' is constant" << eom;
1860  throw 0;
1861  }
1862 
1863  if(type0.id() == ID_c_enum_tag)
1864  {
1865  const c_enum_typet &enum_type = follow_tag(to_c_enum_tag_type(type0));
1866  if(enum_type.is_incomplete())
1867  {
1869  error() << "operator '" << statement << "' given incomplete type '"
1870  << to_string(type0) << "'" << eom;
1871  throw 0;
1872  }
1873 
1874  // increment/decrement on underlying type
1875  to_unary_expr(expr).op() =
1876  typecast_exprt(op0, enum_type.underlying_type());
1877  expr.type() = enum_type.underlying_type();
1878  }
1879  else if(type0.id() == ID_c_bit_field)
1880  {
1881  // promote to underlying type
1882  typet underlying_type = to_c_bit_field_type(type0).underlying_type();
1883  to_unary_expr(expr).op() = typecast_exprt(op0, underlying_type);
1884  expr.type()=underlying_type;
1885  }
1886  else if(type0.id() == ID_bool || type0.id() == ID_c_bool)
1887  {
1889  expr.type() = op0.type();
1890  }
1891  else if(is_numeric_type(type0))
1892  {
1893  expr.type()=type0;
1894  }
1895  else if(type0.id() == ID_pointer)
1896  {
1897  expr.type()=type0;
1899  }
1900  else
1901  {
1903  error() << "operator '" << statement << "' not defined for type '"
1904  << to_string(type0) << "'" << eom;
1905  throw 0;
1906  }
1907  }
1908  else if(has_prefix(id2string(statement), "assign"))
1910  else if(statement==ID_function_call)
1913  else if(statement==ID_statement_expression)
1915  else if(statement==ID_gcc_conditional_expression)
1917  else
1918  {
1920  error() << "unknown side effect: " << statement << eom;
1921  throw 0;
1922  }
1923 }
1924 
1927 {
1928  INVARIANT(
1929  expr.function().id() == ID_symbol &&
1931  "typed_target",
1932  "expression must be a " CPROVER_PREFIX "typed_target function call");
1933 
1934  auto &f_op = to_symbol_expr(expr.function());
1935 
1936  if(expr.arguments().size() != 1)
1937  {
1939  "expected 1 argument for " CPROVER_PREFIX "typed_target, found " +
1940  std::to_string(expr.arguments().size()),
1941  expr.source_location()};
1942  }
1943 
1944  auto arg0 = expr.arguments().front();
1945  typecheck_expr(arg0);
1946  if(!is_assignable(arg0) || !arg0.get_bool(ID_C_lvalue))
1947  {
1949  "argument of " CPROVER_PREFIX "typed_target must be assignable",
1950  arg0.source_location()};
1951  }
1952 
1953  const auto &size = size_of_expr(arg0.type(), *this);
1954  if(!size.has_value())
1955  {
1957  "sizeof not defined for argument of " CPROVER_PREFIX
1958  "typed_target of type " +
1959  to_string(arg0.type()),
1960  arg0.source_location()};
1961  }
1962 
1963  // rewrite call to "assignable"
1964  f_op.set_identifier(CPROVER_PREFIX "assignable");
1965  exprt::operandst arguments;
1966  // pointer
1967  arguments.push_back(address_of_exprt(arg0));
1968  // size
1969  arguments.push_back(size.value());
1970  // is_pointer
1971  if(arg0.type().id() == ID_pointer)
1972  arguments.push_back(true_exprt());
1973  else
1974  arguments.push_back(false_exprt());
1975 
1976  expr.arguments().swap(arguments);
1978 }
1979 
1982 {
1983  if(expr.operands().size()!=2)
1984  {
1986  error() << "function_call side effect expects two operands" << eom;
1987  throw 0;
1988  }
1989 
1990  exprt &f_op=expr.function();
1991 
1992  // f_op is not yet typechecked, in contrast to the other arguments.
1993  // This is a big special case!
1994 
1995  if(f_op.id()==ID_symbol)
1996  {
1997  irep_idt identifier=to_symbol_expr(f_op).get_identifier();
1998 
1999  asm_label_mapt::const_iterator entry=
2000  asm_label_map.find(identifier);
2001  if(entry!=asm_label_map.end())
2002  identifier=entry->second;
2003 
2004  if(symbol_table.symbols.find(identifier)==symbol_table.symbols.end())
2005  {
2006  // This is an undeclared function.
2007 
2008  // Is it the polymorphic typed_target function ?
2009  if(identifier == CPROVER_PREFIX "typed_target")
2010  {
2012  }
2013  // Is this a builtin?
2014  else if(!builtin_factory(identifier, symbol_table, get_message_handler()))
2015  {
2016  // yes, it's a builtin
2017  }
2018  else if(
2019  identifier == "__noop" &&
2021  {
2022  // https://docs.microsoft.com/en-us/cpp/intrinsics/noop
2023  // typecheck and discard, just generating 0 instead
2024  for(auto &op : expr.arguments())
2025  typecheck_expr(op);
2026 
2028  expr.swap(result);
2029 
2030  return;
2031  }
2032  else if(
2033  identifier == "__builtin_shuffle" &&
2035  {
2037  expr.swap(result);
2038 
2039  return;
2040  }
2041  else if(
2042  identifier == "__builtin_shufflevector" &&
2044  {
2046  expr.swap(result);
2047 
2048  return;
2049  }
2050  else if(
2051  identifier == CPROVER_PREFIX "saturating_minus" ||
2052  identifier == CPROVER_PREFIX "saturating_plus")
2053  {
2055  expr.swap(result);
2056 
2057  return;
2058  }
2059  else if(
2060  auto gcc_polymorphic = typecheck_gcc_polymorphic_builtin(
2061  identifier, expr.arguments(), f_op.source_location()))
2062  {
2063  irep_idt identifier_with_type = gcc_polymorphic->get_identifier();
2064  auto &parameters = to_code_type(gcc_polymorphic->type()).parameters();
2065  INVARIANT(
2066  !parameters.empty(),
2067  "GCC polymorphic built-ins should have at least one parameter");
2068 
2069  // For all atomic/sync polymorphic built-ins (which are the ones handled
2070  // by typecheck_gcc_polymorphic_builtin), looking at the first parameter
2071  // suffices to distinguish different implementations.
2072  if(parameters.front().type().id() == ID_pointer)
2073  {
2074  identifier_with_type =
2075  id2string(identifier) + "_" +
2077  to_pointer_type(parameters.front().type()).base_type(), *this);
2078  }
2079  else
2080  {
2081  identifier_with_type =
2082  id2string(identifier) + "_" +
2083  type_to_partial_identifier(parameters.front().type(), *this);
2084  }
2085  gcc_polymorphic->set_identifier(identifier_with_type);
2086 
2087  if(!symbol_table.has_symbol(identifier_with_type))
2088  {
2089  for(std::size_t i = 0; i < parameters.size(); ++i)
2090  {
2091  const std::string base_name = "p_" + std::to_string(i);
2092 
2093  parameter_symbolt new_symbol;
2094 
2095  new_symbol.name =
2096  id2string(identifier_with_type) + "::" + base_name;
2097  new_symbol.base_name = base_name;
2098  new_symbol.location = f_op.source_location();
2099  new_symbol.type = parameters[i].type();
2100  new_symbol.is_parameter = true;
2101  new_symbol.is_lvalue = true;
2102  new_symbol.mode = ID_C;
2103 
2104  parameters[i].set_identifier(new_symbol.name);
2105  parameters[i].set_base_name(new_symbol.base_name);
2106 
2107  symbol_table.add(new_symbol);
2108  }
2109 
2110  symbolt new_symbol;
2111 
2112  new_symbol.name = identifier_with_type;
2113  new_symbol.base_name = identifier_with_type;
2114  new_symbol.location = f_op.source_location();
2115  new_symbol.type = gcc_polymorphic->type();
2116  new_symbol.mode = ID_C;
2117  code_blockt implementation =
2118  instantiate_gcc_polymorphic_builtin(identifier, *gcc_polymorphic);
2119  typet parent_return_type = return_type;
2120  return_type = to_code_type(gcc_polymorphic->type()).return_type();
2121  typecheck_code(implementation);
2122  return_type = parent_return_type;
2123  new_symbol.value = implementation;
2124 
2125  symbol_table.add(new_symbol);
2126  }
2127 
2128  f_op = std::move(*gcc_polymorphic);
2129  }
2130  else
2131  {
2132  // This is an undeclared function that's not a builtin.
2133  // Let's just add it.
2134  // We do a bit of return-type guessing, but just a bit.
2135  typet guessed_return_type = signed_int_type();
2136 
2137  // The following isn't really right and sound, but there
2138  // are too many idiots out there who use malloc and the like
2139  // without the right header file.
2140  if(identifier=="malloc" ||
2141  identifier=="realloc" ||
2142  identifier=="reallocf" ||
2143  identifier=="valloc")
2144  {
2145  guessed_return_type = pointer_type(void_type()); // void *
2146  }
2147 
2148  symbolt new_symbol;
2149 
2150  new_symbol.name=identifier;
2151  new_symbol.base_name=identifier;
2152  new_symbol.location=expr.source_location();
2153  new_symbol.type = code_typet({}, guessed_return_type);
2154  new_symbol.type.set(ID_C_incomplete, true);
2155 
2156  // TODO: should also guess some argument types
2157 
2158  symbolt *symbol_ptr;
2159  move_symbol(new_symbol, symbol_ptr);
2160 
2162  warning() << "function '" << identifier << "' is not declared" << eom;
2163  }
2164  }
2165  }
2166 
2167  // typecheck it now
2168  typecheck_expr(f_op);
2169 
2170  const typet f_op_type = f_op.type();
2171 
2172  if(f_op_type.id() == ID_mathematical_function)
2173  {
2174  const auto &mathematical_function_type =
2175  to_mathematical_function_type(f_op_type);
2176 
2177  // check number of arguments
2178  if(expr.arguments().size() != mathematical_function_type.domain().size())
2179  {
2181  error() << "expected " << mathematical_function_type.domain().size()
2182  << " arguments but got " << expr.arguments().size() << eom;
2183  throw 0;
2184  }
2185 
2186  // check the types of the arguments
2187  for(auto &p :
2188  make_range(expr.arguments()).zip(mathematical_function_type.domain()))
2189  {
2190  if(p.first.type() != p.second)
2191  {
2192  error().source_location = p.first.source_location();
2193  error() << "expected argument of type " << to_string(p.second)
2194  << " but got " << to_string(p.first.type()) << eom;
2195  throw 0;
2196  }
2197  }
2198 
2199  function_application_exprt function_application(f_op, expr.arguments());
2200 
2201  function_application.add_source_location() = expr.source_location();
2202 
2203  expr.swap(function_application);
2204  return;
2205  }
2206 
2207  if(f_op_type.id()!=ID_pointer)
2208  {
2210  error() << "expected function/function pointer as argument but got '"
2211  << to_string(f_op_type) << "'" << eom;
2212  throw 0;
2213  }
2214 
2215  // do implicit dereference
2216  if(f_op.id() == ID_address_of && f_op.get_bool(ID_C_implicit))
2217  {
2218  f_op = to_address_of_expr(f_op).object();
2219  }
2220  else
2221  {
2222  dereference_exprt tmp{f_op};
2223  tmp.set(ID_C_implicit, true);
2224  tmp.add_source_location()=f_op.source_location();
2225  f_op.swap(tmp);
2226  }
2227 
2228  if(f_op.type().id()!=ID_code)
2229  {
2231  error() << "expected code as argument" << eom;
2232  throw 0;
2233  }
2234 
2235  const code_typet &code_type=to_code_type(f_op.type());
2236 
2237  expr.type()=code_type.return_type();
2238 
2239  exprt tmp=do_special_functions(expr);
2240 
2241  if(tmp.is_not_nil())
2242  expr.swap(tmp);
2243  else
2245 }
2246 
2249 {
2250  const exprt &f_op=expr.function();
2251  const source_locationt &source_location=expr.source_location();
2252 
2253  // some built-in functions
2254  if(f_op.id()!=ID_symbol)
2255  return nil_exprt();
2256 
2257  const irep_idt &identifier=to_symbol_expr(f_op).get_identifier();
2258 
2259  if(identifier == CPROVER_PREFIX "is_fresh")
2260  {
2261  if(expr.arguments().size() != 2)
2262  {
2264  error() << CPROVER_PREFIX "is_fresh expects two operands; "
2265  << expr.arguments().size() << "provided." << eom;
2266  throw 0;
2267  }
2269  return nil_exprt();
2270  }
2271  else if(identifier == CPROVER_PREFIX "same_object")
2272  {
2273  if(expr.arguments().size()!=2)
2274  {
2276  error() << "same_object expects two operands" << eom;
2277  throw 0;
2278  }
2279 
2281 
2282  exprt same_object_expr=
2283  same_object(expr.arguments()[0], expr.arguments()[1]);
2284  same_object_expr.add_source_location()=source_location;
2285 
2286  return same_object_expr;
2287  }
2288  else if(identifier==CPROVER_PREFIX "get_must")
2289  {
2290  if(expr.arguments().size()!=2)
2291  {
2293  error() << "get_must expects two operands" << eom;
2294  throw 0;
2295  }
2296 
2298 
2299  binary_predicate_exprt get_must_expr(
2300  expr.arguments()[0], ID_get_must, expr.arguments()[1]);
2301  get_must_expr.add_source_location()=source_location;
2302 
2303  return std::move(get_must_expr);
2304  }
2305  else if(identifier==CPROVER_PREFIX "get_may")
2306  {
2307  if(expr.arguments().size()!=2)
2308  {
2310  error() << "get_may expects two operands" << eom;
2311  throw 0;
2312  }
2313 
2315 
2316  binary_predicate_exprt get_may_expr(
2317  expr.arguments()[0], ID_get_may, expr.arguments()[1]);
2318  get_may_expr.add_source_location()=source_location;
2319 
2320  return std::move(get_may_expr);
2321  }
2322  else if(identifier == CPROVER_PREFIX "is_invalid_pointer")
2323  {
2324  if(expr.arguments().size()!=1)
2325  {
2327  error() << "is_invalid_pointer expects one operand" << eom;
2328  throw 0;
2329  }
2330 
2332 
2333  exprt same_object_expr = is_invalid_pointer_exprt{expr.arguments().front()};
2334  same_object_expr.add_source_location()=source_location;
2335 
2336  return same_object_expr;
2337  }
2338  else if(identifier==CPROVER_PREFIX "buffer_size")
2339  {
2340  if(expr.arguments().size()!=1)
2341  {
2343  error() << "buffer_size expects one operand" << eom;
2344  throw 0;
2345  }
2346 
2348 
2349  exprt buffer_size_expr("buffer_size", size_type());
2350  buffer_size_expr.operands()=expr.arguments();
2351  buffer_size_expr.add_source_location()=source_location;
2352 
2353  return buffer_size_expr;
2354  }
2355  else if(identifier == CPROVER_PREFIX "is_list")
2356  {
2357  // experimental feature for CHC encodings -- do not use
2358  if(expr.arguments().size() != 1)
2359  {
2361  error() << "is_list expects one operand" << eom;
2362  throw 0;
2363  }
2364 
2366 
2367  if(
2368  expr.arguments()[0].type().id() != ID_pointer ||
2369  to_pointer_type(expr.arguments()[0].type()).base_type().id() !=
2370  ID_struct_tag)
2371  {
2372  error().source_location = expr.arguments()[0].source_location();
2373  error() << "is_list expects a struct-pointer operand" << eom;
2374  throw 0;
2375  }
2376 
2377  predicate_exprt is_list_expr("is_list");
2378  is_list_expr.operands() = expr.arguments();
2379  is_list_expr.add_source_location() = source_location;
2380 
2381  return std::move(is_list_expr);
2382  }
2383  else if(identifier == CPROVER_PREFIX "is_dll")
2384  {
2385  // experimental feature for CHC encodings -- do not use
2386  if(expr.arguments().size() != 1)
2387  {
2389  error() << "is_dll expects one operand" << eom;
2390  throw 0;
2391  }
2392 
2394 
2395  if(
2396  expr.arguments()[0].type().id() != ID_pointer ||
2397  to_pointer_type(expr.arguments()[0].type()).base_type().id() !=
2398  ID_struct_tag)
2399  {
2400  error().source_location = expr.arguments()[0].source_location();
2401  error() << "is_dll expects a struct-pointer operand" << eom;
2402  throw 0;
2403  }
2404 
2405  predicate_exprt is_dll_expr("is_dll");
2406  is_dll_expr.operands() = expr.arguments();
2407  is_dll_expr.add_source_location() = source_location;
2408 
2409  return std::move(is_dll_expr);
2410  }
2411  else if(identifier == CPROVER_PREFIX "is_cyclic_dll")
2412  {
2413  // experimental feature for CHC encodings -- do not use
2414  if(expr.arguments().size() != 1)
2415  {
2417  error() << "is_cyclic_dll expects one operand" << eom;
2418  throw 0;
2419  }
2420 
2422 
2423  if(
2424  expr.arguments()[0].type().id() != ID_pointer ||
2425  to_pointer_type(expr.arguments()[0].type()).base_type().id() !=
2426  ID_struct_tag)
2427  {
2428  error().source_location = expr.arguments()[0].source_location();
2429  error() << "is_cyclic_dll expects a struct-pointer operand" << eom;
2430  throw 0;
2431  }
2432 
2433  predicate_exprt is_cyclic_dll_expr("is_cyclic_dll");
2434  is_cyclic_dll_expr.operands() = expr.arguments();
2435  is_cyclic_dll_expr.add_source_location() = source_location;
2436 
2437  return std::move(is_cyclic_dll_expr);
2438  }
2439  else if(identifier == CPROVER_PREFIX "is_sentinel_dll")
2440  {
2441  // experimental feature for CHC encodings -- do not use
2442  if(expr.arguments().size() != 2 && expr.arguments().size() != 3)
2443  {
2445  error() << "is_sentinel_dll expects two or three operands" << eom;
2446  throw 0;
2447  }
2448 
2450 
2451  for(const auto &argument : expr.arguments())
2452  {
2453  if(
2454  argument.type().id() != ID_pointer ||
2455  to_pointer_type(argument.type()).base_type().id() != ID_struct_tag)
2456  {
2457  error().source_location = expr.arguments()[0].source_location();
2458  error() << "is_sentinel_dll_node expects struct-pointer operands"
2459  << eom;
2460  throw 0;
2461  }
2462  }
2463 
2464  predicate_exprt is_sentinel_dll_expr("is_sentinel_dll");
2465  is_sentinel_dll_expr.operands() = expr.arguments();
2466  is_sentinel_dll_expr.add_source_location() = source_location;
2467 
2468  return std::move(is_sentinel_dll_expr);
2469  }
2470  else if(identifier == CPROVER_PREFIX "is_cstring")
2471  {
2472  // experimental feature for CHC encodings -- do not use
2473  if(expr.arguments().size() != 1)
2474  {
2476  error() << "is_cstring expects one operand" << eom;
2477  throw 0;
2478  }
2479 
2481 
2482  if(expr.arguments()[0].type().id() != ID_pointer)
2483  {
2484  error().source_location = expr.arguments()[0].source_location();
2485  error() << "is_cstring expects a pointer operand" << eom;
2486  throw 0;
2487  }
2488 
2489  is_cstring_exprt is_cstring_expr(expr.arguments()[0]);
2490  is_cstring_expr.add_source_location() = source_location;
2491 
2492  return std::move(is_cstring_expr);
2493  }
2494  else if(identifier == CPROVER_PREFIX "cstrlen")
2495  {
2496  // experimental feature for CHC encodings -- do not use
2497  if(expr.arguments().size() != 1)
2498  {
2500  error() << "cstrlen expects one operand" << eom;
2501  throw 0;
2502  }
2503 
2505 
2506  if(expr.arguments()[0].type().id() != ID_pointer)
2507  {
2508  error().source_location = expr.arguments()[0].source_location();
2509  error() << "cstrlen expects a pointer operand" << eom;
2510  throw 0;
2511  }
2512 
2513  cstrlen_exprt cstrlen_expr(expr.arguments()[0], size_type());
2514  cstrlen_expr.add_source_location() = source_location;
2515 
2516  return std::move(cstrlen_expr);
2517  }
2518  else if(identifier==CPROVER_PREFIX "is_zero_string")
2519  {
2520  if(expr.arguments().size()!=1)
2521  {
2523  error() << "is_zero_string expects one operand" << eom;
2524  throw 0;
2525  }
2526 
2528 
2529  unary_exprt is_zero_string_expr(
2530  "is_zero_string", expr.arguments()[0], c_bool_type());
2531  is_zero_string_expr.set(ID_C_lvalue, true); // make it an lvalue
2532  is_zero_string_expr.add_source_location()=source_location;
2533 
2534  return std::move(is_zero_string_expr);
2535  }
2536  else if(identifier==CPROVER_PREFIX "zero_string_length")
2537  {
2538  if(expr.arguments().size()!=1)
2539  {
2541  error() << "zero_string_length expects one operand" << eom;
2542  throw 0;
2543  }
2544 
2546 
2547  exprt zero_string_length_expr("zero_string_length", size_type());
2548  zero_string_length_expr.operands()=expr.arguments();
2549  zero_string_length_expr.set(ID_C_lvalue, true); // make it an lvalue
2550  zero_string_length_expr.add_source_location()=source_location;
2551 
2552  return zero_string_length_expr;
2553  }
2554  else if(identifier==CPROVER_PREFIX "DYNAMIC_OBJECT")
2555  {
2556  if(expr.arguments().size()!=1)
2557  {
2559  error() << "dynamic_object expects one argument" << eom;
2560  throw 0;
2561  }
2562 
2564 
2565  exprt is_dynamic_object_expr = is_dynamic_object_exprt(expr.arguments()[0]);
2566  is_dynamic_object_expr.add_source_location() = source_location;
2567 
2568  return is_dynamic_object_expr;
2569  }
2570  else if(identifier == CPROVER_PREFIX "LIVE_OBJECT")
2571  {
2572  if(expr.arguments().size() != 1)
2573  {
2575  error() << "live_object expects one argument" << eom;
2576  throw 0;
2577  }
2578 
2580 
2581  exprt live_object_expr = live_object_exprt(expr.arguments()[0]);
2582  live_object_expr.add_source_location() = source_location;
2583 
2584  return live_object_expr;
2585  }
2586  else if(identifier == CPROVER_PREFIX "WRITEABLE_OBJECT")
2587  {
2588  if(expr.arguments().size() != 1)
2589  {
2591  error() << "writeable_object expects one argument" << eom;
2592  throw 0;
2593  }
2594 
2596 
2597  exprt writeable_object_expr = writeable_object_exprt(expr.arguments()[0]);
2598  writeable_object_expr.add_source_location() = source_location;
2599 
2600  return writeable_object_expr;
2601  }
2602  else if(identifier==CPROVER_PREFIX "POINTER_OFFSET")
2603  {
2604  if(expr.arguments().size()!=1)
2605  {
2607  error() << "pointer_offset expects one argument" << eom;
2608  throw 0;
2609  }
2610 
2612 
2613  exprt pointer_offset_expr=pointer_offset(expr.arguments().front());
2614  pointer_offset_expr.add_source_location()=source_location;
2615 
2616  return typecast_exprt::conditional_cast(pointer_offset_expr, expr.type());
2617  }
2618  else if(identifier == CPROVER_PREFIX "OBJECT_SIZE")
2619  {
2620  if(expr.arguments().size() != 1)
2621  {
2623  error() << "object_size expects one operand" << eom;
2624  throw 0;
2625  }
2626 
2628 
2629  object_size_exprt object_size_expr(expr.arguments()[0], size_type());
2630  object_size_expr.add_source_location() = source_location;
2631 
2632  return std::move(object_size_expr);
2633  }
2634  else if(identifier==CPROVER_PREFIX "POINTER_OBJECT")
2635  {
2636  if(expr.arguments().size()!=1)
2637  {
2639  error() << "pointer_object expects one argument" << eom;
2640  throw 0;
2641  }
2642 
2644 
2645  exprt pointer_object_expr = pointer_object(expr.arguments().front());
2646  pointer_object_expr.add_source_location() = source_location;
2647 
2648  return typecast_exprt::conditional_cast(pointer_object_expr, expr.type());
2649  }
2650  else if(identifier=="__builtin_bswap16" ||
2651  identifier=="__builtin_bswap32" ||
2652  identifier=="__builtin_bswap64")
2653  {
2654  if(expr.arguments().size()!=1)
2655  {
2657  error() << identifier << " expects one operand" << eom;
2658  throw 0;
2659  }
2660 
2662 
2663  // these are hard-wired to 8 bits according to the gcc manual
2664  bswap_exprt bswap_expr(expr.arguments().front(), 8, expr.type());
2665  bswap_expr.add_source_location()=source_location;
2666 
2667  return std::move(bswap_expr);
2668  }
2669  else if(
2670  identifier == "__builtin_rotateleft8" ||
2671  identifier == "__builtin_rotateleft16" ||
2672  identifier == "__builtin_rotateleft32" ||
2673  identifier == "__builtin_rotateleft64" ||
2674  identifier == "__builtin_rotateright8" ||
2675  identifier == "__builtin_rotateright16" ||
2676  identifier == "__builtin_rotateright32" ||
2677  identifier == "__builtin_rotateright64")
2678  {
2679  // clang only
2680  if(expr.arguments().size() != 2)
2681  {
2683  error() << identifier << " expects two operands" << eom;
2684  throw 0;
2685  }
2686 
2688 
2689  irep_idt id = (identifier == "__builtin_rotateleft8" ||
2690  identifier == "__builtin_rotateleft16" ||
2691  identifier == "__builtin_rotateleft32" ||
2692  identifier == "__builtin_rotateleft64")
2693  ? ID_rol
2694  : ID_ror;
2695 
2696  shift_exprt rotate_expr(expr.arguments()[0], id, expr.arguments()[1]);
2697  rotate_expr.add_source_location() = source_location;
2698 
2699  return std::move(rotate_expr);
2700  }
2701  else if(identifier=="__builtin_nontemporal_load")
2702  {
2703  if(expr.arguments().size()!=1)
2704  {
2706  error() << identifier << " expects one operand" << eom;
2707  throw 0;
2708  }
2709 
2711 
2712  // these return the subtype of the argument
2713  exprt &ptr_arg=expr.arguments().front();
2714 
2715  if(ptr_arg.type().id()!=ID_pointer)
2716  {
2718  error() << "__builtin_nontemporal_load takes pointer as argument" << eom;
2719  throw 0;
2720  }
2721 
2722  expr.type() = to_pointer_type(expr.arguments().front().type()).base_type();
2723 
2724  return expr;
2725  }
2726  else if(
2727  identifier == "__builtin_fpclassify" ||
2728  identifier == CPROVER_PREFIX "fpclassify")
2729  {
2730  if(expr.arguments().size() != 6)
2731  {
2733  error() << identifier << " expects six arguments" << eom;
2734  throw 0;
2735  }
2736 
2738 
2739  // This gets 5 integers followed by a float or double.
2740  // The five integers are the return values for the cases
2741  // FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL and FP_ZERO.
2742  // gcc expects this to be able to produce compile-time constants.
2743 
2744  const exprt &fp_value = expr.arguments()[5];
2745 
2746  if(fp_value.type().id() != ID_floatbv)
2747  {
2748  error().source_location = fp_value.source_location();
2749  error() << "non-floating-point argument for " << identifier << eom;
2750  throw 0;
2751  }
2752 
2753  const auto &floatbv_type = to_floatbv_type(fp_value.type());
2754 
2755  const exprt zero = ieee_floatt::zero(floatbv_type).to_expr();
2756 
2757  const auto &arguments = expr.arguments();
2758 
2759  return if_exprt(
2760  isnan_exprt(fp_value),
2761  arguments[0],
2762  if_exprt(
2763  isinf_exprt(fp_value),
2764  arguments[1],
2765  if_exprt(
2766  isnormal_exprt(fp_value),
2767  arguments[2],
2768  if_exprt(
2769  ieee_float_equal_exprt(fp_value, zero),
2770  arguments[4],
2771  arguments[3])))); // subnormal
2772  }
2773  else if(identifier==CPROVER_PREFIX "isnanf" ||
2774  identifier==CPROVER_PREFIX "isnand" ||
2775  identifier==CPROVER_PREFIX "isnanld" ||
2776  identifier=="__builtin_isnan")
2777  {
2778  if(expr.arguments().size()!=1)
2779  {
2781  error() << "isnan expects one operand" << eom;
2782  throw 0;
2783  }
2784 
2786 
2787  isnan_exprt isnan_expr(expr.arguments().front());
2788  isnan_expr.add_source_location()=source_location;
2789 
2790  return typecast_exprt::conditional_cast(isnan_expr, expr.type());
2791  }
2792  else if(identifier==CPROVER_PREFIX "isfinitef" ||
2793  identifier==CPROVER_PREFIX "isfinited" ||
2794  identifier==CPROVER_PREFIX "isfiniteld")
2795  {
2796  if(expr.arguments().size()!=1)
2797  {
2799  error() << "isfinite expects one operand" << eom;
2800  throw 0;
2801  }
2802 
2804 
2805  isfinite_exprt isfinite_expr(expr.arguments().front());
2806  isfinite_expr.add_source_location()=source_location;
2807 
2808  return typecast_exprt::conditional_cast(isfinite_expr, expr.type());
2809  }
2810  else if(identifier==CPROVER_PREFIX "inf" ||
2811  identifier=="__builtin_inf")
2812  {
2813  constant_exprt inf_expr=
2816  inf_expr.add_source_location()=source_location;
2817 
2818  return std::move(inf_expr);
2819  }
2820  else if(identifier==CPROVER_PREFIX "inff")
2821  {
2822  constant_exprt inff_expr=
2825  inff_expr.add_source_location()=source_location;
2826 
2827  return std::move(inff_expr);
2828  }
2829  else if(identifier==CPROVER_PREFIX "infl")
2830  {
2832  constant_exprt infl_expr=
2834  infl_expr.add_source_location()=source_location;
2835 
2836  return std::move(infl_expr);
2837  }
2838  else if(identifier==CPROVER_PREFIX "abs" ||
2839  identifier==CPROVER_PREFIX "labs" ||
2840  identifier==CPROVER_PREFIX "llabs" ||
2841  identifier==CPROVER_PREFIX "fabs" ||
2842  identifier==CPROVER_PREFIX "fabsf" ||
2843  identifier==CPROVER_PREFIX "fabsl")
2844  {
2845  if(expr.arguments().size()!=1)
2846  {
2848  error() << "abs-functions expect one operand" << eom;
2849  throw 0;
2850  }
2851 
2853 
2854  abs_exprt abs_expr(expr.arguments().front());
2855  abs_expr.add_source_location()=source_location;
2856 
2857  return std::move(abs_expr);
2858  }
2859  else if(
2860  identifier == CPROVER_PREFIX "fmod" ||
2861  identifier == CPROVER_PREFIX "fmodf" ||
2862  identifier == CPROVER_PREFIX "fmodl")
2863  {
2864  if(expr.arguments().size() != 2)
2865  {
2867  error() << "fmod-functions expect two operands" << eom;
2868  throw 0;
2869  }
2870 
2872 
2873  // Note that the semantics differ from the
2874  // "floating point remainder" operation as defined by IEEE.
2875  // Note that these do not take a rounding mode.
2876  binary_exprt fmod_expr(
2877  expr.arguments()[0], ID_floatbv_mod, expr.arguments()[1]);
2878 
2879  fmod_expr.add_source_location() = source_location;
2880 
2881  return std::move(fmod_expr);
2882  }
2883  else if(
2884  identifier == CPROVER_PREFIX "remainder" ||
2885  identifier == CPROVER_PREFIX "remainderf" ||
2886  identifier == CPROVER_PREFIX "remainderl")
2887  {
2888  if(expr.arguments().size() != 2)
2889  {
2891  error() << "remainder-functions expect two operands" << eom;
2892  throw 0;
2893  }
2894 
2896 
2897  // The semantics of these functions is meant to match the
2898  // "floating point remainder" operation as defined by IEEE.
2899  // Note that these do not take a rounding mode.
2900  binary_exprt floatbv_rem_expr(
2901  expr.arguments()[0], ID_floatbv_rem, expr.arguments()[1]);
2902 
2903  floatbv_rem_expr.add_source_location() = source_location;
2904 
2905  return std::move(floatbv_rem_expr);
2906  }
2907  else if(identifier==CPROVER_PREFIX "allocate")
2908  {
2909  if(expr.arguments().size()!=2)
2910  {
2912  error() << "allocate expects two operands" << eom;
2913  throw 0;
2914  }
2915 
2917 
2918  side_effect_exprt malloc_expr(ID_allocate, expr.type(), source_location);
2919  malloc_expr.operands()=expr.arguments();
2920 
2921  return std::move(malloc_expr);
2922  }
2923  else if(
2924  identifier == CPROVER_PREFIX "r_ok" ||
2925  identifier == CPROVER_PREFIX "w_ok" || identifier == CPROVER_PREFIX "rw_ok")
2926  {
2927  if(expr.arguments().size() != 1 && expr.arguments().size() != 2)
2928  {
2930  error() << identifier << " expects one or two operands" << eom;
2931  throw 0;
2932  }
2933 
2935 
2936  // the first argument must be a pointer
2937  const auto &pointer_expr = expr.arguments()[0];
2938  if(pointer_expr.type().id() != ID_pointer)
2939  {
2941  error() << identifier << " expects a pointer as first argument" << eom;
2942  throw 0;
2943  }
2944 
2945  // The second argument, when given, is a size_t.
2946  // When not given, use the pointer subtype.
2947  exprt size_expr;
2948 
2949  if(expr.arguments().size() == 2)
2950  {
2951  implicit_typecast(expr.arguments()[1], size_type());
2952  size_expr = expr.arguments()[1];
2953  }
2954  else
2955  {
2956  // Won't do void *
2957  const auto &subtype = to_pointer_type(pointer_expr.type()).base_type();
2958  if(subtype.id() == ID_empty)
2959  {
2961  error() << identifier << " expects a size when given a void pointer"
2962  << eom;
2963  throw 0;
2964  }
2965 
2966  auto size_expr_opt = size_of_expr(subtype, *this);
2967  if(!size_expr_opt.has_value())
2968  {
2970  error() << identifier << " was given object pointer without size"
2971  << eom;
2972  throw 0;
2973  }
2974 
2975  size_expr = std::move(size_expr_opt.value());
2976  }
2977 
2978  irep_idt id = identifier == CPROVER_PREFIX "r_ok"
2979  ? ID_r_ok
2980  : identifier == CPROVER_PREFIX "w_ok" ? ID_w_ok : ID_rw_ok;
2981 
2982  r_or_w_ok_exprt ok_expr(id, pointer_expr, size_expr);
2983  ok_expr.add_source_location() = source_location;
2984 
2985  return std::move(ok_expr);
2986  }
2987  else if(
2988  (identifier == CPROVER_PREFIX "old") ||
2989  (identifier == CPROVER_PREFIX "loop_entry"))
2990  {
2991  if(expr.arguments().size() != 1)
2992  {
2994  error() << identifier << " expects one operand" << eom;
2995  throw 0;
2996  }
2997 
2998  const auto &param_id = expr.arguments().front().id();
2999  if(!(param_id == ID_dereference || param_id == ID_member ||
3000  param_id == ID_symbol || param_id == ID_ptrmember ||
3001  param_id == ID_constant || param_id == ID_typecast ||
3002  param_id == ID_index))
3003  {
3005  error() << "Tracking history of " << param_id
3006  << " expressions is not supported yet." << eom;
3007  throw 0;
3008  }
3009 
3010  irep_idt id = identifier == CPROVER_PREFIX "old" ? ID_old : ID_loop_entry;
3011 
3012  history_exprt old_expr(expr.arguments()[0], id);
3013  old_expr.add_source_location() = source_location;
3014 
3015  return std::move(old_expr);
3016  }
3017  else if(identifier==CPROVER_PREFIX "isinff" ||
3018  identifier==CPROVER_PREFIX "isinfd" ||
3019  identifier==CPROVER_PREFIX "isinfld" ||
3020  identifier=="__builtin_isinf")
3021  {
3022  if(expr.arguments().size()!=1)
3023  {
3025  error() << identifier << " expects one operand" << eom;
3026  throw 0;
3027  }
3028 
3030 
3031  const exprt &fp_value = expr.arguments().front();
3032 
3033  if(fp_value.type().id() != ID_floatbv)
3034  {
3035  error().source_location = fp_value.source_location();
3036  error() << "non-floating-point argument for " << identifier << eom;
3037  throw 0;
3038  }
3039 
3040  isinf_exprt isinf_expr(expr.arguments().front());
3041  isinf_expr.add_source_location()=source_location;
3042 
3043  return typecast_exprt::conditional_cast(isinf_expr, expr.type());
3044  }
3045  else if(identifier == "__builtin_isinf_sign")
3046  {
3047  if(expr.arguments().size() != 1)
3048  {
3050  error() << identifier << " expects one operand" << eom;
3051  throw 0;
3052  }
3053 
3055 
3056  // returns 1 for +inf and -1 for -inf, and 0 otherwise
3057 
3058  const exprt &fp_value = expr.arguments().front();
3059 
3060  if(fp_value.type().id() != ID_floatbv)
3061  {
3062  error().source_location = fp_value.source_location();
3063  error() << "non-floating-point argument for " << identifier << eom;
3064  throw 0;
3065  }
3066 
3067  isinf_exprt isinf_expr(fp_value);
3068  isinf_expr.add_source_location() = source_location;
3069 
3070  return if_exprt(
3071  isinf_exprt(fp_value),
3072  if_exprt(
3073  sign_exprt(fp_value),
3074  from_integer(-1, expr.type()),
3075  from_integer(1, expr.type())),
3076  from_integer(0, expr.type()));
3077  }
3078  else if(identifier == CPROVER_PREFIX "isnormalf" ||
3079  identifier == CPROVER_PREFIX "isnormald" ||
3080  identifier == CPROVER_PREFIX "isnormalld" ||
3081  identifier == "__builtin_isnormal")
3082  {
3083  if(expr.arguments().size()!=1)
3084  {
3086  error() << identifier << " expects one operand" << eom;
3087  throw 0;
3088  }
3089 
3091 
3092  const exprt &fp_value = expr.arguments()[0];
3093 
3094  if(fp_value.type().id() != ID_floatbv)
3095  {
3096  error().source_location = fp_value.source_location();
3097  error() << "non-floating-point argument for " << identifier << eom;
3098  throw 0;
3099  }
3100 
3101  isnormal_exprt isnormal_expr(expr.arguments().front());
3102  isnormal_expr.add_source_location()=source_location;
3103 
3104  return typecast_exprt::conditional_cast(isnormal_expr, expr.type());
3105  }
3106  else if(identifier==CPROVER_PREFIX "signf" ||
3107  identifier==CPROVER_PREFIX "signd" ||
3108  identifier==CPROVER_PREFIX "signld" ||
3109  identifier=="__builtin_signbit" ||
3110  identifier=="__builtin_signbitf" ||
3111  identifier=="__builtin_signbitl")
3112  {
3113  if(expr.arguments().size()!=1)
3114  {
3116  error() << identifier << " expects one operand" << eom;
3117  throw 0;
3118  }
3119 
3121 
3122  sign_exprt sign_expr(expr.arguments().front());
3123  sign_expr.add_source_location()=source_location;
3124 
3125  return typecast_exprt::conditional_cast(sign_expr, expr.type());
3126  }
3127  else if(identifier=="__builtin_popcount" ||
3128  identifier=="__builtin_popcountl" ||
3129  identifier=="__builtin_popcountll" ||
3130  identifier=="__popcnt16" ||
3131  identifier=="__popcnt" ||
3132  identifier=="__popcnt64")
3133  {
3134  if(expr.arguments().size()!=1)
3135  {
3137  error() << identifier << " expects one operand" << eom;
3138  throw 0;
3139  }
3140 
3142 
3143  popcount_exprt popcount_expr(expr.arguments().front(), expr.type());
3144  popcount_expr.add_source_location()=source_location;
3145 
3146  return std::move(popcount_expr);
3147  }
3148  else if(
3149  identifier == "__builtin_clz" || identifier == "__builtin_clzl" ||
3150  identifier == "__builtin_clzll" || identifier == "__lzcnt16" ||
3151  identifier == "__lzcnt" || identifier == "__lzcnt64")
3152  {
3153  if(expr.arguments().size() != 1)
3154  {
3156  error() << identifier << " expects one operand" << eom;
3157  throw 0;
3158  }
3159 
3161 
3162  count_leading_zeros_exprt clz{expr.arguments().front(),
3163  has_prefix(id2string(identifier), "__lzcnt"),
3164  expr.type()};
3165  clz.add_source_location() = source_location;
3166 
3167  return std::move(clz);
3168  }
3169  else if(
3170  identifier == "__builtin_ctz" || identifier == "__builtin_ctzl" ||
3171  identifier == "__builtin_ctzll")
3172  {
3173  if(expr.arguments().size() != 1)
3174  {
3176  error() << identifier << " expects one operand" << eom;
3177  throw 0;
3178  }
3179 
3181 
3183  expr.arguments().front(), false, expr.type()};
3184  ctz.add_source_location() = source_location;
3185 
3186  return std::move(ctz);
3187  }
3188  else if(
3189  identifier == "__builtin_ffs" || identifier == "__builtin_ffsl" ||
3190  identifier == "__builtin_ffsll")
3191  {
3192  if(expr.arguments().size() != 1)
3193  {
3195  error() << identifier << " expects one operand" << eom;
3196  throw 0;
3197  }
3198 
3200 
3201  find_first_set_exprt ffs{expr.arguments().front(), expr.type()};
3202  ffs.add_source_location() = source_location;
3203 
3204  return std::move(ffs);
3205  }
3206  else if(identifier==CPROVER_PREFIX "equal")
3207  {
3208  if(expr.arguments().size()!=2)
3209  {
3211  error() << "equal expects two operands" << eom;
3212  throw 0;
3213  }
3214 
3216 
3217  equal_exprt equality_expr(
3218  expr.arguments().front(), expr.arguments().back());
3219  equality_expr.add_source_location()=source_location;
3220 
3221  if(equality_expr.lhs().type() != equality_expr.rhs().type())
3222  {
3224  error() << "equal expects two operands of same type" << eom;
3225  throw 0;
3226  }
3227 
3228  return std::move(equality_expr);
3229  }
3230  else if(identifier=="__builtin_expect")
3231  {
3232  // This is a gcc extension to provide branch prediction.
3233  // We compile it away, but adding some IR instruction for
3234  // this would clearly be an option. Note that the type
3235  // of the return value is wired to "long", i.e.,
3236  // this may trigger a type conversion due to the signature
3237  // of this function.
3238  if(expr.arguments().size()!=2)
3239  {
3241  error() << "__builtin_expect expects two arguments" << eom;
3242  throw 0;
3243  }
3244 
3246 
3247  return typecast_exprt(expr.arguments()[0], expr.type());
3248  }
3249  else if(identifier=="__builtin_object_size")
3250  {
3251  // this is a gcc extension to provide information about
3252  // object sizes at compile time
3253  // http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
3254 
3255  if(expr.arguments().size()!=2)
3256  {
3258  error() << "__builtin_object_size expects two arguments" << eom;
3259  throw 0;
3260  }
3261 
3263 
3264  make_constant(expr.arguments()[1]);
3265 
3266  mp_integer arg1;
3267 
3268  if(expr.arguments()[1].is_true())
3269  arg1=1;
3270  else if(expr.arguments()[1].is_false())
3271  arg1=0;
3272  else if(to_integer(to_constant_expr(expr.arguments()[1]), arg1))
3273  {
3275  error() << "__builtin_object_size expects constant as second argument, "
3276  << "but got " << to_string(expr.arguments()[1]) << eom;
3277  throw 0;
3278  }
3279 
3280  exprt tmp;
3281 
3282  // the following means "don't know"
3283  if(arg1==0 || arg1==1)
3284  {
3285  tmp=from_integer(-1, size_type());
3286  tmp.add_source_location()=f_op.source_location();
3287  }
3288  else
3289  {
3290  tmp=from_integer(0, size_type());
3291  tmp.add_source_location()=f_op.source_location();
3292  }
3293 
3294  return tmp;
3295  }
3296  else if(identifier=="__builtin_choose_expr")
3297  {
3298  // this is a gcc extension similar to ?:
3299  if(expr.arguments().size()!=3)
3300  {
3302  error() << "__builtin_choose_expr expects three arguments" << eom;
3303  throw 0;
3304  }
3305 
3307 
3308  exprt arg0 =
3310  make_constant(arg0);
3311 
3312  if(arg0.is_true())
3313  return expr.arguments()[1];
3314  else
3315  return expr.arguments()[2];
3316  }
3317  else if(identifier=="__builtin_constant_p")
3318  {
3319  // this is a gcc extension to tell whether the argument
3320  // is known to be a compile-time constant
3321  if(expr.arguments().size()!=1)
3322  {
3324  error() << "__builtin_constant_p expects one argument" << eom;
3325  throw 0;
3326  }
3327 
3328  // do not typecheck the argument - it is never evaluated, and thus side
3329  // effects must not show up either
3330 
3331  // try to produce constant
3332  exprt tmp1=expr.arguments().front();
3333  simplify(tmp1, *this);
3334 
3335  bool is_constant=false;
3336 
3337  // Need to do some special treatment for string literals,
3338  // which are (void *)&("lit"[0])
3339  if(
3340  tmp1.id() == ID_typecast &&
3341  to_typecast_expr(tmp1).op().id() == ID_address_of &&
3342  to_address_of_expr(to_typecast_expr(tmp1).op()).object().id() ==
3343  ID_index &&
3344  to_index_expr(to_address_of_expr(to_typecast_expr(tmp1).op()).object())
3345  .array()
3346  .id() == ID_string_constant)
3347  {
3348  is_constant=true;
3349  }
3350  else
3351  is_constant=tmp1.is_constant();
3352 
3353  exprt tmp2=from_integer(is_constant, expr.type());
3354  tmp2.add_source_location()=source_location;
3355 
3356  return tmp2;
3357  }
3358  else if(identifier=="__builtin_classify_type")
3359  {
3360  // This is a gcc/clang extension that produces an integer
3361  // constant for the type of the argument expression.
3362  if(expr.arguments().size()!=1)
3363  {
3365  error() << "__builtin_classify_type expects one argument" << eom;
3366  throw 0;
3367  }
3368 
3370 
3371  exprt object=expr.arguments()[0];
3372 
3373  // The value doesn't matter at all, we only care about the type.
3374  // Need to sync with typeclass.h.
3375  typet type = follow(object.type());
3376 
3377  // use underlying type for bit fields
3378  if(type.id() == ID_c_bit_field)
3379  type = to_c_bit_field_type(type).underlying_type();
3380 
3381  unsigned type_number;
3382 
3383  if(type.id() == ID_bool || type.id() == ID_c_bool)
3384  {
3385  // clang returns 4 for _Bool, gcc treats these as 'int'.
3386  type_number =
3388  }
3389  else
3390  {
3391  type_number =
3392  type.id() == ID_empty
3393  ? 0u
3394  : (type.id() == ID_bool || type.id() == ID_c_bool)
3395  ? 4u
3396  : (type.id() == ID_pointer || type.id() == ID_array)
3397  ? 5u
3398  : type.id() == ID_floatbv
3399  ? 8u
3400  : (type.id() == ID_complex &&
3401  to_complex_type(type).subtype().id() == ID_floatbv)
3402  ? 9u
3403  : type.id() == ID_struct
3404  ? 12u
3405  : type.id() == ID_union
3406  ? 13u
3407  : 1u; // int, short, char, enum_tag
3408  }
3409 
3410  exprt tmp=from_integer(type_number, expr.type());
3411  tmp.add_source_location()=source_location;
3412 
3413  return tmp;
3414  }
3415  else if(
3416  identifier == CPROVER_PREFIX "overflow_minus" ||
3417  identifier == CPROVER_PREFIX "overflow_mult" ||
3418  identifier == CPROVER_PREFIX "overflow_plus" ||
3419  identifier == CPROVER_PREFIX "overflow_shl")
3420  {
3421  exprt overflow{identifier, typet{}, exprt::operandst{expr.arguments()}};
3422  overflow.add_source_location() = f_op.source_location();
3423 
3424  if(identifier == CPROVER_PREFIX "overflow_minus")
3425  {
3426  overflow.id(ID_minus);
3428  }
3429  else if(identifier == CPROVER_PREFIX "overflow_mult")
3430  {
3431  overflow.id(ID_mult);
3433  }
3434  else if(identifier == CPROVER_PREFIX "overflow_plus")
3435  {
3436  overflow.id(ID_plus);
3438  }
3439  else if(identifier == CPROVER_PREFIX "overflow_shl")
3440  {
3441  overflow.id(ID_shl);
3443  }
3444 
3446  overflow.operands()[0], overflow.id(), overflow.operands()[1]};
3447  of.add_source_location() = overflow.source_location();
3448  return std::move(of);
3449  }
3450  else if(identifier == CPROVER_PREFIX "overflow_unary_minus")
3451  {
3452  exprt tmp{ID_unary_minus, typet{}, exprt::operandst{expr.arguments()}};
3453  tmp.add_source_location() = f_op.source_location();
3454 
3456 
3457  unary_minus_overflow_exprt overflow{tmp.operands().front()};
3458  overflow.add_source_location() = tmp.source_location();
3459  return std::move(overflow);
3460  }
3461  else if(identifier == CPROVER_PREFIX "enum_is_in_range")
3462  {
3463  // Check correct number of arguments
3464  if(expr.arguments().size() != 1)
3465  {
3466  std::ostringstream error_message;
3467  error_message << identifier << " takes exactly 1 argument, but "
3468  << expr.arguments().size() << " were provided";
3470  error_message.str(), expr.source_location()};
3471  }
3472  auto arg1 = expr.arguments()[0];
3473  typecheck_expr(arg1);
3474  if(!can_cast_type<c_enum_tag_typet>(arg1.type()))
3475  {
3476  // Can't enum range check a non-enum
3477  std::ostringstream error_message;
3478  error_message << identifier << " expects enum, but ("
3479  << expr2c(arg1, *this) << ") has type `"
3480  << type2c(arg1.type(), *this) << '`';
3482  error_message.str(), expr.source_location()};
3483  }
3484  else
3485  {
3486  return expr;
3487  }
3488  }
3489  else if(
3490  identifier == "__builtin_add_overflow" ||
3491  identifier == "__builtin_sadd_overflow" ||
3492  identifier == "__builtin_saddl_overflow" ||
3493  identifier == "__builtin_saddll_overflow" ||
3494  identifier == "__builtin_uadd_overflow" ||
3495  identifier == "__builtin_uaddl_overflow" ||
3496  identifier == "__builtin_uaddll_overflow" ||
3497  identifier == "__builtin_add_overflow_p")
3498  {
3499  return typecheck_builtin_overflow(expr, ID_plus);
3500  }
3501  else if(
3502  identifier == "__builtin_sub_overflow" ||
3503  identifier == "__builtin_ssub_overflow" ||
3504  identifier == "__builtin_ssubl_overflow" ||
3505  identifier == "__builtin_ssubll_overflow" ||
3506  identifier == "__builtin_usub_overflow" ||
3507  identifier == "__builtin_usubl_overflow" ||
3508  identifier == "__builtin_usubll_overflow" ||
3509  identifier == "__builtin_sub_overflow_p")
3510  {
3511  return typecheck_builtin_overflow(expr, ID_minus);
3512  }
3513  else if(
3514  identifier == "__builtin_mul_overflow" ||
3515  identifier == "__builtin_smul_overflow" ||
3516  identifier == "__builtin_smull_overflow" ||
3517  identifier == "__builtin_smulll_overflow" ||
3518  identifier == "__builtin_umul_overflow" ||
3519  identifier == "__builtin_umull_overflow" ||
3520  identifier == "__builtin_umulll_overflow" ||
3521  identifier == "__builtin_mul_overflow_p")
3522  {
3523  return typecheck_builtin_overflow(expr, ID_mult);
3524  }
3525  else if(
3526  identifier == "__builtin_bitreverse8" ||
3527  identifier == "__builtin_bitreverse16" ||
3528  identifier == "__builtin_bitreverse32" ||
3529  identifier == "__builtin_bitreverse64")
3530  {
3531  // clang only
3532  if(expr.arguments().size() != 1)
3533  {
3534  std::ostringstream error_message;
3535  error_message << "error: " << identifier << " expects one operand";
3537  error_message.str(), expr.source_location()};
3538  }
3539 
3541 
3542  bitreverse_exprt bitreverse{expr.arguments()[0]};
3543  bitreverse.add_source_location() = source_location;
3544 
3545  return std::move(bitreverse);
3546  }
3547  else
3548  return nil_exprt();
3549  // NOLINTNEXTLINE(readability/fn_size)
3550 }
3551 
3554  const irep_idt &arith_op)
3555 {
3556  const irep_idt &identifier = to_symbol_expr(expr.function()).get_identifier();
3557 
3558  // check function signature
3559  if(expr.arguments().size() != 3)
3560  {
3561  std::ostringstream error_message;
3562  error_message << identifier << " takes exactly 3 arguments, but "
3563  << expr.arguments().size() << " were provided";
3565  error_message.str(), expr.source_location()};
3566  }
3567 
3569 
3570  auto lhs = expr.arguments()[0];
3571  auto rhs = expr.arguments()[1];
3572  auto result = expr.arguments()[2];
3573 
3574  const bool is__p_variant = has_suffix(id2string(identifier), "_p");
3575 
3576  {
3577  auto const raise_wrong_argument_error =
3578  [this, identifier](
3579  const exprt &wrong_argument, std::size_t argument_number, bool _p) {
3580  std::ostringstream error_message;
3581  error_message << "error: " << identifier << " has signature "
3582  << identifier << "(integral, integral, integral"
3583  << (_p ? "" : "*") << "), "
3584  << "but argument " << argument_number << " ("
3585  << expr2c(wrong_argument, *this) << ") has type `"
3586  << type2c(wrong_argument.type(), *this) << '`';
3588  error_message.str(), wrong_argument.source_location()};
3589  };
3590  for(int arg_index = 0; arg_index <= (!is__p_variant ? 1 : 2); ++arg_index)
3591  {
3592  auto const &argument = expr.arguments()[arg_index];
3593 
3594  if(!is_signed_or_unsigned_bitvector(argument.type()))
3595  {
3596  raise_wrong_argument_error(argument, arg_index + 1, is__p_variant);
3597  }
3598  }
3599  if(
3600  !is__p_variant && (result.type().id() != ID_pointer ||
3602  to_pointer_type(result.type()).base_type())))
3603  {
3604  raise_wrong_argument_error(result, 3, is__p_variant);
3605  }
3606  }
3607 
3608  return side_effect_expr_overflowt{arith_op,
3609  std::move(lhs),
3610  std::move(rhs),
3611  std::move(result),
3612  expr.source_location()};
3613 }
3614 
3616  const side_effect_expr_function_callt &expr)
3617 {
3618  const irep_idt &identifier = to_symbol_expr(expr.function()).get_identifier();
3619 
3620  // check function signature
3621  if(expr.arguments().size() != 2)
3622  {
3623  std::ostringstream error_message;
3624  error_message << "error: " << identifier
3625  << " takes exactly two arguments, but "
3626  << expr.arguments().size() << " were provided";
3628  error_message.str(), expr.source_location()};
3629  }
3630 
3631  exprt result;
3632  if(identifier == CPROVER_PREFIX "saturating_minus")
3633  result = saturating_minus_exprt{expr.arguments()[0], expr.arguments()[1]};
3634  else if(identifier == CPROVER_PREFIX "saturating_plus")
3635  result = saturating_plus_exprt{expr.arguments()[0], expr.arguments()[1]};
3636  else
3637  UNREACHABLE;
3638 
3640  result.add_source_location() = expr.source_location();
3641 
3642  return result;
3643 }
3644 
3649 {
3650  const exprt &f_op=expr.function();
3651  const code_typet &code_type=to_code_type(f_op.type());
3652  exprt::operandst &arguments=expr.arguments();
3653  const code_typet::parameterst &parameter_types=
3654  code_type.parameters();
3655 
3656  // no. of arguments test
3657 
3658  if(code_type.get_bool(ID_C_incomplete))
3659  {
3660  // can't check
3661  }
3662  else if(code_type.is_KnR())
3663  {
3664  // We are generous on KnR; any number is ok.
3665  // We will in missing ones with "NIL".
3666 
3667  while(parameter_types.size()>arguments.size())
3668  arguments.push_back(nil_exprt());
3669  }
3670  else if(code_type.has_ellipsis())
3671  {
3672  if(parameter_types.size()>arguments.size())
3673  {
3675  error() << "not enough function arguments" << eom;
3676  throw 0;
3677  }
3678  }
3679  else if(parameter_types.size()!=arguments.size())
3680  {
3682  error() << "wrong number of function arguments: "
3683  << "expected " << parameter_types.size()
3684  << ", but got " << arguments.size() << eom;
3685  throw 0;
3686  }
3687 
3688  for(std::size_t i=0; i<arguments.size(); i++)
3689  {
3690  exprt &op=arguments[i];
3691 
3692  if(op.is_nil())
3693  {
3694  // ignore
3695  }
3696  else if(i<parameter_types.size())
3697  {
3698  const code_typet::parametert &parameter_type=
3699  parameter_types[i];
3700 
3701  const typet &op_type=parameter_type.type();
3702 
3703  if(op_type.id()==ID_bool &&
3704  op.id()==ID_side_effect &&
3705  op.get(ID_statement)==ID_assign &&
3706  op.type().id()!=ID_bool)
3707  {
3709  warning() << "assignment where Boolean argument is expected" << eom;
3710  }
3711 
3712  implicit_typecast(op, op_type);
3713  }
3714  else
3715  {
3716  // don't know type, just do standard conversion
3717 
3718  if(op.type().id() == ID_array)
3719  {
3720  auto dest_type = pointer_type(void_type());
3721  dest_type.base_type().set(ID_C_constant, true);
3722  implicit_typecast(op, dest_type);
3723  }
3724  }
3725  }
3726 }
3727 
3729 {
3730  // nothing to do
3731 }
3732 
3734 {
3735  exprt &operand = to_unary_expr(expr).op();
3736 
3737  const typet &o_type = operand.type();
3738 
3739  if(o_type.id()==ID_vector)
3740  {
3741  if(is_number(to_vector_type(o_type).element_type()))
3742  {
3743  // Vector arithmetic.
3744  expr.type()=operand.type();
3745  return;
3746  }
3747  }
3748 
3750 
3751  if(is_number(operand.type()))
3752  {
3753  expr.type()=operand.type();
3754  return;
3755  }
3756 
3758  error() << "operator '" << expr.id() << "' not defined for type '"
3759  << to_string(operand.type()) << "'" << eom;
3760  throw 0;
3761 }
3762 
3764 {
3766 
3767  // This is not quite accurate: the standard says the result
3768  // should be of type 'int'.
3769  // We do 'bool' anyway to get more compact formulae. Eventually,
3770  // this should be achieved by means of simplification, and not
3771  // in the frontend.
3772  expr.type()=bool_typet();
3773 }
3774 
3776  const vector_typet &type0,
3777  const vector_typet &type1)
3778 {
3779  // This is relatively restrictive!
3780 
3781  // compare dimension
3782  const auto s0 = numeric_cast<mp_integer>(type0.size());
3783  const auto s1 = numeric_cast<mp_integer>(type1.size());
3784  if(!s0.has_value())
3785  return false;
3786  if(!s1.has_value())
3787  return false;
3788  if(*s0 != *s1)
3789  return false;
3790 
3791  // compare subtype
3792  if(
3793  (type0.element_type().id() == ID_signedbv ||
3794  type0.element_type().id() == ID_unsignedbv) &&
3795  (type1.element_type().id() == ID_signedbv ||
3796  type1.element_type().id() == ID_unsignedbv) &&
3799  return true;
3800 
3801  return type0.element_type() == type1.element_type();
3802 }
3803 
3805 {
3806  auto &binary_expr = to_binary_expr(expr);
3807  exprt &op0 = binary_expr.op0();
3808  exprt &op1 = binary_expr.op1();
3809 
3810  const typet o_type0 = op0.type();
3811  const typet o_type1 = op1.type();
3812 
3813  if(o_type0.id()==ID_vector &&
3814  o_type1.id()==ID_vector)
3815  {
3816  if(
3818  to_vector_type(o_type0), to_vector_type(o_type1)) &&
3819  is_number(to_vector_type(o_type0).element_type()))
3820  {
3821  // Vector arithmetic has fairly strict typing rules, no promotion
3822  op1 = typecast_exprt::conditional_cast(op1, op0.type());
3823  expr.type()=op0.type();
3824  return;
3825  }
3826  }
3827  else if(
3828  o_type0.id() == ID_vector && o_type1.id() != ID_vector &&
3829  is_number(o_type1))
3830  {
3831  // convert op1 to the vector type
3832  op1 = typecast_exprt(op1, o_type0);
3833  expr.type() = o_type0;
3834  return;
3835  }
3836  else if(
3837  o_type0.id() != ID_vector && o_type1.id() == ID_vector &&
3838  is_number(o_type0))
3839  {
3840  // convert op0 to the vector type
3841  op0 = typecast_exprt(op0, o_type1);
3842  expr.type() = o_type1;
3843  return;
3844  }
3845 
3846  if(expr.id() == ID_saturating_minus || expr.id() == ID_saturating_plus)
3847  {
3848  implicit_typecast(op1, o_type0);
3849  }
3850  else
3851  {
3852  // promote!
3853  implicit_typecast_arithmetic(op0, op1);
3854  }
3855 
3856  const typet &type0 = op0.type();
3857  const typet &type1 = op1.type();
3858 
3859  if(expr.id()==ID_plus || expr.id()==ID_minus ||
3860  expr.id()==ID_mult || expr.id()==ID_div)
3861  {
3862  if(type0.id()==ID_pointer || type1.id()==ID_pointer)
3863  {
3865  return;
3866  }
3867  else if(type0==type1)
3868  {
3869  if(is_number(type0))
3870  {
3871  expr.type()=type0;
3872  return;
3873  }
3874  }
3875  }
3876  else if(expr.id()==ID_mod)
3877  {
3878  if(type0==type1)
3879  {
3880  if(type0.id()==ID_signedbv || type0.id()==ID_unsignedbv)
3881  {
3882  expr.type()=type0;
3883  return;
3884  }
3885  }
3886  }
3887  else if(
3888  expr.id() == ID_bitand || expr.id() == ID_bitnand ||
3889  expr.id() == ID_bitxor || expr.id() == ID_bitor)
3890  {
3891  if(type0==type1)
3892  {
3893  if(is_number(type0))
3894  {
3895  expr.type()=type0;
3896  return;
3897  }
3898  else if(type0.id()==ID_bool)
3899  {
3900  if(expr.id()==ID_bitand)
3901  expr.id(ID_and);
3902  else if(expr.id() == ID_bitnand)
3903  expr.id(ID_nand);
3904  else if(expr.id()==ID_bitor)
3905  expr.id(ID_or);
3906  else if(expr.id()==ID_bitxor)
3907  expr.id(ID_xor);
3908  else
3909  UNREACHABLE;
3910  expr.type()=type0;
3911  return;
3912  }
3913  }
3914  }
3915  else if(expr.id() == ID_saturating_minus || expr.id() == ID_saturating_plus)
3916  {
3917  if(
3918  type0 == type1 &&
3919  (type0.id() == ID_signedbv || type0.id() == ID_unsignedbv))
3920  {
3921  expr.type() = type0;
3922  return;
3923  }
3924  }
3925 
3927  error() << "operator '" << expr.id() << "' not defined for types '"
3928  << to_string(o_type0) << "' and '" << to_string(o_type1) << "'"
3929  << eom;
3930  throw 0;
3931 }
3932 
3934 {
3935  assert(expr.id()==ID_shl || expr.id()==ID_shr);
3936 
3937  exprt &op0=expr.op0();
3938  exprt &op1=expr.op1();
3939 
3940  const typet o_type0 = op0.type();
3941  const typet o_type1 = op1.type();
3942 
3943  if(o_type0.id()==ID_vector &&
3944  o_type1.id()==ID_vector)
3945  {
3946  if(
3947  to_vector_type(o_type0).element_type() ==
3948  to_vector_type(o_type1).element_type() &&
3949  is_number(to_vector_type(o_type0).element_type()))
3950  {
3951  // {a0, a1, ..., an} >> {b0, b1, ..., bn} ==
3952  // {a0 >> b0, a1 >> b1, ..., an >> bn}
3953  // Fairly strict typing rules, no promotion
3954  expr.type()=op0.type();
3955  return;
3956  }
3957  }
3958 
3959  if(
3960  o_type0.id() == ID_vector &&
3961  is_number(to_vector_type(o_type0).element_type()) && is_number(o_type1))
3962  {
3963  // {a0, a1, ..., an} >> b == {a0 >> b, a1 >> b, ..., an >> b}
3964  op1 = typecast_exprt(op1, o_type0);
3965  expr.type()=op0.type();
3966  return;
3967  }
3968 
3969  // must do the promotions _separately_!
3972 
3973  if(is_number(op0.type()) &&
3974  is_number(op1.type()))
3975  {
3976  expr.type()=op0.type();
3977 
3978  if(expr.id()==ID_shr) // shifting operation depends on types
3979  {
3980  const typet &op0_type = op0.type();
3981 
3982  if(op0_type.id()==ID_unsignedbv)
3983  {
3984  expr.id(ID_lshr);
3985  return;
3986  }
3987  else if(op0_type.id()==ID_signedbv)
3988  {
3989  expr.id(ID_ashr);
3990  return;
3991  }
3992  }
3993 
3994  return;
3995  }
3996 
3998  error() << "operator '" << expr.id() << "' not defined for types '"
3999  << to_string(o_type0) << "' and '" << to_string(o_type1) << "'"
4000  << eom;
4001  throw 0;
4002 }
4003 
4005 {
4006  const typet &type=expr.type();
4007  PRECONDITION(type.id() == ID_pointer);
4008 
4009  const typet &base_type = to_pointer_type(type).base_type();
4010 
4011  if(
4012  base_type.id() == ID_struct_tag &&
4013  follow_tag(to_struct_tag_type(base_type)).is_incomplete())
4014  {
4016  error() << "pointer arithmetic with unknown object size" << eom;
4017  throw 0;
4018  }
4019  else if(
4020  base_type.id() == ID_union_tag &&
4021  follow_tag(to_union_tag_type(base_type)).is_incomplete())
4022  {
4024  error() << "pointer arithmetic with unknown object size" << eom;
4025  throw 0;
4026  }
4027  else if(
4028  base_type.id() == ID_empty &&
4030  {
4032  error() << "pointer arithmetic with unknown object size" << eom;
4033  throw 0;
4034  }
4035 }
4036 
4038 {
4039  auto &binary_expr = to_binary_expr(expr);
4040  exprt &op0 = binary_expr.op0();
4041  exprt &op1 = binary_expr.op1();
4042 
4043  const typet &type0 = op0.type();
4044  const typet &type1 = op1.type();
4045 
4046  if(expr.id()==ID_minus ||
4047  (expr.id()==ID_side_effect && expr.get(ID_statement)==ID_assign_minus))
4048  {
4049  if(type0.id()==ID_pointer &&
4050  type1.id()==ID_pointer)
4051  {
4052  // We should check the subtypes, and complain if
4053  // they are really different.
4054  expr.type()=pointer_diff_type();
4057  return;
4058  }
4059 
4060  if(type0.id()==ID_pointer &&
4061  (type1.id()==ID_bool ||
4062  type1.id()==ID_c_bool ||
4063  type1.id()==ID_unsignedbv ||
4064  type1.id()==ID_signedbv ||
4065  type1.id()==ID_c_bit_field ||
4066  type1.id()==ID_c_enum_tag))
4067  {
4069  make_index_type(op1);
4070  expr.type()=type0;
4071  return;
4072  }
4073  }
4074  else if(expr.id()==ID_plus ||
4075  (expr.id()==ID_side_effect && expr.get(ID_statement)==ID_assign_plus))
4076  {
4077  exprt *p_op, *int_op;
4078 
4079  if(type0.id()==ID_pointer)
4080  {
4081  p_op=&op0;
4082  int_op=&op1;
4083  }
4084  else if(type1.id()==ID_pointer)
4085  {
4086  p_op=&op1;
4087  int_op=&op0;
4088  }
4089  else
4090  {
4091  p_op=int_op=nullptr;
4092  UNREACHABLE;
4093  }
4094 
4095  const typet &int_op_type = int_op->type();
4096 
4097  if(int_op_type.id()==ID_bool ||
4098  int_op_type.id()==ID_c_bool ||
4099  int_op_type.id()==ID_unsignedbv ||
4100  int_op_type.id()==ID_signedbv ||
4101  int_op_type.id()==ID_c_bit_field ||
4102  int_op_type.id()==ID_c_enum_tag)
4103  {
4105  make_index_type(*int_op);
4106  expr.type()=p_op->type();
4107  return;
4108  }
4109  }
4110 
4111  irep_idt op_name;
4112 
4113  if(expr.id()==ID_side_effect)
4114  op_name=to_side_effect_expr(expr).get_statement();
4115  else
4116  op_name=expr.id();
4117 
4119  error() << "operator '" << op_name << "' not defined for types '"
4120  << to_string(type0) << "' and '" << to_string(type1) << "'" << eom;
4121  throw 0;
4122 }
4123 
4125 {
4126  auto &binary_expr = to_binary_expr(expr);
4127  implicit_typecast_bool(binary_expr.op0());
4128  implicit_typecast_bool(binary_expr.op1());
4129 
4130  // This is not quite accurate: the standard says the result
4131  // should be of type 'int'.
4132  // We do 'bool' anyway to get more compact formulae. Eventually,
4133  // this should be achieved by means of simplification, and not
4134  // in the frontend.
4135  expr.type()=bool_typet();
4136 }
4137 
4139  side_effect_exprt &expr)
4140 {
4141  const irep_idt &statement=expr.get_statement();
4142 
4143  auto &binary_expr = to_binary_expr(expr);
4144  exprt &op0 = binary_expr.op0();
4145  exprt &op1 = binary_expr.op1();
4146 
4147  {
4148  const typet &type0=op0.type();
4149 
4150  if(type0.id()==ID_empty)
4151  {
4153  error() << "cannot assign void" << eom;
4154  throw 0;
4155  }
4156 
4157  if(!op0.get_bool(ID_C_lvalue))
4158  {
4160  error() << "assignment error: '" << to_string(op0) << "' not an lvalue"
4161  << eom;
4162  throw 0;
4163  }
4164 
4165  if(type0.get_bool(ID_C_constant))
4166  {
4168  error() << "'" << to_string(op0) << "' is constant" << eom;
4169  throw 0;
4170  }
4171 
4172  // refuse to assign arrays
4173  if(type0.id() == ID_array)
4174  {
4176  error() << "direct assignments to arrays not permitted" << eom;
4177  throw 0;
4178  }
4179  }
4180 
4181  // Add a cast to the underlying type for bit fields.
4182  // In particular, sizeof(s.f=1) works for bit fields.
4183  if(op0.type().id()==ID_c_bit_field)
4184  op0 =
4186 
4187  const typet o_type0=op0.type();
4188  const typet o_type1=op1.type();
4189 
4190  expr.type()=o_type0;
4191 
4192  if(statement==ID_assign)
4193  {
4194  implicit_typecast(op1, o_type0);
4195  return;
4196  }
4197  else if(statement==ID_assign_shl ||
4198  statement==ID_assign_shr)
4199  {
4200  if(o_type0.id() == ID_vector)
4201  {
4202  auto &vector_o_type0 = to_vector_type(o_type0);
4203 
4204  if(
4205  o_type1.id() == ID_vector &&
4206  vector_o_type0.element_type() ==
4207  to_vector_type(o_type1).element_type() &&
4208  is_number(vector_o_type0.element_type()))
4209  {
4210  return;
4211  }
4212  else if(is_number(vector_o_type0.element_type()) && is_number(o_type1))
4213  {
4214  op1 = typecast_exprt(op1, o_type0);
4215  return;
4216  }
4217  }
4218 
4221 
4222  if(is_number(op0.type()) && is_number(op1.type()))
4223  {
4224  if(statement==ID_assign_shl)
4225  {
4226  return;
4227  }
4228  else // assign_shr
4229  {
4230  // distinguish arithmetic from logical shifts by looking at type
4231 
4232  typet underlying_type=op0.type();
4233 
4234  if(underlying_type.id()==ID_unsignedbv ||
4235  underlying_type.id()==ID_c_bool)
4236  {
4237  expr.set(ID_statement, ID_assign_lshr);
4238  return;
4239  }
4240  else if(underlying_type.id()==ID_signedbv)
4241  {
4242  expr.set(ID_statement, ID_assign_ashr);
4243  return;
4244  }
4245  }
4246  }
4247  }
4248  else if(statement==ID_assign_bitxor ||
4249  statement==ID_assign_bitand ||
4250  statement==ID_assign_bitor)
4251  {
4252  // these are more restrictive
4253  if(o_type0.id()==ID_bool ||
4254  o_type0.id()==ID_c_bool)
4255  {
4256  implicit_typecast_arithmetic(op0, op1);
4257  if(
4258  op1.type().id() == ID_bool || op1.type().id() == ID_c_bool ||
4259  op1.type().id() == ID_c_enum_tag || op1.type().id() == ID_unsignedbv ||
4260  op1.type().id() == ID_signedbv || op1.type().id() == ID_c_bit_field)
4261  {
4262  return;
4263  }
4264  }
4265  else if(o_type0.id()==ID_c_enum_tag ||
4266  o_type0.id()==ID_unsignedbv ||
4267  o_type0.id()==ID_signedbv ||
4268  o_type0.id()==ID_c_bit_field)
4269  {
4270  implicit_typecast_arithmetic(op0, op1);
4271  if(
4272  op1.type().id() == ID_c_enum_tag || op1.type().id() == ID_unsignedbv ||
4273  op1.type().id() == ID_signedbv || op1.type().id() == ID_c_bit_field)
4274  {
4275  return;
4276  }
4277  }
4278  else if(o_type0.id()==ID_vector &&
4279  o_type1.id()==ID_vector)
4280  {
4281  // We are willing to do a modest amount of conversion
4283  to_vector_type(o_type0), to_vector_type(o_type1)))
4284  {
4285  op1 = typecast_exprt::conditional_cast(op1, o_type0);
4286  return;
4287  }
4288  }
4289  else if(
4290  o_type0.id() == ID_vector &&
4291  (o_type1.id() == ID_bool || o_type1.id() == ID_c_bool ||
4292  o_type1.id() == ID_c_enum_tag || o_type1.id() == ID_unsignedbv ||
4293  o_type1.id() == ID_signedbv))
4294  {
4296  op1 = typecast_exprt(op1, o_type0);
4297  return;
4298  }
4299  }
4300  else
4301  {
4302  if(o_type0.id()==ID_pointer &&
4303  (statement==ID_assign_minus || statement==ID_assign_plus))
4304  {
4306  return;
4307  }
4308  else if(o_type0.id()==ID_vector &&
4309  o_type1.id()==ID_vector)
4310  {
4311  // We are willing to do a modest amount of conversion
4313  to_vector_type(o_type0), to_vector_type(o_type1)))
4314  {
4315  op1 = typecast_exprt::conditional_cast(op1, o_type0);
4316  return;
4317  }
4318  }
4319  else if(o_type0.id() == ID_vector)
4320  {
4322 
4323  if(
4324  is_number(op1.type()) || op1.type().id() == ID_bool ||
4325  op1.type().id() == ID_c_bool || op1.type().id() == ID_c_enum_tag)
4326  {
4327  op1 = typecast_exprt(op1, o_type0);
4328  return;
4329  }
4330  }
4331  else if(o_type0.id()==ID_bool ||
4332  o_type0.id()==ID_c_bool)
4333  {
4334  implicit_typecast_arithmetic(op0, op1);
4335  if(op1.type().id()==ID_bool ||
4336  op1.type().id()==ID_c_bool ||
4337  op1.type().id()==ID_c_enum_tag ||
4338  op1.type().id()==ID_unsignedbv ||
4339  op1.type().id()==ID_signedbv)
4340  return;
4341  }
4342  else
4343  {
4344  implicit_typecast_arithmetic(op0, op1);
4345 
4346  if(is_number(op1.type()) ||
4347  op1.type().id()==ID_bool ||
4348  op1.type().id()==ID_c_bool ||
4349  op1.type().id()==ID_c_enum_tag)
4350  return;
4351  }
4352  }
4353 
4355  error() << "assignment '" << statement << "' not defined for types '"
4356  << to_string(o_type0) << "' and '" << to_string(o_type1) << "'"
4357  << eom;
4358 
4359  throw 0;
4360 }
4361 
4363 {
4364 public:
4366  {
4367  }
4368 
4369 protected:
4370  const namespacet &ns;
4371 
4372  bool is_constant(const exprt &e) const override
4373  {
4374  if(e.id() == ID_infinity)
4375  return true;
4376  else
4377  return is_constantt::is_constant(e);
4378  }
4379 
4380  bool is_constant_address_of(const exprt &e) const override
4381  {
4382  if(e.id() == ID_symbol)
4383  {
4384  return e.type().id() == ID_code ||
4385  ns.lookup(to_symbol_expr(e).get_identifier()).is_static_lifetime;
4386  }
4387  else if(e.id() == ID_array && e.get_bool(ID_C_string_constant))
4388  return true;
4389  else
4391  }
4392 };
4393 
4395 {
4396  // Floating-point expressions may require a rounding mode.
4397  // ISO 9899:1999 F.7.2 says that the default is "round to nearest".
4398  // Some compilers have command-line options to override.
4399  const auto rounding_mode =
4401  adjust_float_expressions(expr, rounding_mode);
4402 
4403  simplify(expr, *this);
4404 
4405  if(!is_compile_time_constantt(*this)(expr))
4406  {
4408  error() << "expected constant expression, but got '" << to_string(expr)
4409  << "'" << eom;
4410  throw 0;
4411  }
4412 }
4413 
4415 {
4416  make_constant(expr);
4417  make_index_type(expr);
4418  simplify(expr, *this);
4419 
4420  if(!is_compile_time_constantt(*this)(expr))
4421  {
4423  error() << "conversion to integer constant failed" << eom;
4424  throw 0;
4425  }
4426 }
4427 
4429  const exprt &expr,
4430  const irep_idt &id,
4431  const std::string &message) const
4432 {
4433  if(!has_subexpr(expr, id))
4434  return;
4435 
4437  error() << message << eom;
4438  throw 0;
4439 }
c_typecheck_baset::do_initializer
virtual void do_initializer(exprt &initializer, const typet &type, bool force_constant)
Definition: c_typecheck_initializer.cpp:26
is_constantt
Determine whether an expression is constant.
Definition: expr_util.h:88
to_union_tag_type
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:202
exprt::copy_to_operands
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition: expr.h:155
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:147
c_typecheck_baset::typecheck_expr_side_effect
virtual void typecheck_expr_side_effect(side_effect_exprt &expr)
Definition: c_typecheck_expr.cpp:1836
symbol_table_baset::has_symbol
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
Definition: symbol_table_base.h:87
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
source_locationt::get_function
const irep_idt & get_function() const
Definition: source_location.h:55
code_typet::has_ellipsis
bool has_ellipsis() const
Definition: std_types.h:611
code_blockt
A codet representing sequential composition of program statements.
Definition: std_code.h:129
typecast_exprt::conditional_cast
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2025
c_typecheck_baset::implicit_typecast_arithmetic
virtual void implicit_typecast_arithmetic(exprt &expr)
Definition: c_typecheck_typecast.cpp:68
is_assignable
bool is_assignable(const exprt &expr)
Returns true iff the argument is one of the following:
Definition: expr_util.cpp:22
to_unary_expr
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:361
get_component_rec
exprt get_component_rec(const exprt &struct_union, const irep_idt &component_name, const namespacet &ns)
Definition: anonymous_member.cpp:41
ansi_c_declaration.h
c_enum_typet
The type of C enums.
Definition: c_types.h:216
type_with_subtypest
Type with multiple subtypes.
Definition: type.h:206
c_typecheck_baset::gcc_vector_types_compatible
bool gcc_vector_types_compatible(const vector_typet &, const vector_typet &)
Definition: c_typecheck_expr.cpp:3775
code_blockt::from_list
static code_blockt from_list(const std::list< codet > &_list)
Definition: std_code.h:148
to_side_effect_expr_function_call
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
Definition: std_code.h:1739
has_subexpr
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
Definition: expr_util.cpp:139
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
pointer_object
exprt pointer_object(const exprt &p)
Definition: pointer_predicates.cpp:23
ansi_c_declarationt::declarators
const declaratorst & declarators() const
Definition: ansi_c_declaration.h:216
binary_exprt::rhs
exprt & rhs()
Definition: std_expr.h:623
c_enum_typet::is_incomplete
bool is_incomplete() const
enum types may be incomplete
Definition: c_types.h:261
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
arith_tools.h
is_number
bool is_number(const typet &type)
Returns true if the type is a rational, real, integer, natural, complex, unsignedbv,...
Definition: mathematical_types.cpp:17
symbolt::is_macro
bool is_macro
Definition: symbol.h:61
c_typecheck_baset::typecheck_expr_builtin_offsetof
virtual void typecheck_expr_builtin_offsetof(exprt &expr)
Definition: c_typecheck_expr.cpp:574
codet::op0
exprt & op0()
Definition: expr.h:125
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
c_typecheck_baset::typecheck_expr_shifts
virtual void typecheck_expr_shifts(shift_exprt &expr)
Definition: c_typecheck_expr.cpp:3933
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
address_of_exprt::object
exprt & object()
Definition: pointer_expr.h:380
to_struct_union_type
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition: std_types.h:214
c_typecheck_baset::do_special_functions
virtual exprt do_special_functions(side_effect_expr_function_callt &expr)
Definition: c_typecheck_expr.cpp:2247
symbolt::display_name
const irep_idt & display_name() const
Return language specific display name if present.
Definition: symbol.h:55
typet
The type of an expression, extends irept.
Definition: type.h:28
to_already_typechecked_expr
already_typechecked_exprt & to_already_typechecked_expr(exprt &expr)
Definition: c_typecheck_base.h:348
code_typet::parameterst
std::vector< parametert > parameterst
Definition: std_types.h:541
c_typecheck_base.h
irept::pretty
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:495
c_typecheck_baset::typecheck_declaration
void typecheck_declaration(ansi_c_declarationt &)
Definition: c_typecheck_base.cpp:704
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
c_typecheck_baset::to_string
virtual std::string to_string(const exprt &expr)
Definition: c_typecheck_base.cpp:24
c_typecheck_baset::adjust_float_rel
virtual void adjust_float_rel(binary_relation_exprt &)
Definition: c_typecheck_expr.cpp:1313
struct_union_typet
Base type for structs and unions.
Definition: std_types.h:61
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
long_double_type
floatbv_typet long_double_type()
Definition: c_types.cpp:211
dereference_exprt
Operator to dereference a pointer.
Definition: pointer_expr.h:659
vector_typet::size
const constant_exprt & size() const
Definition: std_types.cpp:269
side_effect_expr_function_callt
A side_effect_exprt representation of a function call side effect.
Definition: std_code.h:1691
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:2322
c_typecheck_baset::add_rounding_mode
static void add_rounding_mode(exprt &)
Definition: c_typecheck_expr.cpp:61
is_dynamic_object_exprt
Evaluates to true if the operand is a pointer to a dynamic object.
Definition: pointer_expr.h:320
floatbv_typet
Fixed-width bit-vector with IEEE floating-point interpretation.
Definition: bitvector_types.h:321
pointer_predicates.h
configt::ansi_ct::flavourt::VISUAL_STUDIO
@ VISUAL_STUDIO
is_constantt::is_constant_address_of
virtual bool is_constant_address_of(const exprt &) const
this function determines which reference-typed expressions are constant
Definition: expr_util.cpp:255
c_typecheck_baset::typecheck_function_call_arguments
virtual void typecheck_function_call_arguments(side_effect_expr_function_callt &expr)
Typecheck the parameters in a function call expression, and where necessary, make implicit casts arou...
Definition: c_typecheck_expr.cpp:3647
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
type2name.h
c_bool_type
typet c_bool_type()
Definition: c_types.cpp:118
prefix.h
complex_real_exprt
Real part of the expression describing a complex number.
Definition: std_expr.h:1925
builtin_factory
bool builtin_factory(const irep_idt &identifier, symbol_tablet &symbol_table, message_handlert &mh)
Check whether given identifier is a compiler built-in.
Definition: builtin_factory.cpp:97
s1
int8_t s1
Definition: bytecode_info.h:59
union_exprt
Union constructor from single element.
Definition: std_expr.h:1707
c_typecheck_baset::disallow_subexpr_by_id
void disallow_subexpr_by_id(const exprt &, const irep_idt &, const std::string &) const
Definition: c_typecheck_expr.cpp:4428
to_type_with_subtype
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:193
c_typecheck_baset::typecheck_side_effect_statement_expression
virtual void typecheck_side_effect_statement_expression(side_effect_exprt &expr)
Definition: c_typecheck_expr.cpp:912
plus_exprt
The plus expression Associativity is not specified.
Definition: std_expr.h:946
c_typecheck_baset::typecheck_expr_symbol
virtual void typecheck_expr_symbol(exprt &expr)
Definition: c_typecheck_expr.cpp:809
code_frontend_declt
A codet representing the declaration of a local variable.
Definition: std_code.h:346
to_mathematical_function_type
const mathematical_function_typet & to_mathematical_function_type(const typet &type)
Cast a typet to a mathematical_function_typet.
Definition: mathematical_types.h:119
string_constant.h
exprt
Base class for all expressions.
Definition: expr.h:55
c_typecheck_baset::typecheck_expr_pointer_arithmetic
virtual void typecheck_expr_pointer_arithmetic(exprt &expr)
Definition: c_typecheck_expr.cpp:4037
binary_exprt::lhs
exprt & lhs()
Definition: std_expr.h:613
unary_exprt
Generic base class for unary expressions.
Definition: std_expr.h:313
binary_exprt
A base class for binary expressions.
Definition: std_expr.h:582
symbolt::base_name
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
namespace_baset::follow_tag
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
complex_typet
Complex numbers made of pair of given subtype.
Definition: std_types.h:1076
sign_exprt
Sign of an expression Predicate is true if _op is negative, false otherwise.
Definition: std_expr.h:538
c_typecheck_baset::typecheck_expr_address_of
virtual void typecheck_expr_address_of(exprt &expr)
Definition: c_typecheck_expr.cpp:1711
c_typecheck_baset::typecheck_expr_alignof
virtual void typecheck_expr_alignof(exprt &expr)
Definition: c_typecheck_expr.cpp:1045
exprt::op0
exprt & op0()
Definition: expr.h:125
invalid_source_file_exceptiont
Thrown when we can't handle something in an input source file.
Definition: exception_utils.h:171
component
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:76
is_compile_time_constantt
Definition: c_typecheck_expr.cpp:4362
vector_typet
The vector type.
Definition: std_types.h:1007
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
c_typecheck_baset::move_symbol
void move_symbol(symbolt &symbol, symbolt *&new_symbol)
Definition: c_typecheck_base.cpp:34
bool_typet
The Boolean type.
Definition: std_types.h:35
c_typecheck_baset::typecheck_type
virtual void typecheck_type(typet &type)
Definition: c_typecheck_type.cpp:35
to_string
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Definition: string_constraint.cpp:58
to_code_frontend_decl
const code_frontend_declt & to_code_frontend_decl(const codet &code)
Definition: std_code.h:429
messaget::eom
static eomt eom
Definition: message.h:297
c_typecheck_baset::typecheck_side_effect_function_call
virtual void typecheck_side_effect_function_call(side_effect_expr_function_callt &expr)
Definition: c_typecheck_expr.cpp:1980
exprt::is_true
bool is_true() const
Return whether the expression is a constant representing true.
Definition: expr.cpp:34
c_qualifiers.h
to_side_effect_expr
side_effect_exprt & to_side_effect_expr(exprt &expr)
Definition: std_code.h:1506
c_typecheck_baset::typecheck_expr_binary_arithmetic
virtual void typecheck_expr_binary_arithmetic(exprt &expr)
Definition: c_typecheck_expr.cpp:3804
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
is_compile_time_constantt::is_compile_time_constantt
is_compile_time_constantt(const namespacet &ns)
Definition: c_typecheck_expr.cpp:4365
to_complex_type
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
Definition: std_types.h:1102
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
has_suffix
bool has_suffix(const std::string &s, const std::string &suffix)
Definition: suffix.h:17
string_constantt
Definition: string_constant.h:14
object_size_exprt
Expression for finding the size (in bytes) of the object a pointer points to.
Definition: pointer_expr.h:1006
index_type
bitvector_typet index_type()
Definition: c_types.cpp:22
saturating_minus_exprt
Saturating subtraction expression.
Definition: bitvector_expr.h:1258
equal_exprt
Equality.
Definition: std_expr.h:1305
void_type
empty_typet void_type()
Definition: c_types.cpp:263
c_typecheck_baset::typecheck_expr_binary_boolean
virtual void typecheck_expr_binary_boolean(exprt &expr)
Definition: c_typecheck_expr.cpp:4124
to_side_effect_expr_statement_expression
side_effect_expr_statement_expressiont & to_side_effect_expr_statement_expression(exprt &expr)
Definition: std_code.h:1669
configt::ansi_ct::flavourt::CLANG
@ CLANG
infinity_exprt
An expression denoting infinity.
Definition: std_expr.h:3041
if_exprt::false_case
exprt & false_case()
Definition: std_expr.h:2360
isfinite_exprt
Evaluates to true if the operand is finite.
Definition: floatbv_expr.h:175
vector_typet::index_type
typet index_type() const
The type of any index expression into an instance of this type.
Definition: std_types.cpp:257
saturating_plus_exprt
The saturating plus expression.
Definition: bitvector_expr.h:1204
c_typecheck_baset::clean_code
std::list< codet > clean_code
Definition: c_typecheck_base.h:266
irept::get
const irep_idt & get(const irep_idt &name) const
Definition: irep.cpp:45
ieee_float_spect
Definition: ieee_float.h:22
c_typecheck_baset::make_constant
virtual void make_constant(exprt &expr)
Definition: c_typecheck_expr.cpp:4394
to_binary_expr
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:660
c_typecheck_baset::typecheck_expr_operands
virtual void typecheck_expr_operands(exprt &expr)
Definition: c_typecheck_expr.cpp:734
c_typecheck_baset::typecheck_typed_target_call
virtual void typecheck_typed_target_call(side_effect_expr_function_callt &expr)
Definition: c_typecheck_expr.cpp:1925
mathematical_types.h
array_typet::size
const exprt & size() const
Definition: std_types.h:800
c_typecheck_baset::typecheck_expr_member
virtual void typecheck_expr_member(exprt &expr)
Definition: c_typecheck_expr.cpp:1492
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
to_code
const codet & to_code(const exprt &expr)
Definition: std_code_base.h:104
is_constantt::is_constant
virtual bool is_constant(const exprt &) const
This function determines what expressions are to be propagated as "constants".
Definition: expr_util.cpp:227
namespace_baset::follow_macros
void follow_macros(exprt &) const
Follow macros to their values in a given expression.
Definition: namespace.cpp:97
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
is_compile_time_constantt::is_constant_address_of
bool is_constant_address_of(const exprt &e) const override
this function determines which reference-typed expressions are constant
Definition: c_typecheck_expr.cpp:4380
has_component_rec
bool has_component_rec(const typet &type, const irep_idt &component_name, const namespacet &ns)
Definition: anonymous_member.cpp:74
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
c_typecheck_baset::asm_label_map
asm_label_mapt asm_label_map
Definition: c_typecheck_base.h:303
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
c_typecheck_baset::typecheck_expr_rel
virtual void typecheck_expr_rel(binary_relation_exprt &expr)
Definition: c_typecheck_expr.cpp:1325
vector_typet::element_type
const typet & element_type() const
The type of the elements of the vector.
Definition: std_types.h:1026
symbolt::mode
irep_idt mode
Language mode.
Definition: symbol.h:49
messaget::result
mstreamt & result() const
Definition: message.h:409
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
messaget::error
mstreamt & error() const
Definition: message.h:399
ieee_float_spect::double_precision
static ieee_float_spect double_precision()
Definition: ieee_float.h:77
signed_int_type
signedbv_typet signed_int_type()
Definition: c_types.cpp:40
has_prefix
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
c_typecheck_baset::typecheck_expr_unary_arithmetic
virtual void typecheck_expr_unary_arithmetic(exprt &expr)
Definition: c_typecheck_expr.cpp:3733
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
c_typecheck_baset::implicit_typecast_bool
virtual void implicit_typecast_bool(exprt &expr)
Definition: c_typecheck_base.h:118
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
can_cast_type< c_enum_tag_typet >
bool can_cast_type< c_enum_tag_typet >(const typet &type)
Check whether a reference to a typet is a c_enum_tag_typet.
Definition: c_types.h:331
c_typecheck_baset::instantiate_gcc_polymorphic_builtin
virtual code_blockt instantiate_gcc_polymorphic_builtin(const irep_idt &identifier, const symbol_exprt &function_symbol)
Definition: c_typecheck_gcc_polymorphic_builtins.cpp:1228
messaget::mstreamt::source_location
source_locationt source_location
Definition: message.h:247
get_identifier
static optionalt< smt_termt > get_identifier(const exprt &expr, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_handle_identifiers, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_identifiers)
Definition: smt2_incremental_decision_procedure.cpp:328
predicate_exprt
A base class for expressions that are predicates, i.e., Boolean-typed.
Definition: std_expr.h:516
c_typecheck_baset::typecheck_expr_function_identifier
virtual void typecheck_expr_function_identifier(exprt &expr)
Definition: c_typecheck_expr.cpp:1825
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
forall_operands
#define forall_operands(it, expr)
Definition: expr.h:20
irept::set
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:420
expr2c.h
c_typecheck_baset::typecheck_expr_dereference
virtual void typecheck_expr_dereference(exprt &expr)
Definition: c_typecheck_expr.cpp:1780
expr2c
std::string expr2c(const exprt &expr, const namespacet &ns, const expr2c_configurationt &configuration)
Definition: expr2c.cpp:4046
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
binary_predicate_exprt
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
Definition: std_expr.h:675
c_expr.h
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
exprt::find_source_location
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition: expr.cpp:165
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
c_typecheck_baset::typecheck_saturating_arithmetic
exprt typecheck_saturating_arithmetic(const side_effect_expr_function_callt &expr)
Definition: c_typecheck_expr.cpp:3615
nil_exprt
The NIL expression.
Definition: std_expr.h:3025
c_typecheck_baset::is_complete_type
virtual bool is_complete_type(const typet &type) const
Definition: c_typecheck_code.cpp:366
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
symbolt::symbol_expr
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
pointer_expr.h
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
mathematical_function_typet::domaint
std::vector< typet > domaint
Definition: mathematical_types.h:63
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
is_cstring_exprt
A predicate that indicates that a zero-terminated string starts at the given address.
Definition: pointer_expr.h:1065
is_signed_or_unsigned_bitvector
bool is_signed_or_unsigned_bitvector(const typet &type)
This method tests, if the given typet is a signed or unsigned bitvector.
Definition: bitvector_types.h:19
c_typecheck_baset::typecheck_expr_unary_boolean
virtual void typecheck_expr_unary_boolean(exprt &expr)
Definition: c_typecheck_expr.cpp:3763
symbol_tablet::insert
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
Definition: symbol_table.cpp:17
c_typecheck_baset::typecheck_gcc_polymorphic_builtin
virtual optionalt< symbol_exprt > typecheck_gcc_polymorphic_builtin(const irep_idt &identifier, const exprt::operandst &arguments, const source_locationt &source_location)
Definition: c_typecheck_gcc_polymorphic_builtins.cpp:493
c_qualifierst
Definition: c_qualifiers.h:61
c_typecheck_baset::symbol_table
symbol_tablet & symbol_table
Definition: c_typecheck_base.h:68
c_typecheck_baset::gcc_types_compatible_p
virtual bool gcc_types_compatible_p(const typet &, const typet &)
Definition: c_typecheck_expr.cpp:96
alignment
mp_integer alignment(const typet &type, const namespacet &ns)
Definition: padding.cpp:23
pointer_type
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:253
unsigned_int_type
unsignedbv_typet unsigned_int_type()
Definition: c_types.cpp:54
c_typecheck_baset::typecheck_code
virtual void typecheck_code(codet &code)
Definition: c_typecheck_code.cpp:29
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
c_typecheck_baset::typecheck_side_effect_gcc_conditional_expression
virtual void typecheck_side_effect_gcc_conditional_expression(side_effect_exprt &expr)
Definition: c_typecheck_expr.cpp:1683
c_typecheck_baset::typecheck_arithmetic_pointer
virtual void typecheck_arithmetic_pointer(const exprt &expr)
Definition: c_typecheck_expr.cpp:4004
code_typet
Base type of functions.
Definition: std_types.h:538
symbolt::is_parameter
bool is_parameter
Definition: symbol.h:67
struct_union_typet::has_component
bool has_component(const irep_idt &component_name) const
Definition: std_types.h:157
c_typecheck_baset::make_constant_index
virtual void make_constant_index(exprt &expr)
Definition: c_typecheck_expr.cpp:4414
c_typecheck_baset::typecheck_shuffle_vector
virtual exprt typecheck_shuffle_vector(const side_effect_expr_function_callt &expr)
Definition: c_typecheck_gcc_polymorphic_builtins.cpp:1393
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
c_typecheck_baset::typecheck_expr_trinary
virtual void typecheck_expr_trinary(if_exprt &expr)
Definition: c_typecheck_expr.cpp:1571
to_struct_tag_type
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:474
range.h
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
false_exprt
The Boolean constant false.
Definition: std_expr.h:3016
floatbv_expr.h
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
to_ansi_c_declaration
ansi_c_declarationt & to_ansi_c_declaration(exprt &expr)
Definition: ansi_c_declaration.h:248
cstrlen_exprt
An expression, akin to ISO C's strlen, that denotes the length of a zero-terminated string that start...
Definition: pointer_expr.h:1123
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:655
cprover_prefix.h
typet::add_source_location
source_locationt & add_source_location()
Definition: type.h:95
c_typecheck_baset::typecheck_side_effect_assignment
virtual void typecheck_side_effect_assignment(side_effect_exprt &expr)
Definition: c_typecheck_expr.cpp:4138
writeable_object_exprt
A predicate that indicates that the object pointed to is writeable.
Definition: pointer_expr.h:1235
c_typecheck_baset::parameter_map
id_type_mapt parameter_map
Definition: c_typecheck_base.h:74
pointer_offset
exprt pointer_offset(const exprt &pointer)
Definition: pointer_predicates.cpp:38
to_shift_expr
const shift_exprt & to_shift_expr(const exprt &expr)
Cast an exprt to a shift_exprt.
Definition: bitvector_expr.h:278
c_typecheck_baset::typecheck_expr_rel_vector
virtual void typecheck_expr_rel_vector(binary_exprt &expr)
Definition: c_typecheck_expr.cpp:1427
builtin_factory.h
is_compile_time_constantt::ns
const namespacet & ns
Definition: c_typecheck_expr.cpp:4370
sharing_treet< irept, forward_list_as_mapt< irep_idt, irept > >::subt
typename dt::subt subt
Definition: irep.h:160
c_typecheck_baset::labels_used
std::map< irep_idt, source_locationt > labels_used
Definition: c_typecheck_base.h:173
ieee_floatt::plus_infinity
static ieee_floatt plus_infinity(const ieee_float_spect &_spec)
Definition: ieee_float.h:212
side_effect_exprt::get_statement
const irep_idt & get_statement() const
Definition: std_code.h:1472
c_typecheck_baset::typecheck_expr_ptrmember
virtual void typecheck_expr_ptrmember(exprt &expr)
Definition: c_typecheck_expr.cpp:1458
c_typecheck_baset::typecheck_expr
virtual void typecheck_expr(exprt &expr)
Definition: c_typecheck_expr.cpp:46
c_bit_field_typet::underlying_type
const typet & underlying_type() const
Definition: c_types.h:30
config
configt config
Definition: config.cpp:25
source_locationt
Definition: source_location.h:18
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
symbol_table_baset::add
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
Definition: symbol_table_base.cpp:18
struct_union_typet::componentt
Definition: std_types.h:68
to_c_bit_field_type
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition: c_types.h:58
expr_util.h
Deprecated expression utility functions.
configt::ansi_ct::mode
flavourt mode
Definition: config.h:237
shift_exprt
A base class for shift and rotate operators.
Definition: bitvector_expr.h:229
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
messaget::get_message_handler
message_handlert & get_message_handler()
Definition: message.h:184
ansi_c_declarationt
Definition: ansi_c_declaration.h:71
ieee_float_op_exprt::rounding_mode
exprt & rounding_mode()
Definition: floatbv_expr.h:395
irept::add
irept & add(const irep_idt &name)
Definition: irep.cpp:116
c_typecheck_baset::is_numeric_type
static bool is_numeric_type(const typet &src)
Definition: c_typecheck_base.h:287
history_exprt
A class for an expression that indicates a history variable.
Definition: c_expr.h:204
if_exprt::true_case
exprt & true_case()
Definition: std_expr.h:2350
symbolt::is_extern
bool is_extern
Definition: symbol.h:66
c_typecheck_baset::typecheck_builtin_overflow
exprt typecheck_builtin_overflow(side_effect_expr_function_callt &expr, const irep_idt &arith_op)
Definition: c_typecheck_expr.cpp:3552
ieee_floatt::ROUND_TO_EVEN
@ ROUND_TO_EVEN
Definition: ieee_float.h:125
c_typecheck_baset::typecheck_expr_main
virtual void typecheck_expr_main(exprt &expr)
Definition: c_typecheck_expr.cpp:175
suffix.h
unary_minus_overflow_exprt
A Boolean expression returning true, iff negation would result in an overflow when applied to the (si...
Definition: bitvector_expr.h:909
namespace_baset::follow
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:49
isinf_exprt
Evaluates to true if the operand is infinite.
Definition: floatbv_expr.h:131
symbolt::location
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
symbolt
Symbol table entry.
Definition: symbol.h:27
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
side_effect_expr_function_callt::arguments
exprt::operandst & arguments()
Definition: std_code.h:1718
c_typecheck_baset::typecheck_expr_cw_va_arg_typeof
virtual void typecheck_expr_cw_va_arg_typeof(exprt &expr)
Definition: c_typecheck_expr.cpp:557
to_typecast_expr
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2051
ieee_float.h
symbol_table_baset::symbols
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Definition: symbol_table_base.h:30
exprt::is_constant
bool is_constant() const
Return whether the expression is a constant.
Definition: expr.cpp:27
symbolt::is_type
bool is_type
Definition: symbol.h:61
live_object_exprt
A predicate that indicates that the object pointed to is live.
Definition: pointer_expr.h:1179
binary_relation_exprt
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition: std_expr.h:706
pointer_typet::base_type
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
c_typecheck_baset::return_type
typet return_type
Definition: c_typecheck_base.h:170
complex_imag_exprt
Imaginary part of the expression describing a complex number.
Definition: std_expr.h:1970
CPROVER_PREFIX
#define CPROVER_PREFIX
Definition: cprover_prefix.h:14
irept::get_sub
subt & get_sub()
Definition: irep.h:456
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
same_object
exprt same_object(const exprt &p1, const exprt &p2)
Definition: pointer_predicates.cpp:28
code_typet::parametert
Definition: std_types.h:555
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
symbolt::is_static_lifetime
bool is_static_lifetime
Definition: symbol.h:65
c_typecheck_baset::typecheck_expr_constant
virtual void typecheck_expr_constant(exprt &expr)
Definition: c_typecheck_expr.cpp:3728
code_typet::is_KnR
bool is_KnR() const
Definition: std_types.h:630
r_or_w_ok_exprt
A base class for a predicate that indicates that an address range is ok to read or write or both.
Definition: pointer_expr.h:745
config.h
type_to_partial_identifier
std::string type_to_partial_identifier(const typet &type, const namespacet &ns)
Constructs a string describing the given type, which can be used as part of a C identifier.
Definition: type2name.cpp:324
type_with_subtypet::subtype
const typet & subtype() const
Definition: type.h:172
to_vector_type
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
Definition: std_types.h:1060
ieee_floatt::zero
static ieee_floatt zero(const floatbv_typet &type)
Definition: ieee_float.h:196
configt::ansi_ct::flavourt::GCC
@ GCC
code_typet::return_type
const typet & return_type() const
Definition: std_types.h:645
size_of_expr
optionalt< exprt > size_of_expr(const typet &type, const namespacet &ns)
Definition: pointer_offset_size.cpp:280
to_code_block
const code_blockt & to_code_block(const codet &code)
Definition: std_code.h:203
bswap_exprt
The byte swap expression.
Definition: bitvector_expr.h:18
anonymous_member.h
adjust_float_expressions
void adjust_float_expressions(exprt &expr, const exprt &rounding_mode)
Replaces arithmetic operations and typecasts involving floating point numbers with their equivalent f...
Definition: adjust_float_expressions.cpp:85
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
side_effect_expr_overflowt
A Boolean expression returning true, iff the result of performing operation kind on operands a and b ...
Definition: c_expr.h:116
code_blockt::find_last_statement
codet & find_last_statement()
Definition: std_code.cpp:99
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
side_effect_expr_function_callt::function
exprt & function()
Definition: std_code.h:1708
exprt::operands
operandst & operands()
Definition: expr.h:94
symbolt::is_lvalue
bool is_lvalue
Definition: symbol.h:66
type2c
std::string type2c(const typet &type, const namespacet &ns, const expr2c_configurationt &configuration)
Definition: expr2c.cpp:4062
parameter_symbolt
Symbol table entry of function parameter.
Definition: symbol.h:170
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
irept::remove
void remove(const irep_idt &name)
Definition: irep.cpp:96
index_exprt
Array index operator.
Definition: std_expr.h:1409
is_invalid_pointer_exprt
Definition: pointer_predicates.h:37
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
typecast_exprt
Semantic type conversion.
Definition: std_expr.h:2016
pointer_diff_type
signedbv_typet pointer_diff_type()
Definition: c_types.cpp:238
size_type
unsignedbv_typet size_type()
Definition: c_types.cpp:68
is_compile_time_constantt::is_constant
bool is_constant(const exprt &e) const override
This function determines what expressions are to be propagated as "constants".
Definition: c_typecheck_expr.cpp:4372
adjust_float_expressions.h
true_exprt
The Boolean constant true.
Definition: std_expr.h:3007
codet::get_statement
const irep_idt & get_statement() const
Definition: std_code_base.h:65
constant_exprt
A constant literal expression.
Definition: std_expr.h:2941
ieee_float_equal_exprt
IEEE-floating-point equality.
Definition: floatbv_expr.h:263
messaget::warning
mstreamt & warning() const
Definition: message.h:404
member_offset_expr
optionalt< exprt > member_offset_expr(const member_exprt &member_expr, const namespacet &ns)
Definition: pointer_offset_size.cpp:221
c_typecheck_baset::typecheck_expr_sizeof
virtual void typecheck_expr_sizeof(exprt &expr)
Definition: c_typecheck_expr.cpp:945
c_index_type
bitvector_typet c_index_type()
Definition: c_types.cpp:16
code_frontend_declt::symbol
symbol_exprt & symbol()
Definition: std_code.h:354
binary_exprt::op1
exprt & op1()
Definition: expr.h:128
is_constant
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition: std_types.h:29
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
ieee_float_spect::single_precision
static ieee_float_spect single_precision()
Definition: ieee_float.h:71
exprt::source_location
const source_locationt & source_location() const
Definition: expr.h:211
struct_union_typet::is_incomplete
bool is_incomplete() const
A struct/union may be incomplete.
Definition: std_types.h:185
make_range
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition: range.h:524
mathematical_function_typet
A type for mathematical functions (do not confuse with functions/methods in code)
Definition: mathematical_types.h:58
c_types.h
isnormal_exprt
Evaluates to true if the operand is a normal number.
Definition: floatbv_expr.h:219
symbol_exprt::set_identifier
void set_identifier(const irep_idt &identifier)
Definition: std_expr.h:137
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
irept::get_bool
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:58
side_effect_exprt
An expression containing a side effect.
Definition: std_code.h:1449
bitvector_expr.h
c_typecheck_baset::typecheck_expr_index
virtual void typecheck_expr_index(exprt &expr)
Definition: c_typecheck_expr.cpp:1255
binary_exprt::op0
exprt & op0()
Definition: expr.h:125
validation_modet::INVARIANT
@ INVARIANT
c_typecheck_baset::make_index_type
virtual void make_index_type(exprt &expr)
Definition: c_typecheck_expr.cpp:1250
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
c_typecheck_baset::typecheck_expr_builtin_va_arg
virtual void typecheck_expr_builtin_va_arg(exprt &expr)
Definition: c_typecheck_expr.cpp:516
c_typecheck_baset::implicit_typecast
virtual void implicit_typecast(exprt &expr, const typet &type)
Definition: c_typecheck_typecast.cpp:13
array_typet::element_type
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:785
isnan_exprt
Evaluates to true if the operand is NaN.
Definition: floatbv_expr.h:87
bitreverse_exprt
Reverse the order of bits in a bit-vector.
Definition: bitvector_expr.h:1156
mathematical_expr.h
padding.h
codet
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:28
c_typecheck_baset::typecheck_expr_comma
virtual void typecheck_expr_comma(exprt &expr)
Definition: c_typecheck_expr.cpp:507
c_typecheck_baset::typecheck_expr_typecast
virtual void typecheck_expr_typecast(exprt &expr)
Definition: c_typecheck_expr.cpp:1067
to_constant_expr
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:2992