cprover
cpp_typecheck_compound_type.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 <algorithm>
19 
20 #include <util/arith_tools.h>
21 #include <util/simplify_expr.h>
22 #include <util/std_types.h>
23 #include <util/c_types.h>
24 
25 #include <ansi-c/c_qualifiers.h>
26 
27 #include "cpp_type2name.h"
29 #include "cpp_convert_type.h"
30 #include "cpp_name.h"
31 
33 {
34  if(type.id()==ID_const)
35  return true;
36  else if(type.id()==ID_merged_type)
37  {
38  forall_subtypes(it, type)
39  if(has_const(*it))
40  return true;
41 
42  return false;
43  }
44  else
45  return false;
46 }
47 
49 {
50  if(type.id()==ID_volatile)
51  return true;
52  else if(type.id()==ID_merged_type)
53  {
54  forall_subtypes(it, type)
55  if(has_volatile(*it))
56  return true;
57 
58  return false;
59  }
60  else
61  return false;
62 }
63 
65 {
66  if(type.id() == ID_auto)
67  return true;
68  else if(
69  type.id() == ID_merged_type || type.id() == ID_frontend_pointer ||
70  type.id() == ID_pointer)
71  {
72  forall_subtypes(it, type)
73  if(has_auto(*it))
74  return true;
75 
76  return false;
77  }
78  else
79  return false;
80 }
81 
83  const irep_idt &base_name,
84  bool has_body,
85  bool tag_only_declaration)
86 {
87  // The scope of a compound identifier is difficult,
88  // and is different from C.
89  //
90  // For instance:
91  // class A { class B {} } --> A::B
92  // class A { class B; } --> A::B
93  // class A { class B *p; } --> ::B
94  // class B { }; class A { class B *p; } --> ::B
95  // class B { }; class A { class B; class B *p; } --> A::B
96 
97  // If there is a body, or it's a tag-only declaration,
98  // it's always in the current scope, even if we already have
99  // it in an upwards scope.
100 
101  if(has_body || tag_only_declaration)
102  return cpp_scopes.current_scope();
103 
104  // No body. Not a tag-only-declaration.
105  // Check if we have it already. If so, take it.
106 
107  // we should only look for tags, but we don't
110 
111  for(const auto &id : id_set)
112  if(id->is_class())
113  return static_cast<cpp_scopet &>(id->get_parent());
114 
115  // Tags without body that we don't have already
116  // and that are not a tag-only declaration go into
117  // the global scope of the namespace.
118  return cpp_scopes.get_global_scope();
119 }
120 
122  struct_union_typet &type)
123 {
124  // first save qualifiers
125  c_qualifierst qualifiers(type);
126 
127  // now clear them from the type
128  type.remove(ID_C_constant);
129  type.remove(ID_C_volatile);
130  type.remove(ID_C_restricted);
131 
132  // get the tag name
133  bool has_tag=type.find(ID_tag).is_not_nil();
134  irep_idt base_name;
135  cpp_scopet *dest_scope=nullptr;
136  bool has_body=type.find(ID_body).is_not_nil();
137  bool tag_only_declaration=type.get_bool(ID_C_tag_only_declaration);
138 
139  if(!has_tag)
140  {
141  // most of these should be named by now; see
142  // cpp_declarationt::name_anon_struct_union()
143 
144  base_name=std::string("#anon_")+std::to_string(++anon_counter);
145  type.set(ID_C_is_anonymous, true);
146  dest_scope=&cpp_scopes.current_scope();
147  }
148  else
149  {
150  const cpp_namet &cpp_name=
151  to_cpp_name(type.find(ID_tag));
152 
153  // scope given?
154  if(cpp_name.is_simple_name())
155  {
156  base_name=cpp_name.get_base_name();
157 
158  // anonymous structs always go into the current scope
159  if(type.get_bool(ID_C_is_anonymous))
160  dest_scope=&cpp_scopes.current_scope();
161  else
162  dest_scope=&tag_scope(base_name, has_body, tag_only_declaration);
163  }
164  else
165  {
166  cpp_save_scopet cpp_save_scope(cpp_scopes);
167  cpp_typecheck_resolvet cpp_typecheck_resolve(*this);
169  dest_scope=
170  &cpp_typecheck_resolve.resolve_scope(cpp_name, base_name, t_args);
171  }
172  }
173 
174  // The identifier 'tag-X' matches what the C front-end does!
175  // The hyphen is deliberate to avoid collisions with other
176  // identifiers.
177  const irep_idt symbol_name=
178  dest_scope->prefix+
179  "tag-"+id2string(base_name)+
180  dest_scope->suffix;
181 
182  // check if we have it already
183 
184  if(const auto maybe_symbol=symbol_table.lookup(symbol_name))
185  {
186  // we do!
187  const symbolt &symbol=*maybe_symbol;
188 
189  if(has_body)
190  {
191  if(symbol.type.id()=="incomplete_"+type.id_string())
192  {
193  // a previously incomplete struct/union becomes complete
194  symbolt &symbol=*symbol_table.get_writeable(symbol_name);
195  symbol.type.swap(type);
196  typecheck_compound_body(symbol);
197  }
198  else if(symbol.type.get_bool(ID_C_is_anonymous))
199  {
200  // we silently ignore
201  }
202  else
203  {
205  error() << "error: compound tag `" << base_name
206  << "' declared previously\n"
207  << "location of previous definition: "
208  << symbol.location << eom;
209  throw 0;
210  }
211  }
212  }
213  else
214  {
215  // produce new symbol
216  symbolt symbol;
217 
218  symbol.name=symbol_name;
219  symbol.base_name=base_name;
220  symbol.value.make_nil();
221  symbol.location=type.source_location();
222  symbol.mode=ID_cpp;
223  symbol.module=module;
224  symbol.type.swap(type);
225  symbol.is_type=true;
226  symbol.is_macro=false;
227  symbol.pretty_name=
229  id2string(symbol.base_name)+
231  symbol.type.set(
233 
234  // move early, must be visible before doing body
235  symbolt *new_symbol;
236 
237  if(symbol_table.move(symbol, new_symbol))
238  {
239  error().source_location=symbol.location;
240  error() << "cpp_typecheckt::typecheck_compound_type: "
241  << "symbol_table.move() failed" << eom;
242  throw 0;
243  }
244 
245  // put into dest_scope
246  cpp_idt &id=cpp_scopes.put_into_scope(*new_symbol, *dest_scope);
247 
249  id.is_scope=true;
250  id.prefix=cpp_scopes.current_scope().prefix+
251  id2string(new_symbol->base_name)+
253  id.class_identifier=new_symbol->name;
254  id.id_class=cpp_idt::id_classt::CLASS;
255 
256  if(has_body)
257  typecheck_compound_body(*new_symbol);
258  else
259  {
260  typet new_type("incomplete_"+new_symbol->type.id_string());
261  new_type.set(ID_tag, new_symbol->base_name);
262  new_symbol->type.swap(new_type);
263  }
264  }
265 
266  // create type symbol
267  symbol_typet symbol_type(symbol_name);
268  qualifiers.write(symbol_type);
269  type.swap(symbol_type);
270 }
271 
273  const symbolt &symbol,
274  const cpp_declarationt &declaration,
275  cpp_declaratort &declarator,
276  struct_typet::componentst &components,
277  const irep_idt &access,
278  bool is_static,
279  bool is_typedef,
280  bool is_mutable)
281 {
282  bool is_cast_operator=
283  declaration.type().id()=="cpp-cast-operator";
284 
285  if(is_cast_operator)
286  {
287  assert(declarator.name().get_sub().size()==2 &&
288  declarator.name().get_sub().front().id()==ID_operator);
289 
290  typet type=static_cast<typet &>(declarator.name().get_sub()[1]);
291  declarator.type().subtype()=type;
292 
293  irept name(ID_name);
294  name.set(ID_identifier, "("+cpp_type2name(type)+")");
295  declarator.name().get_sub().back().swap(name);
296  }
297 
298  typet final_type=
299  declarator.merge_type(declaration.type());
300 
301  // this triggers template elaboration
302  elaborate_class_template(final_type);
303 
304  typecheck_type(final_type);
305 
306  cpp_namet cpp_name;
307  cpp_name.swap(declarator.name());
308 
309  irep_idt base_name;
310 
311  if(cpp_name.is_nil())
312  {
313  // Yes, there can be members without name.
314  base_name=irep_idt();
315  }
316  else if(cpp_name.is_simple_name())
317  {
318  base_name=cpp_name.get_base_name();
319  }
320  else
321  {
323  error() << "declarator in compound needs to be simple name"
324  << eom;
325  throw 0;
326  }
327 
328  bool is_method=!is_typedef && final_type.id()==ID_code;
329  bool is_constructor=declaration.is_constructor();
330  bool is_destructor=declaration.is_destructor();
331  bool is_virtual=declaration.member_spec().is_virtual();
332  bool is_explicit=declaration.member_spec().is_explicit();
333  bool is_inline=declaration.member_spec().is_inline();
334 
335  final_type.set(ID_C_member_name, symbol.name);
336 
337  // first do some sanity checks
338 
339  if(is_virtual && !is_method)
340  {
342  error() << "only methods can be virtual" << eom;
343  throw 0;
344  }
345 
346  if(is_inline && !is_method)
347  {
349  error() << "only methods can be inlined" << eom;
350  throw 0;
351  }
352 
353  if(is_virtual && is_static)
354  {
356  error() << "static methods cannot be virtual" << eom;
357  throw 0;
358  }
359 
360  if(is_cast_operator && is_static)
361  {
363  error() << "cast operators cannot be static`" << eom;
364  throw 0;
365  }
366 
367  if(is_constructor && is_virtual)
368  {
370  error() << "constructors cannot be virtual" << eom;
371  throw 0;
372  }
373 
374  if(!is_constructor && is_explicit)
375  {
377  error() << "only constructors can be explicit" << eom;
378  throw 0;
379  }
380 
381  if(is_constructor && base_name != symbol.base_name)
382  {
384  error() << "member function must return a value or void" << eom;
385  throw 0;
386  }
387 
388  if(is_destructor &&
389  base_name!="~"+id2string(symbol.base_name))
390  {
392  error() << "destructor with wrong name" << eom;
393  throw 0;
394  }
395 
396  // now do actual work
397 
398  struct_typet::componentt component;
399  irep_idt identifier;
400 
401  // the below is a temporary hack
402  // if(is_method || is_static)
403  if(id2string(cpp_scopes.current_scope().prefix).find("#anon")==
404  std::string::npos ||
405  is_method || is_static)
406  {
407  // Identifiers for methods include the scope prefix.
408  // Identifiers for static members include the scope prefix.
409  identifier=
411  id2string(base_name);
412  }
413  else
414  {
415  // otherwise, we keep them simple
416  identifier=base_name;
417  }
418 
419  component.set(ID_name, identifier);
420  component.type()=final_type;
421  component.set(ID_access, access);
422  component.set(ID_base_name, base_name);
423  component.set(ID_pretty_name, base_name);
424  component.add_source_location()=cpp_name.source_location();
425 
426  if(cpp_name.is_operator())
427  {
428  component.set("is_operator", true);
429  component.type().set(ID_C_is_operator, true);
430  }
431 
432  if(is_cast_operator)
433  component.set("is_cast_operator", true);
434 
435  if(declaration.member_spec().is_explicit())
436  component.set("is_explicit", true);
437 
438  // either blank, const, volatile, or const volatile
439  const typet &method_qualifier=
440  static_cast<const typet &>(declarator.add(ID_method_qualifier));
441 
442  if(is_static)
443  {
444  component.set(ID_is_static, true);
445  component.type().set(ID_C_is_static, true);
446  }
447 
448  if(is_typedef)
449  component.set(ID_is_type, true);
450 
451  if(is_mutable)
452  component.set("is_mutable", true);
453 
454  exprt &value=declarator.value();
455  irept &initializers=declarator.member_initializers();
456 
457  if(is_method)
458  {
459  if(
460  value.id() == ID_code &&
461  to_code(value).get_statement() == ID_cpp_delete)
462  {
463  value.make_nil();
464  component.set(ID_access, "noaccess");
465  }
466 
467  component.set(ID_is_inline, declaration.member_spec().is_inline());
468 
469  // the 'virtual' name of the function
470  std::string virtual_name=
471  component.get_string(ID_base_name)+
472  id2string(
474  static_cast<const typet &>(component.find(ID_type))));
475 
476  if(has_const(method_qualifier))
477  virtual_name+="$const";
478 
479  if(has_volatile(method_qualifier))
480  virtual_name += "$volatile";
481 
482  if(component.type().get(ID_return_type)==ID_destructor)
483  virtual_name="@dtor";
484 
485  // The method may be virtual implicitly.
486  std::set<irep_idt> virtual_bases;
487 
488  for(const auto &comp : components)
489  {
490  if(comp.get_bool(ID_is_virtual))
491  {
492  if(comp.get("virtual_name")==virtual_name)
493  {
494  is_virtual=true;
495  const code_typet &code_type=to_code_type(comp.type());
496  assert(!code_type.parameters().empty());
497  const typet &pointer_type=code_type.parameters()[0].type();
498  assert(pointer_type.id()==ID_pointer);
499  virtual_bases.insert(pointer_type.subtype().get(ID_identifier));
500  }
501  }
502  }
503 
504  if(!is_virtual)
505  {
507  symbol.name, component, initializers,
508  method_qualifier, value);
509 
510  if(!value.is_nil() && !is_static)
511  {
513  error() << "no initialization allowed here" << eom;
514  throw 0;
515  }
516  }
517  else // virtual
518  {
519  component.type().set(ID_C_is_virtual, true);
520  component.type().set(ID_C_virtual_name, virtual_name);
521 
522  // Check if it is a pure virtual method
523  if(value.is_not_nil() && value.id() == ID_constant)
524  {
525  mp_integer i;
526  to_integer(value, i);
527  if(i!=0)
528  {
529  error().source_location = declarator.name().source_location();
530  error() << "expected 0 to mark pure virtual method, got " << i << eom;
531  throw 0;
532  }
533  component.set("is_pure_virtual", true);
534  value.make_nil();
535  }
536 
538  symbol.name,
539  component,
540  initializers,
541  method_qualifier,
542  value);
543 
544  // get the virtual-table symbol type
545  irep_idt vt_name="virtual_table::"+id2string(symbol.name);
546 
547  if(!symbol_table.has_symbol(vt_name))
548  {
549  // first time: create a virtual-table symbol type
550  symbolt vt_symb_type;
551  vt_symb_type.name= vt_name;
552  vt_symb_type.base_name="virtual_table::"+id2string(symbol.base_name);
553  vt_symb_type.pretty_name=vt_symb_type.base_name;
554  vt_symb_type.mode=ID_cpp;
555  vt_symb_type.module=module;
556  vt_symb_type.location=symbol.location;
557  vt_symb_type.type=struct_typet();
558  vt_symb_type.type.set(ID_name, vt_symb_type.name);
559  vt_symb_type.is_type=true;
560 
561  const bool failed=!symbol_table.insert(std::move(vt_symb_type)).second;
562  CHECK_RETURN(!failed);
563 
564  // add a virtual-table pointer
566  compo.type()=pointer_type(symbol_typet(vt_name));
567  compo.set_name(id2string(symbol.name) +"::@vtable_pointer");
568  compo.set(ID_base_name, "@vtable_pointer");
569  compo.set(
570  ID_pretty_name,
571  id2string(symbol.base_name) +"@vtable_pointer");
572  compo.set("is_vtptr", true);
573  compo.set(ID_access, ID_public);
574  components.push_back(compo);
576  }
577 
579  INVARIANT(vt.id()==ID_struct, "Virtual tables must be stored as struct");
580  struct_typet &virtual_table=to_struct_type(vt);
581 
582  component.set("virtual_name", virtual_name);
583  component.set("is_virtual", is_virtual);
584 
585  // add an entry to the virtual table
586  struct_typet::componentt vt_entry;
587  vt_entry.type()=pointer_type(component.type());
588  vt_entry.set_name(id2string(vt_name)+"::"+virtual_name);
589  vt_entry.set(ID_base_name, virtual_name);
590  vt_entry.set(ID_pretty_name, virtual_name);
591  vt_entry.set(ID_access, ID_public);
592  vt_entry.add_source_location()=symbol.location;
593  virtual_table.components().push_back(vt_entry);
594 
595  // take care of overloading
596  while(!virtual_bases.empty())
597  {
598  irep_idt virtual_base=*virtual_bases.begin();
599 
600  // a new function that does 'late casting' of the 'this' parameter
601  symbolt func_symb;
602  func_symb.name=
603  id2string(component.get_name())+"::"+id2string(virtual_base);
604  func_symb.base_name=component.get(ID_base_name);
605  func_symb.pretty_name=component.get(ID_base_name);
606  func_symb.mode=ID_cpp;
607  func_symb.module=module;
608  func_symb.location=component.source_location();
609  func_symb.type=component.type();
610 
611  // change the type of the 'this' pointer
612  code_typet &code_type=to_code_type(func_symb.type);
613  code_typet::parametert &arg= code_type.parameters().front();
614  arg.type().subtype().set(ID_identifier, virtual_base);
615 
616  // create symbols for the parameters
617  code_typet::parameterst &args=code_type.parameters();
618  std::size_t i=0;
619  for(auto &arg : args)
620  {
621  irep_idt base_name=arg.get_base_name();
622 
623  if(base_name.empty())
624  base_name="arg"+std::to_string(i++);
625 
626  symbolt arg_symb;
627  arg_symb.name=id2string(func_symb.name) + "::"+ id2string(base_name);
628  arg_symb.base_name=base_name;
629  arg_symb.pretty_name=base_name;
630  arg_symb.mode=ID_cpp;
631  arg_symb.location=func_symb.location;
632  arg_symb.type=arg.type();
633 
634  arg.set(ID_C_identifier, arg_symb.name);
635 
636  // add the parameter to the symbol table
637  const bool failed=!symbol_table.insert(std::move(arg_symb)).second;
638  CHECK_RETURN(!failed);
639  }
640 
641  // do the body of the function
642  typecast_exprt late_cast(
643  lookup(args[0].get(ID_C_identifier)).symbol_expr(),
644  to_code_type(component.type()).parameters()[0].type());
645 
647  expr_call.function() =
648  symbol_exprt(component.get_name(), component.type());
649  expr_call.arguments().reserve(args.size());
650  expr_call.arguments().push_back(late_cast);
651 
652  for(const auto &arg : args)
653  {
654  expr_call.arguments().push_back(
655  lookup(arg.get(ID_C_identifier)).symbol_expr());
656  }
657 
658  if(code_type.return_type().id()!=ID_empty &&
659  code_type.return_type().id()!=ID_destructor)
660  {
661  expr_call.type()=to_code_type(component.type()).return_type();
662  exprt already_typechecked(ID_already_typechecked);
663  already_typechecked.move_to_operands(expr_call);
664 
666  }
667  else
668  {
669  exprt already_typechecked(ID_already_typechecked);
670  already_typechecked.move_to_operands(expr_call);
671 
673  }
674 
675  // add this new function to the list of components
676 
677  struct_typet::componentt new_compo=component;
678  new_compo.type()=func_symb.type;
679  new_compo.set_name(func_symb.name);
680  components.push_back(new_compo);
681 
682  // add the function to the symbol table
683  {
684  const bool failed=!symbol_table.insert(std::move(func_symb)).second;
685  CHECK_RETURN(!failed);
686  }
687 
688  put_compound_into_scope(new_compo);
689 
690  // next base
691  virtual_bases.erase(virtual_bases.begin());
692  }
693  }
694  }
695 
696  if(is_static && !is_method) // static non-method member
697  {
698  // add as global variable to symbol_table
699  symbolt static_symbol;
700  static_symbol.mode=symbol.mode;
701  static_symbol.name=identifier;
702  static_symbol.type=component.type();
703  static_symbol.base_name=component.get(ID_base_name);
704  static_symbol.is_lvalue=true;
705  static_symbol.is_static_lifetime=true;
706  static_symbol.location=cpp_name.source_location();
707  static_symbol.is_extern=true;
708 
709  // TODO: not sure about this: should be defined separately!
710  dynamic_initializations.push_back(static_symbol.name);
711 
712  symbolt *new_symbol;
713  if(symbol_table.move(static_symbol, new_symbol))
714  {
716  error() << "redeclaration of static member `"
717  << static_symbol.base_name
718  << "'" << eom;
719  throw 0;
720  }
721 
722  if(value.is_not_nil())
723  {
724  if(cpp_is_pod(new_symbol->type))
725  {
726  new_symbol->value.swap(value);
728 
729  // these are macros if they are PODs and come with a (constant) value
730  if(new_symbol->type.get_bool(ID_C_constant))
731  {
732  simplify(new_symbol->value, *this);
733  new_symbol->is_macro=true;
734  }
735  }
736  else
737  {
738  symbol_exprt symexpr;
739  symexpr.set_identifier(new_symbol->name);
740 
741  exprt::operandst ops;
742  ops.push_back(value);
743  codet defcode =
744  cpp_constructor(source_locationt(), symexpr, ops);
745 
746  new_symbol->value.swap(defcode);
747  }
748  }
749  }
750 
751  // array members must have fixed size
752  check_fixed_size_array(component.type());
753 
754  put_compound_into_scope(component);
755 
756  components.push_back(component);
757 }
758 
761 {
762  if(type.id()==ID_array)
763  {
764  array_typet &array_type=to_array_type(type);
765 
766  if(array_type.size().is_not_nil())
767  make_constant_index(array_type.size());
768 
769  // recursive call for multi-dimensional arrays
770  check_fixed_size_array(array_type.subtype());
771  }
772 }
773 
775  const struct_union_typet::componentt &compound)
776 {
777  const irep_idt &base_name=compound.get_base_name();
778  const irep_idt &name=compound.get_name();
779 
780  // nothing to do if no base_name (e.g., an anonymous bitfield)
781  if(base_name.empty())
782  return;
783 
784  if(compound.type().id()==ID_code)
785  {
786  // put the symbol into scope
787  cpp_idt &id=cpp_scopes.current_scope().insert(base_name);
788  id.id_class=compound.get_bool("is_type")?
791  id.identifier=name;
792  id.class_identifier=cpp_scopes.current_scope().identifier;
793  id.is_member=true;
794  id.is_constructor =
795  compound.find(ID_type).get(ID_return_type)==ID_constructor;
796  id.is_method=true;
797  id.is_static_member=compound.get_bool(ID_is_static);
798 
799  // create function block-scope in the scope
800  cpp_idt &id_block=
802  irep_idt(std::string("$block:") + base_name.c_str()));
803 
805  id_block.identifier=name;
806  id_block.class_identifier=cpp_scopes.current_scope().identifier;
807  id_block.is_method=true;
808  id_block.is_static_member=compound.get_bool(ID_is_static);
809 
810  id_block.is_scope=true;
811  id_block.prefix=compound.get_string("prefix");
812  cpp_scopes.id_map[id.identifier]=&id_block;
813  }
814  else
815  {
816  // check if it's already there
818 
820  base_name, cpp_scopet::SCOPE_ONLY, id_set);
821 
822  for(const auto &id_it : id_set)
823  {
824  const cpp_idt &id=*id_it;
825 
826  // the name is already in the scope
827  // this is ok if they belong to different categories
828  if(!id.is_class() && !id.is_enum())
829  {
831  error() << "`" << base_name
832  << "' already in compound scope" << eom;
833  throw 0;
834  }
835  }
836 
837  // put into the scope
838  cpp_idt &id=cpp_scopes.current_scope().insert(base_name);
839  id.id_class=compound.get_bool(ID_is_type)?
842  id.identifier=name;
843  id.class_identifier=cpp_scopes.current_scope().identifier;
844  id.is_member=true;
845  id.is_method=false;
846  id.is_static_member=compound.get_bool(ID_is_static);
847  }
848 }
849 
851  symbolt &symbol,
852  cpp_declarationt &declaration)
853 {
854  // A friend of a class can be a function/method,
855  // or a struct/class/union type.
856 
857  if(declaration.is_template())
858  {
859  return; // TODO
860 
861 #if 0
862  error().source_location=declaration.type().source_location();
863  error() << "friend template not supported" << eom;
864  throw 0;
865 #endif
866  }
867 
868  // we distinguish these whether there is a declarator
869  if(declaration.declarators().empty())
870  {
871  typet &ftype=declaration.type();
872 
873  // must be struct or union
874  if(ftype.id()!=ID_struct && ftype.id()!=ID_union)
875  {
876  error().source_location=declaration.type().source_location();
877  error() << "unexpected friend" << eom;
878  throw 0;
879  }
880 
881  if(ftype.find(ID_body).is_not_nil())
882  {
883  error().source_location=declaration.type().source_location();
884  error() << "friend declaration must not have compound body" << eom;
885  throw 0;
886  }
887 
888  // typecheck ftype
889 
890  // TODO
891  // typecheck_type(ftype);
892  // assert(ftype.id()==ID_symbol);
893  // symbol.type.add("ID_C_friends").move_to_sub(ftype);
894 
895  return;
896  }
897 
898  // It should be a friend function.
899  // Do the declarators.
900 
901  for(auto &sub_it : declaration.declarators())
902  {
903  bool has_value = sub_it.value().is_not_nil();
904 
905  if(!has_value)
906  {
907  // If no value is found, then we jump to the
908  // global scope, and we convert the declarator
909  // as if it were declared there
910  cpp_save_scopet saved_scope(cpp_scopes);
912  cpp_declarator_convertert cpp_declarator_converter(*this);
913  const symbolt &conv_symb=cpp_declarator_converter.convert(
914  declaration.type(), declaration.storage_spec(),
915  declaration.member_spec(), sub_it);
916  exprt symb_expr=cpp_symbol_expr(conv_symb);
917  symbol.type.add(ID_C_friends).move_to_sub(symb_expr);
918  }
919  else
920  {
921  cpp_declarator_convertert cpp_declarator_converter(*this);
922  cpp_declarator_converter.is_friend=true;
923 
924  declaration.member_spec().set_inline(true);
925 
926  const symbolt &conv_symb=cpp_declarator_converter.convert(
927  declaration.type(), declaration.storage_spec(),
928  declaration.member_spec(), sub_it);
929 
930  exprt symb_expr=cpp_symbol_expr(conv_symb);
931 
932  symbol.type.add(ID_C_friends).move_to_sub(symb_expr);
933  }
934  }
935 }
936 
938 {
939  cpp_save_scopet saved_scope(cpp_scopes);
940 
941  // enter scope of compound
942  cpp_scopes.set_scope(symbol.name);
943 
944  assert(symbol.type.id()==ID_struct ||
945  symbol.type.id()==ID_union);
946 
947  struct_union_typet &type=
948  to_struct_union_type(symbol.type);
949 
950  // pull the base types in
951  if(!type.find(ID_bases).get_sub().empty())
952  {
953  if(type.id()==ID_union)
954  {
955  error().source_location=symbol.location;
956  error() << "union types must not have bases" << eom;
957  throw 0;
958  }
959 
961  }
962 
963  exprt &body=static_cast<exprt &>(type.add(ID_body));
964  struct_union_typet::componentst &components=type.components();
965 
966  symbol.type.set(ID_name, symbol.name);
967 
968  // default access
969  irep_idt access=
970  type.get_bool(ID_C_class)?ID_private:ID_public;
971 
972  bool found_ctor=false;
973  bool found_dtor=false;
974 
975  // we first do everything _but_ the constructors
976 
977  Forall_operands(it, body)
978  {
979  if(it->id()==ID_cpp_declaration)
980  {
981  cpp_declarationt &declaration=
982  to_cpp_declaration(*it);
983 
984  if(declaration.member_spec().is_friend())
985  {
986  typecheck_friend_declaration(symbol, declaration);
987  continue; // done
988  }
989 
990  if(declaration.is_template())
991  {
992  // remember access mode
993  declaration.set(ID_C_access, access);
994  convert_template_declaration(declaration);
995  continue;
996  }
997 
998  if(declaration.type().id().empty())
999  continue;
1000 
1001  bool is_typedef=declaration.is_typedef();
1002 
1003  // is it tag-only?
1004  if(declaration.type().id()==ID_struct ||
1005  declaration.type().id()==ID_union ||
1006  declaration.type().id()==ID_c_enum)
1007  if(declaration.declarators().empty())
1008  declaration.type().set(ID_C_tag_only_declaration, true);
1009 
1010  declaration.name_anon_struct_union();
1011  typecheck_type(declaration.type());
1012 
1013  bool is_static=declaration.storage_spec().is_static();
1014  bool is_mutable=declaration.storage_spec().is_mutable();
1015 
1016  if(declaration.storage_spec().is_extern() ||
1017  declaration.storage_spec().is_auto() ||
1018  declaration.storage_spec().is_register())
1019  {
1020  error().source_location=declaration.storage_spec().location();
1021  error() << "invalid storage class specified for field" << eom;
1022  throw 0;
1023  }
1024 
1025  typet final_type=follow(declaration.type());
1026 
1027  // anonymous member?
1028  if(declaration.declarators().empty() &&
1029  final_type.get_bool(ID_C_is_anonymous))
1030  {
1031  // we only allow this on struct/union types
1032  if(final_type.id()!=ID_union &&
1033  final_type.id()!=ID_struct)
1034  {
1035  error().source_location=declaration.type().source_location();
1036  error() << "member declaration does not declare anything"
1037  << eom;
1038  throw 0;
1039  }
1040 
1042  declaration, access, components);
1043 
1044  continue;
1045  }
1046 
1047  // declarators
1048  for(auto &declarator : declaration.declarators())
1049  {
1050  // Skip the constructors until all the data members
1051  // are discovered
1052  if(declaration.is_destructor())
1053  found_dtor=true;
1054 
1055  if(declaration.is_constructor())
1056  {
1057  found_ctor=true;
1058  continue;
1059  }
1060 
1062  symbol,
1063  declaration, declarator, components,
1064  access, is_static, is_typedef, is_mutable);
1065  }
1066  }
1067  else if(it->id()=="cpp-public")
1068  access=ID_public;
1069  else if(it->id()=="cpp-private")
1070  access=ID_private;
1071  else if(it->id()=="cpp-protected")
1072  access=ID_protected;
1073  else
1074  {
1075  }
1076  }
1077 
1078  // Add the default dtor, if needed
1079  // (we have to do the destructor before building the virtual tables,
1080  // as the destructor may be virtual!)
1081 
1082  if((found_ctor || !cpp_is_pod(symbol.type)) && !found_dtor)
1083  {
1084  // build declaration
1086  default_dtor(symbol, dtor);
1087 
1089  symbol,
1090  dtor, dtor.declarators()[0], components,
1091  ID_public, false, false, false);
1092  }
1093 
1094  // set up virtual tables before doing the constructors
1095  if(symbol.type.id()==ID_struct)
1096  do_virtual_table(symbol);
1097 
1098  if(!found_ctor && !cpp_is_pod(symbol.type))
1099  {
1100  // it's public!
1101  exprt cpp_public("cpp-public");
1102  body.move_to_operands(cpp_public);
1103 
1104  // build declaration
1105  cpp_declarationt ctor;
1106  default_ctor(symbol.type.source_location(), symbol.base_name, ctor);
1107  body.move_to_operands(ctor);
1108  }
1109 
1110  // Reset the access type
1111  access=
1112  type.get_bool(ID_C_class)?ID_private:ID_public;
1113 
1114  // All the data members are now known.
1115  // We now deal with the constructors that we are given.
1116  Forall_operands(it, body)
1117  {
1118  if(it->id()==ID_cpp_declaration)
1119  {
1120  cpp_declarationt &declaration=
1121  to_cpp_declaration(*it);
1122 
1123  if(!declaration.is_constructor())
1124  continue;
1125 
1126  for(auto &declarator : declaration.declarators())
1127  {
1128  #if 0
1129  irep_idt ctor_base_name=
1130  declarator.name().get_base_name();
1131  #endif
1132 
1133  if(declarator.value().is_not_nil()) // body?
1134  {
1135  if(declarator.find(ID_member_initializers).is_nil())
1136  declarator.set(ID_member_initializers, ID_member_initializers);
1137 
1139  type.add(ID_bases),
1140  type.components(),
1141  declarator.member_initializers());
1142 
1144  type,
1145  declarator.member_initializers());
1146  }
1147 
1148  // Finally, we typecheck the constructor with the
1149  // full member-initialization list
1150  // Shall all be false
1151  bool is_static=declaration.storage_spec().is_static();
1152  bool is_mutable=declaration.storage_spec().is_mutable();
1153  bool is_typedef=declaration.is_typedef();
1154 
1156  symbol,
1157  declaration, declarator, components,
1158  access, is_static, is_typedef, is_mutable);
1159  }
1160  }
1161  else if(it->id()=="cpp-public")
1162  access=ID_public;
1163  else if(it->id()=="cpp-private")
1164  access=ID_private;
1165  else if(it->id()=="cpp-protected")
1166  access=ID_protected;
1167  else
1168  {
1169  }
1170  }
1171 
1172  if(!cpp_is_pod(symbol.type))
1173  {
1174  // Add the default copy constructor
1175  struct_typet::componentt component;
1176 
1177  if(!find_cpctor(symbol))
1178  {
1179  // build declaration
1180  cpp_declarationt cpctor;
1181  default_cpctor(symbol, cpctor);
1182  assert(cpctor.declarators().size()==1);
1183 
1184  exprt value("cpp_not_typechecked");
1185  value.copy_to_operands(cpctor.declarators()[0].value());
1186  cpctor.declarators()[0].value()=value;
1187 
1189  symbol,
1190  cpctor, cpctor.declarators()[0], components,
1191  ID_public, false, false, false);
1192  }
1193 
1194  // Add the default assignment operator
1195  if(!find_assignop(symbol))
1196  {
1197  // build declaration
1198  cpp_declarationt assignop;
1199  default_assignop(symbol, assignop);
1200  assert(assignop.declarators().size()==1);
1201 
1202  // The value will be typechecked only if the operator
1203  // is actually used
1204  cpp_declaratort declarator;
1205  assignop.declarators().push_back(declarator);
1206  assignop.declarators()[0].value()=exprt("cpp_not_typechecked");
1207 
1209  symbol,
1210  assignop, assignop.declarators()[0], components,
1211  ID_public, false, false, false);
1212  }
1213  }
1214 
1215  // clean up!
1216  symbol.type.remove(ID_body);
1217 }
1218 
1220  irept &initializers,
1221  const typet &type,
1222  exprt &value)
1223 {
1224  bool is_constructor=
1225  type.find(ID_return_type).id()==ID_constructor;
1226 
1227  // see if we have initializers
1228  if(!initializers.get_sub().empty())
1229  {
1230  const source_locationt &location=
1231  static_cast<const source_locationt &>(
1232  initializers.find(ID_C_source_location));
1233 
1234  if(!is_constructor)
1235  {
1236  error().source_location=location;
1237  error() << "only constructors are allowed to "
1238  << "have member initializers" << eom;
1239  throw 0;
1240  }
1241 
1242  if(value.is_nil())
1243  {
1244  error().source_location=location;
1245  error() << "only constructors with body are allowed to "
1246  << "have member initializers" << eom;
1247  throw 0;
1248  }
1249 
1250  to_code(value).make_block();
1251 
1252  exprt::operandst::iterator o_it=value.operands().begin();
1253  forall_irep(it, initializers.get_sub())
1254  {
1255  o_it=value.operands().insert(o_it, static_cast<const exprt &>(*it));
1256  o_it++;
1257  }
1258  }
1259 }
1260 
1262  const irep_idt &compound_identifier,
1263  struct_typet::componentt &component,
1264  irept &initializers,
1265  const typet &method_qualifier,
1266  exprt &value)
1267 {
1268  symbolt symbol;
1269 
1270  typet &type=component.type();
1271 
1272  if(component.get_bool(ID_is_static))
1273  {
1274  if(!method_qualifier.id().empty())
1275  {
1276  error().source_location=component.source_location();
1277  error() << "method is static -- no qualifiers allowed" << eom;
1278  throw 0;
1279  }
1280  }
1281  else
1282  {
1284  compound_identifier,
1285  type,
1286  method_qualifier);
1287  }
1288 
1289  if(value.id() == "cpp_not_typechecked" && value.has_operands())
1290  move_member_initializers(initializers, type, value.op0());
1291  else
1292  move_member_initializers(initializers, type, value);
1293 
1294  irep_idt f_id=
1295  function_identifier(component.type());
1296 
1297  const irep_idt identifier=
1299  id2string(component.get_base_name())+
1300  id2string(f_id);
1301 
1302  component.set_name(identifier);
1303  component.set("prefix", id2string(identifier)+"::");
1304 
1305  if(value.is_not_nil())
1306  type.set(ID_C_inlined, true);
1307 
1308  symbol.name=identifier;
1309  symbol.base_name=component.get_base_name();
1310  symbol.value.swap(value);
1311  symbol.mode=ID_cpp;
1312  symbol.module=module;
1313  symbol.type=type;
1314  symbol.is_type=false;
1315  symbol.is_macro=false;
1316  symbol.location=component.source_location();
1317 
1318  // move early, it must be visible before doing any value
1319  symbolt *new_symbol;
1320 
1321  if(symbol_table.move(symbol, new_symbol))
1322  {
1323  error().source_location=symbol.location;
1324  error() << "failed to insert new method symbol: "
1325  << symbol.name << "\n"
1326  << "name of previous symbol: "
1327  << new_symbol->name << "\n"
1328  << "location of previous symbol: "
1329  << new_symbol->location << eom;
1330 
1331  throw 0;
1332  }
1333 
1334  // Is this in a class template?
1335  // If so, we defer typechecking until used.
1337  {
1338  }
1339  else // remember for later typechecking of body
1340  add_method_body(new_symbol);
1341 }
1342 
1344  const irep_idt &compound_symbol,
1345  typet &type,
1346  const typet &method_qualifier)
1347 {
1348  code_typet::parameterst &parameters=to_code_type(type).parameters();
1349 
1350  parameters.insert(
1351  parameters.begin(), code_typet::parametert());
1352 
1353  code_typet::parametert &parameter=parameters.front();
1354 
1355  parameter.set_identifier(ID_this); // check? Not qualified
1356  parameter.set_base_name(ID_this);
1357  parameter.set_this();
1358 
1359  typet subtype=symbol_typet(compound_symbol);
1360 
1361  if(has_const(method_qualifier))
1362  subtype.set(ID_C_constant, true);
1363 
1364  if(has_volatile(method_qualifier))
1365  subtype.set(ID_C_volatile, true);
1366 
1367  parameter.type()=pointer_type(subtype);
1368 }
1369 
1371  const symbolt &struct_union_symbol)
1372 {
1373  const struct_union_typet &struct_union_type=
1374  to_struct_union_type(struct_union_symbol.type);
1375 
1376  const struct_union_typet::componentst &struct_union_components=
1377  struct_union_type.components();
1378 
1379  // do scoping -- the members of the struct/union
1380  // should be visible in the containing struct/union,
1381  // and that recursively!
1382 
1383  for(const auto &comp : struct_union_components)
1384  {
1385  if(comp.type().id()==ID_code)
1386  {
1387  error().source_location=struct_union_symbol.type.source_location();
1388  error() << "anonymous struct/union member `"
1389  << struct_union_symbol.base_name
1390  << "' shall not have function members" << eom;
1391  throw 0;
1392  }
1393 
1394  if(comp.get_anonymous())
1395  {
1396  const symbolt &symbol=lookup(comp.type().get(ID_identifier));
1397  // recursive call
1399  }
1400  else
1401  {
1402  const irep_idt &base_name=comp.get_base_name();
1403 
1404  if(cpp_scopes.current_scope().contains(base_name))
1405  {
1406  error().source_location=comp.source_location();
1407  error() << "`" << base_name << "' already in scope" << eom;
1408  throw 0;
1409  }
1410 
1411  cpp_idt &id=cpp_scopes.current_scope().insert(base_name);
1413  id.identifier=comp.get_name();
1414  id.class_identifier=struct_union_symbol.name;
1415  id.is_member=true;
1416  }
1417  }
1418 }
1419 
1421  const cpp_declarationt &declaration,
1422  const irep_idt &access,
1423  struct_typet::componentst &components)
1424 {
1425  symbolt &struct_union_symbol=
1426  *symbol_table.get_writeable(follow(declaration.type()).get(ID_name));
1427 
1428  if(declaration.storage_spec().is_static() ||
1429  declaration.storage_spec().is_mutable())
1430  {
1431  error().source_location=struct_union_symbol.type.source_location();
1432  error() << "storage class is not allowed here" << eom;
1433  throw 0;
1434  }
1435 
1436  if(!cpp_is_pod(struct_union_symbol.type))
1437  {
1438  error().source_location=struct_union_symbol.type.source_location();
1439  error() << "anonymous struct/union member is not POD" << eom;
1440  throw 0;
1441  }
1442 
1443  // produce an anonymous member
1444  irep_idt base_name="#anon_member"+std::to_string(components.size());
1445 
1446  irep_idt identifier=
1448  base_name.c_str();
1449 
1450  const symbol_typet symbol_type(struct_union_symbol.name);
1451 
1452  struct_typet::componentt component(identifier, symbol_type);
1453  component.set_access(access);
1454  component.set_base_name(base_name);
1455  component.set_pretty_name(base_name);
1456  component.set_anonymous(true);
1457  component.add_source_location()=declaration.source_location();
1458 
1459  components.push_back(component);
1460 
1461  add_anonymous_members_to_scope(struct_union_symbol);
1462 
1463  put_compound_into_scope(component);
1464 
1465  struct_union_symbol.type.set(ID_C_unnamed_object, base_name);
1466 }
1467 
1469  const source_locationt &source_location,
1470  const exprt &object,
1471  const irep_idt &component_name,
1472  exprt &member)
1473 {
1474  const typet &followed_type=follow(object.type());
1475 
1476  assert(followed_type.id()==ID_struct ||
1477  followed_type.id()==ID_union);
1478 
1479  struct_union_typet final_type=
1480  to_struct_union_type(followed_type);
1481 
1482  const struct_union_typet::componentst &components=
1483  final_type.components();
1484 
1485  for(const auto &component : components)
1486  {
1487  member_exprt tmp(object, component.get_name(), component.type());
1488  tmp.add_source_location()=source_location;
1489 
1490  if(component.get_name()==component_name)
1491  {
1492  member.swap(tmp);
1493 
1494  bool not_ok=check_component_access(component, final_type);
1495  if(not_ok)
1496  {
1498  {
1499  member.set(ID_C_not_accessible, true);
1500  member.set(ID_C_access, component.get(ID_access));
1501  }
1502  else
1503  {
1504  error().source_location=source_location;
1505  error() << "error: member `" << component_name
1506  << "' is not accessible (" << component.get(ID_access) << ")"
1507  << eom;
1508  throw 0;
1509  }
1510  }
1511 
1512  if(object.get_bool(ID_C_lvalue))
1513  member.set(ID_C_lvalue, true);
1514 
1515  if(object.type().get_bool(ID_C_constant) &&
1516  !component.get_bool("is_mutable"))
1517  member.type().set(ID_C_constant, true);
1518 
1519  member.add_source_location()=source_location;
1520 
1521  return true; // component found
1522  }
1523  else if(follow(component.type()).find(ID_C_unnamed_object).is_not_nil())
1524  {
1525  // could be anonymous union or struct
1526 
1527  const typet &component_type=follow(component.type());
1528 
1529  if(component_type.id()==ID_union ||
1530  component_type.id()==ID_struct)
1531  {
1532  // recursive call!
1533  if(get_component(source_location, tmp, component_name, member))
1534  {
1535  if(check_component_access(component, final_type))
1536  {
1537  error().source_location=source_location;
1538  error() << "error: member `" << component_name
1539  << "' is not accessible" << eom;
1540  throw 0;
1541  }
1542 
1543  if(object.get_bool(ID_C_lvalue))
1544  member.set(ID_C_lvalue, true);
1545 
1546  if(object.get_bool(ID_C_constant) &&
1547  !component.get_bool("is_mutable"))
1548  member.type().set(ID_C_constant, true);
1549 
1550  member.add_source_location()=source_location;
1551  return true; // component found
1552  }
1553  }
1554  }
1555  }
1556 
1557  return false; // component not found
1558 }
1559 
1561  const struct_union_typet::componentt &component,
1562  const struct_union_typet &struct_union_type)
1563 {
1564  const irep_idt &access=component.get(ID_access);
1565 
1566  if(access=="noaccess")
1567  return true; // not ok
1568 
1569  if(access==ID_public)
1570  return false; // ok
1571 
1572  assert(access==ID_private ||
1573  access==ID_protected);
1574 
1575  const irep_idt &struct_identifier=
1576  struct_union_type.get(ID_name);
1577 
1578  cpp_scopet *pscope=&(cpp_scopes.current_scope());
1579  while(!(pscope->is_root_scope()))
1580  {
1581  if(pscope->is_class())
1582  {
1583  if(pscope->identifier==struct_identifier)
1584  return false; // ok
1585 
1586  const struct_typet &scope_struct=
1587  to_struct_type(lookup(pscope->identifier).type);
1588 
1589  if(subtype_typecast(
1590  to_struct_type(struct_union_type), scope_struct))
1591  return false; // ok
1592 
1593  else break;
1594  }
1595  pscope=&(pscope->get_parent());
1596  }
1597 
1598  // check friendship
1599  const irept::subt &friends = struct_union_type.find(ID_C_friends).get_sub();
1600 
1601  forall_irep(f_it, friends)
1602  {
1603  const irept &friend_symb=*f_it;
1604 
1605  const cpp_scopet &friend_scope =
1606  cpp_scopes.get_scope(friend_symb.get(ID_identifier));
1607 
1608  cpp_scopet *pscope=&(cpp_scopes.current_scope());
1609 
1610  while(!(pscope->is_root_scope()))
1611  {
1612  if(friend_scope.identifier==pscope->identifier)
1613  return false; // ok
1614 
1615  if(pscope->is_class())
1616  break;
1617 
1618  pscope=&(pscope->get_parent());
1619  }
1620  }
1621 
1622  return true; // not ok
1623 }
1624 
1626  const struct_typet &type,
1627  std::set<irep_idt> &set_bases) const
1628 {
1629  const irept::subt &bases=type.find(ID_bases).get_sub();
1630 
1631  forall_irep(it, bases)
1632  {
1633  assert(it->id()==ID_base);
1634  assert(it->get(ID_type)==ID_symbol);
1635 
1636  const struct_typet &base=
1637  to_struct_type(lookup(it->find(ID_type).get(ID_identifier)).type);
1638 
1639  set_bases.insert(base.get(ID_name));
1640  get_bases(base, set_bases);
1641  }
1642 }
1643 
1645  const struct_typet &type,
1646  std::list<irep_idt> &vbases) const
1647 {
1648  if(std::find(vbases.begin(), vbases.end(), type.get(ID_name))!=vbases.end())
1649  return;
1650 
1651  const irept::subt &bases=type.find(ID_bases).get_sub();
1652 
1653  forall_irep(it, bases)
1654  {
1655  assert(it->id()==ID_base);
1656  assert(it->get(ID_type)==ID_symbol);
1657 
1658  const struct_typet &base=
1659  to_struct_type(lookup(it->find(ID_type).get(ID_identifier)).type);
1660 
1661  if(it->get_bool(ID_virtual))
1662  vbases.push_back(base.get(ID_name));
1663 
1664  get_virtual_bases(base, vbases);
1665  }
1666 }
1667 
1669  const struct_typet &from,
1670  const struct_typet &to) const
1671 {
1672  if(from.get(ID_name)==to.get(ID_name))
1673  return true;
1674 
1675  std::set<irep_idt> bases;
1676 
1677  get_bases(from, bases);
1678 
1679  return bases.find(to.get(ID_name))!=bases.end();
1680 }
1681 
1683  exprt &expr,
1684  const typet &dest_type)
1685 {
1686  typet src_type=expr.type();
1687 
1688  assert(src_type.id()== ID_pointer);
1689  assert(dest_type.id()== ID_pointer);
1690 
1691  struct_typet src_struct =
1692  to_struct_type(static_cast<const typet&>(follow(src_type.subtype())));
1693 
1694  struct_typet dest_struct =
1695  to_struct_type(static_cast<const typet&>(follow(dest_type.subtype())));
1696 
1697  assert(subtype_typecast(src_struct, dest_struct) ||
1698  subtype_typecast(dest_struct, src_struct));
1699 
1700  expr.make_typecast(dest_type);
1701 }
bool is_typedef() const
C++ Language Type Checking.
const irep_idt & get_statement() const
Definition: std_code.h:40
const irep_idt & get_name() const
Definition: std_types.h:182
The type of an expression.
Definition: type.h:22
irep_idt name
The unique identifier.
Definition: symbol.h:43
void add_anonymous_members_to_scope(const symbolt &struct_union_symbol)
#define forall_subtypes(it, type)
Definition: type.h:161
bool find_cpctor(const symbolt &symbol) const
void check_fixed_size_array(typet &type)
check that an array has fixed size
semantic type conversion
Definition: std_expr.h:2111
static bool is_constructor(const irep_idt &method_name)
BigInt mp_integer
Definition: mp_arith.h:22
codet dtor(const symbolt &symb)
produces destructor code for a class object
void typecheck_type(typet &type)
Base type of functions.
Definition: std_types.h:764
bool is_nil() const
Definition: irep.h:172
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
bool is_not_nil() const
Definition: irep.h:173
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:243
bool is_operator() const
Definition: cpp_name.h:97
bool is_mutable() const
const cpp_storage_spect & storage_spec() const
std::set< cpp_idt * > id_sett
Definition: cpp_scopes.h:31
void lookup(const irep_idt &base_name, lookup_kindt kind, id_sett &id_set)
Definition: cpp_scope.cpp:29
static bool has_const(const typet &type)
static bool has_auto(const typet &type)
exprt & op0()
Definition: expr.h:72
bool is_destructor() const
std::vector< irept > subt
Definition: irep.h:160
irep_idt mode
Language mode.
Definition: symbol.h:52
void move_to_sub(irept &irep)
Definition: irep.cpp:204
void name_anon_struct_union()
void get_bases(const struct_typet &type, std::set< irep_idt > &set_bases) const
const code_typet & to_code_type(const typet &type)
Cast a generic typet to a code_typet.
Definition: std_types.h:993
void set_base_name(const irep_idt &base_name)
Definition: std_types.h:197
void set_name(const irep_idt &name)
Definition: std_types.h:187
void full_member_initialization(const struct_union_typet &struct_union_type, irept &initializers)
Build the full initialization list of the constructor.
bool check_component_access(const struct_union_typet::componentt &component, const struct_union_typet &struct_union_type)
bool is_auto() const
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
cpp_namet & to_cpp_name(irept &cpp_name)
Definition: cpp_name.h:144
std::vector< componentt > componentst
Definition: std_types.h:243
void move_to_operands(exprt &expr)
Definition: expr.cpp:22
cpp_scopet & get_parent() const
Definition: cpp_scope.h:89
std::vector< parametert > parameterst
Definition: std_types.h:767
void already_typechecked(irept &irep)
Definition: cpp_util.h:18
exprt value
Initial value of symbol.
Definition: symbol.h:37
const componentst & components() const
Definition: std_types.h:245
cpp_idt & put_into_scope(const symbolt &symbol, cpp_scopet &scope, bool is_friend=false)
Definition: cpp_scopes.cpp:22
irep_idt module
Name of module the symbol belongs to.
Definition: symbol.h:46
irep_idt pretty_name
Language-specific display name.
Definition: symbol.h:55
bool is_register() const
void default_dtor(const symbolt &symb, cpp_declarationt &dtor)
Note:
typet & type()
Definition: expr.h:56
void move_member_initializers(irept &initializers, const typet &type, exprt &value)
void add_this_to_method_type(const irep_idt &compound_identifier, typet &method_type, const typet &method_qualifier)
cpp_scopet & get_global_scope()
Definition: cpp_scopes.h:116
bool is_simple_name() const
Definition: cpp_name.h:89
typet merge_type(const typet &declaration_type) const
Symbol table entry.This is a symbol in the symbol table, stored in an object of type symbol_tablet...
Definition: symbol.h:30
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:266
static mstreamt & eom(mstreamt &m)
Definition: message.h:272
Structure type.
Definition: std_types.h:297
void check_member_initializers(const irept &bases, const struct_typet::componentst &components, const irept &initializers)
Check a constructor initialization-list.
bool get_bool(const irep_namet &name) const
Definition: irep.cpp:240
An expression statement.
Definition: std_code.h:1220
const cpp_member_spect & member_spec() const
void set_inline(bool value)
bool is_static_lifetime
Definition: symbol.h:67
std::string suffix
Definition: cpp_id.h:80
#define INVARIANT(CONDITION, REASON)
Definition: invariant.h:204
subt & get_sub()
Definition: irep.h:317
void set_base_name(const irep_idt &name)
Definition: std_types.h:835
void typecheck_compound_declarator(const symbolt &symbol, const cpp_declarationt &declaration, cpp_declaratort &declarator, struct_typet::componentst &components, const irep_idt &access, bool is_static, bool is_typedef, bool is_mutable)
Extract member of struct or union.
Definition: std_expr.h:3869
symbol_tablet & symbol_table
virtual symbolt * get_writeable(const irep_idt &name) override
Find a symbol in the symbol table for read-write access.
Definition: symbol_table.h:87
const irep_idt & get_base_name() const
Definition: std_types.h:192
std::string prefix
Definition: cpp_id.h:80
void add_method_body(symbolt *_method_symbol)
const irep_idt & id() const
Definition: irep.h:259
const source_locationt & source_location() const
Definition: cpp_name.h:73
const irep_idt & get_base_name() const
Definition: std_types.h:845
void elaborate_class_template(const typet &type)
elaborate class template instances
class code_blockt & make_block()
Definition: std_code.cpp:24
const declaratorst & declarators() const
bool is_friend() const
source_locationt & location()
bool is_extern() const
A reference into the symbol table.
Definition: std_types.h:110
virtual bool move(symbolt &symbol, symbolt *&new_symbol) override
Move a symbol into the symbol table.
C++ Language Module.
source_locationt source_location
Definition: message.h:214
bool cpp_is_pod(const typet &type) const
Definition: cpp_is_pod.cpp:14
void set_access(const irep_idt &access)
Definition: std_types.h:207
irep_idt identifier
Definition: cpp_id.h:73
void typecheck_friend_declaration(symbolt &symbol, cpp_declarationt &cpp_declaration)
C++ Language Conversion.
id_classt id_class
Definition: cpp_id.h:51
const irep_idt & get(const irep_namet &name) const
Definition: irep.cpp:213
mstreamt & error() const
Definition: message.h:302
bool is_static() const
void go_to_global_scope()
Definition: cpp_scopes.h:111
void typecheck_member_function(const irep_idt &compound_identifier, struct_typet::componentt &component, irept &initializers, const typet &method_qualifier, exprt &value)
void do_virtual_table(const symbolt &symbol)
std::string cpp_type2name(const typet &type)
const exprt & size() const
Definition: std_types.h:1023
Base class for tree-like data structures with sharing.
Definition: irep.h:156
void convert_template_declaration(cpp_declarationt &declaration)
C++ Language Type Checking.
const typet & follow(const typet &) const
Definition: namespace.cpp:55
const struct_typet & to_struct_type(const typet &type)
Cast a generic typet to a struct_typet.
Definition: std_types.h:318
dstringt has one field, an unsigned integer no which is an index into a static table of strings...
Definition: dstring.h:33
bool is_constructor() const
unsigned anon_counter
void default_assignop(const symbolt &symbol, cpp_declarationt &cpctor)
Generate declaration of the implicit default assignment operator.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
bool has_operands() const
Definition: expr.h:63
void default_cpctor(const symbolt &, cpp_declarationt &cpctor) const
Generate code for implicit default copy constructor.
void make_ptr_typecast(exprt &expr, const typet &dest_type)
bool is_class() const
Definition: cpp_id.h:53
id_mapt id_map
Definition: cpp_scopes.h:69
std::vector< exprt > operandst
Definition: expr.h:45
bool is_explicit() const
const source_locationt & source_location() const
Definition: type.h:97
irep_idt get_base_name() const
Definition: cpp_name.cpp:17
cpp_scopet & set_scope(const irep_idt &identifier)
Definition: cpp_scopes.h:88
A function call side effect.
Definition: std_code.h:1395
bool is_extern
Definition: symbol.h:68
bool get_component(const source_locationt &source_location, const exprt &object, const irep_idt &component_name, exprt &member)
bool is_template() const
irep_idt function_identifier(const typet &type)
for function overloading
typet type
Type of symbol.
Definition: symbol.h:34
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:40
cpp_declarationt & to_cpp_declaration(irept &irep)
void set_identifier(const irep_idt &identifier)
Definition: std_types.h:830
API to type classes.
bool subtype_typecast(const struct_typet &from, const struct_typet &to) const
void typecheck_compound_bases(struct_typet &type)
Base type of C structs and unions, and C++ classes.
Definition: std_types.h:162
void default_ctor(const source_locationt &source_location, const irep_idt &base_name, cpp_declarationt &ctor) const
Generate code for implicit default constructors.
const array_typet & to_array_type(const typet &type)
Cast a generic typet to an array_typet.
Definition: std_types.h:1054
bool find_assignop(const symbolt &symbol) const
Base class for all expressions.
Definition: expr.h:42
void get_virtual_bases(const struct_typet &type, std::list< irep_idt > &vbases) const
bool contains(const irep_idt &base_name)
Definition: cpp_scope.cpp:212
const parameterst & parameters() const
Definition: std_types.h:905
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:49
cpp_scopet & current_scope()
Definition: cpp_scopes.h:33
irept & member_initializers()
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a generic typet to a struct_union_typet.
Definition: std_types.h:280
void set_pretty_name(const irep_idt &name)
Definition: std_types.h:217
std::string to_string(const string_constraintt &expr)
Used for debug printing.
symbolt & convert(const typet &type, const cpp_storage_spect &storage_spec, const cpp_member_spect &member_spec, cpp_declaratort &declarator)
const source_locationt & source_location() const
Definition: expr.h:125
virtual void make_constant_index(exprt &expr)
irept & add(const irep_namet &name)
Definition: irep.cpp:306
void typecheck_compound_type(struct_union_typet &type)
const std::string & get_string(const irep_namet &name) const
Definition: irep.h:272
const irep_idt module
void make_nil()
Definition: irep.h:315
void set_identifier(const irep_idt &identifier)
Definition: std_expr.h:123
dynamic_initializationst dynamic_initializations
const std::string & id_string() const
Definition: irep.h:262
bool disable_access_control
void swap(irept &irep)
Definition: irep.h:303
virtual void write(typet &src) const override
#define Forall_operands(it, expr)
Definition: expr.h:23
source_locationt & add_source_location()
Definition: expr.h:130
const codet & to_code(const exprt &expr)
Definition: std_code.h:75
arrays with given size
Definition: std_types.h:1013
cpp_namet & name()
void typecheck_compound_body(symbolt &symbol)
Expression to hold a symbol (variable)
Definition: std_expr.h:90
void set_anonymous(bool anonymous)
Definition: std_types.h:227
cpp_scopet & get_scope(const irep_idt &identifier)
Definition: cpp_scopes.h:81
const char * c_str() const
Definition: dstring.h:84
bool to_integer(const exprt &expr, mp_integer &int_value)
Definition: arith_tools.cpp:17
virtual void do_initializer(exprt &initializer, const typet &type, bool force_constant)
dstringt irep_idt
Definition: irep.h:32
void put_compound_into_scope(const struct_union_typet::componentt &component)
Definition: cpp_id.h:28
A statement in a programming language.
Definition: std_code.h:21
Return from a function.
Definition: std_code.h:923
exprt cpp_symbol_expr(const symbolt &symbol)
Definition: cpp_util.cpp:14
void remove(const irep_namet &name)
Definition: irep.cpp:270
bool is_type
Definition: symbol.h:63
const typet & subtype() const
Definition: type.h:33
operandst & operands()
Definition: expr.h:66
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
static bool has_volatile(const typet &type)
bool is_root_scope() const
Definition: cpp_scope.h:73
void convert_anon_struct_union_member(const cpp_declarationt &declaration, const irep_idt &access, struct_typet::componentst &components)
cpp_idt & insert(const irep_idt &_base_name)
Definition: cpp_scope.h:48
bool empty() const
Definition: dstring.h:73
std::set< cpp_idt * > id_sett
Definition: cpp_scope.h:28
void make_typecast(const typet &_type)
Definition: expr.cpp:84
const irept & find(const irep_namet &name) const
Definition: irep.cpp:285
cpp_scopet & tag_scope(const irep_idt &_base_name, bool has_body, bool tag_only_declaration)
bool is_inline() const
const typet & return_type() const
Definition: std_types.h:895
bool is_macro
Definition: symbol.h:63
codet cpp_constructor(const source_locationt &source_location, const exprt &object, const exprt::operandst &operands)
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See namespace_baset::lookup().
Definition: namespace.cpp:136
bool is_template_scope() const
Definition: cpp_scope.h:84
void set(const irep_namet &name, const irep_idt &value)
Definition: irep.h:286
bool is_virtual() const
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
bool simplify(exprt &expr, const namespacet &ns)
cpp_scopet & resolve_scope(const cpp_namet &cpp_name, irep_idt &base_name, cpp_template_args_non_tct &template_args)
bool is_lvalue
Definition: symbol.h:68
#define forall_irep(it, irep)
Definition: irep.h:62
cpp_scopest cpp_scopes