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