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