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 <util/arith_tools.h>
13 #include <util/bitvector_expr.h>
14 #include <util/c_types.h>
15 #include <util/config.h>
16 #include <util/cprover_prefix.h>
17 #include <util/expr_util.h>
18 #include <util/floatbv_expr.h>
19 #include <util/ieee_float.h>
20 #include <util/mathematical_expr.h>
22 #include <util/pointer_expr.h>
25 #include <util/range.h>
26 #include <util/simplify_expr.h>
27 #include <util/string_constant.h>
28 #include <util/suffix.h>
29 #include <util/symbol_table_base.h>
30 
32 
33 #include "anonymous_member.h"
34 #include "ansi_c_declaration.h"
35 #include "builtin_factory.h"
36 #include "c_expr.h"
37 #include "c_qualifiers.h"
38 #include "c_typecast.h"
39 #include "c_typecheck_base.h"
40 #include "expr2c.h"
41 #include "padding.h"
42 #include "type2name.h"
43 
44 #include <sstream>
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.is_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  PRECONDITION(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.is_boolean())
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 = 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(op_type == static_cast<const typet &>(irep.find(ID_type_arg)))
461  {
462  assoc_match = static_cast<const exprt &>(irep.find(ID_value));
463  }
464  }
465 
466  if(assoc_match.is_nil())
467  {
468  if(default_match.is_not_nil())
469  expr.swap(default_match);
470  else
471  {
473  error() << "unmatched generic selection: " << to_string(op.type())
474  << eom;
475  throw 0;
476  }
477  }
478  else
479  expr.swap(assoc_match);
480 
481  // still need to typecheck the result
482  typecheck_expr(expr);
483  }
484  else if(expr.id()==ID_gcc_asm_input ||
485  expr.id()==ID_gcc_asm_output ||
486  expr.id()==ID_gcc_asm_clobbered_register)
487  {
488  }
489  else if(expr.id()==ID_lshr || expr.id()==ID_ashr ||
490  expr.id()==ID_assign_lshr || expr.id()==ID_assign_ashr)
491  {
492  // already type checked
493  }
494  else if(
495  expr.id() == ID_C_spec_assigns || expr.id() == ID_C_spec_frees ||
496  expr.id() == ID_target_list)
497  {
498  // already type checked
499  }
500  else
501  {
503  error() << "unexpected expression: " << expr.pretty() << eom;
504  throw 0;
505  }
506 }
507 
509 {
510  expr.type() = to_binary_expr(expr).op1().type();
511 
512  // make this an l-value if the last operand is one
513  if(to_binary_expr(expr).op1().get_bool(ID_C_lvalue))
514  expr.set(ID_C_lvalue, true);
515 }
516 
518 {
519  // The first parameter is the va_list, and the second
520  // is the type, which will need to be fixed and checked.
521  // The type is given by the parser as type of the expression.
522 
523  typet arg_type=expr.type();
524  typecheck_type(arg_type);
525 
526  const code_typet new_type(
527  {code_typet::parametert(pointer_type(void_type()))}, std::move(arg_type));
528 
529  exprt arg = to_unary_expr(expr).op();
530 
532 
533  symbol_exprt function(ID_gcc_builtin_va_arg, new_type);
534  function.add_source_location() = expr.source_location();
535 
536  // turn into function call
538  function, {arg}, new_type.return_type(), expr.source_location());
539 
540  expr.swap(result);
541 
542  // Make sure symbol exists, but we have it return void
543  // to avoid collisions of the same symbol with different
544  // types.
545 
546  code_typet symbol_type=new_type;
547  symbol_type.return_type()=void_type();
548 
549  symbolt symbol{ID_gcc_builtin_va_arg, symbol_type, ID_C};
550  symbol.base_name=ID_gcc_builtin_va_arg;
551 
552  symbol_table.insert(std::move(symbol));
553 }
554 
556 {
557  // used in Code Warrior via
558  //
559  // __va_arg( <Symbol>, _var_arg_typeof( <Typ> ) )
560  //
561  // where __va_arg is declared as
562  //
563  // extern void* __va_arg(void*, int);
564 
565  typet &type=static_cast<typet &>(expr.add(ID_type_arg));
566  typecheck_type(type);
567 
568  // these return an integer
569  expr.type()=signed_int_type();
570 }
571 
573 {
574  // these need not be constant, due to array indices!
575 
576  if(!expr.operands().empty())
577  {
579  error() << "builtin_offsetof expects no operands" << eom;
580  throw 0;
581  }
582 
583  typet &type=static_cast<typet &>(expr.add(ID_type_arg));
584  typecheck_type(type);
585 
586  const exprt &member = static_cast<const exprt &>(expr.add(ID_designator));
587 
589 
590  for(const auto &op : member.operands())
591  {
592  if(op.id() == ID_member)
593  {
594  if(type.id() != ID_union_tag && type.id() != ID_struct_tag)
595  {
597  error() << "offsetof of member expects struct/union type, "
598  << "but got '" << to_string(type) << "'" << eom;
599  throw 0;
600  }
601 
602  bool found=false;
603  irep_idt component_name = op.get(ID_component_name);
604 
605  while(!found)
606  {
607  PRECONDITION(type.id() == ID_union_tag || type.id() == ID_struct_tag);
608 
609  const struct_union_typet &struct_union_type =
611 
612  // direct member?
613  if(struct_union_type.has_component(component_name))
614  {
615  found=true;
616 
617  if(type.id() == ID_struct_tag)
618  {
619  auto o_opt = member_offset_expr(
620  follow_tag(to_struct_tag_type(type)), component_name, *this);
621 
622  if(!o_opt.has_value())
623  {
625  error() << "offsetof failed to determine offset of '"
626  << component_name << "'" << eom;
627  throw 0;
628  }
629 
630  result = plus_exprt(
631  result,
632  typecast_exprt::conditional_cast(o_opt.value(), size_type()));
633  }
634 
635  type=struct_union_type.get_component(component_name).type();
636  }
637  else
638  {
639  // maybe anonymous?
640  bool found2=false;
641 
642  for(const auto &c : struct_union_type.components())
643  {
644  if(
645  c.get_anonymous() &&
646  (c.type().id() == ID_struct_tag || c.type().id() == ID_union_tag))
647  {
648  if(has_component_rec(c.type(), component_name, *this))
649  {
650  if(type.id() == ID_struct_tag)
651  {
652  auto o_opt = member_offset_expr(
653  follow_tag(to_struct_tag_type(type)), c.get_name(), *this);
654 
655  if(!o_opt.has_value())
656  {
658  error() << "offsetof failed to determine offset of '"
659  << component_name << "'" << eom;
660  throw 0;
661  }
662 
663  result = plus_exprt(
664  result,
666  o_opt.value(), size_type()));
667  }
668 
669  typet tmp = c.type();
670  type=tmp;
671  CHECK_RETURN(
672  type.id() == ID_union_tag || type.id() == ID_struct_tag);
673  found2=true;
674  break; // we run into another iteration of the outer loop
675  }
676  }
677  }
678 
679  if(!found2)
680  {
682  error() << "offset-of of member failed to find component '"
683  << component_name << "' in '" << to_string(type) << "'"
684  << eom;
685  throw 0;
686  }
687  }
688  }
689  }
690  else if(op.id() == ID_index)
691  {
692  if(type.id()!=ID_array)
693  {
695  error() << "offsetof of index expects array type" << eom;
696  throw 0;
697  }
698 
699  exprt index = to_unary_expr(op).op();
700 
701  // still need to typecheck index
702  typecheck_expr(index);
703 
704  auto element_size_opt =
705  size_of_expr(to_array_type(type).element_type(), *this);
706 
707  if(!element_size_opt.has_value())
708  {
710  error() << "offsetof failed to determine array element size" << eom;
711  throw 0;
712  }
713 
715 
716  result = plus_exprt(result, mult_exprt(element_size_opt.value(), index));
717 
718  typet tmp = to_array_type(type).element_type();
719  type=tmp;
720  }
721  }
722 
723  // We make an effort to produce a constant,
724  // but this may depend on variables
725  simplify(result, *this);
726  result.add_source_location()=expr.source_location();
727 
728  expr.swap(result);
729 }
730 
732 {
733  if(expr.id()==ID_side_effect &&
734  expr.get(ID_statement)==ID_function_call)
735  {
736  // don't do function operand
737  typecheck_expr(to_binary_expr(expr).op1()); // arguments
738  }
739  else if(expr.id()==ID_side_effect &&
740  expr.get(ID_statement)==ID_statement_expression)
741  {
743  }
744  else if(
745  expr.id() == ID_forall || expr.id() == ID_exists || expr.id() == ID_lambda)
746  {
747  // These introduce new symbols, which need to be added to the symbol table
748  // before the second operand is typechecked.
749 
750  auto &binary_expr = to_binary_expr(expr);
751  auto &bindings = binary_expr.op0().operands();
752 
753  for(auto &binding : bindings)
754  {
755  ansi_c_declarationt &declaration = to_ansi_c_declaration(binding);
756 
757  typecheck_declaration(declaration);
758 
759  if(declaration.declarators().size() != 1)
760  {
762  error() << "forall/exists expects one declarator exactly" << eom;
763  throw 0;
764  }
765 
766  irep_idt identifier = declaration.declarators().front().get_name();
767 
768  // look it up
769  symbol_table_baset::symbolst::const_iterator s_it =
770  symbol_table.symbols.find(identifier);
771 
772  if(s_it == symbol_table.symbols.end())
773  {
775  error() << "failed to find bound symbol `" << identifier
776  << "' in symbol table" << eom;
777  throw 0;
778  }
779 
780  const symbolt &symbol = s_it->second;
781 
782  if(
783  symbol.is_type || symbol.is_extern || symbol.is_static_lifetime ||
784  !is_complete_type(symbol.type) || symbol.type.id() == ID_code)
785  {
787  error() << "unexpected quantified symbol" << eom;
788  throw 0;
789  }
790 
791  code_frontend_declt decl(symbol.symbol_expr());
792  decl.add_source_location() = declaration.source_location();
793 
794  binding = decl;
795  }
796 
797  typecheck_expr(binary_expr.op1());
798  }
799  else
800  {
801  Forall_operands(it, expr)
802  typecheck_expr(*it);
803  }
804 }
805 
807 {
808  irep_idt identifier=to_symbol_expr(expr).get_identifier();
809 
810  // Is it a parameter? We do this while checking parameter lists.
811  id_type_mapt::const_iterator p_it=parameter_map.find(identifier);
812  if(p_it!=parameter_map.end())
813  {
814  // yes
815  expr.type()=p_it->second;
816  expr.set(ID_C_lvalue, true);
817  return;
818  }
819 
820  // renaming via GCC asm label
821  asm_label_mapt::const_iterator entry=
822  asm_label_map.find(identifier);
823  if(entry!=asm_label_map.end())
824  {
825  identifier=entry->second;
826  to_symbol_expr(expr).set_identifier(identifier);
827  }
828 
829  // look it up
830  const symbolt *symbol_ptr;
831  if(lookup(identifier, symbol_ptr))
832  {
834  error() << "failed to find symbol '" << identifier << "'" << eom;
835  throw 0;
836  }
837 
838  const symbolt &symbol=*symbol_ptr;
839 
840  if(symbol.is_type)
841  {
843  error() << "did not expect a type symbol here, but got '"
844  << symbol.display_name() << "'" << eom;
845  throw 0;
846  }
847 
848  // save the source location
849  source_locationt source_location=expr.source_location();
850 
851  if(symbol.is_macro)
852  {
853  // preserve enum key
854  #if 0
855  irep_idt base_name=expr.get(ID_C_base_name);
856  #endif
857 
858  follow_macros(expr);
859 
860  #if 0
861  if(expr.is_constant() && !base_name.empty())
862  expr.set(ID_C_cformat, base_name);
863  else
864  #endif
865  typecheck_expr(expr);
866 
867  // preserve location
868  expr.add_source_location()=source_location;
869  }
870  else if(identifier.starts_with(CPROVER_PREFIX "constant_infinity"))
871  {
872  expr=infinity_exprt(symbol.type);
873 
874  // put it back
875  expr.add_source_location()=source_location;
876  }
877  else if(identifier=="__func__" ||
878  identifier=="__FUNCTION__" ||
879  identifier=="__PRETTY_FUNCTION__")
880  {
881  // __func__ is an ANSI-C standard compliant hack to get the function name
882  // __FUNCTION__ and __PRETTY_FUNCTION__ are GCC-specific
883  string_constantt s(source_location.get_function());
884  s.add_source_location()=source_location;
885  s.set(ID_C_lvalue, true);
886  expr.swap(s);
887  }
888  else
889  {
890  expr=symbol.symbol_expr();
891 
892  // put it back
893  expr.add_source_location()=source_location;
894 
895  if(symbol.is_lvalue)
896  expr.set(ID_C_lvalue, true);
897 
898  if(expr.type().id()==ID_code) // function designator
899  { // special case: this is sugar for &f
900  address_of_exprt tmp(expr, pointer_type(expr.type()));
901  tmp.set(ID_C_implicit, true);
903  expr=tmp;
904  }
905  }
906 }
907 
909  side_effect_exprt &expr)
910 {
911  codet &code = to_code(to_unary_expr(expr).op());
912 
913  // the type is the type of the last statement in the
914  // block, but do worry about labels!
915 
917 
918  irep_idt last_statement=last.get_statement();
919 
920  if(last_statement==ID_expression)
921  {
922  PRECONDITION(last.operands().size() == 1);
923  exprt &op=last.op0();
924 
925  // arrays here turn into pointers (array decay)
926  if(op.type().id()==ID_array)
929 
930  expr.type()=op.type();
931  }
932  else
933  {
934  // we used to do this, but don't expect it any longer
935  PRECONDITION(last_statement != ID_function_call);
936 
937  expr.type()=typet(ID_empty);
938  }
939 }
940 
942 {
943  typet type;
944 
945  // these come in two flavors: with zero operands, for a type,
946  // and with one operand, for an expression.
947  PRECONDITION(expr.operands().size() <= 1);
948 
949  if(expr.operands().empty())
950  {
951  type.swap(static_cast<typet &>(expr.add(ID_type_arg)));
952  typecheck_type(type);
953  }
954  else
955  {
956  const exprt &op = to_unary_expr(as_const(expr)).op();
957  // This is one of the few places where it's detectable
958  // that we are using "bool" for boolean operators instead
959  // of "int". We convert for this reason.
960  if(op.is_boolean())
961  type = signed_int_type();
962  else
963  type = op.type();
964  }
965 
966  exprt new_expr;
967 
968  if(type.id()==ID_c_bit_field)
969  {
970  // only comma or side-effect expressions are permitted
971  const exprt &op = skip_typecast(to_unary_expr(as_const(expr)).op());
972  if(op.id() == ID_comma || op.id() == ID_side_effect)
973  {
974  const c_bit_field_typet &bf_type = to_c_bit_field_type(type);
976  {
977  new_expr = from_integer(
978  (bf_type.get_width() + config.ansi_c.char_width - 1) /
980  size_type());
981  }
982  else
983  {
984  auto size_of_opt = size_of_expr(bf_type.underlying_type(), *this);
985 
986  if(!size_of_opt.has_value())
987  {
989  error() << "type has no size: "
990  << to_string(bf_type.underlying_type()) << eom;
991  throw 0;
992  }
993 
994  new_expr = size_of_opt.value();
995  }
996  }
997  else
998  {
1000  error() << "sizeof cannot be applied to bit fields" << eom;
1001  throw 0;
1002  }
1003  }
1004  else if(type.id() == ID_bool)
1005  {
1007  error() << "sizeof cannot be applied to single bits" << eom;
1008  throw 0;
1009  }
1010  else if(type.id() == ID_empty)
1011  {
1012  // This is a gcc extension.
1013  // https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Pointer-Arith.html
1014  new_expr = from_integer(1, size_type());
1015  }
1016  else
1017  {
1018  if(
1019  (type.id() == ID_struct_tag &&
1020  follow_tag(to_struct_tag_type(type)).is_incomplete()) ||
1021  (type.id() == ID_union_tag &&
1022  follow_tag(to_union_tag_type(type)).is_incomplete()) ||
1023  (type.id() == ID_c_enum_tag &&
1024  follow_tag(to_c_enum_tag_type(type)).is_incomplete()) ||
1025  (type.id() == ID_array && to_array_type(type).is_incomplete()))
1026  {
1028  error() << "invalid application of \'sizeof\' to an incomplete type\n\t\'"
1029  << to_string(type) << "\'" << eom;
1030  throw 0;
1031  }
1032 
1033  auto size_of_opt = size_of_expr(type, *this);
1034 
1035  if(!size_of_opt.has_value())
1036  {
1038  error() << "type has no size: " << to_string(type) << eom;
1039  throw 0;
1040  }
1041 
1042  new_expr = size_of_opt.value();
1043  }
1044 
1045  source_locationt location = expr.source_location();
1046  new_expr.swap(expr);
1047  expr.add_source_location() = location;
1048  expr.add(ID_C_c_sizeof_type)=type;
1049 
1050  // The type may contain side-effects.
1051  if(!clean_code.empty())
1052  {
1053  side_effect_exprt side_effect_expr(
1054  ID_statement_expression, void_type(), location);
1055  auto decl_block=code_blockt::from_list(clean_code);
1056  decl_block.set_statement(ID_decl_block);
1057  side_effect_expr.copy_to_operands(decl_block);
1058  clean_code.clear();
1059 
1060  // We merge the side-effect into the operand of the typecast,
1061  // using a comma-expression.
1062  // I.e., (type)e becomes (type)(side-effect, e)
1063  // It is not obvious whether the type or 'e' should be evaluated
1064  // first.
1065 
1066  exprt comma_expr =
1067  binary_exprt{std::move(side_effect_expr), ID_comma, expr, expr.type()}
1068  .with_source_location(location);
1069  expr.swap(comma_expr);
1070  }
1071 }
1072 
1074 {
1075  typet argument_type;
1076 
1077  if(expr.operands().size()==1)
1078  argument_type = to_unary_expr(expr).op().type();
1079  else
1080  {
1081  typet &op_type=static_cast<typet &>(expr.add(ID_type_arg));
1082  typecheck_type(op_type);
1083  argument_type=op_type;
1084  }
1085 
1086  // we only care about the type
1087  mp_integer a=alignment(argument_type, *this);
1088 
1089  exprt tmp=from_integer(a, size_type());
1090  tmp.add_source_location()=expr.source_location();
1091 
1092  expr.swap(tmp);
1093 }
1094 
1096 {
1097  exprt &op = to_unary_expr(expr).op();
1098 
1099  typecheck_type(expr.type());
1100 
1101  // The type may contain side-effects.
1102  if(!clean_code.empty())
1103  {
1104  side_effect_exprt side_effect_expr(
1105  ID_statement_expression, void_type(), expr.source_location());
1106  auto decl_block=code_blockt::from_list(clean_code);
1107  decl_block.set_statement(ID_decl_block);
1108  side_effect_expr.copy_to_operands(decl_block);
1109  clean_code.clear();
1110 
1111  // We merge the side-effect into the operand of the typecast,
1112  // using a comma-expression.
1113  // I.e., (type)e becomes (type)(side-effect, e)
1114  // It is not obvious whether the type or 'e' should be evaluated
1115  // first.
1116 
1117  binary_exprt comma_expr{
1118  std::move(side_effect_expr), ID_comma, op, op.type()};
1119  op.swap(comma_expr);
1120  }
1121 
1122  const typet expr_type = expr.type();
1123 
1124  if(
1125  expr_type.id() == ID_union_tag && expr_type != op.type() &&
1126  op.id() != ID_initializer_list)
1127  {
1128  // This is a GCC extension. It's either a 'temporary union',
1129  // where the argument is one of the member types.
1130 
1131  // This is one of the few places where it's detectable
1132  // that we are using "bool" for boolean operators instead
1133  // of "int". We convert for this reason.
1134  if(op.is_boolean())
1135  op = typecast_exprt(op, signed_int_type());
1136 
1137  // we need to find a member with the right type
1138  const auto &union_type = follow_tag(to_union_tag_type(expr_type));
1139  for(const auto &c : union_type.components())
1140  {
1141  if(c.type() == op.type())
1142  {
1143  // found! build union constructor
1144  union_exprt union_expr(c.get_name(), op, expr.type());
1145  union_expr.add_source_location()=expr.source_location();
1146  expr=union_expr;
1147  expr.set(ID_C_lvalue, true);
1148  return;
1149  }
1150  }
1151 
1152  // not found, complain
1154  error() << "type cast to union: type '" << to_string(op.type())
1155  << "' not found in union" << eom;
1156  throw 0;
1157  }
1158 
1159  // We allow (TYPE){ initializer_list }
1160  // This is called "compound literal", and is syntactic
1161  // sugar for a (possibly local) declaration.
1162  if(op.id()==ID_initializer_list)
1163  {
1164  // just do a normal initialization
1165  do_initializer(op, expr.type(), false);
1166 
1167  // This produces a struct-expression,
1168  // union-expression, array-expression,
1169  // or an expression for a pointer or scalar.
1170  // We produce a compound_literal expression.
1171  exprt tmp(ID_compound_literal, expr.type());
1172  tmp.copy_to_operands(op);
1173 
1174  // handle the case of TYPE being an array with unspecified size
1175  if(op.id()==ID_array &&
1176  expr.type().id()==ID_array &&
1177  to_array_type(expr.type()).size().is_nil())
1178  tmp.type()=op.type();
1179 
1180  expr=tmp;
1181  expr.set(ID_C_lvalue, true); // these are l-values
1182  return;
1183  }
1184 
1185  // a cast to void is always fine
1186  if(expr_type.id()==ID_empty)
1187  return;
1188 
1189  const typet op_type = op.type();
1190 
1191  // cast to same type?
1192  if(expr_type == op_type)
1193  return; // it's ok
1194 
1195  // vectors?
1196 
1197  if(expr_type.id()==ID_vector)
1198  {
1199  // we are generous -- any vector to vector is fine
1200  if(op_type.id()==ID_vector)
1201  return;
1202  else if(op_type.id()==ID_signedbv ||
1203  op_type.id()==ID_unsignedbv)
1204  return;
1205  }
1206 
1207  if(!is_numeric_type(expr_type) && expr_type.id()!=ID_pointer)
1208  {
1210  error() << "type cast to '" << to_string(expr_type) << "' is not permitted"
1211  << eom;
1212  throw 0;
1213  }
1214 
1215  if(is_numeric_type(op_type) || op_type.id()==ID_pointer)
1216  {
1217  }
1218  else if(op_type.id()==ID_array)
1219  {
1220  // This is the promotion from an array
1221  // to a pointer to the first element.
1222  auto error_opt = c_typecastt::check_address_can_be_taken(op_type);
1223  if(error_opt.has_value())
1224  throw invalid_source_file_exceptiont{*error_opt, expr.source_location()};
1225 
1226  index_exprt index(op, from_integer(0, c_index_type()));
1227  op=address_of_exprt(index);
1228  }
1229  else if(op_type.id()==ID_empty)
1230  {
1231  if(expr_type.id()!=ID_empty)
1232  {
1234  error() << "type cast from void only permitted to void, but got '"
1235  << to_string(expr.type()) << "'" << eom;
1236  throw 0;
1237  }
1238  }
1239  else if(op_type.id()==ID_vector)
1240  {
1241  const vector_typet &op_vector_type=
1242  to_vector_type(op_type);
1243 
1244  // gcc allows conversion of a vector of size 1 to
1245  // an integer/float of the same size
1246  if((expr_type.id()==ID_signedbv ||
1247  expr_type.id()==ID_unsignedbv) &&
1248  pointer_offset_bits(expr_type, *this)==
1249  pointer_offset_bits(op_vector_type, *this))
1250  {
1251  }
1252  else
1253  {
1255  error() << "type cast from vector to '" << to_string(expr.type())
1256  << "' not permitted" << eom;
1257  throw 0;
1258  }
1259  }
1260  else
1261  {
1263  error() << "type cast from '" << to_string(op_type) << "' not permitted"
1264  << eom;
1265  throw 0;
1266  }
1267 
1268  // The new thing is an lvalue if the previous one is
1269  // an lvalue and it's just a pointer type cast.
1270  // This isn't really standard conformant!
1271  // Note that gcc says "warning: target of assignment not really an lvalue;
1272  // this will be a hard error in the future", i.e., we
1273  // can hope that the code below will one day simply go away.
1274 
1275  // Current versions of gcc in fact refuse to do this! Yay!
1276 
1277  if(op.get_bool(ID_C_lvalue))
1278  {
1279  if(expr_type.id()==ID_pointer)
1280  expr.set(ID_C_lvalue, true);
1281  }
1282 }
1283 
1285 {
1287 }
1288 
1290 {
1291  exprt &array_expr = to_binary_expr(expr).op0();
1292  exprt &index_expr = to_binary_expr(expr).op1();
1293 
1294  // we might have to swap them
1295 
1296  {
1297  const typet &array_type = array_expr.type();
1298  const typet &index_type = index_expr.type();
1299 
1300  if(
1301  array_type.id() != ID_array && array_type.id() != ID_pointer &&
1302  array_type.id() != ID_vector &&
1303  (index_type.id() == ID_array || index_type.id() == ID_pointer ||
1304  index_type.id() == ID_vector))
1305  std::swap(array_expr, index_expr);
1306  }
1307 
1308  make_index_type(index_expr);
1309 
1310  // array_expr is a reference to one of expr.operands(), when that vector is
1311  // swapped below the reference is no longer valid. final_array_type exists
1312  // beyond that point so can't be a reference
1313  const typet final_array_type = array_expr.type();
1314 
1315  if(final_array_type.id()==ID_array ||
1316  final_array_type.id()==ID_vector)
1317  {
1318  expr.type() = to_type_with_subtype(final_array_type).subtype();
1319 
1320  if(array_expr.get_bool(ID_C_lvalue))
1321  expr.set(ID_C_lvalue, true);
1322 
1323  if(final_array_type.get_bool(ID_C_constant))
1324  expr.type().set(ID_C_constant, true);
1325  }
1326  else if(final_array_type.id()==ID_pointer)
1327  {
1328  // p[i] is syntactic sugar for *(p+i)
1329 
1331  exprt::operandst summands;
1332  std::swap(summands, expr.operands());
1333  expr.add_to_operands(plus_exprt(std::move(summands), array_expr.type()));
1334  expr.id(ID_dereference);
1335  expr.set(ID_C_lvalue, true);
1336  expr.type() = to_pointer_type(final_array_type).base_type();
1337  }
1338  else
1339  {
1341  error() << "operator [] must take array/vector or pointer but got '"
1342  << to_string(array_expr.type()) << "'" << eom;
1343  throw 0;
1344  }
1345 }
1346 
1348 {
1349  // equality and disequality on float is not mathematical equality!
1350  if(expr.op0().type().id() == ID_floatbv)
1351  {
1352  if(expr.id()==ID_equal)
1353  expr.id(ID_ieee_float_equal);
1354  else if(expr.id()==ID_notequal)
1355  expr.id(ID_ieee_float_notequal);
1356  }
1357 }
1358 
1360  binary_relation_exprt &expr)
1361 {
1362  exprt &op0=expr.op0();
1363  exprt &op1=expr.op1();
1364 
1365  const typet o_type0=op0.type();
1366  const typet o_type1=op1.type();
1367 
1368  if(o_type0.id() == ID_vector || o_type1.id() == ID_vector)
1369  {
1371  return;
1372  }
1373 
1374  expr.type()=bool_typet();
1375 
1376  if(expr.id()==ID_equal || expr.id()==ID_notequal)
1377  {
1378  if(o_type0 == o_type1)
1379  {
1380  if(o_type0.id() != ID_array)
1381  {
1382  adjust_float_rel(expr);
1383  return; // no promotion necessary
1384  }
1385  }
1386  }
1387 
1388  implicit_typecast_arithmetic(op0, op1);
1389 
1390  const typet &type0=op0.type();
1391  const typet &type1=op1.type();
1392 
1393  if(type0==type1)
1394  {
1395  if(is_number(type0))
1396  {
1397  adjust_float_rel(expr);
1398  return;
1399  }
1400 
1401  if(type0.id()==ID_pointer)
1402  {
1403  if(expr.id()==ID_equal || expr.id()==ID_notequal)
1404  return;
1405 
1406  if(expr.id()==ID_le || expr.id()==ID_lt ||
1407  expr.id()==ID_ge || expr.id()==ID_gt)
1408  return;
1409  }
1410 
1411  if(type0.id()==ID_string_constant)
1412  {
1413  if(expr.id()==ID_equal || expr.id()==ID_notequal)
1414  return;
1415  }
1416  }
1417  else
1418  {
1419  // pointer and zero
1420  if(type0.id()==ID_pointer &&
1421  simplify_expr(op1, *this).is_zero())
1422  {
1423  op1 = null_pointer_exprt{to_pointer_type(type0)};
1424  return;
1425  }
1426 
1427  if(type1.id()==ID_pointer &&
1428  simplify_expr(op0, *this).is_zero())
1429  {
1430  op0 = null_pointer_exprt{to_pointer_type(type1)};
1431  return;
1432  }
1433 
1434  // pointer and integer
1435  if(type0.id()==ID_pointer && is_number(type1))
1436  {
1437  op1 = typecast_exprt(op1, type0);
1438  return;
1439  }
1440 
1441  if(type1.id()==ID_pointer && is_number(type0))
1442  {
1443  op0 = typecast_exprt(op0, type1);
1444  return;
1445  }
1446 
1447  if(type0.id()==ID_pointer && type1.id()==ID_pointer)
1448  {
1449  op1 = typecast_exprt(op1, type0);
1450  return;
1451  }
1452  }
1453 
1455  error() << "operator '" << expr.id() << "' not defined for types '"
1456  << to_string(o_type0) << "' and '" << to_string(o_type1) << "'"
1457  << eom;
1458  throw 0;
1459 }
1460 
1462 {
1463  const typet &o_type0 = as_const(expr).op0().type();
1464  const typet &o_type1 = as_const(expr).op1().type();
1465 
1466  if(o_type0.id() != ID_vector || o_type0 != o_type1)
1467  {
1469  error() << "vector operator '" << expr.id() << "' not defined for types '"
1470  << to_string(o_type0) << "' and '" << to_string(o_type1) << "'"
1471  << eom;
1472  throw 0;
1473  }
1474 
1475  // Comparisons between vectors produce a vector of integers of the same width
1476  // with the same dimension.
1477  auto subtype_width =
1478  to_bitvector_type(to_vector_type(o_type0).element_type()).get_width();
1479  expr.type() = vector_typet{
1480  to_vector_type(o_type0).index_type(),
1481  signedbv_typet{subtype_width},
1482  to_vector_type(o_type0).size()};
1483 
1484  // Replace the id as the semantics of these are point-wise application (and
1485  // the result is not of bool type).
1486  if(expr.id() == ID_notequal)
1487  expr.id(ID_vector_notequal);
1488  else
1489  expr.id("vector-" + id2string(expr.id()));
1490 }
1491 
1493 {
1494  auto &op = to_unary_expr(expr).op();
1495  const typet &op0_type = op.type();
1496 
1497  if(op0_type.id() == ID_array)
1498  {
1499  // a->f is the same as a[0].f
1500  exprt zero = from_integer(0, c_index_type());
1501  index_exprt index_expr(op, zero, to_array_type(op0_type).element_type());
1502  index_expr.set(ID_C_lvalue, true);
1503  op.swap(index_expr);
1504  }
1505  else if(op0_type.id() == ID_pointer)
1506  {
1507  // turn x->y into (*x).y
1511  op.swap(deref_expr);
1512  }
1513  else
1514  {
1516  error() << "ptrmember operator requires pointer or array type "
1517  "on left hand side, but got '"
1518  << to_string(op0_type) << "'" << eom;
1519  throw 0;
1520  }
1521 
1522  expr.id(ID_member);
1523  typecheck_expr_member(expr);
1524 }
1525 
1527 {
1528  exprt &op0 = to_unary_expr(expr).op();
1529  typet type=op0.type();
1530 
1531  if(type.id() != ID_struct_tag && type.id() != ID_union_tag)
1532  {
1534  error() << "member operator requires structure type "
1535  "on left hand side but got '"
1536  << to_string(type) << "'" << eom;
1537  throw 0;
1538  }
1539 
1540  const struct_union_typet &struct_union_type =
1542 
1543  if(struct_union_type.is_incomplete())
1544  {
1546  error() << "member operator got incomplete " << type.id()
1547  << " type on left hand side" << eom;
1548  throw 0;
1549  }
1550 
1551  const irep_idt &component_name=
1552  expr.get(ID_component_name);
1553 
1554  // first try to find directly
1556  struct_union_type.get_component(component_name);
1557 
1558  // if that fails, search the anonymous members
1559 
1560  if(component.is_nil())
1561  {
1562  exprt tmp=get_component_rec(op0, component_name, *this);
1563 
1564  if(tmp.is_nil())
1565  {
1566  // give up
1568  error() << "member '" << component_name << "' not found in '"
1569  << to_string(type) << "'" << eom;
1570  throw 0;
1571  }
1572 
1573  // done!
1574  expr.swap(tmp);
1575  return;
1576  }
1577 
1578  expr.type()=component.type();
1579 
1580  if(op0.get_bool(ID_C_lvalue))
1581  expr.set(ID_C_lvalue, true);
1582 
1583  if(
1584  op0.type().get_bool(ID_C_constant) ||
1585  struct_union_type.get_bool(ID_C_constant))
1586  {
1587  expr.type().set(ID_C_constant, true);
1588  }
1589 
1590  // copy method identifier
1591  const irep_idt &identifier=component.get(ID_C_identifier);
1592 
1593  if(!identifier.empty())
1594  expr.set(ID_C_identifier, identifier);
1595 
1596  const irep_idt &access=component.get_access();
1597 
1598  if(access==ID_private)
1599  {
1601  error() << "member '" << component_name << "' is " << access << eom;
1602  throw 0;
1603  }
1604 }
1605 
1607 {
1608  exprt::operandst &operands=expr.operands();
1609 
1610  PRECONDITION(operands.size() == 3);
1611 
1612  // copy (save) original types
1613  const typet o_type0=operands[0].type();
1614  const typet o_type1=operands[1].type();
1615  const typet o_type2=operands[2].type();
1616 
1617  implicit_typecast_bool(operands[0]);
1618 
1619  if(o_type1.id() == ID_empty || o_type2.id() == ID_empty)
1620  {
1621  operands[1] = typecast_exprt::conditional_cast(operands[1], void_type());
1622  operands[2] = typecast_exprt::conditional_cast(operands[2], void_type());
1623  expr.type() = void_type();
1624  return;
1625  }
1626 
1627  if(operands[1].type().id()==ID_pointer &&
1628  operands[2].type().id()!=ID_pointer)
1629  implicit_typecast(operands[2], operands[1].type());
1630  else if(operands[2].type().id()==ID_pointer &&
1631  operands[1].type().id()!=ID_pointer)
1632  implicit_typecast(operands[1], operands[2].type());
1633 
1634  if(operands[1].type().id()==ID_pointer &&
1635  operands[2].type().id()==ID_pointer &&
1636  operands[1].type()!=operands[2].type())
1637  {
1638  exprt tmp1=simplify_expr(operands[1], *this);
1639  exprt tmp2=simplify_expr(operands[2], *this);
1640 
1641  // is one of them void * AND null? Convert that to the other.
1642  // (at least that's how GCC behaves)
1643  if(
1644  to_pointer_type(operands[1].type()).base_type().id() == ID_empty &&
1645  tmp1.is_constant() && is_null_pointer(to_constant_expr(tmp1)))
1646  {
1647  implicit_typecast(operands[1], operands[2].type());
1648  }
1649  else if(
1650  to_pointer_type(operands[2].type()).base_type().id() == ID_empty &&
1651  tmp2.is_constant() && is_null_pointer(to_constant_expr(tmp2)))
1652  {
1653  implicit_typecast(operands[2], operands[1].type());
1654  }
1655  else if(
1656  to_pointer_type(operands[1].type()).base_type().id() != ID_code ||
1657  to_pointer_type(operands[2].type()).base_type().id() != ID_code)
1658  {
1659  // Make it void *.
1660  // gcc and clang issue a warning for this.
1661  expr.type() = pointer_type(void_type());
1662  implicit_typecast(operands[1], expr.type());
1663  implicit_typecast(operands[2], expr.type());
1664  }
1665  else
1666  {
1667  // maybe functions without parameter lists
1668  const code_typet &c_type1 =
1669  to_code_type(to_pointer_type(operands[1].type()).base_type());
1670  const code_typet &c_type2 =
1671  to_code_type(to_pointer_type(operands[2].type()).base_type());
1672 
1673  if(c_type1.return_type()==c_type2.return_type())
1674  {
1675  if(c_type1.parameters().empty() && c_type1.has_ellipsis())
1676  implicit_typecast(operands[1], operands[2].type());
1677  else if(c_type2.parameters().empty() && c_type2.has_ellipsis())
1678  implicit_typecast(operands[2], operands[1].type());
1679  }
1680  }
1681  }
1682 
1683  if(operands[1].type().id()==ID_empty ||
1684  operands[2].type().id()==ID_empty)
1685  {
1686  expr.type()=void_type();
1687  return;
1688  }
1689 
1690  if(
1691  operands[1].type() != operands[2].type() ||
1692  operands[1].type().id() == ID_array)
1693  {
1694  implicit_typecast_arithmetic(operands[1], operands[2]);
1695  }
1696 
1697  if(operands[1].type() == operands[2].type())
1698  {
1699  expr.type()=operands[1].type();
1700 
1701  // GCC says: "A conditional expression is a valid lvalue
1702  // if its type is not void and the true and false branches
1703  // are both valid lvalues."
1704 
1705  if(operands[1].get_bool(ID_C_lvalue) &&
1706  operands[2].get_bool(ID_C_lvalue))
1707  expr.set(ID_C_lvalue, true);
1708 
1709  return;
1710  }
1711 
1713  error() << "operator ?: not defined for types '" << to_string(o_type1)
1714  << "' and '" << to_string(o_type2) << "'" << eom;
1715  throw 0;
1716 }
1717 
1719  side_effect_exprt &expr)
1720 {
1721  // x ? : y is almost the same as x ? x : y,
1722  // but not quite, as x is evaluated only once
1723 
1724  exprt::operandst &operands=expr.operands();
1725 
1726  if(operands.size()!=2)
1727  {
1729  error() << "gcc conditional_expr expects two operands" << eom;
1730  throw 0;
1731  }
1732 
1733  // use typechecking code for "if"
1734 
1735  if_exprt if_expr(operands[0], operands[0], operands[1]);
1736  if_expr.add_source_location()=expr.source_location();
1737 
1738  typecheck_expr_trinary(if_expr);
1739 
1740  // copy the result
1741  operands[0] = if_expr.true_case();
1742  operands[1] = if_expr.false_case();
1743  expr.type()=if_expr.type();
1744 }
1745 
1747 {
1748  exprt &op = to_unary_expr(expr).op();
1749 
1750  auto error_opt = c_typecastt::check_address_can_be_taken(op.type());
1751 
1752  if(error_opt.has_value())
1753  throw invalid_source_file_exceptiont{*error_opt, expr.source_location()};
1754 
1755  // special case: address of label
1756  if(op.id()==ID_label)
1757  {
1758  expr.type()=pointer_type(void_type());
1759 
1760  // remember the label
1761  labels_used[op.get(ID_identifier)]=op.source_location();
1762  return;
1763  }
1764 
1765  // special case: address of function designator
1766  // ANSI-C 99 section 6.3.2.1 paragraph 4
1767 
1768  if(
1769  op.id() == ID_address_of && op.get_bool(ID_C_implicit) &&
1770  to_address_of_expr(op).object().type().id() == ID_code)
1771  {
1772  // make the implicit address_of an explicit address_of
1773  exprt tmp;
1774  tmp.swap(op);
1775  tmp.set(ID_C_implicit, false);
1776  expr.swap(tmp);
1777  return;
1778  }
1779 
1780  if(op.id()==ID_struct ||
1781  op.id()==ID_union ||
1782  op.id()==ID_array ||
1783  op.id()==ID_string_constant)
1784  {
1785  // these are really objects
1786  }
1787  else if(op.get_bool(ID_C_lvalue))
1788  {
1789  // ok
1790  }
1791  else if(op.type().id()==ID_code)
1792  {
1793  // ok
1794  }
1795  else
1796  {
1798  error() << "address_of error: '" << to_string(op) << "' not an lvalue"
1799  << eom;
1800  throw 0;
1801  }
1802 
1803  expr.type()=pointer_type(op.type());
1804 }
1805 
1807 {
1808  exprt &op = to_unary_expr(expr).op();
1809 
1810  const typet op_type = op.type();
1811 
1812  if(op_type.id()==ID_array)
1813  {
1814  // *a is the same as a[0]
1815  expr.id(ID_index);
1816  expr.type() = to_array_type(op_type).element_type();
1818  CHECK_RETURN(expr.operands().size() == 2);
1819  }
1820  else if(op_type.id()==ID_pointer)
1821  {
1822  expr.type() = to_pointer_type(op_type).base_type();
1823 
1824  if(
1825  expr.type().id() == ID_empty &&
1827  {
1829  error() << "dereferencing void pointer" << eom;
1830  throw 0;
1831  }
1832  }
1833  else
1834  {
1836  error() << "operand of unary * '" << to_string(op)
1837  << "' is not a pointer, but got '" << to_string(op_type) << "'"
1838  << eom;
1839  throw 0;
1840  }
1841 
1842  expr.set(ID_C_lvalue, true);
1843 
1844  // if you dereference a pointer pointing to
1845  // a function, you get a pointer again
1846  // allowing ******...*p
1847 
1849 }
1850 
1852 {
1853  if(expr.type().id()==ID_code)
1854  {
1855  address_of_exprt tmp(expr, pointer_type(expr.type()));
1856  tmp.set(ID_C_implicit, true);
1857  tmp.add_source_location()=expr.source_location();
1858  expr=tmp;
1859  }
1860 }
1861 
1863 {
1864  const irep_idt &statement=expr.get_statement();
1865 
1866  if(statement==ID_preincrement ||
1867  statement==ID_predecrement ||
1868  statement==ID_postincrement ||
1869  statement==ID_postdecrement)
1870  {
1871  const exprt &op0 = to_unary_expr(expr).op();
1872  const typet &type0=op0.type();
1873 
1874  if(!op0.get_bool(ID_C_lvalue))
1875  {
1877  error() << "prefix operator error: '" << to_string(op0)
1878  << "' not an lvalue" << eom;
1879  throw 0;
1880  }
1881 
1882  if(type0.get_bool(ID_C_constant))
1883  {
1885  error() << "'" << to_string(op0) << "' is constant" << eom;
1886  throw 0;
1887  }
1888 
1889  if(type0.id() == ID_c_enum_tag)
1890  {
1891  const c_enum_typet &enum_type = follow_tag(to_c_enum_tag_type(type0));
1892  if(enum_type.is_incomplete())
1893  {
1895  error() << "operator '" << statement << "' given incomplete type '"
1896  << to_string(type0) << "'" << eom;
1897  throw 0;
1898  }
1899 
1900  // increment/decrement on underlying type
1901  to_unary_expr(expr).op() =
1902  typecast_exprt(op0, enum_type.underlying_type());
1903  expr.type() = enum_type.underlying_type();
1904  }
1905  else if(type0.id() == ID_c_bit_field)
1906  {
1907  // promote to underlying type
1908  typet underlying_type = to_c_bit_field_type(type0).underlying_type();
1909  typet type_before{type0};
1910  to_unary_expr(expr).op() = typecast_exprt(op0, underlying_type);
1911  expr.type()=underlying_type;
1912  typecast_exprt result{expr, type_before};
1913  expr.swap(result);
1914  }
1915  else if(type0.id() == ID_bool || type0.id() == ID_c_bool)
1916  {
1918  expr.type() = op0.type();
1919  }
1920  else if(is_numeric_type(type0))
1921  {
1922  expr.type()=type0;
1923  }
1924  else if(type0.id() == ID_pointer)
1925  {
1927  expr.type() = to_unary_expr(expr).op().type();
1928  }
1929  else
1930  {
1932  error() << "operator '" << statement << "' not defined for type '"
1933  << to_string(type0) << "'" << eom;
1934  throw 0;
1935  }
1936  }
1937  else if(statement.starts_with("assign"))
1939  else if(statement==ID_function_call)
1942  else if(statement==ID_statement_expression)
1944  else if(statement==ID_gcc_conditional_expression)
1946  else
1947  {
1949  error() << "unknown side effect: " << statement << eom;
1950  throw 0;
1951  }
1952 }
1953 
1956 {
1957  INVARIANT(
1958  expr.function().id() == ID_symbol &&
1960  "typed_target",
1961  "expression must be a " CPROVER_PREFIX "typed_target function call");
1962 
1963  auto &f_op = to_symbol_expr(expr.function());
1964 
1965  if(expr.arguments().size() != 1)
1966  {
1968  "expected 1 argument for " CPROVER_PREFIX "typed_target, found " +
1969  std::to_string(expr.arguments().size()),
1970  expr.source_location()};
1971  }
1972 
1973  auto arg0 = expr.arguments().front();
1974 
1975  if(!is_assignable(arg0) || !arg0.get_bool(ID_C_lvalue))
1976  {
1978  "argument of " CPROVER_PREFIX "typed_target must be assignable",
1979  arg0.source_location()};
1980  }
1981 
1982  const auto &size = size_of_expr(arg0.type(), *this);
1983  if(!size.has_value())
1984  {
1986  "sizeof not defined for argument of " CPROVER_PREFIX
1987  "typed_target of type " +
1988  to_string(arg0.type()),
1989  arg0.source_location()};
1990  }
1991 
1992  // rewrite call to "assignable"
1993  f_op.set_identifier(CPROVER_PREFIX "assignable");
1994  exprt::operandst arguments;
1995  // pointer
1996  arguments.push_back(address_of_exprt(arg0));
1997  // size
1998  arguments.push_back(size.value());
1999  // is_pointer
2000  if(arg0.type().id() == ID_pointer)
2001  arguments.push_back(true_exprt());
2002  else
2003  arguments.push_back(false_exprt());
2004 
2005  expr.arguments().swap(arguments);
2006  expr.type() = empty_typet();
2007 }
2008 
2011 {
2012  INVARIANT(
2013  expr.function().id() == ID_symbol &&
2015  "obeys_contract",
2016  "expression must be a " CPROVER_PREFIX "obeys_contract function call");
2017 
2018  if(expr.arguments().size() != 2)
2019  {
2021  "expected 2 arguments for " CPROVER_PREFIX "obeys_contract, found " +
2022  std::to_string(expr.arguments().size()),
2023  expr.source_location()};
2024  }
2025 
2026  // the first parameter must be a function pointer typed assignable path
2027  // expression, without side effects or ternary operator
2028  auto &function_pointer = expr.arguments()[0];
2029 
2030  if(
2031  function_pointer.type().id() != ID_pointer ||
2032  to_pointer_type(function_pointer.type()).base_type().id() != ID_code ||
2033  !function_pointer.get_bool(ID_C_lvalue))
2034  {
2036  "the first argument of " CPROVER_PREFIX
2037  "obeys_contract must be a function pointer lvalue expression",
2038  function_pointer.source_location());
2039  }
2040 
2041  if(has_subexpr(function_pointer, ID_if))
2042  {
2044  "the first argument of " CPROVER_PREFIX
2045  "obeys_contract must have no ternary operator",
2046  function_pointer.source_location());
2047  }
2048 
2049  // second parameter must be the address of a function symbol
2050  auto &address_of_contract = expr.arguments()[1];
2051 
2052  if(
2053  address_of_contract.id() != ID_address_of ||
2054  to_address_of_expr(address_of_contract).object().id() != ID_symbol ||
2055  address_of_contract.type().id() != ID_pointer ||
2056  to_pointer_type(address_of_contract.type()).base_type().id() != ID_code)
2057  {
2059  "the second argument of " CPROVER_PREFIX
2060  "obeys_contract must must be a function symbol",
2061  address_of_contract.source_location());
2062  }
2063 
2064  if(function_pointer.type() != address_of_contract.type())
2065  {
2067  "the first and second arguments of " CPROVER_PREFIX
2068  "obeys_contract must have the same function pointer type",
2069  expr.source_location());
2070  }
2071 
2072  expr.type() = bool_typet();
2073 }
2074 
2076 {
2078  identifier,
2080  symbol_table,
2082 }
2083 
2086 {
2087  if(expr.operands().size()!=2)
2088  {
2090  error() << "function_call side effect expects two operands" << eom;
2091  throw 0;
2092  }
2093 
2094  exprt &f_op=expr.function();
2095 
2096  // f_op is not yet typechecked, in contrast to the other arguments.
2097  // This is a big special case!
2098 
2099  if(f_op.id()==ID_symbol)
2100  {
2101  irep_idt identifier=to_symbol_expr(f_op).get_identifier();
2102 
2103  asm_label_mapt::const_iterator entry=
2104  asm_label_map.find(identifier);
2105  if(entry!=asm_label_map.end())
2106  identifier=entry->second;
2107 
2108  if(symbol_table.symbols.find(identifier)==symbol_table.symbols.end())
2109  {
2110  // This is an undeclared function.
2111 
2112  // Is it the polymorphic typed_target function ?
2113  if(identifier == CPROVER_PREFIX "typed_target")
2114  {
2116  }
2117  // Is this a builtin?
2118  else if(!builtin_factory(identifier))
2119  {
2120  // yes, it's a builtin
2121  }
2122  else if(
2123  identifier == "__noop" &&
2125  {
2126  // https://docs.microsoft.com/en-us/cpp/intrinsics/noop
2127  // typecheck and discard, just generating 0 instead
2128  for(auto &op : expr.arguments())
2129  typecheck_expr(op);
2130 
2132  expr.swap(result);
2133 
2134  return;
2135  }
2136  else if(
2137  identifier == "__builtin_shuffle" &&
2139  {
2141  expr.swap(result);
2142 
2143  return;
2144  }
2145  else if(identifier == "__builtin_shufflevector")
2146  {
2148  expr.swap(result);
2149 
2150  return;
2151  }
2152  else if(
2153  identifier == CPROVER_PREFIX "saturating_minus" ||
2154  identifier == CPROVER_PREFIX "saturating_plus")
2155  {
2157  expr.swap(result);
2158 
2159  return;
2160  }
2161  else if(identifier == CPROVER_PREFIX "equal")
2162  {
2163  if(expr.arguments().size() != 2)
2164  {
2166  error() << "equal expects two operands" << eom;
2167  throw 0;
2168  }
2169 
2170  equal_exprt equality_expr(
2171  expr.arguments().front(), expr.arguments().back());
2172  equality_expr.add_source_location() = expr.source_location();
2173 
2174  if(equality_expr.lhs().type() != equality_expr.rhs().type())
2175  {
2177  error() << "equal expects two operands of same type" << eom;
2178  throw 0;
2179  }
2180 
2181  expr.swap(equality_expr);
2182  return;
2183  }
2184  else if(
2185  identifier == CPROVER_PREFIX "overflow_minus" ||
2186  identifier == CPROVER_PREFIX "overflow_mult" ||
2187  identifier == CPROVER_PREFIX "overflow_plus" ||
2188  identifier == CPROVER_PREFIX "overflow_shl")
2189  {
2190  exprt overflow{identifier, typet{}, exprt::operandst{expr.arguments()}};
2191  overflow.add_source_location() = f_op.source_location();
2192 
2193  if(identifier == CPROVER_PREFIX "overflow_minus")
2194  {
2195  overflow.id(ID_minus);
2197  }
2198  else if(identifier == CPROVER_PREFIX "overflow_mult")
2199  {
2200  overflow.id(ID_mult);
2202  }
2203  else if(identifier == CPROVER_PREFIX "overflow_plus")
2204  {
2205  overflow.id(ID_plus);
2207  }
2208  else if(identifier == CPROVER_PREFIX "overflow_shl")
2209  {
2210  overflow.id(ID_shl);
2212  }
2213 
2215  overflow.operands()[0], overflow.id(), overflow.operands()[1]};
2216  of.add_source_location() = overflow.source_location();
2217  expr.swap(of);
2218  return;
2219  }
2220  else if(identifier == CPROVER_PREFIX "overflow_unary_minus")
2221  {
2222  exprt tmp{ID_unary_minus, typet{}, exprt::operandst{expr.arguments()}};
2223  tmp.add_source_location() = f_op.source_location();
2224 
2226 
2227  unary_minus_overflow_exprt overflow{tmp.operands().front()};
2228  overflow.add_source_location() = tmp.source_location();
2229  expr.swap(overflow);
2230  return;
2231  }
2232  else if(identifier == CPROVER_PREFIX "enum_is_in_range")
2233  {
2234  // Check correct number of arguments
2235  if(expr.arguments().size() != 1)
2236  {
2237  std::ostringstream error_message;
2238  error_message << identifier << " takes exactly 1 argument, but "
2239  << expr.arguments().size() << " were provided";
2241  error_message.str(), expr.source_location()};
2242  }
2243  const auto &arg1 = expr.arguments()[0];
2244  if(!can_cast_type<c_enum_tag_typet>(arg1.type()))
2245  {
2246  // Can't enum range check a non-enum
2247  std::ostringstream error_message;
2248  error_message << identifier << " expects enum, but ("
2249  << expr2c(arg1, *this) << ") has type `"
2250  << type2c(arg1.type(), *this) << '`';
2252  error_message.str(), expr.source_location()};
2253  }
2254 
2255  enum_is_in_range_exprt in_range{arg1};
2256  in_range.add_source_location() = expr.source_location();
2257  exprt lowered = in_range.lower(*this);
2258  expr.swap(lowered);
2259  return;
2260  }
2261  else if(
2262  identifier == CPROVER_PREFIX "r_ok" ||
2263  identifier == CPROVER_PREFIX "w_ok" ||
2264  identifier == CPROVER_PREFIX "rw_ok")
2265  {
2266  if(expr.arguments().size() != 1 && expr.arguments().size() != 2)
2267  {
2269  id2string(identifier) + " expects one or two operands",
2270  f_op.source_location()};
2271  }
2272 
2273  // the first argument must be a pointer
2274  auto &pointer_expr = expr.arguments()[0];
2275  if(pointer_expr.type().id() == ID_array)
2276  {
2277  auto dest_type = pointer_type(void_type());
2278  dest_type.base_type().set(ID_C_constant, true);
2279  implicit_typecast(pointer_expr, dest_type);
2280  }
2281  else if(pointer_expr.type().id() != ID_pointer)
2282  {
2284  id2string(identifier) + " expects a pointer as first argument",
2285  f_op.source_location()};
2286  }
2287 
2288  // The second argument, when given, is a size_t.
2289  // When not given, use the pointer subtype.
2290  exprt size_expr;
2291 
2292  if(expr.arguments().size() == 2)
2293  {
2294  implicit_typecast(expr.arguments()[1], size_type());
2295  size_expr = expr.arguments()[1];
2296  }
2297  else
2298  {
2299  // Won't do void *
2300  const auto &subtype =
2301  to_pointer_type(pointer_expr.type()).base_type();
2302  if(subtype.id() == ID_empty)
2303  {
2305  id2string(identifier) +
2306  " expects a size when given a void pointer",
2307  f_op.source_location()};
2308  }
2309 
2310  auto size_expr_opt = size_of_expr(subtype, *this);
2311  CHECK_RETURN(size_expr_opt.has_value());
2312  size_expr = std::move(size_expr_opt.value());
2313  }
2314 
2315  irep_idt id = identifier == CPROVER_PREFIX "r_ok" ? ID_r_ok
2316  : identifier == CPROVER_PREFIX "w_ok" ? ID_w_ok
2317  : ID_rw_ok;
2318 
2319  r_or_w_ok_exprt ok_expr(id, pointer_expr, size_expr);
2320  ok_expr.add_source_location() = expr.source_location();
2321 
2322  expr.swap(ok_expr);
2323  return;
2324  }
2325  else if(
2326  auto shadow_memory_builtin = typecheck_shadow_memory_builtin(expr))
2327  {
2328  irep_idt shadow_memory_builtin_id =
2329  shadow_memory_builtin->get_identifier();
2330 
2331  const auto builtin_code_type =
2332  to_code_type(shadow_memory_builtin->type());
2333 
2334  INVARIANT(
2335  builtin_code_type.has_ellipsis() &&
2336  builtin_code_type.parameters().empty(),
2337  "Shadow memory builtins should be an ellipsis with 0 parameter");
2338 
2339  // Add the symbol to the symbol table if it is not present yet.
2340  if(!symbol_table.has_symbol(shadow_memory_builtin_id))
2341  {
2342  symbolt new_symbol{
2343  shadow_memory_builtin_id, shadow_memory_builtin->type(), ID_C};
2344  new_symbol.base_name = shadow_memory_builtin_id;
2345  new_symbol.location = f_op.source_location();
2346  // Add an empty implementation to avoid warnings about missing
2347  // implementation later on
2348  new_symbol.value = code_blockt{};
2349 
2350  symbol_table.add(new_symbol);
2351  }
2352 
2353  // Swap the current `function` field with the newly generated
2354  // `shadow_memory_builtin` `symbol_exprt` and carry on with typechecking
2355  f_op = std::move(*shadow_memory_builtin);
2356  }
2357  else if(
2358  auto gcc_polymorphic = typecheck_gcc_polymorphic_builtin(
2359  identifier, expr.arguments(), f_op.source_location()))
2360  {
2361  irep_idt identifier_with_type = gcc_polymorphic->get_identifier();
2362  auto &parameters = to_code_type(gcc_polymorphic->type()).parameters();
2363  INVARIANT(
2364  !parameters.empty(),
2365  "GCC polymorphic built-ins should have at least one parameter");
2366 
2367  // For all atomic/sync polymorphic built-ins (which are the ones handled
2368  // by typecheck_gcc_polymorphic_builtin), looking at the first parameter
2369  // suffices to distinguish different implementations.
2370  if(parameters.front().type().id() == ID_pointer)
2371  {
2372  identifier_with_type =
2373  id2string(identifier) + "_" +
2375  to_pointer_type(parameters.front().type()).base_type(), *this);
2376  }
2377  else
2378  {
2379  identifier_with_type =
2380  id2string(identifier) + "_" +
2381  type_to_partial_identifier(parameters.front().type(), *this);
2382  }
2383  gcc_polymorphic->set_identifier(identifier_with_type);
2384 
2385  if(!symbol_table.has_symbol(identifier_with_type))
2386  {
2387  for(std::size_t i = 0; i < parameters.size(); ++i)
2388  {
2389  const std::string base_name = "p_" + std::to_string(i);
2390 
2391  parameter_symbolt new_symbol;
2392 
2393  new_symbol.name =
2394  id2string(identifier_with_type) + "::" + base_name;
2395  new_symbol.base_name = base_name;
2396  new_symbol.location = f_op.source_location();
2397  new_symbol.type = parameters[i].type();
2398  new_symbol.is_parameter = true;
2399  new_symbol.is_lvalue = true;
2400  new_symbol.mode = ID_C;
2401 
2402  parameters[i].set_identifier(new_symbol.name);
2403  parameters[i].set_base_name(new_symbol.base_name);
2404 
2405  symbol_table.add(new_symbol);
2406  }
2407 
2408  symbolt new_symbol{
2409  identifier_with_type, gcc_polymorphic->type(), ID_C};
2410  new_symbol.base_name = identifier_with_type;
2411  new_symbol.location = f_op.source_location();
2412  code_blockt implementation =
2413  instantiate_gcc_polymorphic_builtin(identifier, *gcc_polymorphic);
2414  typet parent_return_type = return_type;
2415  return_type = to_code_type(gcc_polymorphic->type()).return_type();
2416  typecheck_code(implementation);
2417  return_type = parent_return_type;
2418  new_symbol.value = implementation;
2419 
2420  symbol_table.add(new_symbol);
2421  }
2422 
2423  f_op = std::move(*gcc_polymorphic);
2424  }
2425  else
2426  {
2427  // This is an undeclared function that's not a builtin.
2428  // Let's just add it.
2429  // We do a bit of return-type guessing, but just a bit.
2430  typet guessed_return_type = signed_int_type();
2431 
2432  // The following isn't really right and sound, but there
2433  // are too many idiots out there who use malloc and the like
2434  // without the right header file.
2435  if(identifier=="malloc" ||
2436  identifier=="realloc" ||
2437  identifier=="reallocf" ||
2438  identifier=="valloc")
2439  {
2440  guessed_return_type = pointer_type(void_type()); // void *
2441  }
2442 
2443  symbolt new_symbol{
2444  identifier, code_typet({}, guessed_return_type), mode};
2445  new_symbol.base_name=identifier;
2446  new_symbol.location=expr.source_location();
2447  new_symbol.type.set(ID_C_incomplete, true);
2448 
2449  // TODO: should also guess some argument types
2450 
2451  symbolt *symbol_ptr;
2452  move_symbol(new_symbol, symbol_ptr);
2453 
2455  warning() << "function '" << identifier << "' is not declared" << eom;
2456  }
2457  }
2458  }
2459 
2460  // typecheck it now
2461  typecheck_expr(f_op);
2462 
2463  const typet f_op_type = f_op.type();
2464 
2465  if(f_op_type.id() == ID_mathematical_function)
2466  {
2467  const auto &mathematical_function_type =
2468  to_mathematical_function_type(f_op_type);
2469 
2470  // check number of arguments
2471  if(expr.arguments().size() != mathematical_function_type.domain().size())
2472  {
2474  error() << "expected " << mathematical_function_type.domain().size()
2475  << " arguments but got " << expr.arguments().size() << eom;
2476  throw 0;
2477  }
2478 
2479  // check the types of the arguments
2480  for(auto &p :
2481  make_range(expr.arguments()).zip(mathematical_function_type.domain()))
2482  {
2483  if(p.first.type() != p.second)
2484  {
2485  error().source_location = p.first.source_location();
2486  error() << "expected argument of type " << to_string(p.second)
2487  << " but got " << to_string(p.first.type()) << eom;
2488  throw 0;
2489  }
2490  }
2491 
2492  function_application_exprt function_application(f_op, expr.arguments());
2493 
2494  function_application.add_source_location() = expr.source_location();
2495 
2496  expr.swap(function_application);
2497  return;
2498  }
2499 
2500  if(f_op_type.id()!=ID_pointer)
2501  {
2503  error() << "expected function/function pointer as argument but got '"
2504  << to_string(f_op_type) << "'" << eom;
2505  throw 0;
2506  }
2507 
2508  // do implicit dereference
2509  if(f_op.id() == ID_address_of && f_op.get_bool(ID_C_implicit))
2510  {
2511  f_op = to_address_of_expr(f_op).object();
2512  }
2513  else
2514  {
2515  dereference_exprt tmp{f_op};
2516  tmp.set(ID_C_implicit, true);
2517  tmp.add_source_location()=f_op.source_location();
2518  f_op.swap(tmp);
2519  }
2520 
2521  if(f_op.type().id()!=ID_code)
2522  {
2524  error() << "expected code as argument" << eom;
2525  throw 0;
2526  }
2527 
2528  const code_typet &code_type=to_code_type(f_op.type());
2529 
2530  expr.type()=code_type.return_type();
2531 
2532  exprt tmp=do_special_functions(expr);
2533 
2534  if(tmp.is_not_nil())
2535  expr.swap(tmp);
2536  else
2538 }
2539 
2542 {
2543  const exprt &f_op=expr.function();
2544  const source_locationt &source_location=expr.source_location();
2545 
2546  // some built-in functions
2547  if(f_op.id()!=ID_symbol)
2548  return nil_exprt();
2549 
2550  const irep_idt &identifier=to_symbol_expr(f_op).get_identifier();
2551 
2552  if(identifier == CPROVER_PREFIX "is_fresh")
2553  {
2554  if(expr.arguments().size() != 2)
2555  {
2557  error() << CPROVER_PREFIX "is_fresh expects two operands; "
2558  << expr.arguments().size() << "provided." << eom;
2559  throw 0;
2560  }
2562  return nil_exprt();
2563  }
2564  else if(identifier == CPROVER_PREFIX "obeys_contract")
2565  {
2567  // returning nil leaves the call expression in place
2568  return nil_exprt();
2569  }
2570  else if(identifier == CPROVER_PREFIX "pointer_in_range_dfcc")
2571  {
2572  // same as pointer_in_range with experimental support for DFCC contracts
2573  // -- do not use
2574  if(expr.arguments().size() != 3)
2575  {
2577  CPROVER_PREFIX "pointer_in_range_dfcc expects three arguments",
2578  expr.source_location()};
2579  }
2580 
2581  for(const auto &arg : expr.arguments())
2582  {
2583  if(arg.type().id() != ID_pointer)
2584  {
2587  "pointer_in_range_dfcc expects pointer-typed arguments",
2588  arg.source_location()};
2589  }
2590  }
2591  return nil_exprt();
2592  }
2593  else if(identifier == CPROVER_PREFIX "same_object")
2594  {
2595  if(expr.arguments().size()!=2)
2596  {
2598  error() << "same_object expects two operands" << eom;
2599  throw 0;
2600  }
2601 
2603 
2604  exprt same_object_expr=
2605  same_object(expr.arguments()[0], expr.arguments()[1]);
2606  same_object_expr.add_source_location()=source_location;
2607 
2608  return same_object_expr;
2609  }
2610  else if(identifier==CPROVER_PREFIX "get_must")
2611  {
2612  if(expr.arguments().size()!=2)
2613  {
2615  error() << "get_must expects two operands" << eom;
2616  throw 0;
2617  }
2618 
2620 
2621  binary_predicate_exprt get_must_expr(
2622  expr.arguments()[0], ID_get_must, expr.arguments()[1]);
2623  get_must_expr.add_source_location()=source_location;
2624 
2625  return std::move(get_must_expr);
2626  }
2627  else if(identifier==CPROVER_PREFIX "get_may")
2628  {
2629  if(expr.arguments().size()!=2)
2630  {
2632  error() << "get_may expects two operands" << eom;
2633  throw 0;
2634  }
2635 
2637 
2638  binary_predicate_exprt get_may_expr(
2639  expr.arguments()[0], ID_get_may, expr.arguments()[1]);
2640  get_may_expr.add_source_location()=source_location;
2641 
2642  return std::move(get_may_expr);
2643  }
2644  else if(identifier == CPROVER_PREFIX "is_invalid_pointer")
2645  {
2646  if(expr.arguments().size()!=1)
2647  {
2649  error() << "is_invalid_pointer expects one operand" << eom;
2650  throw 0;
2651  }
2652 
2654 
2655  exprt same_object_expr = is_invalid_pointer_exprt{expr.arguments().front()};
2656  same_object_expr.add_source_location()=source_location;
2657 
2658  return same_object_expr;
2659  }
2660  else if(identifier==CPROVER_PREFIX "buffer_size")
2661  {
2662  if(expr.arguments().size()!=1)
2663  {
2665  error() << "buffer_size expects one operand" << eom;
2666  throw 0;
2667  }
2668 
2670 
2671  exprt buffer_size_expr("buffer_size", size_type());
2672  buffer_size_expr.operands()=expr.arguments();
2673  buffer_size_expr.add_source_location()=source_location;
2674 
2675  return buffer_size_expr;
2676  }
2677  else if(identifier == CPROVER_PREFIX "is_list")
2678  {
2679  // experimental feature for CHC encodings -- do not use
2680  if(expr.arguments().size() != 1)
2681  {
2683  error() << "is_list expects one operand" << eom;
2684  throw 0;
2685  }
2686 
2688 
2689  if(
2690  expr.arguments()[0].type().id() != ID_pointer ||
2691  to_pointer_type(expr.arguments()[0].type()).base_type().id() !=
2692  ID_struct_tag)
2693  {
2694  error().source_location = expr.arguments()[0].source_location();
2695  error() << "is_list expects a struct-pointer operand" << eom;
2696  throw 0;
2697  }
2698 
2699  predicate_exprt is_list_expr("is_list");
2700  is_list_expr.operands() = expr.arguments();
2701  is_list_expr.add_source_location() = source_location;
2702 
2703  return std::move(is_list_expr);
2704  }
2705  else if(identifier == CPROVER_PREFIX "is_dll")
2706  {
2707  // experimental feature for CHC encodings -- do not use
2708  if(expr.arguments().size() != 1)
2709  {
2711  error() << "is_dll expects one operand" << eom;
2712  throw 0;
2713  }
2714 
2716 
2717  if(
2718  expr.arguments()[0].type().id() != ID_pointer ||
2719  to_pointer_type(expr.arguments()[0].type()).base_type().id() !=
2720  ID_struct_tag)
2721  {
2722  error().source_location = expr.arguments()[0].source_location();
2723  error() << "is_dll expects a struct-pointer operand" << eom;
2724  throw 0;
2725  }
2726 
2727  predicate_exprt is_dll_expr("is_dll");
2728  is_dll_expr.operands() = expr.arguments();
2729  is_dll_expr.add_source_location() = source_location;
2730 
2731  return std::move(is_dll_expr);
2732  }
2733  else if(identifier == CPROVER_PREFIX "is_cyclic_dll")
2734  {
2735  // experimental feature for CHC encodings -- do not use
2736  if(expr.arguments().size() != 1)
2737  {
2739  error() << "is_cyclic_dll expects one operand" << eom;
2740  throw 0;
2741  }
2742 
2744 
2745  if(
2746  expr.arguments()[0].type().id() != ID_pointer ||
2747  to_pointer_type(expr.arguments()[0].type()).base_type().id() !=
2748  ID_struct_tag)
2749  {
2750  error().source_location = expr.arguments()[0].source_location();
2751  error() << "is_cyclic_dll expects a struct-pointer operand" << eom;
2752  throw 0;
2753  }
2754 
2755  predicate_exprt is_cyclic_dll_expr("is_cyclic_dll");
2756  is_cyclic_dll_expr.operands() = expr.arguments();
2757  is_cyclic_dll_expr.add_source_location() = source_location;
2758 
2759  return std::move(is_cyclic_dll_expr);
2760  }
2761  else if(identifier == CPROVER_PREFIX "is_sentinel_dll")
2762  {
2763  // experimental feature for CHC encodings -- do not use
2764  if(expr.arguments().size() != 2 && expr.arguments().size() != 3)
2765  {
2767  error() << "is_sentinel_dll expects two or three operands" << eom;
2768  throw 0;
2769  }
2770 
2772 
2773  exprt::operandst args_no_cast;
2774  args_no_cast.reserve(expr.arguments().size());
2775  for(const auto &argument : expr.arguments())
2776  {
2777  args_no_cast.push_back(skip_typecast(argument));
2778  if(
2779  args_no_cast.back().type().id() != ID_pointer ||
2780  to_pointer_type(args_no_cast.back().type()).base_type().id() !=
2781  ID_struct_tag)
2782  {
2783  error().source_location = expr.arguments()[0].source_location();
2784  error() << "is_sentinel_dll_node expects struct-pointer operands"
2785  << eom;
2786  throw 0;
2787  }
2788  }
2789 
2790  predicate_exprt is_sentinel_dll_expr("is_sentinel_dll");
2791  is_sentinel_dll_expr.operands() = args_no_cast;
2792  is_sentinel_dll_expr.add_source_location() = source_location;
2793 
2794  return std::move(is_sentinel_dll_expr);
2795  }
2796  else if(identifier == CPROVER_PREFIX "is_cstring")
2797  {
2798  // experimental feature for CHC encodings -- do not use
2799  if(expr.arguments().size() != 1)
2800  {
2802  error() << "is_cstring expects one operand" << eom;
2803  throw 0;
2804  }
2805 
2807 
2808  if(expr.arguments()[0].type().id() != ID_pointer)
2809  {
2810  error().source_location = expr.arguments()[0].source_location();
2811  error() << "is_cstring expects a pointer operand" << eom;
2812  throw 0;
2813  }
2814 
2815  is_cstring_exprt is_cstring_expr(expr.arguments()[0]);
2816  is_cstring_expr.add_source_location() = source_location;
2817 
2818  return std::move(is_cstring_expr);
2819  }
2820  else if(identifier == CPROVER_PREFIX "cstrlen")
2821  {
2822  // experimental feature for CHC encodings -- do not use
2823  if(expr.arguments().size() != 1)
2824  {
2826  error() << "cstrlen expects one operand" << eom;
2827  throw 0;
2828  }
2829 
2831 
2832  if(expr.arguments()[0].type().id() != ID_pointer)
2833  {
2834  error().source_location = expr.arguments()[0].source_location();
2835  error() << "cstrlen expects a pointer operand" << eom;
2836  throw 0;
2837  }
2838 
2839  cstrlen_exprt cstrlen_expr(expr.arguments()[0], size_type());
2840  cstrlen_expr.add_source_location() = source_location;
2841 
2842  return std::move(cstrlen_expr);
2843  }
2844  else if(identifier==CPROVER_PREFIX "is_zero_string")
2845  {
2846  if(expr.arguments().size()!=1)
2847  {
2849  error() << "is_zero_string expects one operand" << eom;
2850  throw 0;
2851  }
2852 
2854 
2855  unary_exprt is_zero_string_expr(
2856  "is_zero_string", expr.arguments()[0], c_bool_type());
2857  is_zero_string_expr.set(ID_C_lvalue, true); // make it an lvalue
2858  is_zero_string_expr.add_source_location()=source_location;
2859 
2860  return std::move(is_zero_string_expr);
2861  }
2862  else if(identifier==CPROVER_PREFIX "zero_string_length")
2863  {
2864  if(expr.arguments().size()!=1)
2865  {
2867  error() << "zero_string_length expects one operand" << eom;
2868  throw 0;
2869  }
2870 
2872 
2873  exprt zero_string_length_expr("zero_string_length", size_type());
2874  zero_string_length_expr.operands()=expr.arguments();
2875  zero_string_length_expr.set(ID_C_lvalue, true); // make it an lvalue
2876  zero_string_length_expr.add_source_location()=source_location;
2877 
2878  return zero_string_length_expr;
2879  }
2880  else if(identifier==CPROVER_PREFIX "DYNAMIC_OBJECT")
2881  {
2882  if(expr.arguments().size()!=1)
2883  {
2885  error() << "dynamic_object expects one argument" << eom;
2886  throw 0;
2887  }
2888 
2890 
2891  exprt is_dynamic_object_expr = is_dynamic_object_exprt(expr.arguments()[0]);
2892  is_dynamic_object_expr.add_source_location() = source_location;
2893 
2894  return is_dynamic_object_expr;
2895  }
2896  else if(identifier == CPROVER_PREFIX "LIVE_OBJECT")
2897  {
2898  if(expr.arguments().size() != 1)
2899  {
2901  error() << "live_object expects one argument" << eom;
2902  throw 0;
2903  }
2904 
2906 
2907  exprt live_object_expr = live_object_exprt(expr.arguments()[0]);
2908  live_object_expr.add_source_location() = source_location;
2909 
2910  return live_object_expr;
2911  }
2912  else if(identifier == CPROVER_PREFIX "pointer_in_range")
2913  {
2914  if(expr.arguments().size() != 3)
2915  {
2917  error() << "pointer_in_range expects three arguments" << eom;
2918  throw 0;
2919  }
2920 
2922 
2923  exprt pointer_in_range_expr = pointer_in_range_exprt(
2924  expr.arguments()[0], expr.arguments()[1], expr.arguments()[2]);
2925  pointer_in_range_expr.add_source_location() = source_location;
2926 
2927  return pointer_in_range_expr;
2928  }
2929  else if(identifier == CPROVER_PREFIX "WRITEABLE_OBJECT")
2930  {
2931  if(expr.arguments().size() != 1)
2932  {
2934  error() << "writeable_object expects one argument" << eom;
2935  throw 0;
2936  }
2937 
2939 
2940  exprt writeable_object_expr = writeable_object_exprt(expr.arguments()[0]);
2941  writeable_object_expr.add_source_location() = source_location;
2942 
2943  return writeable_object_expr;
2944  }
2945  else if(identifier == CPROVER_PREFIX "separate")
2946  {
2947  // experimental feature for CHC encodings -- do not use
2948  if(expr.arguments().size() < 2)
2949  {
2951  error() << "separate expects two or more arguments" << eom;
2952  throw 0;
2953  }
2954 
2956 
2957  exprt separate_expr = separate_exprt(expr.arguments());
2958  separate_expr.add_source_location() = source_location;
2959 
2960  return separate_expr;
2961  }
2962  else if(identifier==CPROVER_PREFIX "POINTER_OFFSET")
2963  {
2964  if(expr.arguments().size()!=1)
2965  {
2967  error() << "pointer_offset expects one argument" << eom;
2968  throw 0;
2969  }
2970 
2972 
2973  exprt pointer_offset_expr=pointer_offset(expr.arguments().front());
2974  pointer_offset_expr.add_source_location()=source_location;
2975 
2976  return typecast_exprt::conditional_cast(pointer_offset_expr, expr.type());
2977  }
2978  else if(identifier == CPROVER_PREFIX "OBJECT_SIZE")
2979  {
2980  if(expr.arguments().size() != 1)
2981  {
2983  error() << "object_size expects one operand" << eom;
2984  throw 0;
2985  }
2986 
2988 
2989  object_size_exprt object_size_expr(expr.arguments()[0], size_type());
2990  object_size_expr.add_source_location() = source_location;
2991 
2992  return std::move(object_size_expr);
2993  }
2994  else if(identifier==CPROVER_PREFIX "POINTER_OBJECT")
2995  {
2996  if(expr.arguments().size()!=1)
2997  {
2999  error() << "pointer_object expects one argument" << eom;
3000  throw 0;
3001  }
3002 
3004 
3005  exprt pointer_object_expr = pointer_object(expr.arguments().front());
3006  pointer_object_expr.add_source_location() = source_location;
3007 
3008  return typecast_exprt::conditional_cast(pointer_object_expr, expr.type());
3009  }
3010  else if(identifier=="__builtin_bswap16" ||
3011  identifier=="__builtin_bswap32" ||
3012  identifier=="__builtin_bswap64")
3013  {
3014  if(expr.arguments().size()!=1)
3015  {
3017  error() << identifier << " expects one operand" << eom;
3018  throw 0;
3019  }
3020 
3022 
3023  // these are hard-wired to 8 bits according to the gcc manual
3024  bswap_exprt bswap_expr(expr.arguments().front(), 8, expr.type());
3025  bswap_expr.add_source_location()=source_location;
3026 
3027  return std::move(bswap_expr);
3028  }
3029  else if(
3030  identifier == "__builtin_rotateleft8" ||
3031  identifier == "__builtin_rotateleft16" ||
3032  identifier == "__builtin_rotateleft32" ||
3033  identifier == "__builtin_rotateleft64" ||
3034  identifier == "__builtin_rotateright8" ||
3035  identifier == "__builtin_rotateright16" ||
3036  identifier == "__builtin_rotateright32" ||
3037  identifier == "__builtin_rotateright64")
3038  {
3039  // clang only
3040  if(expr.arguments().size() != 2)
3041  {
3043  error() << identifier << " expects two operands" << eom;
3044  throw 0;
3045  }
3046 
3048 
3049  irep_idt id = (identifier == "__builtin_rotateleft8" ||
3050  identifier == "__builtin_rotateleft16" ||
3051  identifier == "__builtin_rotateleft32" ||
3052  identifier == "__builtin_rotateleft64")
3053  ? ID_rol
3054  : ID_ror;
3055 
3056  shift_exprt rotate_expr(expr.arguments()[0], id, expr.arguments()[1]);
3057  rotate_expr.add_source_location() = source_location;
3058 
3059  return std::move(rotate_expr);
3060  }
3061  else if(identifier=="__builtin_nontemporal_load")
3062  {
3063  if(expr.arguments().size()!=1)
3064  {
3066  error() << identifier << " expects one operand" << eom;
3067  throw 0;
3068  }
3069 
3071 
3072  // these return the subtype of the argument
3073  exprt &ptr_arg=expr.arguments().front();
3074 
3075  if(ptr_arg.type().id()!=ID_pointer)
3076  {
3078  error() << "__builtin_nontemporal_load takes pointer as argument" << eom;
3079  throw 0;
3080  }
3081 
3082  expr.type() = to_pointer_type(expr.arguments().front().type()).base_type();
3083 
3084  return expr;
3085  }
3086  else if(
3087  identifier == "__builtin_fpclassify" ||
3088  identifier == CPROVER_PREFIX "fpclassify")
3089  {
3090  if(expr.arguments().size() != 6)
3091  {
3093  error() << identifier << " expects six arguments" << eom;
3094  throw 0;
3095  }
3096 
3098 
3099  // This gets 5 integers followed by a float or double.
3100  // The five integers are the return values for the cases
3101  // FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL and FP_ZERO.
3102  // gcc expects this to be able to produce compile-time constants.
3103 
3104  const exprt &fp_value = expr.arguments()[5];
3105 
3106  if(fp_value.type().id() != ID_floatbv)
3107  {
3108  error().source_location = fp_value.source_location();
3109  error() << "non-floating-point argument for " << identifier << eom;
3110  throw 0;
3111  }
3112 
3113  const auto &floatbv_type = to_floatbv_type(fp_value.type());
3114 
3115  const exprt zero = ieee_floatt::zero(floatbv_type).to_expr();
3116 
3117  const auto &arguments = expr.arguments();
3118 
3119  return if_exprt(
3120  isnan_exprt(fp_value),
3121  arguments[0],
3122  if_exprt(
3123  isinf_exprt(fp_value),
3124  arguments[1],
3125  if_exprt(
3126  isnormal_exprt(fp_value),
3127  arguments[2],
3128  if_exprt(
3129  ieee_float_equal_exprt(fp_value, zero),
3130  arguments[4],
3131  arguments[3])))); // subnormal
3132  }
3133  else if(identifier==CPROVER_PREFIX "isnanf" ||
3134  identifier==CPROVER_PREFIX "isnand" ||
3135  identifier==CPROVER_PREFIX "isnanld" ||
3136  identifier=="__builtin_isnan")
3137  {
3138  if(expr.arguments().size()!=1)
3139  {
3141  error() << "isnan expects one operand" << eom;
3142  throw 0;
3143  }
3144 
3146 
3147  isnan_exprt isnan_expr(expr.arguments().front());
3148  isnan_expr.add_source_location()=source_location;
3149 
3150  return typecast_exprt::conditional_cast(isnan_expr, expr.type());
3151  }
3152  else if(identifier==CPROVER_PREFIX "isfinitef" ||
3153  identifier==CPROVER_PREFIX "isfinited" ||
3154  identifier==CPROVER_PREFIX "isfiniteld")
3155  {
3156  if(expr.arguments().size()!=1)
3157  {
3159  error() << "isfinite expects one operand" << eom;
3160  throw 0;
3161  }
3162 
3164 
3165  isfinite_exprt isfinite_expr(expr.arguments().front());
3166  isfinite_expr.add_source_location()=source_location;
3167 
3168  return typecast_exprt::conditional_cast(isfinite_expr, expr.type());
3169  }
3170  else if(identifier==CPROVER_PREFIX "inf" ||
3171  identifier=="__builtin_inf")
3172  {
3173  constant_exprt inf_expr=
3176  inf_expr.add_source_location()=source_location;
3177 
3178  return std::move(inf_expr);
3179  }
3180  else if(identifier==CPROVER_PREFIX "inff")
3181  {
3182  constant_exprt inff_expr=
3185  inff_expr.add_source_location()=source_location;
3186 
3187  return std::move(inff_expr);
3188  }
3189  else if(identifier==CPROVER_PREFIX "infl")
3190  {
3192  constant_exprt infl_expr=
3194  infl_expr.add_source_location()=source_location;
3195 
3196  return std::move(infl_expr);
3197  }
3198  else if(
3199  identifier == CPROVER_PREFIX "abs" || identifier == CPROVER_PREFIX "labs" ||
3200  identifier == CPROVER_PREFIX "llabs" ||
3201  identifier == CPROVER_PREFIX "imaxabs" ||
3202  identifier == CPROVER_PREFIX "fabs" ||
3203  identifier == CPROVER_PREFIX "fabsf" ||
3204  identifier == CPROVER_PREFIX "fabsl")
3205  {
3206  if(expr.arguments().size()!=1)
3207  {
3209  error() << "abs-functions expect one operand" << eom;
3210  throw 0;
3211  }
3212 
3214 
3215  abs_exprt abs_expr(expr.arguments().front());
3216  abs_expr.add_source_location()=source_location;
3217 
3218  return std::move(abs_expr);
3219  }
3220  else if(
3221  identifier == CPROVER_PREFIX "fmod" ||
3222  identifier == CPROVER_PREFIX "fmodf" ||
3223  identifier == CPROVER_PREFIX "fmodl")
3224  {
3225  if(expr.arguments().size() != 2)
3226  {
3228  error() << "fmod-functions expect two operands" << eom;
3229  throw 0;
3230  }
3231 
3233 
3234  // Note that the semantics differ from the
3235  // "floating point remainder" operation as defined by IEEE.
3236  // Note that these do not take a rounding mode.
3237  binary_exprt fmod_expr(
3238  expr.arguments()[0], ID_floatbv_mod, expr.arguments()[1]);
3239 
3240  fmod_expr.add_source_location() = source_location;
3241 
3242  return std::move(fmod_expr);
3243  }
3244  else if(
3245  identifier == CPROVER_PREFIX "remainder" ||
3246  identifier == CPROVER_PREFIX "remainderf" ||
3247  identifier == CPROVER_PREFIX "remainderl")
3248  {
3249  if(expr.arguments().size() != 2)
3250  {
3252  error() << "remainder-functions expect two operands" << eom;
3253  throw 0;
3254  }
3255 
3257 
3258  // The semantics of these functions is meant to match the
3259  // "floating point remainder" operation as defined by IEEE.
3260  // Note that these do not take a rounding mode.
3261  binary_exprt floatbv_rem_expr(
3262  expr.arguments()[0], ID_floatbv_rem, expr.arguments()[1]);
3263 
3264  floatbv_rem_expr.add_source_location() = source_location;
3265 
3266  return std::move(floatbv_rem_expr);
3267  }
3268  else if(identifier==CPROVER_PREFIX "allocate")
3269  {
3270  if(expr.arguments().size()!=2)
3271  {
3273  error() << "allocate expects two operands" << eom;
3274  throw 0;
3275  }
3276 
3278 
3279  side_effect_exprt malloc_expr(ID_allocate, expr.type(), source_location);
3280  malloc_expr.operands()=expr.arguments();
3281 
3282  return std::move(malloc_expr);
3283  }
3284  else if(
3285  (identifier == CPROVER_PREFIX "old") ||
3286  (identifier == CPROVER_PREFIX "loop_entry"))
3287  {
3288  if(expr.arguments().size() != 1)
3289  {
3291  error() << identifier << " expects one operand" << eom;
3292  throw 0;
3293  }
3294 
3295  const auto &param_id = expr.arguments().front().id();
3296  if(!(param_id == ID_dereference || param_id == ID_member ||
3297  param_id == ID_symbol || param_id == ID_ptrmember ||
3298  param_id == ID_constant || param_id == ID_typecast ||
3299  param_id == ID_index))
3300  {
3302  error() << "Tracking history of " << param_id
3303  << " expressions is not supported yet." << eom;
3304  throw 0;
3305  }
3306 
3307  irep_idt id = identifier == CPROVER_PREFIX "old" ? ID_old : ID_loop_entry;
3308 
3309  history_exprt old_expr(expr.arguments()[0], id);
3310  old_expr.add_source_location() = source_location;
3311 
3312  return std::move(old_expr);
3313  }
3314  else if(identifier==CPROVER_PREFIX "isinff" ||
3315  identifier==CPROVER_PREFIX "isinfd" ||
3316  identifier==CPROVER_PREFIX "isinfld" ||
3317  identifier=="__builtin_isinf")
3318  {
3319  if(expr.arguments().size()!=1)
3320  {
3322  error() << identifier << " expects one operand" << eom;
3323  throw 0;
3324  }
3325 
3327 
3328  const exprt &fp_value = expr.arguments().front();
3329 
3330  if(fp_value.type().id() != ID_floatbv)
3331  {
3332  error().source_location = fp_value.source_location();
3333  error() << "non-floating-point argument for " << identifier << eom;
3334  throw 0;
3335  }
3336 
3337  isinf_exprt isinf_expr(expr.arguments().front());
3338  isinf_expr.add_source_location()=source_location;
3339 
3340  return typecast_exprt::conditional_cast(isinf_expr, expr.type());
3341  }
3342  else if(identifier == "__builtin_isinf_sign")
3343  {
3344  if(expr.arguments().size() != 1)
3345  {
3347  error() << identifier << " expects one operand" << eom;
3348  throw 0;
3349  }
3350 
3352 
3353  // returns 1 for +inf and -1 for -inf, and 0 otherwise
3354 
3355  const exprt &fp_value = expr.arguments().front();
3356 
3357  if(fp_value.type().id() != ID_floatbv)
3358  {
3359  error().source_location = fp_value.source_location();
3360  error() << "non-floating-point argument for " << identifier << eom;
3361  throw 0;
3362  }
3363 
3364  isinf_exprt isinf_expr(fp_value);
3365  isinf_expr.add_source_location() = source_location;
3366 
3367  return if_exprt(
3368  isinf_exprt(fp_value),
3369  if_exprt(
3370  sign_exprt(fp_value),
3371  from_integer(-1, expr.type()),
3372  from_integer(1, expr.type())),
3373  from_integer(0, expr.type()));
3374  }
3375  else if(identifier == CPROVER_PREFIX "isnormalf" ||
3376  identifier == CPROVER_PREFIX "isnormald" ||
3377  identifier == CPROVER_PREFIX "isnormalld" ||
3378  identifier == "__builtin_isnormal")
3379  {
3380  if(expr.arguments().size()!=1)
3381  {
3383  error() << identifier << " expects one operand" << eom;
3384  throw 0;
3385  }
3386 
3388 
3389  const exprt &fp_value = expr.arguments()[0];
3390 
3391  if(fp_value.type().id() != ID_floatbv)
3392  {
3393  error().source_location = fp_value.source_location();
3394  error() << "non-floating-point argument for " << identifier << eom;
3395  throw 0;
3396  }
3397 
3398  isnormal_exprt isnormal_expr(expr.arguments().front());
3399  isnormal_expr.add_source_location()=source_location;
3400 
3401  return typecast_exprt::conditional_cast(isnormal_expr, expr.type());
3402  }
3403  else if(identifier==CPROVER_PREFIX "signf" ||
3404  identifier==CPROVER_PREFIX "signd" ||
3405  identifier==CPROVER_PREFIX "signld" ||
3406  identifier=="__builtin_signbit" ||
3407  identifier=="__builtin_signbitf" ||
3408  identifier=="__builtin_signbitl")
3409  {
3410  if(expr.arguments().size()!=1)
3411  {
3413  error() << identifier << " expects one operand" << eom;
3414  throw 0;
3415  }
3416 
3418 
3419  sign_exprt sign_expr(expr.arguments().front());
3420  sign_expr.add_source_location()=source_location;
3421 
3422  return typecast_exprt::conditional_cast(sign_expr, expr.type());
3423  }
3424  else if(identifier=="__builtin_popcount" ||
3425  identifier=="__builtin_popcountl" ||
3426  identifier=="__builtin_popcountll" ||
3427  identifier=="__popcnt16" ||
3428  identifier=="__popcnt" ||
3429  identifier=="__popcnt64")
3430  {
3431  if(expr.arguments().size()!=1)
3432  {
3434  error() << identifier << " expects one operand" << eom;
3435  throw 0;
3436  }
3437 
3439 
3440  popcount_exprt popcount_expr(expr.arguments().front(), expr.type());
3441  popcount_expr.add_source_location()=source_location;
3442 
3443  return std::move(popcount_expr);
3444  }
3445  else if(
3446  identifier == "__builtin_clz" || identifier == "__builtin_clzl" ||
3447  identifier == "__builtin_clzll" || identifier == "__lzcnt16" ||
3448  identifier == "__lzcnt" || identifier == "__lzcnt64")
3449  {
3450  if(expr.arguments().size() != 1)
3451  {
3453  error() << identifier << " expects one operand" << eom;
3454  throw 0;
3455  }
3456 
3458 
3460  expr.arguments().front(), identifier.starts_with("__lzcnt"), expr.type()};
3461  clz.add_source_location() = source_location;
3462 
3463  return std::move(clz);
3464  }
3465  else if(
3466  identifier == "__builtin_ctz" || identifier == "__builtin_ctzl" ||
3467  identifier == "__builtin_ctzll")
3468  {
3469  if(expr.arguments().size() != 1)
3470  {
3472  error() << identifier << " expects one operand" << eom;
3473  throw 0;
3474  }
3475 
3477 
3479  expr.arguments().front(), false, expr.type()};
3480  ctz.add_source_location() = source_location;
3481 
3482  return std::move(ctz);
3483  }
3484  else if(
3485  identifier == "__builtin_ffs" || identifier == "__builtin_ffsl" ||
3486  identifier == "__builtin_ffsll")
3487  {
3488  if(expr.arguments().size() != 1)
3489  {
3491  error() << identifier << " expects one operand" << eom;
3492  throw 0;
3493  }
3494 
3496 
3497  find_first_set_exprt ffs{expr.arguments().front(), expr.type()};
3498  ffs.add_source_location() = source_location;
3499 
3500  return std::move(ffs);
3501  }
3502  else if(identifier=="__builtin_expect")
3503  {
3504  // This is a gcc extension to provide branch prediction.
3505  // We compile it away, but adding some IR instruction for
3506  // this would clearly be an option. Note that the type
3507  // of the return value is wired to "long", i.e.,
3508  // this may trigger a type conversion due to the signature
3509  // of this function.
3510  if(expr.arguments().size()!=2)
3511  {
3513  error() << "__builtin_expect expects two arguments" << eom;
3514  throw 0;
3515  }
3516 
3518 
3519  return typecast_exprt(expr.arguments()[0], expr.type());
3520  }
3521  else if(
3522  identifier == "__builtin_object_size" ||
3523  identifier == "__builtin_dynamic_object_size")
3524  {
3525  // These are gcc extensions to provide information about
3526  // object sizes at compile time
3527  // http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
3528  // Our behavior is as if it was never possible to determine the object that
3529  // the pointer pointed to.
3530 
3531  if(expr.arguments().size()!=2)
3532  {
3534  error() << "__builtin_object_size expects two arguments" << eom;
3535  throw 0;
3536  }
3537 
3539 
3540  make_constant(expr.arguments()[1]);
3541 
3542  mp_integer arg1;
3543 
3544  if(expr.arguments()[1].is_true())
3545  arg1=1;
3546  else if(expr.arguments()[1].is_false())
3547  arg1=0;
3548  else if(to_integer(to_constant_expr(expr.arguments()[1]), arg1))
3549  {
3551  error() << "__builtin_object_size expects constant as second argument, "
3552  << "but got " << to_string(expr.arguments()[1]) << eom;
3553  throw 0;
3554  }
3555 
3556  exprt tmp;
3557 
3558  // the following means "don't know"
3559  if(arg1==0 || arg1==1)
3560  {
3561  tmp=from_integer(-1, size_type());
3562  tmp.add_source_location()=f_op.source_location();
3563  }
3564  else
3565  {
3566  tmp=from_integer(0, size_type());
3567  tmp.add_source_location()=f_op.source_location();
3568  }
3569 
3570  return tmp;
3571  }
3572  else if(identifier=="__builtin_choose_expr")
3573  {
3574  // this is a gcc extension similar to ?:
3575  if(expr.arguments().size()!=3)
3576  {
3578  error() << "__builtin_choose_expr expects three arguments" << eom;
3579  throw 0;
3580  }
3581 
3583 
3584  exprt arg0 =
3586  make_constant(arg0);
3587 
3588  if(arg0.is_true())
3589  return expr.arguments()[1];
3590  else
3591  return expr.arguments()[2];
3592  }
3593  else if(identifier=="__builtin_constant_p")
3594  {
3595  // this is a gcc extension to tell whether the argument
3596  // is known to be a compile-time constant
3597  if(expr.arguments().size()!=1)
3598  {
3600  error() << "__builtin_constant_p expects one argument" << eom;
3601  throw 0;
3602  }
3603 
3604  // do not typecheck the argument - it is never evaluated, and thus side
3605  // effects must not show up either
3606 
3607  // try to produce constant
3608  exprt tmp1=expr.arguments().front();
3609  simplify(tmp1, *this);
3610 
3611  bool is_constant=false;
3612 
3613  // Need to do some special treatment for string literals,
3614  // which are (void *)&("lit"[0])
3615  if(
3616  tmp1.id() == ID_typecast &&
3617  to_typecast_expr(tmp1).op().id() == ID_address_of &&
3618  to_address_of_expr(to_typecast_expr(tmp1).op()).object().id() ==
3619  ID_index &&
3620  to_index_expr(to_address_of_expr(to_typecast_expr(tmp1).op()).object())
3621  .array()
3622  .id() == ID_string_constant)
3623  {
3624  is_constant=true;
3625  }
3626  else
3627  is_constant=tmp1.is_constant();
3628 
3629  exprt tmp2=from_integer(is_constant, expr.type());
3630  tmp2.add_source_location()=source_location;
3631 
3632  return tmp2;
3633  }
3634  else if(identifier=="__builtin_classify_type")
3635  {
3636  // This is a gcc/clang extension that produces an integer
3637  // constant for the type of the argument expression.
3638  if(expr.arguments().size()!=1)
3639  {
3641  error() << "__builtin_classify_type expects one argument" << eom;
3642  throw 0;
3643  }
3644 
3646 
3647  exprt object=expr.arguments()[0];
3648 
3649  // The value doesn't matter at all, we only care about the type.
3650  // Need to sync with typeclass.h.
3651  // use underlying type for bit fields
3652  const typet &type = object.type().id() == ID_c_bit_field
3653  ? to_c_bit_field_type(object.type()).underlying_type()
3654  : object.type();
3655 
3656  unsigned type_number;
3657 
3658  if(type.id() == ID_bool || type.id() == ID_c_bool)
3659  {
3660  // clang returns 4 for _Bool, gcc treats these as 'int'.
3661  type_number =
3663  }
3664  else
3665  {
3666  type_number = type.id() == ID_empty ? 0u
3667  : (type.id() == ID_bool || type.id() == ID_c_bool) ? 4u
3668  : (type.id() == ID_pointer || type.id() == ID_array) ? 5u
3669  : type.id() == ID_floatbv ? 8u
3670  : (type.id() == ID_complex &&
3671  to_complex_type(type).subtype().id() == ID_floatbv)
3672  ? 9u
3673  : type.id() == ID_struct_tag ? 12u
3674  : type.id() == ID_union_tag
3675  ? 13u
3676  : 1u; // int, short, char, enum_tag
3677  }
3678 
3679  exprt tmp=from_integer(type_number, expr.type());
3680  tmp.add_source_location()=source_location;
3681 
3682  return tmp;
3683  }
3684  else if(
3685  identifier == "__builtin_add_overflow" ||
3686  identifier == "__builtin_sadd_overflow" ||
3687  identifier == "__builtin_saddl_overflow" ||
3688  identifier == "__builtin_saddll_overflow" ||
3689  identifier == "__builtin_uadd_overflow" ||
3690  identifier == "__builtin_uaddl_overflow" ||
3691  identifier == "__builtin_uaddll_overflow" ||
3692  identifier == "__builtin_add_overflow_p")
3693  {
3694  return typecheck_builtin_overflow(expr, ID_plus);
3695  }
3696  else if(
3697  identifier == "__builtin_sub_overflow" ||
3698  identifier == "__builtin_ssub_overflow" ||
3699  identifier == "__builtin_ssubl_overflow" ||
3700  identifier == "__builtin_ssubll_overflow" ||
3701  identifier == "__builtin_usub_overflow" ||
3702  identifier == "__builtin_usubl_overflow" ||
3703  identifier == "__builtin_usubll_overflow" ||
3704  identifier == "__builtin_sub_overflow_p")
3705  {
3706  return typecheck_builtin_overflow(expr, ID_minus);
3707  }
3708  else if(
3709  identifier == "__builtin_mul_overflow" ||
3710  identifier == "__builtin_smul_overflow" ||
3711  identifier == "__builtin_smull_overflow" ||
3712  identifier == "__builtin_smulll_overflow" ||
3713  identifier == "__builtin_umul_overflow" ||
3714  identifier == "__builtin_umull_overflow" ||
3715  identifier == "__builtin_umulll_overflow" ||
3716  identifier == "__builtin_mul_overflow_p")
3717  {
3718  return typecheck_builtin_overflow(expr, ID_mult);
3719  }
3720  else if(
3721  identifier == "__builtin_bitreverse8" ||
3722  identifier == "__builtin_bitreverse16" ||
3723  identifier == "__builtin_bitreverse32" ||
3724  identifier == "__builtin_bitreverse64")
3725  {
3726  // clang only
3727  if(expr.arguments().size() != 1)
3728  {
3729  std::ostringstream error_message;
3730  error_message << "error: " << identifier << " expects one operand";
3732  error_message.str(), expr.source_location()};
3733  }
3734 
3736 
3737  bitreverse_exprt bitreverse{expr.arguments()[0]};
3738  bitreverse.add_source_location() = source_location;
3739 
3740  return std::move(bitreverse);
3741  }
3742  else
3743  return nil_exprt();
3744  // NOLINTNEXTLINE(readability/fn_size)
3745 }
3746 
3749  const irep_idt &arith_op)
3750 {
3751  const irep_idt &identifier = to_symbol_expr(expr.function()).get_identifier();
3752 
3753  // check function signature
3754  if(expr.arguments().size() != 3)
3755  {
3756  std::ostringstream error_message;
3757  error_message << identifier << " takes exactly 3 arguments, but "
3758  << expr.arguments().size() << " were provided";
3760  error_message.str(), expr.source_location()};
3761  }
3762 
3764 
3765  auto lhs = expr.arguments()[0];
3766  auto rhs = expr.arguments()[1];
3767  auto result = expr.arguments()[2];
3768 
3769  const bool is__p_variant = has_suffix(id2string(identifier), "_p");
3770 
3771  {
3772  auto const raise_wrong_argument_error =
3773  [this, identifier](
3774  const exprt &wrong_argument, std::size_t argument_number, bool _p) {
3775  std::ostringstream error_message;
3776  error_message << "error: " << identifier << " has signature "
3777  << identifier << "(integral, integral, integral"
3778  << (_p ? "" : "*") << "), "
3779  << "but argument " << argument_number << " ("
3780  << expr2c(wrong_argument, *this) << ") has type `"
3781  << type2c(wrong_argument.type(), *this) << '`';
3783  error_message.str(), wrong_argument.source_location()};
3784  };
3785  for(int arg_index = 0; arg_index <= (!is__p_variant ? 1 : 2); ++arg_index)
3786  {
3787  auto const &argument = expr.arguments()[arg_index];
3788 
3789  if(!is_signed_or_unsigned_bitvector(argument.type()))
3790  {
3791  raise_wrong_argument_error(argument, arg_index + 1, is__p_variant);
3792  }
3793  }
3794  if(
3795  !is__p_variant && (result.type().id() != ID_pointer ||
3797  to_pointer_type(result.type()).base_type())))
3798  {
3799  raise_wrong_argument_error(result, 3, is__p_variant);
3800  }
3801  }
3802 
3803  return side_effect_expr_overflowt{arith_op,
3804  std::move(lhs),
3805  std::move(rhs),
3806  std::move(result),
3807  expr.source_location()};
3808 }
3809 
3811  const side_effect_expr_function_callt &expr)
3812 {
3813  const irep_idt &identifier = to_symbol_expr(expr.function()).get_identifier();
3814 
3815  // check function signature
3816  if(expr.arguments().size() != 2)
3817  {
3818  std::ostringstream error_message;
3819  error_message << "error: " << identifier
3820  << " takes exactly two arguments, but "
3821  << expr.arguments().size() << " were provided";
3823  error_message.str(), expr.source_location()};
3824  }
3825 
3826  exprt result;
3827  if(identifier == CPROVER_PREFIX "saturating_minus")
3828  result = saturating_minus_exprt{expr.arguments()[0], expr.arguments()[1]};
3829  else if(identifier == CPROVER_PREFIX "saturating_plus")
3830  result = saturating_plus_exprt{expr.arguments()[0], expr.arguments()[1]};
3831  else
3832  UNREACHABLE;
3833 
3835  result.add_source_location() = expr.source_location();
3836 
3837  return result;
3838 }
3839 
3844 {
3845  const exprt &f_op=expr.function();
3846  const code_typet &code_type=to_code_type(f_op.type());
3847  exprt::operandst &arguments=expr.arguments();
3848  const code_typet::parameterst &parameters = code_type.parameters();
3849 
3850  // no. of arguments test
3851 
3852  if(code_type.get_bool(ID_C_incomplete))
3853  {
3854  // can't check
3855  }
3856  else if(code_type.is_KnR())
3857  {
3858  // We are generous on KnR; any number is ok.
3859  // We will fill in missing ones with "nondet".
3860  for(std::size_t i = arguments.size(); i < parameters.size(); ++i)
3861  {
3862  arguments.push_back(
3863  side_effect_expr_nondett{parameters[i].type(), expr.source_location()});
3864  }
3865  }
3866  else if(code_type.has_ellipsis())
3867  {
3868  if(parameters.size() > arguments.size())
3869  {
3871  error() << "not enough function arguments" << eom;
3872  throw 0;
3873  }
3874  }
3875  else if(parameters.size() != arguments.size())
3876  {
3878  error() << "wrong number of function arguments: "
3879  << "expected " << parameters.size() << ", but got "
3880  << arguments.size() << eom;
3881  throw 0;
3882  }
3883 
3884  for(std::size_t i=0; i<arguments.size(); i++)
3885  {
3886  exprt &op=arguments[i];
3887 
3888  if(op.is_nil())
3889  {
3890  // ignore
3891  }
3892  else if(i < parameters.size())
3893  {
3894  const code_typet::parametert &parameter = parameters[i];
3895 
3896  if(
3897  parameter.is_boolean() && op.id() == ID_side_effect &&
3898  op.get(ID_statement) == ID_assign && op.type().id() != ID_bool)
3899  {
3901  warning() << "assignment where Boolean argument is expected" << eom;
3902  }
3903 
3904  implicit_typecast(op, parameter.type());
3905  }
3906  else
3907  {
3908  // don't know type, just do standard conversion
3909 
3910  if(op.type().id() == ID_array)
3911  {
3912  auto dest_type = pointer_type(void_type());
3913  dest_type.base_type().set(ID_C_constant, true);
3914  implicit_typecast(op, dest_type);
3915  }
3916  }
3917  }
3918 }
3919 
3921 {
3922  // nothing to do
3923 }
3924 
3926 {
3927  exprt &operand = to_unary_expr(expr).op();
3928 
3929  const typet &o_type = operand.type();
3930 
3931  if(o_type.id()==ID_vector)
3932  {
3933  if(is_number(to_vector_type(o_type).element_type()))
3934  {
3935  // Vector arithmetic.
3936  expr.type()=operand.type();
3937  return;
3938  }
3939  }
3940 
3942 
3943  if(is_number(operand.type()))
3944  {
3945  expr.type()=operand.type();
3946  return;
3947  }
3948 
3950  error() << "operator '" << expr.id() << "' not defined for type '"
3951  << to_string(operand.type()) << "'" << eom;
3952  throw 0;
3953 }
3954 
3956 {
3958 
3959  // This is not quite accurate: the standard says the result
3960  // should be of type 'int'.
3961  // We do 'bool' anyway to get more compact formulae. Eventually,
3962  // this should be achieved by means of simplification, and not
3963  // in the frontend.
3964  expr.type()=bool_typet();
3965 }
3966 
3968  const vector_typet &type0,
3969  const vector_typet &type1)
3970 {
3971  // This is relatively restrictive!
3972 
3973  // compare dimension
3974  const auto s0 = numeric_cast<mp_integer>(type0.size());
3975  const auto s1 = numeric_cast<mp_integer>(type1.size());
3976  if(!s0.has_value())
3977  return false;
3978  if(!s1.has_value())
3979  return false;
3980  if(*s0 != *s1)
3981  return false;
3982 
3983  // compare subtype
3984  if(
3985  (type0.element_type().id() == ID_signedbv ||
3986  type0.element_type().id() == ID_unsignedbv) &&
3987  (type1.element_type().id() == ID_signedbv ||
3988  type1.element_type().id() == ID_unsignedbv) &&
3991  return true;
3992 
3993  return type0.element_type() == type1.element_type();
3994 }
3995 
3997 {
3998  auto &binary_expr = to_binary_expr(expr);
3999  exprt &op0 = binary_expr.op0();
4000  exprt &op1 = binary_expr.op1();
4001 
4002  const typet o_type0 = op0.type();
4003  const typet o_type1 = op1.type();
4004 
4005  if(o_type0.id()==ID_vector &&
4006  o_type1.id()==ID_vector)
4007  {
4008  if(
4010  to_vector_type(o_type0), to_vector_type(o_type1)) &&
4011  is_number(to_vector_type(o_type0).element_type()))
4012  {
4013  // Vector arithmetic has fairly strict typing rules, no promotion
4014  op1 = typecast_exprt::conditional_cast(op1, op0.type());
4015  expr.type()=op0.type();
4016  return;
4017  }
4018  }
4019  else if(
4020  o_type0.id() == ID_vector && o_type1.id() != ID_vector &&
4021  is_number(o_type1))
4022  {
4023  // convert op1 to the vector type
4024  op1 = typecast_exprt(op1, o_type0);
4025  expr.type() = o_type0;
4026  return;
4027  }
4028  else if(
4029  o_type0.id() != ID_vector && o_type1.id() == ID_vector &&
4030  is_number(o_type0))
4031  {
4032  // convert op0 to the vector type
4033  op0 = typecast_exprt(op0, o_type1);
4034  expr.type() = o_type1;
4035  return;
4036  }
4037 
4038  if(expr.id() == ID_saturating_minus || expr.id() == ID_saturating_plus)
4039  {
4040  implicit_typecast(op1, o_type0);
4041  }
4042  else
4043  {
4044  // promote!
4045  implicit_typecast_arithmetic(op0, op1);
4046  }
4047 
4048  const typet &type0 = op0.type();
4049  const typet &type1 = op1.type();
4050 
4051  if(expr.id()==ID_plus || expr.id()==ID_minus ||
4052  expr.id()==ID_mult || expr.id()==ID_div)
4053  {
4054  if(type0.id()==ID_pointer || type1.id()==ID_pointer)
4055  {
4057  return;
4058  }
4059  else if(type0==type1)
4060  {
4061  if(is_number(type0))
4062  {
4063  expr.type()=type0;
4064  return;
4065  }
4066  }
4067  }
4068  else if(expr.id()==ID_mod)
4069  {
4070  if(type0==type1)
4071  {
4072  if(type0.id()==ID_signedbv || type0.id()==ID_unsignedbv)
4073  {
4074  expr.type()=type0;
4075  return;
4076  }
4077  }
4078  }
4079  else if(
4080  expr.id() == ID_bitand || expr.id() == ID_bitnand ||
4081  expr.id() == ID_bitxor || expr.id() == ID_bitor)
4082  {
4083  if(type0==type1)
4084  {
4085  if(is_number(type0))
4086  {
4087  expr.type()=type0;
4088  return;
4089  }
4090  else if(type0.id()==ID_bool)
4091  {
4092  if(expr.id()==ID_bitand)
4093  expr.id(ID_and);
4094  else if(expr.id() == ID_bitnand)
4095  expr.id(ID_nand);
4096  else if(expr.id()==ID_bitor)
4097  expr.id(ID_or);
4098  else if(expr.id()==ID_bitxor)
4099  expr.id(ID_xor);
4100  else
4101  UNREACHABLE;
4102  expr.type()=type0;
4103  return;
4104  }
4105  }
4106  }
4107  else if(expr.id() == ID_saturating_minus || expr.id() == ID_saturating_plus)
4108  {
4109  if(
4110  type0 == type1 &&
4111  (type0.id() == ID_signedbv || type0.id() == ID_unsignedbv))
4112  {
4113  expr.type() = type0;
4114  return;
4115  }
4116  }
4117 
4119  error() << "operator '" << expr.id() << "' not defined for types '"
4120  << to_string(o_type0) << "' and '" << to_string(o_type1) << "'"
4121  << eom;
4122  throw 0;
4123 }
4124 
4126 {
4127  PRECONDITION(expr.id() == ID_shl || expr.id() == ID_shr);
4128 
4129  exprt &op0=expr.op0();
4130  exprt &op1=expr.op1();
4131 
4132  const typet o_type0 = op0.type();
4133  const typet o_type1 = op1.type();
4134 
4135  if(o_type0.id()==ID_vector &&
4136  o_type1.id()==ID_vector)
4137  {
4138  if(
4139  to_vector_type(o_type0).element_type() ==
4140  to_vector_type(o_type1).element_type() &&
4141  is_number(to_vector_type(o_type0).element_type()))
4142  {
4143  // {a0, a1, ..., an} >> {b0, b1, ..., bn} ==
4144  // {a0 >> b0, a1 >> b1, ..., an >> bn}
4145  // Fairly strict typing rules, no promotion
4146  expr.type()=op0.type();
4147  return;
4148  }
4149  }
4150 
4151  if(
4152  o_type0.id() == ID_vector &&
4153  is_number(to_vector_type(o_type0).element_type()) && is_number(o_type1))
4154  {
4155  // {a0, a1, ..., an} >> b == {a0 >> b, a1 >> b, ..., an >> b}
4156  op1 = typecast_exprt(op1, o_type0);
4157  expr.type()=op0.type();
4158  return;
4159  }
4160 
4161  // must do the promotions _separately_!
4164 
4165  if(is_number(op0.type()) &&
4166  is_number(op1.type()))
4167  {
4168  expr.type()=op0.type();
4169 
4170  if(expr.id()==ID_shr) // shifting operation depends on types
4171  {
4172  const typet &op0_type = op0.type();
4173 
4174  if(op0_type.id()==ID_unsignedbv)
4175  {
4176  expr.id(ID_lshr);
4177  return;
4178  }
4179  else if(op0_type.id()==ID_signedbv)
4180  {
4181  expr.id(ID_ashr);
4182  return;
4183  }
4184  }
4185 
4186  return;
4187  }
4188 
4190  error() << "operator '" << expr.id() << "' not defined for types '"
4191  << to_string(o_type0) << "' and '" << to_string(o_type1) << "'"
4192  << eom;
4193  throw 0;
4194 }
4195 
4197 {
4198  const typet &type=expr.type();
4199  PRECONDITION(type.id() == ID_pointer);
4200 
4201  const typet &base_type = to_pointer_type(type).base_type();
4202 
4203  if(
4204  base_type.id() == ID_struct_tag &&
4205  follow_tag(to_struct_tag_type(base_type)).is_incomplete())
4206  {
4208  error() << "pointer arithmetic with unknown object size" << eom;
4209  throw 0;
4210  }
4211  else if(
4212  base_type.id() == ID_union_tag &&
4213  follow_tag(to_union_tag_type(base_type)).is_incomplete())
4214  {
4216  error() << "pointer arithmetic with unknown object size" << eom;
4217  throw 0;
4218  }
4219  else if(
4220  base_type.id() == ID_empty &&
4222  {
4224  error() << "pointer arithmetic with unknown object size" << eom;
4225  throw 0;
4226  }
4227  else if(base_type.id() == ID_empty)
4228  {
4229  // This is a gcc extension.
4230  // https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Pointer-Arith.html
4231  typecast_exprt tc{expr, pointer_type(char_type())};
4232  expr.swap(tc);
4233  }
4234 }
4235 
4237 {
4238  auto &binary_expr = to_binary_expr(expr);
4239  exprt &op0 = binary_expr.op0();
4240  exprt &op1 = binary_expr.op1();
4241 
4242  const typet &type0 = op0.type();
4243  const typet &type1 = op1.type();
4244 
4245  if(expr.id()==ID_minus ||
4246  (expr.id()==ID_side_effect && expr.get(ID_statement)==ID_assign_minus))
4247  {
4248  if(type0.id()==ID_pointer &&
4249  type1.id()==ID_pointer)
4250  {
4251  if(type0 != type1)
4252  {
4254  "pointer subtraction over different types", expr.source_location()};
4255  }
4256  expr.type()=pointer_diff_type();
4259  return;
4260  }
4261 
4262  if(type0.id()==ID_pointer &&
4263  (type1.id()==ID_bool ||
4264  type1.id()==ID_c_bool ||
4265  type1.id()==ID_unsignedbv ||
4266  type1.id()==ID_signedbv ||
4267  type1.id()==ID_c_bit_field ||
4268  type1.id()==ID_c_enum_tag))
4269  {
4271  make_index_type(op1);
4272  expr.type() = op0.type();
4273  return;
4274  }
4275  }
4276  else if(expr.id()==ID_plus ||
4277  (expr.id()==ID_side_effect && expr.get(ID_statement)==ID_assign_plus))
4278  {
4279  exprt *p_op, *int_op;
4280 
4281  if(type0.id()==ID_pointer)
4282  {
4283  p_op=&op0;
4284  int_op=&op1;
4285  }
4286  else if(type1.id()==ID_pointer)
4287  {
4288  p_op=&op1;
4289  int_op=&op0;
4290  }
4291  else
4292  {
4293  p_op=int_op=nullptr;
4294  UNREACHABLE;
4295  }
4296 
4297  const typet &int_op_type = int_op->type();
4298 
4299  if(int_op_type.id()==ID_bool ||
4300  int_op_type.id()==ID_c_bool ||
4301  int_op_type.id()==ID_unsignedbv ||
4302  int_op_type.id()==ID_signedbv ||
4303  int_op_type.id()==ID_c_bit_field ||
4304  int_op_type.id()==ID_c_enum_tag)
4305  {
4307  make_index_type(*int_op);
4308  expr.type()=p_op->type();
4309  return;
4310  }
4311  }
4312 
4313  irep_idt op_name;
4314 
4315  if(expr.id()==ID_side_effect)
4316  op_name=to_side_effect_expr(expr).get_statement();
4317  else
4318  op_name=expr.id();
4319 
4321  error() << "operator '" << op_name << "' not defined for types '"
4322  << to_string(type0) << "' and '" << to_string(type1) << "'" << eom;
4323  throw 0;
4324 }
4325 
4327 {
4328  auto &binary_expr = to_binary_expr(expr);
4329  implicit_typecast_bool(binary_expr.op0());
4330  implicit_typecast_bool(binary_expr.op1());
4331 
4332  // This is not quite accurate: the standard says the result
4333  // should be of type 'int'.
4334  // We do 'bool' anyway to get more compact formulae. Eventually,
4335  // this should be achieved by means of simplification, and not
4336  // in the frontend.
4337  expr.type()=bool_typet();
4338 }
4339 
4341  side_effect_exprt &expr)
4342 {
4343  const irep_idt &statement=expr.get_statement();
4344 
4345  auto &binary_expr = to_binary_expr(expr);
4346  exprt &op0 = binary_expr.op0();
4347  exprt &op1 = binary_expr.op1();
4348 
4349  {
4350  const typet &type0=op0.type();
4351 
4352  if(type0.id()==ID_empty)
4353  {
4355  error() << "cannot assign void" << eom;
4356  throw 0;
4357  }
4358 
4359  if(!op0.get_bool(ID_C_lvalue))
4360  {
4362  error() << "assignment error: '" << to_string(op0) << "' not an lvalue"
4363  << eom;
4364  throw 0;
4365  }
4366 
4367  if(type0.get_bool(ID_C_constant))
4368  {
4370  error() << "'" << to_string(op0) << "' is constant" << eom;
4371  throw 0;
4372  }
4373 
4374  // refuse to assign arrays
4375  if(type0.id() == ID_array)
4376  {
4378  error() << "direct assignments to arrays not permitted" << eom;
4379  throw 0;
4380  }
4381  }
4382 
4383  // Add a cast to the underlying type for bit fields.
4384  if(op0.type() != op1.type() && op0.type().id() == ID_c_bit_field)
4385  {
4386  op1 =
4388  }
4389 
4390  const typet o_type0=op0.type();
4391  const typet o_type1=op1.type();
4392 
4393  expr.type()=o_type0;
4394 
4395  if(statement==ID_assign)
4396  {
4397  implicit_typecast(op1, o_type0);
4398  return;
4399  }
4400  else if(statement==ID_assign_shl ||
4401  statement==ID_assign_shr)
4402  {
4403  if(o_type0.id() == ID_vector)
4404  {
4405  auto &vector_o_type0 = to_vector_type(o_type0);
4406 
4407  if(
4408  o_type1.id() == ID_vector &&
4409  vector_o_type0.element_type() ==
4410  to_vector_type(o_type1).element_type() &&
4411  is_number(vector_o_type0.element_type()))
4412  {
4413  return;
4414  }
4415  else if(is_number(vector_o_type0.element_type()) && is_number(o_type1))
4416  {
4417  op1 = typecast_exprt(op1, o_type0);
4418  return;
4419  }
4420  }
4421 
4424 
4425  if(is_number(op0.type()) && is_number(op1.type()))
4426  {
4427  if(statement==ID_assign_shl)
4428  {
4429  return;
4430  }
4431  else // assign_shr
4432  {
4433  // distinguish arithmetic from logical shifts by looking at type
4434 
4435  typet underlying_type=op0.type();
4436 
4437  if(underlying_type.id()==ID_unsignedbv ||
4438  underlying_type.id()==ID_c_bool)
4439  {
4440  expr.set(ID_statement, ID_assign_lshr);
4441  return;
4442  }
4443  else if(underlying_type.id()==ID_signedbv)
4444  {
4445  expr.set(ID_statement, ID_assign_ashr);
4446  return;
4447  }
4448  }
4449  }
4450  }
4451  else if(statement==ID_assign_bitxor ||
4452  statement==ID_assign_bitand ||
4453  statement==ID_assign_bitor)
4454  {
4455  // these are more restrictive
4456  if(o_type0.id()==ID_bool ||
4457  o_type0.id()==ID_c_bool)
4458  {
4459  implicit_typecast_arithmetic(op0, op1);
4460  if(
4461  op1.is_boolean() || op1.type().id() == ID_c_bool ||
4462  op1.type().id() == ID_c_enum_tag || op1.type().id() == ID_unsignedbv ||
4463  op1.type().id() == ID_signedbv || op1.type().id() == ID_c_bit_field)
4464  {
4465  return;
4466  }
4467  }
4468  else if(o_type0.id()==ID_c_enum_tag ||
4469  o_type0.id()==ID_unsignedbv ||
4470  o_type0.id()==ID_signedbv ||
4471  o_type0.id()==ID_c_bit_field)
4472  {
4473  implicit_typecast_arithmetic(op0, op1);
4474  if(
4475  op1.type().id() == ID_c_enum_tag || op1.type().id() == ID_unsignedbv ||
4476  op1.type().id() == ID_signedbv || op1.type().id() == ID_c_bit_field)
4477  {
4478  return;
4479  }
4480  }
4481  else if(o_type0.id()==ID_vector &&
4482  o_type1.id()==ID_vector)
4483  {
4484  // We are willing to do a modest amount of conversion
4486  to_vector_type(o_type0), to_vector_type(o_type1)))
4487  {
4488  op1 = typecast_exprt::conditional_cast(op1, o_type0);
4489  return;
4490  }
4491  }
4492  else if(
4493  o_type0.id() == ID_vector &&
4494  (o_type1.id() == ID_bool || o_type1.id() == ID_c_bool ||
4495  o_type1.id() == ID_c_enum_tag || o_type1.id() == ID_unsignedbv ||
4496  o_type1.id() == ID_signedbv))
4497  {
4499  op1 = typecast_exprt(op1, o_type0);
4500  return;
4501  }
4502  }
4503  else
4504  {
4505  if(o_type0.id()==ID_pointer &&
4506  (statement==ID_assign_minus || statement==ID_assign_plus))
4507  {
4509  return;
4510  }
4511  else if(o_type0.id()==ID_vector &&
4512  o_type1.id()==ID_vector)
4513  {
4514  // We are willing to do a modest amount of conversion
4516  to_vector_type(o_type0), to_vector_type(o_type1)))
4517  {
4518  op1 = typecast_exprt::conditional_cast(op1, o_type0);
4519  return;
4520  }
4521  }
4522  else if(o_type0.id() == ID_vector)
4523  {
4525 
4526  if(
4527  is_number(op1.type()) || op1.is_boolean() ||
4528  op1.type().id() == ID_c_bool || op1.type().id() == ID_c_enum_tag)
4529  {
4530  op1 = typecast_exprt(op1, o_type0);
4531  return;
4532  }
4533  }
4534  else if(o_type0.id()==ID_bool ||
4535  o_type0.id()==ID_c_bool)
4536  {
4537  implicit_typecast_arithmetic(op0, op1);
4538  if(
4539  op1.is_boolean() || op1.type().id() == ID_c_bool ||
4540  op1.type().id() == ID_c_enum_tag || op1.type().id() == ID_unsignedbv ||
4541  op1.type().id() == ID_signedbv)
4542  {
4543  return;
4544  }
4545  }
4546  else
4547  {
4548  implicit_typecast_arithmetic(op0, op1);
4549 
4550  if(
4551  is_number(op1.type()) || op1.is_boolean() ||
4552  op1.type().id() == ID_c_bool || op1.type().id() == ID_c_enum_tag)
4553  {
4554  return;
4555  }
4556  }
4557  }
4558 
4560  error() << "assignment '" << statement << "' not defined for types '"
4561  << to_string(o_type0) << "' and '" << to_string(o_type1) << "'"
4562  << eom;
4563 
4564  throw 0;
4565 }
4566 
4571 {
4572 public:
4574  {
4575  }
4576 
4578  bool operator()(const exprt &e) const
4579  {
4580  return is_constant(e);
4581  }
4582 
4583 protected:
4584  const namespacet &ns;
4585 
4588  bool is_constant(const exprt &e) const
4589  {
4590  if(e.id() == ID_infinity)
4591  return true;
4592 
4593  if(e.is_constant())
4594  return true;
4595 
4596  if(e.id() == ID_address_of)
4597  {
4598  return is_constant_address_of(to_address_of_expr(e).object());
4599  }
4600  else if(
4601  e.id() == ID_typecast || e.id() == ID_array_of || e.id() == ID_plus ||
4602  e.id() == ID_mult || e.id() == ID_array || e.id() == ID_with ||
4603  e.id() == ID_struct || e.id() == ID_union || e.id() == ID_empty_union ||
4604  e.id() == ID_equal || e.id() == ID_notequal || e.id() == ID_lt ||
4605  e.id() == ID_le || e.id() == ID_gt || e.id() == ID_ge ||
4606  e.id() == ID_if || e.id() == ID_not || e.id() == ID_and ||
4607  e.id() == ID_or || e.id() == ID_bitnot || e.id() == ID_bitand ||
4608  e.id() == ID_bitor || e.id() == ID_bitxor || e.id() == ID_vector)
4609  {
4610  return std::all_of(
4611  e.operands().begin(), e.operands().end(), [this](const exprt &op) {
4612  return is_constant(op);
4613  });
4614  }
4615 
4616  return false;
4617  }
4618 
4620  bool is_constant_address_of(const exprt &e) const
4621  {
4622  if(e.id() == ID_symbol)
4623  {
4624  return e.type().id() == ID_code ||
4625  ns.lookup(to_symbol_expr(e).get_identifier()).is_static_lifetime;
4626  }
4627  else if(e.id() == ID_array && e.get_bool(ID_C_string_constant))
4628  return true;
4629  else if(e.id() == ID_label)
4630  return true;
4631  else if(e.id() == ID_index)
4632  {
4633  const index_exprt &index_expr = to_index_expr(e);
4634 
4635  return is_constant_address_of(index_expr.array()) &&
4636  is_constant(index_expr.index());
4637  }
4638  else if(e.id() == ID_member)
4639  {
4640  return is_constant_address_of(to_member_expr(e).compound());
4641  }
4642  else if(e.id() == ID_dereference)
4643  {
4644  const dereference_exprt &deref = to_dereference_expr(e);
4645 
4646  return is_constant(deref.pointer());
4647  }
4648  else if(e.id() == ID_string_constant)
4649  return true;
4650 
4651  return false;
4652  }
4653 };
4654 
4656 {
4657  source_locationt location = expr.find_source_location();
4658 
4659  // Floating-point expressions may require a rounding mode.
4660  // ISO 9899:1999 F.7.2 says that the default is "round to nearest".
4661  // Some compilers have command-line options to override.
4662  const auto rounding_mode =
4664  adjust_float_expressions(expr, rounding_mode);
4665 
4666  simplify(expr, *this);
4667  expr.add_source_location() = location;
4668 
4669  if(!is_compile_time_constantt(*this)(expr))
4670  {
4671  error().source_location = location;
4672  error() << "expected constant expression, but got '" << to_string(expr)
4673  << "'" << eom;
4674  throw 0;
4675  }
4676 }
4677 
4679 {
4680  source_locationt location = expr.find_source_location();
4681  make_constant(expr);
4682  make_index_type(expr);
4683  simplify(expr, *this);
4684  expr.add_source_location() = location;
4685 
4686  if(!is_compile_time_constantt(*this)(expr))
4687  {
4688  error().source_location = location;
4689  error() << "conversion to integer constant failed" << eom;
4690  throw 0;
4691  }
4692 }
4693 
4695  const exprt &expr,
4696  const irep_idt &id,
4697  const std::string &message) const
4698 {
4699  if(!has_subexpr(expr, id))
4700  return;
4701 
4703  error() << message << eom;
4704  throw 0;
4705 }
void adjust_float_expressions(exprt &expr, const exprt &rounding_mode)
Replaces arithmetic operations and typecasts involving floating point numbers with their equivalent f...
Symbolic Execution.
bool has_component_rec(const typet &type, const irep_idt &component_name, const namespacet &ns)
exprt get_component_rec(const exprt &struct_union, const irep_idt &component_name, const namespacet &ns)
C Language Type Checking.
ANSI-CC Language Type Checking.
ansi_c_declarationt & to_ansi_c_declaration(exprt &expr)
configt config
Definition: config.cpp:25
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
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
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
Definition: as_const.h:14
API to expression classes for bitvectors.
const shift_exprt & to_shift_expr(const exprt &expr)
Cast an exprt to a shift_exprt.
bool is_signed_or_unsigned_bitvector(const typet &type)
This method tests, if the given typet is a signed or unsigned bitvector.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
bool builtin_factory(const irep_idt &identifier, bool support_float16_type, symbol_table_baset &symbol_table, message_handlert &mh)
Check whether given identifier is a compiler built-in.
int8_t s1
Definition: bytecode_info.h:59
API to expression classes that are internal to the C frontend.
ANSI-C Language Type Checking.
already_typechecked_exprt & to_already_typechecked_expr(exprt &expr)
unsignedbv_typet unsigned_int_type()
Definition: c_types.cpp:36
empty_typet void_type()
Definition: c_types.cpp:245
signedbv_typet signed_int_type()
Definition: c_types.cpp:22
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:235
signedbv_typet pointer_diff_type()
Definition: c_types.cpp:220
bitvector_typet char_type()
Definition: c_types.cpp:106
floatbv_typet long_double_type()
Definition: c_types.cpp:193
typet c_bool_type()
Definition: c_types.cpp:100
bitvector_typet c_index_type()
Definition: c_types.cpp:16
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:364
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition: c_types.h:335
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:224
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:80
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:377
Absolute value.
Definition: std_expr.h:442
Operator to return the address of an object.
Definition: pointer_expr.h:540
exprt & object()
Definition: pointer_expr.h:549
const declaratorst & declarators() const
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:827
const exprt & size() const
Definition: std_types.h:840
A base class for binary expressions.
Definition: std_expr.h:638
exprt & op1()
Definition: expr.h:136
exprt & lhs()
Definition: std_expr.h:668
exprt & op0()
Definition: expr.h:133
exprt & rhs()
Definition: std_expr.h:678
A Boolean expression returning true, iff operation kind would result in an overflow when applied to o...
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
Definition: std_expr.h:731
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition: std_expr.h:762
Reverse the order of bits in a bit-vector.
std::size_t get_width() const
Definition: std_types.h:920
The Boolean type.
Definition: std_types.h:36
The byte swap expression.
Type for C bit fields These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (...
Definition: c_types.h:20
const typet & underlying_type() const
Definition: c_types.h:30
The type of C enums.
Definition: c_types.h:239
const typet & underlying_type() const
Definition: c_types.h:307
bool is_incomplete() const
enum types may be incomplete
Definition: c_types.h:294
static std::optional< std::string > check_address_can_be_taken(const typet &)
Definition: c_typecast.cpp:787
virtual void typecheck_obeys_contract_call(side_effect_expr_function_callt &expr)
Checks an obeys_contract predicate occurrence.
virtual void typecheck_expr_main(exprt &expr)
symbol_table_baset & symbol_table
virtual void implicit_typecast(exprt &expr, const typet &type)
virtual void typecheck_expr_alignof(exprt &expr)
static bool is_numeric_type(const typet &src)
virtual void typecheck_expr_pointer_arithmetic(exprt &expr)
virtual void typecheck_expr_rel_vector(binary_exprt &expr)
virtual void typecheck_expr_address_of(exprt &expr)
virtual void make_index_type(exprt &expr)
std::map< irep_idt, source_locationt > labels_used
virtual void typecheck_expr_constant(exprt &expr)
virtual void typecheck_expr(exprt &expr)
virtual void do_initializer(exprt &initializer, const typet &type, bool force_constant)
virtual void typecheck_code(codet &code)
virtual void typecheck_expr_binary_arithmetic(exprt &expr)
virtual void adjust_float_rel(binary_relation_exprt &)
virtual void typecheck_expr_unary_arithmetic(exprt &expr)
virtual void typecheck_expr_sizeof(exprt &expr)
void move_symbol(symbolt &symbol, symbolt *&new_symbol)
virtual void typecheck_expr_side_effect(side_effect_exprt &expr)
void disallow_subexpr_by_id(const exprt &, const irep_idt &, const std::string &) const
bool gcc_vector_types_compatible(const vector_typet &, const vector_typet &)
virtual bool gcc_types_compatible_p(const typet &, const typet &)
virtual void typecheck_expr_index(exprt &expr)
virtual void typecheck_expr_function_identifier(exprt &expr)
virtual void typecheck_expr_shifts(shift_exprt &expr)
const irep_idt mode
virtual void make_constant(exprt &expr)
virtual void typecheck_expr_comma(exprt &expr)
exprt typecheck_saturating_arithmetic(const side_effect_expr_function_callt &expr)
virtual void typecheck_expr_builtin_va_arg(exprt &expr)
virtual void implicit_typecast_arithmetic(exprt &expr)
virtual void typecheck_side_effect_function_call(side_effect_expr_function_callt &expr)
static void add_rounding_mode(exprt &)
std::list< codet > clean_code
virtual std::string to_string(const exprt &expr)
virtual void typecheck_expr_binary_boolean(exprt &expr)
void typecheck_declaration(ansi_c_declarationt &)
virtual void typecheck_side_effect_statement_expression(side_effect_exprt &expr)
virtual exprt do_special_functions(side_effect_expr_function_callt &expr)
asm_label_mapt asm_label_map
virtual std::optional< symbol_exprt > typecheck_shadow_memory_builtin(const side_effect_expr_function_callt &expr)
Typecheck the function if it is a shadow_memory builtin and return a symbol for it.
virtual void typecheck_expr_cw_va_arg_typeof(exprt &expr)
exprt typecheck_builtin_overflow(side_effect_expr_function_callt &expr, const irep_idt &arith_op)
virtual void typecheck_side_effect_gcc_conditional_expression(side_effect_exprt &expr)
virtual void typecheck_side_effect_assignment(side_effect_exprt &expr)
virtual code_blockt instantiate_gcc_polymorphic_builtin(const irep_idt &identifier, const symbol_exprt &function_symbol)
virtual void typecheck_expr_operands(exprt &expr)
virtual std::optional< symbol_exprt > typecheck_gcc_polymorphic_builtin(const irep_idt &identifier, const exprt::operandst &arguments, const source_locationt &source_location)
virtual void typecheck_typed_target_call(side_effect_expr_function_callt &expr)
virtual void make_constant_index(exprt &expr)
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...
virtual bool is_complete_type(const typet &type) const
id_type_mapt parameter_map
virtual void typecheck_expr_symbol(exprt &expr)
virtual void typecheck_expr_trinary(if_exprt &expr)
virtual void typecheck_expr_ptrmember(exprt &expr)
virtual void typecheck_arithmetic_pointer(exprt &expr)
virtual void typecheck_expr_unary_boolean(exprt &expr)
virtual void implicit_typecast_bool(exprt &expr)
virtual exprt typecheck_shuffle_vector(const side_effect_expr_function_callt &expr)
virtual void typecheck_expr_member(exprt &expr)
virtual void typecheck_expr_dereference(exprt &expr)
virtual void typecheck_type(typet &type)
virtual void typecheck_expr_typecast(exprt &expr)
virtual void typecheck_expr_rel(binary_relation_exprt &expr)
virtual void typecheck_expr_builtin_offsetof(exprt &expr)
virtual bool builtin_factory(const irep_idt &)
A codet representing sequential composition of program statements.
Definition: std_code.h:130
static code_blockt from_list(const std::list< codet > &_list)
Definition: std_code.h:148
codet & find_last_statement()
Definition: std_code.cpp:96
A codet representing the declaration of a local variable.
Definition: std_code.h:347
symbol_exprt & symbol()
Definition: std_code.h:354
Base type of functions.
Definition: std_types.h:583
bool is_KnR() const
Definition: std_types.h:674
std::vector< parametert > parameterst
Definition: std_types.h:585
const typet & return_type() const
Definition: std_types.h:689
bool has_ellipsis() const
Definition: std_types.h:655
const parameterst & parameters() const
Definition: std_types.h:699
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:29
exprt & op0()
Definition: expr.h:133
const irep_idt & get_statement() const
Definition: std_code_base.h:65
Imaginary part of the expression describing a complex number.
Definition: std_expr.h:2022
Real part of the expression describing a complex number.
Definition: std_expr.h:1979
Complex numbers made of pair of given subtype.
Definition: std_types.h:1121
struct configt::ansi_ct ansi_c
A constant literal expression.
Definition: std_expr.h:2987
The count leading zeros (counting the number of zero bits starting from the most-significant bit) exp...
The count trailing zeros (counting the number of zero bits starting from the least-significant bit) e...
An expression, akin to ISO C's strlen, that denotes the length of a zero-terminated string that start...
Operator to dereference a pointer.
Definition: pointer_expr.h:834
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
bool starts_with(const char *s) const
equivalent of as_string().starts_with(s)
Definition: dstring.h:95
bool empty() const
Definition: dstring.h:89
The empty type.
Definition: std_types.h:51
A Boolean expression returning true, iff the value of an enum-typed symbol equals one of the enum's d...
Definition: c_expr.h:326
Equality.
Definition: std_expr.h:1361
Base class for all expressions.
Definition: expr.h:56
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition: expr.cpp:147
std::vector< exprt > operandst
Definition: expr.h:58
bool is_true() const
Return whether the expression is a constant representing true.
Definition: expr.cpp:27
exprt & op1()
Definition: expr.h:136
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition: expr.h:163
source_locationt & add_source_location()
Definition: expr.h:236
bool is_boolean() const
Return whether the expression represents a Boolean.
Definition: expr.h:224
const source_locationt & source_location() const
Definition: expr.h:231
typet & type()
Return the type of the expression.
Definition: expr.h:84
bool is_constant() const
Return whether the expression is a constant.
Definition: expr.h:212
exprt & op0()
Definition: expr.h:133
operandst & operands()
Definition: expr.h:94
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:170
The Boolean constant false.
Definition: std_expr.h:3064
Returns one plus the index of the least-significant one bit, or zero if the operand is zero.
Fixed-width bit-vector with IEEE floating-point interpretation.
Application of (mathematical) function.
A class for an expression that indicates a history variable.
Definition: c_expr.h:205
IEEE-floating-point equality.
Definition: floatbv_expr.h:264
exprt & rounding_mode()
Definition: floatbv_expr.h:395
static ieee_float_spect single_precision()
Definition: ieee_float.h:70
static ieee_float_spect double_precision()
Definition: ieee_float.h:76
constant_exprt to_expr() const
Definition: ieee_float.cpp:703
static ieee_floatt plus_infinity(const ieee_float_spect &_spec)
Definition: ieee_float.h:211
static ieee_floatt zero(const floatbv_typet &type)
Definition: ieee_float.h:195
The trinary if-then-else operator.
Definition: std_expr.h:2370
exprt & true_case()
Definition: std_expr.h:2397
exprt & false_case()
Definition: std_expr.h:2407
Array index operator.
Definition: std_expr.h:1465
exprt & array()
Definition: std_expr.h:1495
exprt & index()
Definition: std_expr.h:1505
An expression denoting infinity.
Definition: std_expr.h:3089
Thrown when we can't handle something in an input source file.
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:57
subt & get_sub()
Definition: irep.h:444
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:482
const irep_idt & get(const irep_idt &name) const
Definition: irep.cpp:44
void remove(const irep_idt &name)
Definition: irep.cpp:87
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:408
bool is_not_nil() const
Definition: irep.h:368
const irep_idt & id() const
Definition: irep.h:384
void swap(irept &irep)
Definition: irep.h:430
irept & add(const irep_idt &name)
Definition: irep.cpp:103
bool is_nil() const
Definition: irep.h:364
Architecturally similar to can_forward_propagatet, but specialized for what is a constexpr,...
is_compile_time_constantt(const namespacet &ns)
bool is_constant(const exprt &e) const
This function determines what expressions are to be propagated as "constants".
bool is_constant_address_of(const exprt &e) const
this function determines which reference-typed expressions are constant
bool operator()(const exprt &e) const
returns true iff the expression can be considered constant
A predicate that indicates that a zero-terminated string starts at the given address.
Evaluates to true if the operand is a pointer to a dynamic object.
Definition: pointer_expr.h:335
Evaluates to true if the operand is finite.
Definition: floatbv_expr.h:176
Evaluates to true if the operand is infinite.
Definition: floatbv_expr.h:132
Evaluates to true if the operand is NaN.
Definition: floatbv_expr.h:88
Evaluates to true if the operand is a normal number.
Definition: floatbv_expr.h:220
A predicate that indicates that the object pointed to is live.
A type for mathematical functions (do not confuse with functions/methods in code)
std::vector< typet > domaint
source_locationt source_location
Definition: message.h:247
mstreamt & error() const
Definition: message.h:399
mstreamt & warning() const
Definition: message.h:404
mstreamt & result() const
Definition: message.h:409
message_handlert & get_message_handler()
Definition: message.h:184
static eomt eom
Definition: message.h:297
Binary multiplication Associativity is not specified.
Definition: std_expr.h:1107
void follow_macros(exprt &) const
Follow macros to their values in a given expression.
Definition: namespace.cpp:107
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
const symbolt & lookup(const irep_idt &name) const
Lookup a symbol in the namespace.
Definition: namespace.h:46
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:148
The NIL expression.
Definition: std_expr.h:3073
The null pointer constant.
Definition: pointer_expr.h:909
Expression for finding the size (in bytes) of the object a pointer points to.
Symbol table entry of function parameterThis is a symbol generated as part of type checking.
Definition: symbol.h:179
The plus expression Associativity is not specified.
Definition: std_expr.h:1002
pointer_in_range(a, b, c) evaluates to true iff same_object(a, b, c) ∧ r_ok(a, offset(c)-offset(a)) ∧...
Definition: pointer_expr.h:387
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
The popcount (counting the number of bits set to 1) expression.
A base class for expressions that are predicates, i.e., Boolean-typed.
Definition: std_expr.h:574
A base class for a predicate that indicates that an address range is ok to read or write or both.
Definition: pointer_expr.h:920
Saturating subtraction expression.
The saturating plus expression.
A predicate that indicates that the objects pointed to are distinct.
A base class for shift and rotate operators.
A side_effect_exprt representation of a function call side effect.
Definition: std_code.h:1692
exprt::operandst & arguments()
Definition: std_code.h:1718
A side_effect_exprt that returns a non-deterministically chosen value.
Definition: std_code.h:1520
A Boolean expression returning true, iff the result of performing operation kind on operands a and b ...
Definition: c_expr.h:117
An expression containing a side effect.
Definition: std_code.h:1450
const irep_idt & get_statement() const
Definition: std_code.h:1472
Sign of an expression Predicate is true if _op is negative, false otherwise.
Definition: std_expr.h:596
Fixed-width bit-vector with two's complement interpretation.
const irep_idt & get_function() const
Base type for structs and unions.
Definition: std_types.h:62
const componentt & get_component(const irep_idt &component_name) const
Get the reference to a component with given name.
Definition: std_types.cpp:63
bool has_component(const irep_idt &component_name) const
Definition: std_types.h:157
bool is_incomplete() const
A struct/union may be incomplete.
Definition: std_types.h:185
const componentst & components() const
Definition: std_types.h:147
Expression to hold a symbol (variable)
Definition: std_expr.h:131
void set_identifier(const irep_idt &identifier)
Definition: std_expr.h:155
const irep_idt & get_identifier() const
Definition: std_expr.h:160
const symbolst & symbols
Read-only field, used to look up symbols given their names.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
virtual std::pair< symbolt &, bool > insert(symbolt symbol)=0
Move or copy a new symbol to the symbol table.
Symbol table entry.
Definition: symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
bool is_extern
Definition: symbol.h:74
const irep_idt & display_name() const
Return language specific display name if present.
Definition: symbol.h:55
bool is_macro
Definition: symbol.h:62
bool is_static_lifetime
Definition: symbol.h:70
bool is_parameter
Definition: symbol.h:76
bool is_type
Definition: symbol.h:61
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
typet type
Type of symbol.
Definition: symbol.h:31
irep_idt name
The unique identifier.
Definition: symbol.h:40
bool is_lvalue
Definition: symbol.h:72
irep_idt mode
Language mode.
Definition: symbol.h:49
The Boolean constant true.
Definition: std_expr.h:3055
Type with multiple subtypes.
Definition: type.h:222
const typet & subtype() const
Definition: type.h:187
Semantic type conversion.
Definition: std_expr.h:2068
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2076
The type of an expression, extends irept.
Definition: type.h:29
typet && with_source_location(source_locationt location) &&
This is a 'fluent style' method for creating a new type with an added-on source location.
Definition: type.h:84
source_locationt & add_source_location()
Definition: type.h:77
Generic base class for unary expressions.
Definition: std_expr.h:361
const exprt & op() const
Definition: std_expr.h:391
A Boolean expression returning true, iff negation would result in an overflow when applied to the (si...
Union constructor from single element.
Definition: std_expr.h:1765
The vector type.
Definition: std_types.h:1052
const constant_exprt & size() const
Definition: std_types.cpp:275
const typet & element_type() const
The type of the elements of the vector.
Definition: std_types.h:1068
typet index_type() const
The type of any index expression into an instance of this type.
Definition: std_types.cpp:263
A predicate that indicates that the object pointed to is writeable.
#define CPROVER_PREFIX
std::string expr2c(const exprt &expr, const namespacet &ns, const expr2c_configurationt &configuration)
Definition: expr2c.cpp:4149
std::string type2c(const typet &type, const namespacet &ns, const expr2c_configurationt &configuration)
Definition: expr2c.cpp:4165
#define Forall_operands(it, expr)
Definition: expr.h:27
constant_exprt make_boolean_expr(bool value)
returns true_exprt if given true and false_exprt otherwise
Definition: expr_util.cpp:338
bool is_assignable(const exprt &expr)
Returns true iff the argument is one of the following:
Definition: expr_util.cpp:24
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Definition: expr_util.cpp:219
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:141
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:369
Deprecated expression utility functions.
API to expression classes for floating-point arithmetic.
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
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
API to expression classes for 'mathematical' expressions.
bool is_number(const typet &type)
Returns true if the type is a rational, real, integer, natural, complex, unsignedbv,...
Mathematical types.
const mathematical_function_typet & to_mathematical_function_type(const typet &type)
Cast a typet to a mathematical_function_typet.
mp_integer alignment(const typet &type, const namespacet &ns)
Definition: padding.cpp:23
ANSI-C Language Type Checking.
API to expression classes for Pointers.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:890
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:577
std::optional< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
std::optional< exprt > member_offset_expr(const member_exprt &member_expr, const namespacet &ns)
Pointer Logic.
exprt pointer_offset(const exprt &pointer)
exprt same_object(const exprt &p1, const exprt &p2)
exprt pointer_object(const exprt &p)
Various predicates over pointers in programs.
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition: range.h:522
exprt deref_expr(const exprt &expr)
Wraps a given expression into a dereference_exprt unless it is an address_of_exprt in which case it j...
bool simplify(exprt &expr, const namespacet &ns)
exprt simplify_expr(exprt src, const namespacet &ns)
BigInt mp_integer
Definition: smt_terms.h:17
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:534
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
side_effect_expr_statement_expressiont & to_side_effect_expr_statement_expression(exprt &expr)
Definition: std_code.h:1669
side_effect_exprt & to_side_effect_expr(exprt &expr)
Definition: std_code.h:1506
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
Definition: std_code.h:1739
const code_frontend_declt & to_code_frontend_decl(const codet &code)
Definition: std_code.h:429
const code_blockt & to_code_block(const codet &code)
Definition: std_code.h:203
const codet & to_code(const exprt &expr)
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:80
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition: std_expr.h:2450
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:3037
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2102
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:715
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2933
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:426
const binary_relation_exprt & to_binary_relation_expr(const exprt &expr)
Cast an exprt to a binary_relation_exprt.
Definition: std_expr.h:895
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1533
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
Definition: std_types.h:1104
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:788
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition: std_types.h:29
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:888
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
Definition: std_types.h:1146
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:518
const struct_or_union_tag_typet & to_struct_or_union_tag_type(const typet &type)
Cast a typet to a struct_or_union_tag_typet.
Definition: std_types.h:478
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
bool float16_type
Definition: config.h:154
std::size_t char_width
Definition: config.h:140
flavourt mode
Definition: config.h:253
bool has_suffix(const std::string &s, const std::string &suffix)
Definition: suffix.h:17
Author: Diffblue Ltd.
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:328
Type Naming for C.
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:208
#define size_type
Definition: unistd.c:347