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