cprover
cpp_typecheck_expr.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: C++ Language Type Checking
4 
5 Author: Daniel Kroening, kroening@cs.cmu.edu
6 
7 \*******************************************************************/
8 
11 
12 #include "cpp_typecheck.h"
13 
14 #ifdef DEBUG
15 #include <iostream>
16 #endif
17 
18 #include <util/arith_tools.h>
19 #include <util/base_type.h>
20 #include <util/c_types.h>
21 #include <util/config.h>
22 #include <util/expr_initializer.h>
24 
25 #include <ansi-c/c_qualifiers.h>
26 
27 #include "cpp_exception_id.h"
28 #include "cpp_type2name.h"
29 #include "expr2cpp.h"
30 
32  const symbolt &symb,
33  const irep_idt &base_name,
34  irep_idt &identifier)
35 {
36  for(const auto &b : to_struct_type(symb.type).bases())
37  {
38  const irep_idt &id = b.type().get_identifier();
39  if(lookup(id).base_name == base_name)
40  {
41  identifier = id;
42  return true;
43  }
44  }
45 
46  return false;
47 }
48 
51 {
52  if(expr.id()==ID_cpp_name)
54  else if(expr.id()=="cpp-this")
55  typecheck_expr_this(expr);
56  else if(expr.id()=="pointer-to-member")
57  convert_pmop(expr);
58  else if(expr.id() == ID_new_object)
59  {
60  }
61  else if(operator_is_overloaded(expr))
62  {
63  }
64  else if(expr.id()=="explicit-typecast")
66  else if(expr.id()=="explicit-constructor-call")
68  else if(expr.is_nil())
69  {
70 #ifdef DEBUG
71  std::cerr << "E: " << expr.pretty() << '\n';
72  std::cerr << "cpp_typecheckt::typecheck_expr_main got nil\n";
73 #endif
75  }
76  else if(expr.id()==ID_code)
77  {
78 #ifdef DEBUG
79  std::cerr << "E: " << expr.pretty() << '\n';
80  std::cerr << "cpp_typecheckt::typecheck_expr_main got code\n";
81 #endif
83  }
84  else if(expr.id()==ID_symbol)
85  {
86  // ignore here
87 #ifdef DEBUG
88  std::cerr << "E: " << expr.pretty() << '\n';
89  std::cerr << "cpp_typecheckt::typecheck_expr_main got symbol\n";
90 #endif
91  }
92  else if(expr.id()=="__is_base_of")
93  {
94  // an MS extension
95  // http://msdn.microsoft.com/en-us/library/ms177194(v=vs.80).aspx
96 
97  typet base=static_cast<const typet &>(expr.find("type_arg1"));
98  typet deriv=static_cast<const typet &>(expr.find("type_arg2"));
99 
100  typecheck_type(base);
101  typecheck_type(deriv);
102 
103  base = follow(base);
104  deriv = follow(deriv);
105 
106  if(base.id()!=ID_struct || deriv.id()!=ID_struct)
107  expr=false_exprt();
108  else
109  {
110  irep_idt base_name=base.get(ID_name);
111  const class_typet &class_type=to_class_type(deriv);
112 
113  if(class_type.has_base(base_name))
114  expr=true_exprt();
115  else
116  expr=false_exprt();
117  }
118  }
119  else if(expr.id()==ID_msc_uuidof)
120  {
121  // these appear to have type "struct _GUID"
122  // and they are lvalues!
123  expr.type() = struct_tag_typet("tag-_GUID");
124  follow(expr.type());
125  expr.set(ID_C_lvalue, true);
126  }
127  else if(expr.id()==ID_noexcept)
128  {
129  // TODO
130  expr=false_exprt();
131  }
132  else if(expr.id()==ID_initializer_list)
133  {
134  expr.type().id(ID_initializer_list);
135  }
136  else
138 }
139 
141 {
142  assert(expr.operands().size()==3);
143 
144  implicit_typecast(expr.op0(), bool_typet());
145 
146  if(expr.op1().type().id()==ID_empty ||
147  expr.op1().type().id()==ID_empty)
148  {
149  if(expr.op1().get_bool(ID_C_lvalue))
150  {
151  exprt e1(expr.op1());
153  {
154  error().source_location=e1.find_source_location();
155  error() << "error: lvalue to rvalue conversion" << eom;
156  throw 0;
157  }
158  }
159 
160  if(expr.op1().type().id()==ID_array)
161  {
162  exprt e1(expr.op1());
164  {
165  error().source_location=e1.find_source_location();
166  error() << "error: array to pointer conversion" << eom;
167  throw 0;
168  }
169  }
170 
171  if(expr.op1().type().id()==ID_code)
172  {
173  exprt e1(expr.op1());
175  {
176  error().source_location=e1.find_source_location();
177  error() << "error: function to pointer conversion" << eom;
178  throw 0;
179  }
180  }
181 
182  if(expr.op2().get_bool(ID_C_lvalue))
183  {
184  exprt e2(expr.op2());
186  {
187  error().source_location=e2.find_source_location();
188  error() << "error: lvalue to rvalue conversion" << eom;
189  throw 0;
190  }
191  }
192 
193  if(expr.op2().type().id()==ID_array)
194  {
195  exprt e2(expr.op2());
197  {
198  error().source_location=e2.find_source_location();
199  error() << "error: array to pointer conversion" << eom;
200  throw 0;
201  }
202  }
203 
204  if(expr.op2().type().id()==ID_code)
205  {
206  exprt e2(expr.op2());
208  {
210  error() << "error: function to pointer conversion" << eom;
211  throw 0;
212  }
213  }
214 
215  if(expr.op1().get(ID_statement)==ID_throw &&
216  expr.op2().get(ID_statement)!=ID_throw)
217  expr.type()=expr.op2().type();
218  else if(expr.op2().get(ID_statement)==ID_throw &&
219  expr.op1().get(ID_statement)!=ID_throw)
220  expr.type()=expr.op1().type();
221  else if(expr.op1().type().id()==ID_empty &&
222  expr.op2().type().id()==ID_empty)
223  expr.type()=empty_typet();
224  else
225  {
227  error() << "error: bad types for operands" << eom;
228  throw 0;
229  }
230  return;
231  }
232 
233  if(expr.op1().type() == expr.op2().type())
234  {
235  c_qualifierst qual1, qual2;
236  qual1.read(expr.op1().type());
237  qual2.read(expr.op2().type());
238 
239  if(qual1.is_subset_of(qual2))
240  expr.type()=expr.op1().type();
241  else
242  expr.type()=expr.op2().type();
243  }
244  else
245  {
246  exprt e1=expr.op1();
247  exprt e2=expr.op2();
248 
249  if(implicit_conversion_sequence(expr.op1(), expr.op2().type(), e1))
250  {
251  expr.type()=e1.type();
252  expr.op1().swap(e1);
253  }
254  else if(implicit_conversion_sequence(expr.op2(), expr.op1().type(), e2))
255  {
256  expr.type()=e2.type();
257  expr.op2().swap(e2);
258  }
259  else if(expr.op1().type().id()==ID_array &&
260  expr.op2().type().id()==ID_array &&
261  expr.op1().type().subtype() == expr.op2().type().subtype())
262  {
263  // array-to-pointer conversion
264 
265  index_exprt index1;
266  index1.array()=expr.op1();
267  index1.index()=from_integer(0, index_type());
268  index1.type()=expr.op1().type().subtype();
269 
270  index_exprt index2;
271  index2.array()=expr.op2();
272  index2.index()=from_integer(0, index_type());
273  index2.type()=expr.op2().type().subtype();
274 
275  address_of_exprt addr1(index1);
276  address_of_exprt addr2(index2);
277 
278  expr.op1()=addr1;
279  expr.op2()=addr2;
280  expr.type()=addr1.type();
281  return;
282  }
283  else
284  {
286  error() << "error: types are incompatible.\n"
287  << "I got `" << type2cpp(expr.op1().type(), *this)
288  << "' and `" << type2cpp(expr.op2().type(), *this)
289  << "'." << eom;
290  throw 0;
291  }
292  }
293 
294  if(expr.op1().get_bool(ID_C_lvalue) &&
295  expr.op2().get_bool(ID_C_lvalue))
296  expr.set(ID_C_lvalue, true);
297 
298  return;
299 }
300 
302 {
304  expr,
306 }
307 
309 {
310  // We need to overload, "sizeof-expression" can be mis-parsed
311  // as a type.
312 
313  if(expr.operands().empty())
314  {
315  const typet &type=
316  static_cast<const typet &>(expr.find(ID_type_arg));
317 
318  if(type.id()==ID_cpp_name)
319  {
320  // sizeof(X) may be ambiguous -- X can be either a type or
321  // an expression.
322 
323  cpp_typecheck_fargst fargs;
324 
325  exprt symbol_expr=resolve(
326  to_cpp_name(static_cast<const irept &>(type)),
328  fargs);
329 
330  if(symbol_expr.id()!=ID_type)
331  {
332  expr.copy_to_operands(symbol_expr);
333  expr.remove(ID_type_arg);
334  }
335  }
336  else if(type.id()==ID_array)
337  {
338  // sizeof(expr[index]) can be parsed as an array type!
339 
340  if(type.subtype().id()==ID_cpp_name)
341  {
342  cpp_typecheck_fargst fargs;
343 
344  exprt symbol_expr=resolve(
345  to_cpp_name(static_cast<const irept &>(type.subtype())),
347  fargs);
348 
349  if(symbol_expr.id()!=ID_type)
350  {
351  // _NOT_ a type
352  index_exprt index_expr(symbol_expr, to_array_type(type).size());
353  expr.copy_to_operands(index_expr);
354  expr.remove(ID_type_arg);
355  }
356  }
357  }
358  }
359 
361 }
362 
364 {
366 }
367 
369  exprt &expr,
370  const cpp_typecheck_fargst &fargs)
371 {
372  if(expr.id()==ID_cpp_name)
373  typecheck_expr_cpp_name(expr, fargs);
374  else if(expr.id()==ID_member)
375  {
377  typecheck_expr_member(expr, fargs);
378  }
379  else if(expr.id()==ID_ptrmember)
380  {
383 
384  // is operator-> overloaded?
385  if(expr.op0().type().id() != ID_pointer)
386  {
387  std::string op_name="operator->";
388 
389  // turn this into a function call
390  side_effect_expr_function_callt function_call;
391  function_call.arguments().reserve(expr.operands().size());
392  function_call.add_source_location()=expr.source_location();
393 
394  // first do function/operator
395  const cpp_namet cpp_name(op_name, expr.source_location());
396 
397  function_call.function() = cpp_name.as_expr();
398 
399  // now do the argument
400  function_call.arguments().push_back(expr.op0());
402 
403  exprt tmp(ID_already_typechecked);
404  tmp.copy_to_operands(function_call);
405  function_call.swap(tmp);
406 
407  expr.op0().swap(function_call);
408  typecheck_function_expr(expr, fargs);
409  return;
410  }
411 
412  typecheck_expr_ptrmember(expr, fargs);
413  }
414  else
415  typecheck_expr(expr);
416 }
417 
419 {
420  // at least one argument must have class or enumerated type
421 
422  forall_operands(it, expr)
423  {
424  typet t=follow(it->type());
425 
426  if(is_reference(t))
427  t=t.subtype();
428 
429  if(t.id()==ID_struct ||
430  t.id() == ID_incomplete_struct ||
431  t.id()==ID_union ||
432  t.id()==ID_c_enum || t.id() == ID_c_enum_tag)
433  return true;
434  }
435 
436  return false;
437 }
438 
440 {
441  const irep_idt id;
442  const char *op_name;
443 } const operators[] =
444 {
445  { ID_plus, "+" },
446  { ID_minus, "-" },
447  { ID_mult, "*" },
448  { ID_div, "/" },
449  { ID_bitnot, "~" },
450  { ID_bitand, "&" },
451  { ID_bitor, "|" },
452  { ID_bitxor, "^" },
453  { ID_not, "!" },
454  { ID_unary_minus, "-" },
455  { ID_and, "&&" },
456  { ID_or, "||" },
457  { ID_not, "!" },
458  { ID_index, "[]" },
459  { ID_equal, "==" },
460  { ID_lt, "<"},
461  { ID_le, "<="},
462  { ID_gt, ">"},
463  { ID_ge, ">="},
464  { ID_shl, "<<"},
465  { ID_shr, ">>"},
466  { ID_notequal, "!=" },
467  { ID_dereference, "*" },
468  { ID_ptrmember, "->" },
469  { irep_idt(), nullptr }
470 };
471 
473 {
474  // Check argument types first.
475  // At least one struct/enum operand is required.
476 
477  if(!overloadable(expr))
478  return false;
479  else if(expr.id()==ID_dereference &&
480  expr.get_bool(ID_C_implicit))
481  return false;
482 
483  assert(expr.operands().size()>=1);
484 
485  if(expr.id()=="explicit-typecast")
486  {
487  // the cast operator can be overloaded
488 
489  typet t=expr.type();
490  typecheck_type(t);
491  std::string op_name=std::string("operator")+"("+cpp_type2name(t)+")";
492 
493  // turn this into a function call
494  side_effect_expr_function_callt function_call;
495  function_call.arguments().reserve(expr.operands().size());
496  function_call.add_source_location()=expr.source_location();
497 
498  const cpp_namet cpp_name(op_name, expr.source_location());
499 
500  // See if the struct declares the cast operator as a member
501  bool found_in_struct=false;
502  assert(!expr.operands().empty());
503  typet t0(follow(expr.op0().type()));
504 
505  if(t0.id()==ID_struct)
506  {
507  for(const auto &c : to_struct_type(t0).components())
508  {
509  if(!c.get_bool(ID_from_base) && c.get_base_name() == op_name)
510  {
511  found_in_struct=true;
512  break;
513  }
514  }
515  }
516 
517  if(!found_in_struct)
518  return false;
519 
520  {
521  exprt member(ID_member);
522  member.add(ID_component_cpp_name)= cpp_name;
523 
524  exprt tmp(ID_already_typechecked);
525  tmp.copy_to_operands(expr.op0());
526  member.copy_to_operands(tmp);
527 
528  function_call.function()=member;
529  }
530 
531  if(expr.operands().size()>1)
532  {
533  for(exprt::operandst::const_iterator
534  it=(expr.operands().begin()+1);
535  it!=(expr).operands().end();
536  it++)
537  function_call.arguments().push_back(*it);
538  }
539 
541 
542  if(expr.id()==ID_ptrmember)
543  {
544  add_implicit_dereference(function_call);
545  exprt tmp(ID_already_typechecked);
546  tmp.move_to_operands(function_call);
547  expr.op0().swap(tmp);
548  typecheck_expr(expr);
549  return true;
550  }
551 
552  expr.swap(function_call);
553  return true;
554  }
555 
556  for(const operator_entryt *e=operators;
557  !e->id.empty();
558  e++)
559  if(expr.id()==e->id)
560  {
561  if(expr.id()==ID_dereference)
562  assert(!expr.get_bool(ID_C_implicit));
563 
564  std::string op_name=std::string("operator")+e->op_name;
565 
566  // first do function/operator
567  const cpp_namet cpp_name(op_name, expr.source_location());
568 
569  // turn this into a function call
570  side_effect_expr_function_callt function_call;
571  function_call.arguments().reserve(expr.operands().size());
572  function_call.add_source_location()=expr.source_location();
573 
574  // There are two options to overload an operator:
575  //
576  // 1. In the scope of a as a.operator(b, ...)
577  // 2. Anywhere in scope as operator(a, b, ...)
578  //
579  // Using both is not allowed.
580  //
581  // We try and fail silently, maybe conversions will work
582  // instead.
583 
584  // TODO: need to resolve an incomplete struct (template) here
585  // go into scope of first operand
586  if(
587  expr.op0().type().id() == ID_symbol_type &&
588  follow(expr.op0().type()).id() == ID_struct)
589  {
590  const irep_idt &struct_identifier=
591  expr.op0().type().get(ID_identifier);
592 
593  // get that scope
594  cpp_save_scopet save_scope(cpp_scopes);
595  cpp_scopes.set_scope(struct_identifier);
596 
597  // build fargs for resolver
598  cpp_typecheck_fargst fargs;
599  fargs.operands=expr.operands();
600  fargs.has_object=true;
601  fargs.in_use=true;
602 
603  // should really be a qualified search
604  exprt resolve_result=resolve(
605  cpp_name, cpp_typecheck_resolvet::wantt::VAR, fargs, false);
606 
607  if(resolve_result.is_not_nil())
608  {
609  // Found! We turn op(a, b, ...) into a.op(b, ...)
610  {
611  exprt member(ID_member);
612  member.add(ID_component_cpp_name)=cpp_name;
613 
614  exprt tmp(ID_already_typechecked);
615  tmp.copy_to_operands(expr.op0());
616  member.copy_to_operands(tmp);
617 
618  function_call.function()=member;
619  }
620 
621  if(expr.operands().size()>1)
622  {
623  // skip first
624  for(exprt::operandst::const_iterator
625  it=expr.operands().begin()+1;
626  it!=expr.operands().end();
627  it++)
628  function_call.arguments().push_back(*it);
629  }
630 
632 
633  expr=function_call;
634 
635  return true;
636  }
637  }
638 
639  // 2nd option!
640  {
641  cpp_typecheck_fargst fargs;
642  fargs.operands=expr.operands();
643  fargs.has_object=false;
644  fargs.in_use=true;
645 
646  exprt resolve_result=resolve(
647  cpp_name, cpp_typecheck_resolvet::wantt::VAR, fargs, false);
648 
649  if(resolve_result.is_not_nil())
650  {
651  // found!
652  function_call.function()=
653  static_cast<const exprt &>(
654  static_cast<const irept &>(cpp_name));
655 
656  // now do arguments
657  forall_operands(it, expr)
658  function_call.arguments().push_back(*it);
659 
661 
662  if(expr.id()==ID_ptrmember)
663  {
664  add_implicit_dereference(function_call);
665  exprt tmp(ID_already_typechecked);
666  tmp.move_to_operands(function_call);
667  expr.op0()=tmp;
668  typecheck_expr(expr);
669  return true;
670  }
671 
672  expr=function_call;
673 
674  return true;
675  }
676  }
677  }
678 
679  return false;
680 }
681 
683 {
684  if(expr.operands().size()!=1)
685  {
687  error() << "address_of expects one operand" << eom;
688  throw 0;
689  }
690 
691  exprt &op=expr.op0();
692 
693  if(!op.get_bool(ID_C_lvalue) && expr.type().id()==ID_code)
694  {
696  error() << "expr not an lvalue" << eom;
697  throw 0;
698  }
699 
700  if(expr.op0().type().id()==ID_code)
701  {
702  // we take the address of the method.
703  assert(expr.op0().id()==ID_member);
704  exprt symb=cpp_symbol_expr(lookup(expr.op0().get(ID_component_name)));
705  address_of_exprt address(symb, pointer_type(symb.type()));
706  address.set(ID_C_implicit, true);
707  expr.op0().swap(address);
708  }
709 
710  if(expr.op0().id()==ID_address_of &&
711  expr.op0().get_bool(ID_C_implicit))
712  {
713  // must be the address of a function
714  code_typet &code_type=to_code_type(op.type().subtype());
715 
716  code_typet::parameterst &args=code_type.parameters();
717  if(args.size() > 0 && args[0].get(ID_C_base_name)==ID_this)
718  {
719  // it's a pointer to member function
720  const struct_tag_typet symbol(code_type.get(ID_C_member_name));
721  expr.op0().type().add("to-member")=symbol;
722 
723  if(code_type.get_bool(ID_C_is_virtual))
724  {
726  error() << "error: pointers to virtual methods"
727  << " are currently not implemented" << eom;
728  throw 0;
729  }
730  }
731  }
732  else if(
733  expr.op0().id() == ID_ptrmember && expr.op0().op0().id() == "cpp-this")
734  {
735  expr.type() = pointer_type(expr.op0().type());
736  expr.type().add("to-member") = expr.op0().op0().type().subtype();
737  return;
738  }
739 
740  // the C front end does not know about references
741  const bool is_ref=is_reference(expr.type());
743  if(is_ref)
744  expr.type()=reference_type(expr.type().subtype());
745 }
746 
748 {
749  // these are of type void
750  expr.type()=empty_typet();
751 
752  assert(expr.operands().size()==1 ||
753  expr.operands().empty());
754 
755  if(expr.operands().size()==1)
756  {
757  // nothing really to do; one can throw _almost_ anything
758  const typet &exception_type=expr.op0().type();
759 
760  if(follow(exception_type).id()==ID_empty)
761  {
763  error() << "cannot throw void" << eom;
764  throw 0;
765  }
766 
767  // annotate the relevant exception IDs
768  expr.set(ID_exception_list,
769  cpp_exception_list(exception_type, *this));
770  }
771 }
772 
774 {
775  // next, find out if we do an array
776 
777  if(expr.type().id()==ID_array)
778  {
779  // first typecheck subtype
780  typecheck_type(expr.type().subtype());
781 
782  // typecheck the size
783  exprt &size=to_array_type(expr.type()).size();
784  typecheck_expr(size);
785 
786  bool size_is_unsigned=(size.type().id()==ID_unsignedbv);
787  typet integer_type(size_is_unsigned?ID_unsignedbv:ID_signedbv);
788  integer_type.set(ID_width, config.ansi_c.int_width);
789  implicit_typecast(size, integer_type);
790 
791  expr.set(ID_statement, ID_cpp_new_array);
792 
793  // save the size expression
794  expr.set(ID_size, to_array_type(expr.type()).size());
795 
796  // new actually returns a pointer, not an array
797  pointer_typet ptr_type=
798  pointer_type(expr.type().subtype());
799  expr.type().swap(ptr_type);
800  }
801  else
802  {
803  // first typecheck type
804  typecheck_type(expr.type());
805 
806  expr.set(ID_statement, ID_cpp_new);
807 
808  pointer_typet ptr_type=pointer_type(expr.type());
809  expr.type().swap(ptr_type);
810  }
811 
812  exprt object_expr(ID_new_object, expr.type().subtype());
813  object_expr.set(ID_C_lvalue, true);
814 
815  {
816  exprt tmp(ID_already_typechecked);
817  tmp.move_to_operands(object_expr);
818  object_expr.swap(tmp);
819  }
820 
821  // not yet typechecked-stuff
822  exprt &initializer=static_cast<exprt &>(expr.add(ID_initializer));
823 
824  // arrays must not have an initializer
825  if(!initializer.operands().empty() &&
826  expr.get(ID_statement)==ID_cpp_new_array)
827  {
829  error() << "new with array type must not use initializer" << eom;
830  throw 0;
831  }
832 
833  auto code = cpp_constructor(
834  expr.find_source_location(), object_expr, initializer.operands());
835 
836  if(code.has_value())
837  expr.add(ID_initializer).swap(code.value());
838  else
839  expr.add(ID_initializer) = nil_exprt();
840 
841  // we add the size of the object for convenience of the
842  // runtime library
843 
844  exprt &sizeof_expr=static_cast<exprt &>(expr.add(ID_sizeof));
845  sizeof_expr=size_of_expr(expr.type().subtype(), *this);
846  sizeof_expr.add(ID_C_c_sizeof_type)=expr.type().subtype();
847 }
848 
850 {
851  exprt result;
852 
853  if(src.id()==ID_comma)
854  {
855  assert(src.operands().size()==2);
856  result=collect_comma_expression(src.op0());
857  result.copy_to_operands(src.op1());
858  }
859  else
860  result.copy_to_operands(src);
861 
862  return result;
863 }
864 
866 {
867  // these can have 0 or 1 arguments
868 
869  if(expr.operands().empty())
870  {
871  // Default value, e.g., int()
872  typecheck_type(expr.type());
873  auto new_expr =
874  ::zero_initializer(expr.type(), expr.find_source_location(), *this);
875  if(!new_expr.has_value())
876  {
878  error() << "cannot zero-initialize `" << to_string(expr.type()) << "'"
879  << eom;
880  throw 0;
881  }
882 
883  new_expr->add_source_location() = expr.source_location();
884  expr = *new_expr;
885  }
886  else if(expr.operands().size()==1)
887  {
888  // Explicitly given value, e.g., int(1).
889  // There is an expr-vs-type ambiguity, as it is possible to write
890  // (f)(1), where 'f' is a function symbol and not a type.
891  // This also exists with a "comma expression", e.g.,
892  // (f)(1, 2, 3)
893 
894  if(expr.type().id()==ID_cpp_name)
895  {
896  // try to resolve as type
897  cpp_typecheck_fargst fargs;
898 
899  exprt symbol_expr=resolve(
900  to_cpp_name(static_cast<const irept &>(expr.type())),
902  fargs,
903  false); // fail silently
904 
905  if(symbol_expr.id()==ID_type)
906  expr.type()=symbol_expr.type();
907  else
908  {
909  // It's really a function call. Note that multiple arguments
910  // become a comma expression, and that these are already typechecked.
912 
913  f_call.add_source_location()=expr.source_location();
914  f_call.function().swap(expr.type());
915  f_call.arguments()=collect_comma_expression(expr.op0()).operands();
916 
918 
919  expr.swap(f_call);
920  return;
921  }
922  }
923  else
924  typecheck_type(expr.type());
925 
926  // We allow (TYPE){ initializer_list }
927  // This is called "compound literal", and is syntactic
928  // sugar for a (possibly local) declaration.
929  if(expr.op0().id()==ID_initializer_list)
930  {
931  // just do a normal initialization
932  do_initializer(expr.op0(), expr.type(), false);
933 
934  // This produces a struct-expression,
935  // union-expression, array-expression,
936  // or an expression for a pointer or scalar.
937  // We produce a compound_literal expression.
938  exprt tmp(ID_compound_literal, expr.type());
939  tmp.move_to_operands(expr.op0());
940  expr=tmp;
941  expr.set(ID_C_lvalue, true); // these are l-values
942  return;
943  }
944 
945  exprt new_expr;
946 
947  if(const_typecast(expr.op0(), expr.type(), new_expr) ||
948  static_typecast(expr.op0(), expr.type(), new_expr, false) ||
949  reinterpret_typecast(expr.op0(), expr.type(), new_expr, false))
950  {
951  expr=new_expr;
953  }
954  else
955  {
957  error() << "invalid explicit cast:\n"
958  << "operand type: `" << to_string(expr.op0().type())
959  << "'\n"
960  << "casting to: `" << to_string(expr.type()) << "'"
961  << eom;
962  throw 0;
963  }
964  }
965  else
966  {
968  error() << "explicit typecast expects 0 or 1 operands" << eom;
969  throw 0;
970  }
971 }
972 
974 {
975  typecheck_type(expr.type());
976 
977  if(cpp_is_pod(expr.type()))
978  {
979  expr.id("explicit-typecast");
980  typecheck_expr_main(expr);
981  }
982  else
983  {
984  assert(expr.type().id()==ID_struct);
985 
986  struct_tag_typet tag(expr.type().get(ID_name));
987  tag.add_source_location() = expr.source_location();
988 
989  exprt e=expr;
990  new_temporary(e.source_location(), tag, e.operands(), expr);
991  }
992 }
993 
995 {
997  {
999  error() << "`this' is not allowed here" << eom;
1000  throw 0;
1001  }
1002 
1003  const exprt &this_expr=cpp_scopes.current_scope().this_expr;
1004  const source_locationt source_location=expr.find_source_location();
1005 
1006  assert(this_expr.is_not_nil());
1007  assert(this_expr.type().id()==ID_pointer);
1008 
1009  expr=this_expr;
1010  expr.add_source_location()=source_location;
1011 }
1012 
1014 {
1015  if(expr.operands().size()!=1)
1016  {
1018  error() << "delete expects one operand" << eom;
1019  throw 0;
1020  }
1021 
1022  const irep_idt statement=expr.get(ID_statement);
1023 
1024  if(statement==ID_cpp_delete)
1025  {
1026  }
1027  else if(statement==ID_cpp_delete_array)
1028  {
1029  }
1030  else
1031  UNREACHABLE;
1032 
1033  typet pointer_type=follow(expr.op0().type());
1034 
1035  if(pointer_type.id()!=ID_pointer)
1036  {
1038  error() << "delete takes a pointer type operand, but got `"
1039  << to_string(pointer_type) << "'" << eom;
1040  throw 0;
1041  }
1042 
1043  // remove any const-ness of the argument
1044  // (which would impair the call to the destructor)
1045  pointer_type.subtype().remove(ID_C_constant);
1046 
1047  // delete expressions are always void
1048  expr.type()=typet(ID_empty);
1049 
1050  // we provide the right destructor, for the convenience
1051  // of later stages
1052  exprt new_object(ID_new_object, pointer_type.subtype());
1053  new_object.add_source_location()=expr.source_location();
1054  new_object.set(ID_C_lvalue, true);
1055 
1056  already_typechecked(new_object);
1057 
1058  auto destructor_code = cpp_destructor(expr.source_location(), new_object);
1059 
1060  if(destructor_code.has_value())
1061  {
1062  // this isn't typechecked yet
1063  typecheck_code(destructor_code.value());
1064  expr.set(ID_destructor, destructor_code.value());
1065  }
1066  else
1067  expr.set(ID_destructor, nil_exprt());
1068 }
1069 
1071 {
1072  // should not be called
1073  #if 0
1074  std::cout << "E: " << expr.pretty() << '\n';
1075  UNREACHABLE;
1076  #endif
1077 }
1078 
1080  exprt &expr,
1081  const cpp_typecheck_fargst &fargs)
1082 {
1083  if(expr.operands().size()!=1)
1084  {
1086  error() << "error: member operator expects one operand" << eom;
1087  throw 0;
1088  }
1089 
1090  exprt &op0=expr.op0();
1092 
1093  // The notation for explicit calls to destructors can be used regardless
1094  // of whether the type defines a destructor. This allows you to make such
1095  // explicit calls without knowing if a destructor is defined for the type.
1096  // An explicit call to a destructor where none is defined has no effect.
1097 
1098  if(expr.find(ID_component_cpp_name).is_not_nil() &&
1099  to_cpp_name(expr.find(ID_component_cpp_name)).is_destructor() &&
1100  follow(op0.type()).id()!=ID_struct)
1101  {
1102  exprt tmp(ID_cpp_dummy_destructor);
1103  tmp.add_source_location()=expr.source_location();
1104  expr.swap(tmp);
1105  return;
1106  }
1107 
1108  // The member operator will trigger template elaboration
1110 
1111  const typet &followed_op0_type=follow(op0.type());
1112 
1113  if(followed_op0_type.id()==ID_incomplete_struct ||
1114  followed_op0_type.id()==ID_incomplete_union)
1115  {
1117  error() << "error: member operator got incomplete type "
1118  << "on left hand side" << eom;
1119  throw 0;
1120  }
1121 
1122  if(followed_op0_type.id()!=ID_struct &&
1123  followed_op0_type.id()!=ID_union)
1124  {
1126  error() << "error: member operator requires struct/union type "
1127  << "on left hand side but got `"
1128  << to_string(followed_op0_type) << "'" << eom;
1129  throw 0;
1130  }
1131 
1132  const struct_union_typet &type=
1133  to_struct_union_type(followed_op0_type);
1134 
1135  irep_idt struct_identifier=type.get(ID_name);
1136 
1137  if(expr.find(ID_component_cpp_name).is_not_nil())
1138  {
1139  cpp_namet component_cpp_name=
1140  to_cpp_name(expr.find(ID_component_cpp_name));
1141 
1142  // go to the scope of the struct/union
1143  cpp_save_scopet save_scope(cpp_scopes);
1144  cpp_scopes.set_scope(struct_identifier);
1145 
1146  // resolve the member name in this scope
1147  cpp_typecheck_fargst new_fargs(fargs);
1148  new_fargs.add_object(op0);
1149 
1150  exprt symbol_expr=resolve(
1151  component_cpp_name,
1153  new_fargs);
1154 
1155  if(symbol_expr.id()==ID_dereference)
1156  {
1157  assert(symbol_expr.get_bool(ID_C_implicit));
1158  exprt tmp=symbol_expr.op0();
1159  symbol_expr.swap(tmp);
1160  }
1161 
1162  assert(symbol_expr.id()==ID_symbol ||
1163  symbol_expr.id()==ID_member ||
1164  symbol_expr.id()==ID_constant);
1165 
1166  // If it is a symbol or a constant, just return it!
1167  // Note: the resolver returns a symbol if the member
1168  // is static or if it is a constructor.
1169 
1170  if(symbol_expr.id()==ID_symbol)
1171  {
1172  if(
1173  symbol_expr.type().id() == ID_code &&
1174  to_code_type(symbol_expr.type()).return_type().id() == ID_constructor)
1175  {
1177  error() << "error: member `"
1178  << lookup(symbol_expr.get(ID_identifier)).base_name
1179  << "' is a constructor" << eom;
1180  throw 0;
1181  }
1182  else
1183  {
1184  // it must be a static component
1185  const struct_typet::componentt pcomp=
1186  type.get_component(to_symbol_expr(symbol_expr).get_identifier());
1187 
1188  if(pcomp.is_nil())
1189  {
1191  error() << "error: `"
1192  << symbol_expr.get(ID_identifier)
1193  << "' is not static member "
1194  << "of class `" << to_string(type) << "'"
1195  << eom;
1196  throw 0;
1197  }
1198  }
1199 
1200  expr=symbol_expr;
1201  return;
1202  }
1203  else if(symbol_expr.id()==ID_constant)
1204  {
1205  expr=symbol_expr;
1206  return;
1207  }
1208 
1209  const irep_idt component_name=symbol_expr.get(ID_component_name);
1210 
1211  expr.remove(ID_component_cpp_name);
1212  expr.set(ID_component_name, component_name);
1213  }
1214 
1215  const irep_idt &component_name=expr.get(ID_component_name);
1216 
1217  assert(component_name!="");
1218 
1219  exprt component;
1220  component.make_nil();
1221 
1222  assert(follow(expr.op0().type()).id()==ID_struct ||
1223  follow(expr.op0().type()).id()==ID_union);
1224 
1225  exprt member;
1226 
1227  if(get_component(expr.source_location(),
1228  expr.op0(),
1229  component_name,
1230  member))
1231  {
1232  // because of possible anonymous members
1233  expr.swap(member);
1234  }
1235  else
1236  {
1238  error() << "error: member `" << component_name
1239  << "' of `" << to_string(type)
1240  << "' not found" << eom;
1241  throw 0;
1242  }
1243 
1245 
1246  if(expr.type().id()==ID_code)
1247  {
1248  // Check if the function body has to be typechecked
1249  symbol_tablet::symbolst::const_iterator it=
1250  symbol_table.symbols.find(component_name);
1251 
1252  assert(it!=symbol_table.symbols.end());
1253 
1254  if(it->second.value.id() == ID_cpp_not_typechecked)
1255  symbol_table.get_writeable_ref(component_name)
1256  .value.set(ID_is_used, true);
1257  }
1258 }
1259 
1261  exprt &expr,
1262  const cpp_typecheck_fargst &fargs)
1263 {
1264  assert(expr.id()==ID_ptrmember);
1265 
1266  if(expr.operands().size()!=1)
1267  {
1269  error() << "error: ptrmember operator expects one operand" << eom;
1270  throw 0;
1271  }
1272 
1273  add_implicit_dereference(expr.op0());
1274 
1275  if(expr.op0().type().id()!=ID_pointer)
1276  {
1278  error() << "error: ptrmember operator requires pointer type "
1279  << "on left hand side, but got `"
1280  << to_string(expr.op0().type()) << "'" << eom;
1281  throw 0;
1282  }
1283 
1284  exprt tmp;
1285  exprt &op=expr.op0();
1286 
1287  op.swap(tmp);
1288 
1289  op.id(ID_dereference);
1290  op.move_to_operands(tmp);
1293 
1294  expr.id(ID_member);
1295  typecheck_expr_member(expr, fargs);
1296 }
1297 
1299 {
1302 
1303  if(e.arguments().size() != 1)
1304  {
1306  error() << "cast expressions expect one operand" << eom;
1307  throw 0;
1308  }
1309 
1310  exprt &f_op=e.function();
1311  exprt &cast_op=e.arguments().front();
1312 
1313  add_implicit_dereference(cast_op);
1314 
1315  const irep_idt &id=
1316  f_op.get_sub().front().get(ID_identifier);
1317 
1318  if(f_op.get_sub().size()!=2 ||
1319  f_op.get_sub()[1].id()!=ID_template_args)
1320  {
1322  error() << id << " expects template argument" << eom;
1323  throw 0;
1324  }
1325 
1326  irept &template_arguments=f_op.get_sub()[1].add(ID_arguments);
1327 
1328  if(template_arguments.get_sub().size()!=1)
1329  {
1331  error() << id << " expects one template argument" << eom;
1332  throw 0;
1333  }
1334 
1335  irept &template_arg=template_arguments.get_sub().front();
1336 
1337  if(template_arg.id() != ID_type && template_arg.id() != ID_ambiguous)
1338  {
1340  error() << id << " expects a type as template argument" << eom;
1341  throw 0;
1342  }
1343 
1344  typet &type=static_cast<typet &>(
1345  template_arguments.get_sub().front().add(ID_type));
1346 
1347  typecheck_type(type);
1348 
1349  source_locationt source_location=expr.source_location();
1350 
1351  exprt new_expr;
1352  if(id==ID_const_cast)
1353  {
1354  if(!const_typecast(cast_op, type, new_expr))
1355  {
1357  error() << "type mismatch on const_cast:\n"
1358  << "operand type: `" << to_string(cast_op.type())
1359  << "'\n"
1360  << "cast type: `" << to_string(type) << "'" << eom;
1361  throw 0;
1362  }
1363  }
1364  else if(id==ID_dynamic_cast)
1365  {
1366  if(!dynamic_typecast(cast_op, type, new_expr))
1367  {
1369  error() << "type mismatch on dynamic_cast:\n"
1370  << "operand type: `" << to_string(cast_op.type())
1371  << "'\n"
1372  << "cast type: `" << to_string(type) << "'" << eom;
1373  throw 0;
1374  }
1375  }
1376  else if(id==ID_reinterpret_cast)
1377  {
1378  if(!reinterpret_typecast(cast_op, type, new_expr))
1379  {
1381  error() << "type mismatch on reinterpret_cast:\n"
1382  << "operand type: `" << to_string(cast_op.type())
1383  << "'\n"
1384  << "cast type: `" << to_string(type) << "'" << eom;
1385  throw 0;
1386  }
1387  }
1388  else if(id==ID_static_cast)
1389  {
1390  if(!static_typecast(cast_op, type, new_expr))
1391  {
1393  error() << "type mismatch on static_cast:\n"
1394  << "operand type: `" << to_string(cast_op.type())
1395  << "'\n"
1396  << "cast type: `" << to_string(type) << "'" << eom;
1397  throw 0;
1398  }
1399  }
1400  else
1401  UNREACHABLE;
1402 
1403  expr.swap(new_expr);
1404 }
1405 
1407  exprt &expr,
1408  const cpp_typecheck_fargst &fargs)
1409 {
1410  source_locationt source_location=
1411  to_cpp_name(expr).source_location();
1412 
1413  if(expr.get_sub().size()==1 &&
1414  expr.get_sub()[0].id()==ID_name)
1415  {
1416  const irep_idt identifier=expr.get_sub()[0].get(ID_identifier);
1417 
1418  if(identifier=="__sync_fetch_and_add" ||
1419  identifier=="__sync_fetch_and_sub" ||
1420  identifier=="__sync_fetch_and_or" ||
1421  identifier=="__sync_fetch_and_and" ||
1422  identifier=="__sync_fetch_and_xor" ||
1423  identifier=="__sync_fetch_and_nand" ||
1424  identifier=="__sync_add_and_fetch" ||
1425  identifier=="__sync_sub_and_fetch" ||
1426  identifier=="__sync_or_and_fetch" ||
1427  identifier=="__sync_and_and_fetch" ||
1428  identifier=="__sync_xor_and_fetch" ||
1429  identifier=="__sync_nand_and_fetch" ||
1430  identifier=="__sync_val_compare_and_swap" ||
1431  identifier=="__sync_lock_test_and_set" ||
1432  identifier=="__sync_lock_release")
1433  {
1434  // These are polymorphic, see
1435  // http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html
1436 
1437  // adjust return type of function to match pointer subtype
1438  if(fargs.operands.empty())
1439  {
1440  error().source_location=source_location;
1441  error() << "__sync_* primitives take as least one argument"
1442  << eom;
1443  throw 0;
1444  }
1445 
1446  const exprt &ptr_arg=fargs.operands.front();
1447 
1448  if(ptr_arg.type().id()!=ID_pointer)
1449  {
1450  error().source_location=source_location;
1451  error() << "__sync_* primitives take a pointer as first argument"
1452  << eom;
1453  throw 0;
1454  }
1455 
1457  result.add_source_location()=source_location;
1458  result.set_identifier(identifier);
1459  code_typet t(
1460  {code_typet::parametert(ptr_arg.type())}, ptr_arg.type().subtype());
1461  t.make_ellipsis();
1462  result.type()=t;
1463  expr.swap(result);
1464  return;
1465  }
1466  else if(identifier=="__atomic_load_n")
1467  {
1468  // These are polymorphic
1469  // https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
1470  // type __atomic_load_n(type *ptr, int memorder)
1471 
1472  if(fargs.operands.size()!=2)
1473  {
1474  error().source_location=source_location;
1475  error() << identifier << " expects two arguments" << eom;
1476  throw 0;
1477  }
1478 
1479  const exprt &ptr_arg=fargs.operands.front();
1480 
1481  if(ptr_arg.type().id()!=ID_pointer)
1482  {
1483  error().source_location=source_location;
1484  error() << identifier << " takes a pointer as first argument"
1485  << eom;
1486  throw 0;
1487  }
1488 
1490  result.add_source_location()=source_location;
1491  result.set_identifier(identifier);
1492  const code_typet t(
1493  {code_typet::parametert(ptr_arg.type()),
1495  ptr_arg.type().subtype());
1496  result.type()=t;
1497  expr.swap(result);
1498  return;
1499  }
1500  else if(identifier=="__atomic_store_n")
1501  {
1502  // These are polymorphic
1503  // https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
1504  // void __atomic_store_n(type *ptr, type val, int memorder)
1505 
1506  if(fargs.operands.size()!=3)
1507  {
1508  error().source_location=source_location;
1509  error() << identifier << " expects three arguments" << eom;
1510  throw 0;
1511  }
1512 
1513  const exprt &ptr_arg=fargs.operands.front();
1514 
1515  if(ptr_arg.type().id()!=ID_pointer)
1516  {
1517  error().source_location=source_location;
1518  error() << identifier << " takes a pointer as first argument"
1519  << eom;
1520  throw 0;
1521  }
1522 
1524  result.add_source_location()=source_location;
1525  result.set_identifier(identifier);
1526  const code_typet t(
1527  {code_typet::parametert(ptr_arg.type()),
1528  code_typet::parametert(ptr_arg.type().subtype()),
1530  empty_typet());
1531  result.type()=t;
1532  expr.swap(result);
1533  return;
1534  }
1535  else if(identifier=="__atomic_exchange_n")
1536  {
1537  // These are polymorphic
1538  // https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
1539  // type __atomic_exchange_n(type *ptr, type val, int memorder)
1540 
1541  if(fargs.operands.size()!=3)
1542  {
1543  error().source_location=source_location;
1544  error() << identifier << " expects three arguments" << eom;
1545  throw 0;
1546  }
1547 
1548  const exprt &ptr_arg=fargs.operands.front();
1549 
1550  if(ptr_arg.type().id()!=ID_pointer)
1551  {
1552  error().source_location=source_location;
1553  error() << identifier << " takes a pointer as first argument"
1554  << eom;
1555  throw 0;
1556  }
1557 
1559  result.add_source_location()=source_location;
1560  result.set_identifier(identifier);
1561  const code_typet t(
1562  {code_typet::parametert(ptr_arg.type()),
1563  code_typet::parametert(ptr_arg.type().subtype()),
1565  ptr_arg.type().subtype());
1566  result.type()=t;
1567  expr.swap(result);
1568  return;
1569  }
1570  else if(identifier=="__atomic_load" ||
1571  identifier=="__atomic_store")
1572  {
1573  // void __atomic_load(type *ptr, type *ret, int memorder)
1574  // void __atomic_store(type *ptr, type *val, int memorder)
1575 
1576  if(fargs.operands.size()!=3)
1577  {
1578  error().source_location=source_location;
1579  error() << identifier << " expects three arguments" << eom;
1580  throw 0;
1581  }
1582 
1583  if(fargs.operands[0].type().id()!=ID_pointer)
1584  {
1585  error().source_location=source_location;
1586  error() << identifier << " takes a pointer as first argument"
1587  << eom;
1588  throw 0;
1589  }
1590 
1591  if(fargs.operands[1].type().id()!=ID_pointer)
1592  {
1593  error().source_location=source_location;
1594  error() << identifier << " takes a pointer as second argument"
1595  << eom;
1596  throw 0;
1597  }
1598 
1599  const exprt &ptr_arg=fargs.operands.front();
1600 
1602  result.add_source_location()=source_location;
1603  result.set_identifier(identifier);
1604  const code_typet t(
1605  {code_typet::parametert(ptr_arg.type()),
1606  code_typet::parametert(ptr_arg.type()),
1608  empty_typet());
1609  result.type()=t;
1610  expr.swap(result);
1611  return;
1612  }
1613  else if(identifier=="__atomic_exchange")
1614  {
1615  // void __atomic_exchange(type *ptr, type *val, type *ret, int memorder)
1616 
1617  if(fargs.operands.size()!=4)
1618  {
1619  error().source_location=source_location;
1620  error() << identifier << " expects four arguments" << eom;
1621  throw 0;
1622  }
1623 
1624  if(fargs.operands[0].type().id()!=ID_pointer)
1625  {
1626  error().source_location=source_location;
1627  error() << identifier << " takes a pointer as first argument"
1628  << eom;
1629  throw 0;
1630  }
1631 
1632  if(fargs.operands[1].type().id()!=ID_pointer)
1633  {
1634  error().source_location=source_location;
1635  error() << identifier << " takes a pointer as second argument"
1636  << eom;
1637  throw 0;
1638  }
1639 
1640  if(fargs.operands[2].type().id()!=ID_pointer)
1641  {
1642  error().source_location=source_location;
1643  error() << identifier << " takes a pointer as third argument"
1644  << eom;
1645  throw 0;
1646  }
1647 
1648  const exprt &ptr_arg=fargs.operands.front();
1649 
1651  result.add_source_location()=source_location;
1652  result.set_identifier(identifier);
1653  const code_typet t(
1654  {code_typet::parametert(ptr_arg.type()),
1655  code_typet::parametert(ptr_arg.type()),
1656  code_typet::parametert(ptr_arg.type()),
1658  empty_typet());
1659  result.type()=t;
1660  expr.swap(result);
1661  return;
1662  }
1663  else if(identifier=="__atomic_compare_exchange_n" ||
1664  identifier=="__atomic_compare_exchange")
1665  {
1666  // bool __atomic_compare_exchange_n(type *ptr, type *expected, type
1667  // desired, bool weak, int success_memorder, int failure_memorder)
1668  // bool __atomic_compare_exchange(type *ptr, type *expected, type
1669  // *desired, bool weak, int success_memorder, int failure_memorder)
1670 
1671  if(fargs.operands.size()!=6)
1672  {
1673  error().source_location=source_location;
1674  error() << identifier << " expects six arguments" << eom;
1675  throw 0;
1676  }
1677 
1678  if(fargs.operands[0].type().id()!=ID_pointer)
1679  {
1680  error().source_location=source_location;
1681  error() << identifier << " takes a pointer as first argument"
1682  << eom;
1683  throw 0;
1684  }
1685 
1686  if(fargs.operands[1].type().id()!=ID_pointer)
1687  {
1688  error().source_location=source_location;
1689  error() << identifier << " takes a pointer as second argument"
1690  << eom;
1691  throw 0;
1692  }
1693 
1694  if(identifier=="__atomic_compare_exchange" &&
1695  fargs.operands[2].type().id()!=ID_pointer)
1696  {
1697  error().source_location=source_location;
1698  error() << identifier << " takes a pointer as third argument"
1699  << eom;
1700  throw 0;
1701  }
1702 
1703  const exprt &ptr_arg=fargs.operands.front();
1704 
1706  result.add_source_location()=source_location;
1707  result.set_identifier(identifier);
1708  code_typet::parameterst parameters;
1709  parameters.push_back(code_typet::parametert(ptr_arg.type()));
1710  parameters.push_back(code_typet::parametert(ptr_arg.type()));
1711 
1712  if(identifier=="__atomic_compare_exchange")
1713  parameters.push_back(code_typet::parametert(ptr_arg.type()));
1714  else
1715  parameters.push_back(code_typet::parametert(ptr_arg.type().subtype()));
1716 
1717  parameters.push_back(code_typet::parametert(c_bool_type()));
1718  parameters.push_back(code_typet::parametert(signed_int_type()));
1719  parameters.push_back(code_typet::parametert(signed_int_type()));
1720  code_typet t(std::move(parameters), c_bool_type());
1721  result.type()=t;
1722  expr.swap(result);
1723  return;
1724  }
1725  else if(identifier=="__atomic_add_fetch" ||
1726  identifier=="__atomic_sub_fetch" ||
1727  identifier=="__atomic_and_fetch" ||
1728  identifier=="__atomic_xor_fetch" ||
1729  identifier=="__atomic_or_fetch" ||
1730  identifier=="__atomic_nand_fetch")
1731  {
1732  if(fargs.operands.size()!=3)
1733  {
1734  error().source_location=source_location;
1735  error() << "__atomic_*_fetch primitives take three arguments"
1736  << eom;
1737  throw 0;
1738  }
1739 
1740  const exprt &ptr_arg=fargs.operands.front();
1741 
1742  if(ptr_arg.type().id()!=ID_pointer)
1743  {
1744  error().source_location=source_location;
1745  error() << "__atomic_*_fetch primitives take pointer as first argument"
1746  << eom;
1747  throw 0;
1748  }
1749 
1751  result.add_source_location()=source_location;
1752  result.set_identifier(identifier);
1753  code_typet t(
1754  {code_typet::parametert(ptr_arg.type())}, ptr_arg.type().subtype());
1755  t.make_ellipsis();
1756  result.type()=t;
1757  expr.swap(result);
1758  return;
1759  }
1760  else if(identifier=="__atomic_fetch_add" ||
1761  identifier=="__atomic_fetch_sub" ||
1762  identifier=="__atomic_fetch_and" ||
1763  identifier=="__atomic_fetch_xor" ||
1764  identifier=="__atomic_fetch_or" ||
1765  identifier=="__atomic_fetch_nand")
1766  {
1767  if(fargs.operands.size()!=3)
1768  {
1769  error().source_location=source_location;
1770  error() << "__atomic_fetch_* primitives take three arguments"
1771  << eom;
1772  throw 0;
1773  }
1774 
1775  const exprt &ptr_arg=fargs.operands.front();
1776 
1777  if(ptr_arg.type().id()!=ID_pointer)
1778  {
1779  error().source_location=source_location;
1780  error() << "__atomic_fetch_* primitives take pointer as first argument"
1781  << eom;
1782  throw 0;
1783  }
1784 
1786  result.add_source_location()=source_location;
1787  result.set_identifier(identifier);
1788  code_typet t(
1789  {code_typet::parametert(ptr_arg.type())}, ptr_arg.type().subtype());
1790  t.make_ellipsis();
1791  result.type()=t;
1792  expr.swap(result);
1793  return;
1794  }
1795  else if(identifier=="__atomic_test_and_set")
1796  {
1797  }
1798  else if(identifier=="__atomic_clear")
1799  {
1800  }
1801  else if(identifier=="__atomic_thread_fence")
1802  {
1803  }
1804  else if(identifier=="__atomic_signal_fence")
1805  {
1806  }
1807  else if(identifier=="__atomic_always_lock_free")
1808  {
1809  }
1810  else if(identifier=="__atomic_is_lock_free")
1811  {
1812  }
1813  }
1814 
1815  for(std::size_t i=0; i<expr.get_sub().size(); i++)
1816  {
1817  if(expr.get_sub()[i].id()==ID_cpp_name)
1818  {
1819  typet &type=static_cast<typet &>(expr.get_sub()[i]);
1820  typecheck_type(type);
1821 
1822  std::string tmp="("+cpp_type2name(type)+")";
1823 
1824  typet name(ID_name);
1825  name.set(ID_identifier, tmp);
1826  name.add_source_location()=source_location;
1827 
1828  type=name;
1829  }
1830  }
1831 
1832  if(expr.get_sub().size()>=1 &&
1833  expr.get_sub().front().id()==ID_name)
1834  {
1835  const irep_idt &id=expr.get_sub().front().get(ID_identifier);
1836 
1837  if(id==ID_const_cast ||
1838  id==ID_dynamic_cast ||
1839  id==ID_reinterpret_cast ||
1840  id==ID_static_cast)
1841  {
1842  expr.id(ID_cast_expression);
1843  return;
1844  }
1845  }
1846 
1847  exprt symbol_expr=
1848  resolve(
1849  to_cpp_name(expr),
1851  fargs);
1852 
1853  // we want VAR
1854  assert(symbol_expr.id()!=ID_type);
1855 
1856  if(symbol_expr.id()==ID_member)
1857  {
1858  if(symbol_expr.operands().empty() ||
1859  symbol_expr.op0().is_nil())
1860  {
1861  if(to_code_type(symbol_expr.type()).return_type().id() != ID_constructor)
1862  {
1864  {
1865  if(symbol_expr.type().id()!=ID_code)
1866  {
1867  error().source_location=source_location;
1868  error() << "object missing" << eom;
1869  throw 0;
1870  }
1871 
1872  // may still be good for address of
1873  }
1874  else
1875  {
1876  // Try again
1877  exprt ptrmem(ID_ptrmember);
1878  ptrmem.operands().push_back(
1880 
1881  ptrmem.add(ID_component_cpp_name)=expr;
1882 
1883  ptrmem.add_source_location()=source_location;
1884  typecheck_expr_ptrmember(ptrmem, fargs);
1885  symbol_expr.swap(ptrmem);
1886  }
1887  }
1888  }
1889  }
1890 
1891  symbol_expr.add_source_location()=source_location;
1892  expr=symbol_expr;
1893 
1894  if(expr.id()==ID_symbol)
1896 
1898 }
1899 
1901 {
1902  if(is_reference(expr.type()))
1903  {
1904  // add implicit dereference
1905  dereference_exprt tmp(expr);
1906  tmp.set(ID_C_implicit, true);
1907  tmp.add_source_location()=expr.source_location();
1908  tmp.set(ID_C_lvalue, true);
1909  expr.swap(tmp);
1910  }
1911 }
1912 
1915 {
1916  // For virtual functions, it is important to check whether
1917  // the function name is qualified. If it is qualified, then
1918  // the call is not virtual.
1919  bool is_qualified=false;
1920 
1921  if(expr.function().id()==ID_member ||
1922  expr.function().id()==ID_ptrmember)
1923  {
1924  if(expr.function().get(ID_component_cpp_name)==ID_cpp_name)
1925  {
1926  const cpp_namet &cpp_name=
1927  to_cpp_name(expr.function().find(ID_component_cpp_name));
1928  is_qualified=cpp_name.is_qualified();
1929  }
1930  }
1931  else if(expr.function().id()==ID_cpp_name)
1932  {
1933  const cpp_namet &cpp_name=to_cpp_name(expr.function());
1934  is_qualified=cpp_name.is_qualified();
1935  }
1936 
1937  // Backup of the original operand
1938  exprt op0=expr.function();
1939 
1940  // now do the function -- this has been postponed
1942 
1943  if(expr.function().id() == ID_pod_constructor)
1944  {
1945  assert(expr.function().type().id()==ID_code);
1946 
1947  // This must be a POD.
1948  const typet &pod=to_code_type(expr.function().type()).return_type();
1949  assert(cpp_is_pod(pod));
1950 
1951  // These aren't really function calls, but either conversions or
1952  // initializations.
1953  if(expr.arguments().empty())
1954  {
1955  // create temporary object
1956  side_effect_exprt tmp_object_expr(
1957  ID_temporary_object, pod, expr.source_location());
1958  tmp_object_expr.set(ID_C_lvalue, true);
1959  tmp_object_expr.set(ID_mode, ID_cpp);
1960  expr.swap(tmp_object_expr);
1961  }
1962  else if(expr.arguments().size()==1)
1963  {
1964  exprt typecast("explicit-typecast");
1965  typecast.type()=pod;
1966  typecast.add_source_location()=expr.source_location();
1967  typecast.copy_to_operands(expr.arguments().front());
1969  expr.swap(typecast);
1970  }
1971  else
1972  {
1974  error() << "zero or one argument expected" << eom;
1975  throw 0;
1976  }
1977 
1978  return;
1979  }
1980  else if(expr.function().id() == ID_cast_expression)
1981  {
1982  // These are not really function calls,
1983  // but usually just type adjustments.
1984  typecheck_cast_expr(expr);
1986  return;
1987  }
1988  else if(expr.function().id() == ID_cpp_dummy_destructor)
1989  {
1990  // these don't do anything, e.g., (char*)->~char()
1991  expr.set(ID_statement, ID_skip);
1992  expr.type()=empty_typet();
1993  return;
1994  }
1995 
1996  // look at type of function
1997 
1998  expr.function().type() = follow(expr.function().type());
1999 
2000  if(expr.function().type().id()==ID_pointer)
2001  {
2002  if(expr.function().type().find("to-member").is_not_nil())
2003  {
2004  const exprt &bound =
2005  static_cast<const exprt &>(expr.function().type().find(ID_C_bound));
2006 
2007  if(bound.is_nil())
2008  {
2010  error() << "pointer-to-member not bound" << eom;
2011  throw 0;
2012  }
2013 
2014  // add `this'
2015  assert(bound.type().id()==ID_pointer);
2016  expr.arguments().insert(expr.arguments().begin(), bound);
2017 
2018  // we don't need the object any more
2019  expr.function().type().remove(ID_C_bound);
2020  }
2021 
2022  // do implicit dereference
2023  if(expr.function().id()==ID_address_of &&
2024  expr.function().operands().size()==1)
2025  {
2026  exprt tmp;
2027  tmp.swap(expr.function().op0());
2028  expr.function().swap(tmp);
2029  }
2030  else
2031  {
2032  assert(expr.function().type().id()==ID_pointer);
2033  dereference_exprt tmp(expr.function());
2034  tmp.add_source_location()=expr.op0().source_location();
2035  expr.function().swap(tmp);
2036  }
2037 
2038  if(expr.function().type().id()!=ID_code)
2039  {
2041  error() << "expecting code as argument" << eom;
2042  throw 0;
2043  }
2044  }
2045  else if(expr.function().type().id()==ID_code)
2046  {
2047  if(expr.function().type().get_bool(ID_C_is_virtual) && !is_qualified)
2048  {
2049  exprt vtptr_member;
2050  if(op0.id()==ID_member || op0.id()==ID_ptrmember)
2051  {
2052  vtptr_member.id(op0.id());
2053  vtptr_member.move_to_operands(op0.op0());
2054  }
2055  else
2056  {
2057  vtptr_member.id(ID_ptrmember);
2058  exprt this_expr("cpp-this");
2059  vtptr_member.move_to_operands(this_expr);
2060  }
2061 
2062  // get the virtual table
2063  typet this_type=
2064  to_code_type(expr.function().type()).parameters().front().type();
2065  irep_idt vtable_name=
2066  this_type.subtype().get_string(ID_identifier) +"::@vtable_pointer";
2067 
2068  const struct_typet &vt_struct=
2069  to_struct_type(follow(this_type.subtype()));
2070 
2071  const struct_typet::componentt &vt_compo=
2072  vt_struct.get_component(vtable_name);
2073 
2074  assert(vt_compo.is_not_nil());
2075 
2076  vtptr_member.set(ID_component_name, vtable_name);
2077 
2078  // look for the right entry
2079  irep_idt vtentry_component_name =
2080  vt_compo.type().subtype().get_string(ID_identifier) +
2081  "::" + expr.function().type().get_string(ID_C_virtual_name);
2082 
2083  exprt vtentry_member(ID_ptrmember);
2084  vtentry_member.copy_to_operands(vtptr_member);
2085  vtentry_member.set(ID_component_name, vtentry_component_name);
2086  typecheck_expr(vtentry_member);
2087 
2088  assert(vtentry_member.type().id()==ID_pointer);
2089 
2090  {
2091  dereference_exprt tmp(vtentry_member);
2092  tmp.add_source_location()=expr.op0().source_location();
2093  vtentry_member.swap(tmp);
2094  }
2095 
2096  // Typecheck the expression as if it was not virtual
2097  // (add the this pointer)
2098 
2099  expr.type()=
2100  to_code_type(expr.function().type()).return_type();
2101 
2103 
2104  // Let's make the call virtual
2105  expr.function().swap(vtentry_member);
2106 
2109  return;
2110  }
2111  }
2112  else if(expr.function().type().id()==ID_struct)
2113  {
2114  const cpp_namet cppname("operator()", expr.source_location());
2115 
2116  exprt member(ID_member);
2117  member.add(ID_component_cpp_name)=cppname;
2118 
2119  member.move_to_operands(op0);
2120 
2121  expr.function().swap(member);
2123 
2124  return;
2125  }
2126  else
2127  {
2129  error() << "function call expects function or function "
2130  << "pointer as argument, but got `"
2131  << to_string(expr.op0().type()) << "'" << eom;
2132  throw 0;
2133  }
2134 
2135  expr.type()=
2136  to_code_type(expr.function().type()).return_type();
2137 
2138  if(expr.type().id()==ID_constructor)
2139  {
2140  assert(expr.function().id() == ID_symbol);
2141 
2142  const code_typet::parameterst &parameters=
2143  to_code_type(expr.function().type()).parameters();
2144 
2145  assert(parameters.size()>=1);
2146 
2147  const typet &this_type=parameters[0].type();
2148 
2149  // change type from 'constructor' to object type
2150  expr.type()=this_type.subtype();
2151 
2152  // create temporary object
2153  side_effect_exprt tmp_object_expr(
2154  ID_temporary_object, this_type.subtype(), expr.source_location());
2155  tmp_object_expr.set(ID_C_lvalue, true);
2156  tmp_object_expr.set(ID_mode, ID_cpp);
2157 
2158  exprt member;
2159 
2160  exprt new_object(ID_new_object, tmp_object_expr.type());
2161  new_object.set(ID_C_lvalue, true);
2162 
2163  assert(follow(tmp_object_expr.type()).id()==ID_struct);
2164 
2166  new_object,
2167  expr.function().get(ID_identifier),
2168  member);
2169 
2170  // special case for the initialization of parents
2171  if(member.get_bool(ID_C_not_accessible))
2172  {
2173  assert(member.get(ID_C_access)!="");
2174  tmp_object_expr.set(ID_C_not_accessible, true);
2175  tmp_object_expr.set(ID_C_access, member.get(ID_C_access));
2176  }
2177 
2178  // the constructor is being used, so make sure the destructor
2179  // will be available
2180  {
2181  // find name of destructor
2182  const struct_typet::componentst &components=
2183  to_struct_type(follow(tmp_object_expr.type())).components();
2184 
2185  for(const auto &c : components)
2186  {
2187  const typet &type = c.type();
2188 
2189  if(
2190  !c.get_bool(ID_from_base) && type.id() == ID_code &&
2191  to_code_type(type).return_type().id() == ID_destructor)
2192  {
2194  break;
2195  }
2196  }
2197  }
2198 
2199  expr.function().swap(member);
2200 
2203 
2204  const code_expressiont new_code(expr);
2205  tmp_object_expr.add(ID_initializer)=new_code;
2206  expr.swap(tmp_object_expr);
2207  return;
2208  }
2209 
2210  assert(expr.operands().size()==2);
2211 
2212  if(expr.function().id()==ID_member)
2214  else
2215  {
2216  // for the object of a method call,
2217  // we are willing to add an "address_of"
2218  // for the sake of operator overloading
2219 
2220  const irept::subt &arguments=
2221  expr.function().type().find(ID_arguments).get_sub();
2222 
2223  if(arguments.size()>=1 &&
2224  arguments.front().get(ID_C_base_name)==ID_this &&
2225  expr.arguments().size()>=1)
2226  {
2227  const exprt &argument=
2228  static_cast<const exprt &>(arguments.front());
2229 
2230  exprt &operand=expr.op1();
2231  assert(argument.type().id()==ID_pointer);
2232 
2233  if(operand.type().id()!=ID_pointer &&
2234  operand.type()==argument.type().subtype())
2235  {
2236  address_of_exprt tmp(operand, pointer_type(operand.type()));
2237  tmp.add_source_location()=operand.source_location();
2238  operand=tmp;
2239  }
2240  }
2241  }
2242 
2243  assert(expr.operands().size()==2);
2244 
2246 
2247  assert(expr.operands().size()==2);
2248 
2250 
2251  // we will deal with some 'special' functions here
2252  exprt tmp=do_special_functions(expr);
2253  if(tmp.is_not_nil())
2254  expr.swap(tmp);
2255 }
2256 
2260 {
2261  exprt &f_op=expr.function();
2262  const code_typet &code_type=to_code_type(f_op.type());
2263  const code_typet::parameterst &parameters=code_type.parameters();
2264 
2265  // do default arguments
2266 
2267  if(parameters.size()>expr.arguments().size())
2268  {
2269  std::size_t i=expr.arguments().size();
2270 
2271  for(; i<parameters.size(); i++)
2272  {
2273  if(!parameters[i].has_default_value())
2274  break;
2275 
2276  const exprt &value=parameters[i].default_value();
2277  expr.arguments().push_back(value);
2278  }
2279  }
2280 
2281  exprt::operandst::iterator arg_it=expr.arguments().begin();
2282  for(const auto &parameter : parameters)
2283  {
2284  if(parameter.get_bool(ID_C_call_by_value))
2285  {
2286  assert(is_reference(parameter.type()));
2287 
2288  if(arg_it->id()!=ID_temporary_object)
2289  {
2290  // create a temporary for the parameter
2291 
2292  exprt arg(ID_already_typechecked);
2293  arg.copy_to_operands(*arg_it);
2294 
2295  exprt temporary;
2296  new_temporary(
2297  arg_it->source_location(),
2298  parameter.type().subtype(),
2299  arg,
2300  temporary);
2301  arg_it->swap(temporary);
2302  }
2303  }
2304 
2305  ++arg_it;
2306  }
2307 
2309 }
2310 
2312  side_effect_exprt &expr)
2313 {
2314  const irep_idt &statement=expr.get(ID_statement);
2315 
2316  if(statement==ID_cpp_new ||
2317  statement==ID_cpp_new_array)
2318  {
2319  typecheck_expr_new(expr);
2320  }
2321  else if(statement==ID_cpp_delete ||
2322  statement==ID_cpp_delete_array)
2323  {
2324  typecheck_expr_delete(expr);
2325  }
2326  else if(statement==ID_preincrement ||
2327  statement==ID_predecrement ||
2328  statement==ID_postincrement ||
2329  statement==ID_postdecrement)
2330  {
2332  }
2333  else if(statement==ID_throw)
2334  {
2335  typecheck_expr_throw(expr);
2336  }
2337  else if(statement==ID_temporary_object)
2338  {
2339  // TODO
2340  }
2341  else
2343 }
2344 
2347 {
2348  assert(expr.operands().size()==2);
2349 
2350  assert(expr.function().id()==ID_member);
2351  assert(expr.function().operands().size()==1);
2352 
2353  // turn e.f(...) into xx::f(e, ...)
2354 
2355  exprt member_expr;
2356  member_expr.swap(expr.function());
2357 
2358  const symbolt &symbol=lookup(member_expr.get(ID_component_name));
2359  symbolt &method_symbol=symbol_table.get_writeable_ref(symbol.name);
2360  const symbolt &tag_symbol = lookup(symbol.type.get(ID_C_member_name));
2361 
2362  // build the right template map
2363  // if this is an instantiated template class method
2364  if(tag_symbol.type.find(ID_C_template)!=irept())
2365  {
2367  const irept &template_type = tag_symbol.type.find(ID_C_template);
2368  const irept &template_args = tag_symbol.type.find(ID_C_template_arguments);
2370  static_cast<const template_typet &>(template_type),
2371  static_cast<const cpp_template_args_tct &>(template_args));
2372  add_method_body(&method_symbol);
2373 #ifdef DEBUG
2374  std::cout << "MAP for " << symbol << ":" << std::endl;
2375  template_map.print(std::cout);
2376 #endif
2377  }
2378  else
2379  add_method_body(&method_symbol);
2380 
2381  // build new function expression
2382  exprt new_function(cpp_symbol_expr(symbol));
2383  new_function.add_source_location()=member_expr.source_location();
2384  expr.function().swap(new_function);
2385 
2386  if(!expr.function().type().get_bool(ID_C_is_static))
2387  {
2388  const code_typet &func_type=to_code_type(symbol.type);
2389  typet this_type=func_type.parameters().front().type();
2390 
2391  // Special case. Make it a reference.
2392  assert(this_type.id()==ID_pointer);
2393  this_type.set(ID_C_reference, true);
2394  this_type.set(ID_C_this, true);
2395 
2396  if(expr.arguments().size()==func_type.parameters().size())
2397  {
2398  // this might be set up for base-class initialisation
2399  if(!base_type_eq(expr.arguments().front().type(),
2400  func_type.parameters().front().type(),
2401  *this))
2402  {
2403  implicit_typecast(expr.arguments().front(), this_type);
2404  assert(is_reference(expr.arguments().front().type()));
2405  expr.arguments().front().type().remove(ID_C_reference);
2406  }
2407  }
2408  else
2409  {
2410  exprt this_arg=member_expr.op0();
2411  implicit_typecast(this_arg, this_type);
2412  assert(is_reference(this_arg.type()));
2413  this_arg.type().remove(ID_C_reference);
2414  expr.arguments().insert(expr.arguments().begin(), this_arg);
2415  }
2416  }
2417 
2418  if(
2419  symbol.value.id() == ID_cpp_not_typechecked &&
2420  !symbol.value.get_bool(ID_is_used))
2421  {
2422  symbol_table.get_writeable_ref(symbol.name).value.set(ID_is_used, true);
2423  }
2424 }
2425 
2427 {
2428  if(expr.operands().size()!=2)
2429  {
2431  error() << "assignment side effect expected to have two operands"
2432  << eom;
2433  throw 0;
2434  }
2435 
2436  typet type0=expr.op0().type();
2437 
2438  if(is_reference(type0))
2439  type0=type0.subtype();
2440 
2441  if(cpp_is_pod(type0))
2442  {
2443  // for structs we use the 'implicit assignment operator',
2444  // and therefore, it is allowed to assign to a rvalue struct.
2445  if(follow(type0).id()==ID_struct)
2446  expr.op0().set(ID_C_lvalue, true);
2447 
2449 
2450  // Note that in C++ (as opposed to C), the assignment yields
2451  // an lvalue!
2452  expr.set(ID_C_lvalue, true);
2453  return;
2454  }
2455 
2456  // It's a non-POD.
2457  // Turn into an operator call
2458 
2459  std::string strop="operator";
2460 
2461  const irep_idt statement=expr.get(ID_statement);
2462 
2463  if(statement==ID_assign)
2464  strop += "=";
2465  else if(statement==ID_assign_shl)
2466  strop += "<<=";
2467  else if(statement==ID_assign_shr)
2468  strop += ">>=";
2469  else if(statement==ID_assign_plus)
2470  strop += "+=";
2471  else if(statement==ID_assign_minus)
2472  strop += "-=";
2473  else if(statement==ID_assign_mult)
2474  strop += "*=";
2475  else if(statement==ID_assign_div)
2476  strop += "/=";
2477  else if(statement==ID_assign_bitand)
2478  strop += "&=";
2479  else if(statement==ID_assign_bitor)
2480  strop += "|=";
2481  else if(statement==ID_assign_bitxor)
2482  strop += "^=";
2483  else
2484  {
2486  error() << "bad assignment operator `" << statement << "'" << eom;
2487  throw 0;
2488  }
2489 
2490  const cpp_namet cpp_name(strop, expr.source_location());
2491 
2492  // expr.op0() is already typechecked
2493  exprt already_typechecked(ID_already_typechecked);
2494  already_typechecked.move_to_operands(expr.op0());
2495 
2496  exprt member(ID_member);
2497  member.set(ID_component_cpp_name, cpp_name);
2499 
2501  new_expr.function().swap(member);
2502  new_expr.arguments().push_back(expr.op1());
2503  new_expr.add_source_location()=expr.source_location();
2504 
2506 
2507  expr=new_expr;
2508 }
2509 
2511  side_effect_exprt &expr)
2512 {
2513  if(expr.operands().size()!=1)
2514  {
2516  error() << "statement " << expr.get_statement()
2517  << " expected to have one operand" << eom;
2518  throw 0;
2519  }
2520 
2521  add_implicit_dereference(expr.op0());
2522 
2523  typet tmp_type=follow(expr.op0().type());
2524 
2525  if(is_number(tmp_type) ||
2526  tmp_type.id()==ID_pointer)
2527  {
2528  // standard stuff
2530  return;
2531  }
2532 
2533  // Turn into an operator call
2534 
2535  std::string str_op="operator";
2536  bool post=false;
2537 
2538  if(expr.get(ID_statement)==ID_preincrement)
2539  str_op += "++";
2540  else if(expr.get(ID_statement)==ID_predecrement)
2541  str_op += "--";
2542  else if(expr.get(ID_statement)==ID_postincrement)
2543  {
2544  str_op += "++";
2545  post=true;
2546  }
2547  else if(expr.get(ID_statement)==ID_postdecrement)
2548  {
2549  str_op += "--";
2550  post=true;
2551  }
2552  else
2553  {
2555  error() << "bad assignment operator `"
2556  << expr.get_statement()
2557  << "'" << eom;
2558  throw 0;
2559  }
2560 
2561  const cpp_namet cpp_name(str_op, expr.source_location());
2562 
2563  exprt already_typechecked(ID_already_typechecked);
2564  already_typechecked.move_to_operands(expr.op0());
2565 
2566  exprt member(ID_member);
2567  member.set(ID_component_cpp_name, cpp_name);
2569 
2571  new_expr.function().swap(member);
2572  new_expr.add_source_location()=expr.source_location();
2573 
2574  // the odd C++ way to denote the post-inc/dec operator
2575  if(post)
2576  new_expr.arguments().push_back(
2578 
2580  expr.swap(new_expr);
2581 }
2582 
2584 {
2585  if(expr.operands().size()!=1)
2586  {
2588  error() << "unary operator * expects one operand" << eom;
2589  throw 0;
2590  }
2591 
2592  exprt &op=expr.op0();
2593  const typet op_type=follow(op.type());
2594 
2595  if(op_type.id()==ID_pointer &&
2596  op_type.find("to-member").is_not_nil())
2597  {
2599  error() << "pointer-to-member must use "
2600  << "the .* or ->* operators" << eom;
2601  throw 0;
2602  }
2603 
2605 }
2606 
2608 {
2609  assert(expr.id()=="pointer-to-member");
2610  assert(expr.operands().size() == 2);
2611 
2612  if(expr.op1().type().id()!=ID_pointer
2613  || expr.op1().type().find("to-member").is_nil())
2614  {
2616  error() << "pointer-to-member expected" << eom;
2617  throw 0;
2618  }
2619 
2620  typet t0=expr.op0().type().id()==ID_pointer ?
2621  expr.op0().type().subtype(): expr.op0().type();
2622 
2623  typet t1((const typet&)expr.op1().type().find("to-member"));
2624 
2625  t0=follow(t0);
2626  t1=follow(t1);
2627 
2628  if(t0.id()!=ID_struct)
2629  {
2631  error() << "pointer-to-member type error" << eom;
2632  throw 0;
2633  }
2634 
2635  const struct_typet &from_struct=to_struct_type(t0);
2636  const struct_typet &to_struct=to_struct_type(t1);
2637 
2638  if(!subtype_typecast(from_struct, to_struct))
2639  {
2641  error() << "pointer-to-member type error" << eom;
2642  throw 0;
2643  }
2644 
2645  typecheck_expr_main(expr.op1());
2646 
2647  if(expr.op0().type().id()!=ID_pointer)
2648  {
2649  if(expr.op0().id()==ID_dereference)
2650  {
2651  exprt tmp=expr.op0().op0();
2652  expr.op0().swap(tmp);
2653  }
2654  else
2655  {
2656  assert(expr.op0().get_bool(ID_C_lvalue));
2657  expr.op0()=address_of_exprt(expr.op0());
2658  }
2659  }
2660 
2661  exprt tmp(expr.op1());
2662  tmp.type().set(ID_C_bound, expr.op0());
2663  expr.swap(tmp);
2664  return;
2665 }
2666 
2668 {
2669  if(expr.id()==ID_symbol)
2670  {
2671  // Check if the function body has to be typechecked
2672  symbol_tablet::symbolst::const_iterator it=
2673  symbol_table.symbols.find(expr.get(ID_identifier));
2674 
2675  assert(it != symbol_table.symbols.end());
2676 
2677  if(it->second.value.id() == ID_cpp_not_typechecked)
2678  symbol_table.get_writeable_ref(it->first).value.set(ID_is_used, true);
2679  }
2680 
2682 }
2683 
2685 {
2686  bool override_constantness = expr.get_bool(ID_C_override_constantness);
2687 
2688  // We take care of an ambiguity in the C++ grammar.
2689  // Needs to be done before the operands!
2691 
2692  // cpp_name uses get_sub, which can get confused with expressions.
2693  if(expr.id()==ID_cpp_name)
2695  else
2696  {
2697  // This does the operands, and then calls typecheck_expr_main.
2699  }
2700 
2701  if(override_constantness)
2702  expr.type().set(ID_C_constant, false);
2703 }
2704 
2706 {
2707  // There is an ambiguity in the C++ grammar as follows:
2708  // (TYPENAME) + expr (typecast of unary plus) vs.
2709  // (expr) + expr (sum of two expressions)
2710  // Same issue with the operators & and - and *
2711 
2712  // We figure this out by resolving the type argument
2713  // and re-writing if needed
2714 
2715  if(expr.id()!="explicit-typecast")
2716  return;
2717 
2718  assert(expr.operands().size()==1);
2719 
2720  irep_idt op0_id=expr.op0().id();
2721 
2722  if(expr.type().id()==ID_cpp_name &&
2723  expr.op0().operands().size()==1 &&
2724  (op0_id==ID_unary_plus ||
2725  op0_id==ID_unary_minus ||
2726  op0_id==ID_address_of ||
2727  op0_id==ID_dereference))
2728  {
2729  exprt resolve_result=
2730  resolve(
2731  to_cpp_name(expr.type()),
2734 
2735  if(resolve_result.id()!=ID_type)
2736  {
2737  // need to re-write the expression
2738  // e.g., (ID) +expr -> ID+expr
2739  exprt new_binary_expr;
2740 
2741  new_binary_expr.operands().resize(2);
2742  new_binary_expr.op0().swap(expr.type());
2743  new_binary_expr.op1().swap(expr.op0().op0());
2744 
2745  if(op0_id==ID_unary_plus)
2746  new_binary_expr.id(ID_plus);
2747  else if(op0_id==ID_unary_minus)
2748  new_binary_expr.id(ID_minus);
2749  else if(op0_id==ID_address_of)
2750  new_binary_expr.id(ID_bitand);
2751  else if(op0_id==ID_dereference)
2752  new_binary_expr.id(ID_mult);
2753 
2754  new_binary_expr.add_source_location()=expr.op0().source_location();
2755  expr.swap(new_binary_expr);
2756  }
2757  }
2758 }
2759 
2761 {
2762  if(expr.operands().size()!=2)
2763  {
2765  error() << "operator `" << expr.id() << "' expects two operands"
2766  << eom;
2767  throw 0;
2768  }
2769 
2770  add_implicit_dereference(expr.op0());
2771  add_implicit_dereference(expr.op1());
2772 
2774 }
2775 
2777 {
2779 }
2780 
2782 {
2783  if(expr.operands().size()!=2)
2784  {
2786  error() << "comma operator expects two operands" << eom;
2787  throw 0;
2788  }
2789 
2790  if(follow(expr.op0().type()).id()==ID_struct)
2791  {
2792  // TODO: check if the comma operator has been overloaded!
2793  }
2794 
2796 }
2797 
2799 {
2801 }
c_typecheck_baset::do_initializer
virtual void do_initializer(exprt &initializer, const typet &type, bool force_constant)
Definition: c_typecheck_initializer.cpp:26
c_qualifierst::read
virtual void read(const typet &src) override
Definition: c_qualifiers.cpp:62
exprt::copy_to_operands
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition: expr.h:123
exprt::op2
exprt & op2()
Definition: expr.h:90
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:205
c_typecheck_baset::typecheck_expr_side_effect
virtual void typecheck_expr_side_effect(side_effect_exprt &expr)
Definition: c_typecheck_expr.cpp:1863
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:35
pointer_offset_size.h
cpp_idt::class_identifier
irep_idt class_identifier
Definition: cpp_id.h:76
exprt::move_to_operands
void move_to_operands(exprt &expr)
Move the given argument to the end of exprt's operands.
Definition: expr.cpp:29
typet::subtype
const typet & subtype() const
Definition: type.h:38
class_typet
Class type.
Definition: std_types.h:365
to_side_effect_expr_function_call
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
Definition: std_code.h:1775
cpp_typecheckt::typecheck_expr_side_effect
void typecheck_expr_side_effect(side_effect_exprt &) override
Definition: cpp_typecheck_expr.cpp:2311
cpp_typecheckt::elaborate_class_template
void elaborate_class_template(const typet &type)
elaborate class template instances
Definition: cpp_instantiate_template.cpp:186
cpp_typecheckt::typecheck_expr_dereference
void typecheck_expr_dereference(exprt &) override
Definition: cpp_typecheck_expr.cpp:2583
arith_tools.h
is_number
bool is_number(const typet &type)
Returns true if the type is a rational, real, integer, natural, complex, unsignedbv,...
Definition: mathematical_types.cpp:17
cpp_typecheckt::typecheck_expr_trinary
void typecheck_expr_trinary(if_exprt &) override
Definition: cpp_typecheck_expr.cpp:140
cpp_typecheck_fargst
Definition: cpp_typecheck_fargs.h:22
cpp_typecheckt::convert_pmop
void convert_pmop(exprt &expr)
Definition: cpp_typecheck_expr.cpp:2607
struct_union_typet::get_component
const componentt & get_component(const irep_idt &component_name) const
Get the reference to a component with given name.
Definition: std_types.cpp:53
cpp_typecheckt::typecheck_expr_explicit_constructor_call
void typecheck_expr_explicit_constructor_call(exprt &)
Definition: cpp_typecheck_expr.cpp:973
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:349
cpp_typecheckt::typecheck_expr_cpp_name
void typecheck_expr_cpp_name(exprt &, const cpp_typecheck_fargst &)
Definition: cpp_typecheck_expr.cpp:1406
cpp_save_scopet
Definition: cpp_scopes.h:128
cpp_typecheckt::typecheck_expr_typecast
void typecheck_expr_typecast(exprt &) override
Definition: cpp_typecheck_expr.cpp:1070
to_struct_union_type
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition: std_types.h:260
cpp_typecheckt::cpp_scopes
cpp_scopest cpp_scopes
Definition: cpp_typecheck.h:109
c_typecheck_baset::do_special_functions
virtual exprt do_special_functions(side_effect_expr_function_callt &expr)
Definition: c_typecheck_expr.cpp:2072
cpp_idt::this_expr
exprt this_expr
Definition: cpp_id.h:77
already_typechecked
void already_typechecked(irept &irep)
Definition: cpp_util.h:18
typet
The type of an expression, extends irept.
Definition: type.h:27
code_typet::parameterst
std::vector< parametert > parameterst
Definition: std_types.h:754
cpp_typecheckt::operator_is_overloaded
bool operator_is_overloaded(exprt &)
Definition: cpp_typecheck_expr.cpp:472
irept::pretty
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:640
to_class_type
const class_typet & to_class_type(const typet &type)
Cast a typet to a class_typet.
Definition: std_types.h:409
cpp_typecheckt::reinterpret_typecast
bool reinterpret_typecast(const exprt &expr, const typet &type, exprt &new_expr, bool check_constantness=true)
Definition: cpp_typecheck_conversions.cpp:1756
struct_union_typet
Base type for structs and unions.
Definition: std_types.h:114
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
dereference_exprt
Operator to dereference a pointer.
Definition: std_expr.h:3355
cpp_typecheckt::typecheck_side_effect_assignment
void typecheck_side_effect_assignment(side_effect_exprt &) override
Definition: cpp_typecheck_expr.cpp:2426
side_effect_expr_function_callt
A side_effect_exprt representation of a function call side effect.
Definition: std_code.h:1691
mp_integer
BigInt mp_integer
Definition: mp_arith.h:22
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:3427
irept::add
irept & add(const irep_namet &name)
Definition: irep.cpp:305
struct_typet::has_base
bool has_base(const irep_idt &id) const
Test whether id is a base class/struct.
Definition: std_types.h:326
cpp_typecheck_fargst::operands
exprt::operandst operands
Definition: cpp_typecheck_fargs.h:26
c_typecheck_baset::typecheck_function_call_arguments
virtual void typecheck_function_call_arguments(side_effect_expr_function_callt &expr)
Typecheck the parameters in a function call expression, and where necessary, make implicit casts arou...
Definition: c_typecheck_expr.cpp:2799
cpp_type2name.h
c_bool_type
typet c_bool_type()
Definition: c_types.cpp:108
irept::find
const irept & find(const irep_namet &name) const
Definition: irep.cpp:284
cpp_typecheckt::new_temporary
void new_temporary(const source_locationt &source_location, const typet &, const exprt::operandst &ops, exprt &temporary)
Definition: cpp_constructor.cpp:265
cpp_typecheckt::standard_conversion_lvalue_to_rvalue
bool standard_conversion_lvalue_to_rvalue(const exprt &expr, exprt &new_expr) const
Lvalue-to-rvalue conversion.
Definition: cpp_typecheck_conversions.cpp:46
cpp_typecheckt::typecheck_expr_member
void typecheck_expr_member(exprt &) override
Definition: cpp_typecheck_expr.cpp:301
exprt
Base class for all expressions.
Definition: expr.h:54
struct_union_typet::componentst
std::vector< componentt > componentst
Definition: std_types.h:203
cpp_typecheckt::cpp_constructor
optionalt< codet > cpp_constructor(const source_locationt &source_location, const exprt &object, const exprt::operandst &operands)
Definition: cpp_constructor.cpp:25
struct_tag_typet
A struct tag type, i.e., struct_typet with an identifier.
Definition: std_types.h:517
c_typecheck_baset::typecheck_expr_address_of
virtual void typecheck_expr_address_of(exprt &expr)
Definition: c_typecheck_expr.cpp:1732
exprt::op0
exprt & op0()
Definition: expr.h:84
component
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:173
cpp_typecheckt::typecheck_side_effect_inc_dec
void typecheck_side_effect_inc_dec(side_effect_exprt &)
Definition: cpp_typecheck_expr.cpp:2510
expr2cpp.h
cpp_typecheckt::overloadable
bool overloadable(const exprt &)
Definition: cpp_typecheck_expr.cpp:418
irep_idt
dstringt irep_idt
Definition: irep.h:32
bool_typet
The Boolean type.
Definition: std_types.h:28
configt::ansi_c
struct configt::ansi_ct ansi_c
messaget::eom
static eomt eom
Definition: message.h:284
cpp_typecheckt::zero_initializer
void zero_initializer(const exprt &object, const typet &type, const source_locationt &source_location, exprt::operandst &ops)
Definition: cpp_typecheck_initializer.cpp:192
c_qualifiers.h
c_typecheck_baset::typecheck_expr_binary_arithmetic
virtual void typecheck_expr_binary_arithmetic(exprt &expr)
Definition: c_typecheck_expr.cpp:2974
c_qualifierst::is_subset_of
virtual bool is_subset_of(const qualifierst &other) const override
Definition: c_qualifiers.h:107
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:143
collect_comma_expression
static exprt collect_comma_expression(const exprt &src)
Definition: cpp_typecheck_expr.cpp:849
index_type
bitvector_typet index_type()
Definition: c_types.cpp:16
cpp_typecheckt::typecheck_expr_delete
void typecheck_expr_delete(exprt &)
Definition: cpp_typecheck_expr.cpp:1013
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:478
cpp_typecheckt::standard_conversion_array_to_pointer
bool standard_conversion_array_to_pointer(const exprt &expr, exprt &new_expr) const
Array-to-pointer conversion.
Definition: cpp_typecheck_conversions.cpp:71
cpp_exception_id.h
cpp_typecheckt::typecheck_expr_function_identifier
void typecheck_expr_function_identifier(exprt &) override
Definition: cpp_typecheck_expr.cpp:2667
c_typecheck_baset::typecheck_expr_operands
virtual void typecheck_expr_operands(exprt &expr)
Definition: c_typecheck_expr.cpp:717
cpp_typecheck_resolvet::wantt::TYPE
cpp_typecheckt::cpp_is_pod
bool cpp_is_pod(const typet &type) const
Definition: cpp_is_pod.cpp:14
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:68
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:166
cpp_typecheck_fargst::has_object
bool has_object
Definition: cpp_typecheck_fargs.h:25
cpp_typecheckt::typecheck_type
void typecheck_type(typet &) override
Definition: cpp_typecheck_type.cpp:23
irept::get_bool
bool get_bool(const irep_namet &name) const
Definition: irep.cpp:239
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:173
cpp_typecheckt::typecheck_expr_sizeof
void typecheck_expr_sizeof(exprt &) override
Definition: cpp_typecheck_expr.cpp:308
cpp_typecheckt::typecheck_function_expr
void typecheck_function_expr(exprt &, const cpp_typecheck_fargst &)
Definition: cpp_typecheck_expr.cpp:368
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:982
c_typecheck_baset::typecheck_expr_rel
virtual void typecheck_expr_rel(binary_relation_exprt &expr)
Definition: c_typecheck_expr.cpp:1341
expr_initializer.h
messaget::result
mstreamt & result() const
Definition: message.h:396
messaget::error
mstreamt & error() const
Definition: message.h:386
cpp_typecheckt::typecheck_side_effect_function_call
void typecheck_side_effect_function_call(side_effect_expr_function_callt &) override
Definition: cpp_typecheck_expr.cpp:1913
empty_typet
The empty type.
Definition: std_types.h:48
signed_int_type
signedbv_typet signed_int_type()
Definition: c_types.cpp:30
cpp_typecheckt::add_method_body
void add_method_body(symbolt *_method_symbol)
Definition: cpp_typecheck_method_bodies.cpp:54
base_type.h
size_of_expr
exprt size_of_expr(const typet &type, const namespacet &ns)
Definition: pointer_offset_size.cpp:292
symbol_table_baset::get_writeable_ref
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
Definition: symbol_table_base.h:110
cpp_exception_list
irept cpp_exception_list(const typet &src, const namespacet &ns)
turns a type into a list of relevant exception IDs
Definition: cpp_exception_id.cpp:77
cpp_typecheckt::add_implicit_dereference
void add_implicit_dereference(exprt &)
Definition: cpp_typecheck_expr.cpp:1900
cpp_scopest::current_scope
cpp_scopet & current_scope()
Definition: cpp_scopes.h:33
cpp_saved_template_mapt
Definition: template_map.h:68
messaget::mstreamt::source_location
source_locationt source_location
Definition: message.h:236
c_typecheck_baset::typecheck_expr_function_identifier
virtual void typecheck_expr_function_identifier(exprt &expr)
Definition: c_typecheck_expr.cpp:1852
forall_operands
#define forall_operands(it, expr)
Definition: expr.h:20
template_mapt::print
void print(std::ostream &out) const
Definition: template_map.cpp:133
type2cpp
std::string type2cpp(const typet &type, const namespacet &ns)
Definition: expr2cpp.cpp:482
c_typecheck_baset::typecheck_expr_dereference
virtual void typecheck_expr_dereference(exprt &expr)
Definition: c_typecheck_expr.cpp:1809
base_type_eq
bool base_type_eq(const typet &type1, const typet &type2, const namespacet &ns)
Check types for equality across all levels of hierarchy.
Definition: base_type.cpp:332
exprt::find_source_location
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition: expr.cpp:229
cpp_symbol_expr
symbol_exprt cpp_symbol_expr(const symbolt &symbol)
Definition: cpp_util.cpp:14
nil_exprt
The NIL expression.
Definition: std_expr.h:4461
cpp_typecheckt::typecheck_expr_explicit_typecast
void typecheck_expr_explicit_typecast(exprt &)
Definition: cpp_typecheck_expr.cpp:865
cpp_typecheckt::typecheck_expr_rel
void typecheck_expr_rel(binary_relation_exprt &) override
Definition: cpp_typecheck_expr.cpp:2798
cpp_typecheckt::typecheck_function_call_arguments
void typecheck_function_call_arguments(side_effect_expr_function_callt &) override
Definition: cpp_typecheck_expr.cpp:2258
exprt::op1
exprt & op1()
Definition: expr.h:87
cpp_typecheck_resolvet::wantt::BOTH
index_exprt::index
exprt & index()
Definition: std_expr.h:1631
struct_typet::bases
const basest & bases() const
Get the collection of base classes/structs.
Definition: std_types.h:303
c_qualifierst
Definition: c_qualifiers.h:60
c_typecheck_baset::symbol_table
symbol_tablet & symbol_table
Definition: c_typecheck_base.h:67
pointer_type
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:243
index_exprt::array
exprt & array()
Definition: std_expr.h:1621
cpp_typecheckt::typecheck_cast_expr
void typecheck_cast_expr(exprt &)
Definition: cpp_typecheck_expr.cpp:1298
irept::swap
void swap(irept &irep)
Definition: irep.h:303
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:251
cpp_typecheck_fargst::in_use
bool in_use
Definition: cpp_typecheck_fargs.h:25
cpp_typecheckt::subtype_typecast
bool subtype_typecast(const struct_typet &from, const struct_typet &to) const
Definition: cpp_typecheck_compound_type.cpp:1675
code_typet
Base type of functions.
Definition: std_types.h:751
irept::is_nil
bool is_nil() const
Definition: irep.h:172
irept::id
const irep_idt & id() const
Definition: irep.h:259
cpp_typecheckt::standard_conversion_function_to_pointer
bool standard_conversion_function_to_pointer(const exprt &expr, exprt &new_expr) const
Function-to-pointer conversion.
Definition: cpp_typecheck_conversions.cpp:95
irept::remove
void remove(const irep_namet &name)
Definition: irep.cpp:269
dstringt::empty
bool empty() const
Definition: dstring.h:75
cpp_typecheck_fargst::add_object
void add_object(const exprt &expr)
Definition: cpp_typecheck_fargs.h:51
cpp_typecheckt::get_component
bool get_component(const source_locationt &source_location, const exprt &object, const irep_idt &component_name, exprt &member)
Definition: cpp_typecheck_compound_type.cpp:1479
false_exprt
The Boolean constant false.
Definition: std_expr.h:4452
cpp_typecheckt::typecheck_expr_throw
void typecheck_expr_throw(exprt &)
Definition: cpp_typecheck_expr.cpp:747
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:893
typet::add_source_location
source_locationt & add_source_location()
Definition: type.h:67
c_typecheck_baset::typecheck_side_effect_assignment
virtual void typecheck_side_effect_assignment(side_effect_exprt &expr)
Definition: c_typecheck_expr.cpp:3288
cpp_typecheckt::static_typecast
bool static_typecast(const exprt &expr, const typet &type, exprt &new_expr, bool check_constantness=true)
Definition: cpp_typecheck_conversions.cpp:1857
cpp_typecheck.h
cpp_namet::is_qualified
bool is_qualified() const
Definition: cpp_name.h:109
side_effect_exprt::get_statement
const irep_idt & get_statement() const
Definition: std_code.h:1586
c_typecheck_baset::typecheck_expr
virtual void typecheck_expr(exprt &expr)
Definition: c_typecheck_expr.cpp:36
config
configt config
Definition: config.cpp:24
cpp_typecheckt::typecheck_expr_main
void typecheck_expr_main(exprt &) override
Called after the operands are done.
Definition: cpp_typecheck_expr.cpp:50
source_locationt
Definition: source_location.h:20
reference_type
reference_typet reference_type(const typet &subtype)
Definition: c_types.cpp:248
struct_union_typet::componentt
Definition: std_types.h:121
irept::get_string
const std::string & get_string(const irep_namet &name) const
Definition: irep.h:272
cpp_typecheckt::typecheck_expr
void typecheck_expr(exprt &) override
Definition: cpp_typecheck_expr.cpp:2684
cpp_typecheckt::typecheck_expr_comma
void typecheck_expr_comma(exprt &) override
Definition: cpp_typecheck_expr.cpp:2781
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
struct_typet
Structure type, corresponds to C style structs.
Definition: std_types.h:276
cpp_typecheckt::typecheck_expr_new
void typecheck_expr_new(exprt &)
Definition: cpp_typecheck_expr.cpp:773
cpp_namet::source_location
const source_locationt & source_location() const
Definition: cpp_name.h:73
cpp_typecheckt::const_typecast
bool const_typecast(const exprt &expr, const typet &type, exprt &new_expr)
Definition: cpp_typecheck_conversions.cpp:1646
c_typecheck_baset::typecheck_expr_main
virtual void typecheck_expr_main(exprt &expr)
Definition: c_typecheck_expr.cpp:165
cpp_typecheckt::typecheck_code
void typecheck_code(codet &) override
Definition: cpp_typecheck_code.cpp:22
cpp_type2name
std::string cpp_type2name(const typet &type)
Definition: cpp_type2name.cpp:92
operator_entryt::id
const irep_idt id
Definition: cpp_typecheck_expr.cpp:441
namespace_baset::follow
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:62
is_reference
bool is_reference(const typet &type)
Returns true if the type is a reference.
Definition: std_types.cpp:132
irept::get
const irep_idt & get(const irep_namet &name) const
Definition: irep.cpp:212
operators
struct operator_entryt operators[]
code_typet::make_ellipsis
void make_ellipsis()
Definition: std_types.h:873
symbolt
Symbol table entry.
Definition: symbol.h:27
irept::set
void set(const irep_namet &name, const irep_idt &value)
Definition: irep.h:286
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:123
side_effect_expr_function_callt::arguments
exprt::operandst & arguments()
Definition: std_code.h:1754
cpp_typecheckt::typecheck_expr_this
void typecheck_expr_this(exprt &)
Definition: cpp_typecheck_expr.cpp:994
symbol_table_baset::symbols
const symbolst & symbols
Definition: symbol_table_base.h:27
binary_relation_exprt
A base class for relations, i.e., binary predicates.
Definition: std_expr.h:878
c_typecheck_baset::return_type
typet return_type
Definition: c_typecheck_base.h:152
cpp_typecheckt::typecheck_expr_index
void typecheck_expr_index(exprt &) override
Definition: cpp_typecheck_expr.cpp:2776
cpp_typecheckt::implicit_typecast
void implicit_typecast(exprt &expr, const typet &type) override
Definition: cpp_typecheck_conversions.cpp:1493
irept::get_sub
subt & get_sub()
Definition: irep.h:317
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:1048
code_typet::parametert
Definition: std_types.h:788
cpp_typecheckt::typecheck_expr_binary_arithmetic
void typecheck_expr_binary_arithmetic(exprt &) override
Definition: cpp_typecheck_expr.cpp:2760
cpp_typecheck_resolvet::wantt::VAR
cpp_typecheckt::find_parent
bool find_parent(const symbolt &symb, const irep_idt &base_name, irep_idt &identifier)
Definition: cpp_typecheck_expr.cpp:31
operator_entryt::op_name
const char * op_name
Definition: cpp_typecheck_expr.cpp:442
config.h
code_typet::return_type
const typet & return_type() const
Definition: std_types.h:883
cpp_typecheckt::implicit_conversion_sequence
bool implicit_conversion_sequence(const exprt &expr, const typet &type, exprt &new_expr, unsigned &rank)
implicit conversion sequence
Definition: cpp_typecheck_conversions.cpp:1428
cpp_typecheckt::dynamic_typecast
bool dynamic_typecast(const exprt &expr, const typet &type, exprt &new_expr)
Definition: cpp_typecheck_conversions.cpp:1704
irept
Base class for tree-like data structures with sharing.
Definition: irep.h:156
cpp_typecheckt::to_string
std::string to_string(const typet &) override
Definition: cpp_typecheck.cpp:84
side_effect_expr_function_callt::function
exprt & function()
Definition: std_code.h:1744
exprt::operands
operandst & operands()
Definition: expr.h:78
template_mapt::build
void build(const template_typet &template_type, const cpp_template_args_tct &template_args)
Definition: template_map.cpp:142
index_exprt
Array index operator.
Definition: std_expr.h:1595
address_of_exprt
Operator to return the address of an object.
Definition: std_expr.h:3255
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:233
pointer_typet
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
Definition: std_types.h:1507
cpp_typecheckt::explicit_typecast_ambiguity
void explicit_typecast_ambiguity(exprt &)
Definition: cpp_typecheck_expr.cpp:2705
cpp_typecheckt::cpp_destructor
optionalt< codet > cpp_destructor(const source_locationt &source_location, const exprt &object)
Definition: cpp_destructor.cpp:19
true_exprt
The Boolean constant true.
Definition: std_expr.h:4443
cpp_typecheckt::resolve
exprt resolve(const cpp_namet &cpp_name, const cpp_typecheck_resolvet::wantt want, const cpp_typecheck_fargst &fargs, bool fail_with_exception=true)
Definition: cpp_typecheck.h:88
cpp_typecheckt::template_map
template_mapt template_map
Definition: cpp_typecheck.h:230
cpp_typecheckt::typecheck_method_application
void typecheck_method_application(side_effect_expr_function_callt &)
Definition: cpp_typecheck_expr.cpp:2345
c_typecheck_baset::typecheck_expr_sizeof
virtual void typecheck_expr_sizeof(exprt &expr)
Definition: c_typecheck_expr.cpp:960
operator_entryt
Definition: cpp_typecheck_expr.cpp:439
irept::subt
std::vector< irept > subt
Definition: irep.h:160
cpp_namet
Definition: cpp_name.h:16
cpp_typecheckt::typecheck_expr_address_of
void typecheck_expr_address_of(exprt &) override
Definition: cpp_typecheck_expr.cpp:682
exprt::source_location
const source_locationt & source_location() const
Definition: expr.h:228
configt::ansi_ct::int_width
std::size_t int_width
Definition: config.h:30
c_types.h
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
cpp_scopest::set_scope
cpp_scopet & set_scope(const irep_idt &identifier)
Definition: cpp_scopes.h:88
side_effect_exprt
An expression containing a side effect.
Definition: std_code.h:1560
cpp_typecheckt::typecheck_expr_ptrmember
void typecheck_expr_ptrmember(exprt &) override
Definition: cpp_typecheck_expr.cpp:363
c_typecheck_baset::typecheck_expr_index
virtual void typecheck_expr_index(exprt &expr)
Definition: c_typecheck_expr.cpp:1260
to_cpp_name
cpp_namet & to_cpp_name(irept &cpp_name)
Definition: cpp_name.h:144
code_expressiont
codet representation of an expression statement.
Definition: std_code.h:1504
c_typecheck_baset::typecheck_expr_comma
virtual void typecheck_expr_comma(exprt &expr)
Definition: c_typecheck_expr.cpp:488