cprover
cpp_typecheck_constructor.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 <util/arith_tools.h>
15 #include <util/std_code.h>
16 #include <util/std_expr.h>
17 
18 #include <util/c_types.h>
19 
20 #include "cpp_util.h"
21 
27 static void copy_parent(
28  const source_locationt &source_location,
29  const irep_idt &parent_base_name,
30  const irep_idt &arg_name,
31  exprt &block)
32 {
33  exprt op0(
34  "explicit-typecast",
35  pointer_type(cpp_namet(parent_base_name, source_location).as_type()));
36  op0.copy_to_operands(exprt("cpp-this"));
37  op0.add_source_location()=source_location;
38 
39  exprt op1(
40  "explicit-typecast",
41  pointer_type(cpp_namet(parent_base_name, source_location).as_type()));
42  op1.type().set(ID_C_reference, true);
43  op1.type().subtype().set(ID_C_constant, true);
44  op1.get_sub().push_back(cpp_namet(arg_name, source_location));
45  op1.add_source_location()=source_location;
46 
47  code_assignt code(dereference_exprt(op0), op1);
48  code.add_source_location() = source_location;
49 
50  block.operands().push_back(code);
51 }
52 
58 static void copy_member(
59  const source_locationt &source_location,
60  const irep_idt &member_base_name,
61  const irep_idt &arg_name,
62  exprt &block)
63 {
64  cpp_namet op0(member_base_name, source_location);
65 
66  exprt op1(ID_member);
67  op1.add(ID_component_cpp_name, cpp_namet(member_base_name, source_location));
68  op1.copy_to_operands(cpp_namet(arg_name, source_location).as_expr());
69  op1.add_source_location()=source_location;
70 
71  side_effect_exprt assign(ID_assign, typet(), source_location);
72  assign.copy_to_operands(op0.as_expr());
73  assign.op0().add_source_location() = source_location;
74  assign.copy_to_operands(op1);
75 
76  code_expressiont code(assign);
77  code.add_source_location() = source_location;
78 
79  block.operands().push_back(code);
80 }
81 
88 static void copy_array(
89  const source_locationt &source_location,
90  const irep_idt &member_base_name,
91  mp_integer i,
92  const irep_idt &arg_name,
93  exprt &block)
94 {
95  // Build the index expression
96  const exprt constant = from_integer(i, index_type());
97 
98  const cpp_namet array(member_base_name, source_location);
99 
100  exprt member(ID_member);
101  member.add(
102  ID_component_cpp_name, cpp_namet(member_base_name, source_location));
103  member.copy_to_operands(cpp_namet(arg_name, source_location).as_expr());
104 
105  side_effect_exprt assign(ID_assign, typet(), source_location);
106 
107  assign.copy_to_operands(index_exprt(array.as_expr(), constant));
108  assign.op0().add_source_location() = source_location;
109 
110  assign.copy_to_operands(index_exprt(member, constant));
111  assign.op1().add_source_location() = source_location;
112 
113  code_expressiont code(assign);
114  code.add_source_location() = source_location;
115 
116  block.operands().push_back(code);
117 }
118 
121  const source_locationt &source_location,
122  const irep_idt &base_name,
123  cpp_declarationt &ctor) const
124 {
125  cpp_declaratort decl;
126  decl.name() = cpp_namet(base_name, source_location);
127  decl.type()=typet(ID_function_type);
128  decl.type().subtype().make_nil();
129  decl.add_source_location()=source_location;
130 
131  decl.value().id(ID_code);
132  decl.value().type()=typet(ID_code);
133  decl.value().set(ID_statement, ID_block);
134  decl.add(ID_cv).make_nil();
135  decl.add(ID_throw_decl).make_nil();
136 
137  ctor.type().id(ID_constructor);
138  ctor.add(ID_storage_spec).id(ID_cpp_storage_spec);
139  ctor.move_to_operands(decl);
140  ctor.add_source_location()=source_location;
141 }
142 
145  const symbolt &symbol,
146  cpp_declarationt &cpctor) const
147 {
148  source_locationt source_location=symbol.type.source_location();
149 
150  source_location.set_function(
151  id2string(symbol.base_name)+
152  "::"+id2string(symbol.base_name)+
153  "(const "+id2string(symbol.base_name)+" &)");
154 
155  // Produce default constructor first
156  default_ctor(source_location, symbol.base_name, cpctor);
157  cpp_declaratort &decl0=cpctor.declarators()[0];
158 
159  std::string param_identifier("ref");
160 
161  // Compound name
162  const cpp_namet cppcomp(symbol.base_name, source_location);
163 
164  // Parameter name
165  const cpp_namet cpp_parameter(param_identifier, source_location);
166 
167  // Parameter declarator
168  cpp_declaratort parameter_tor;
169  parameter_tor.add(ID_value).make_nil();
170  parameter_tor.set(ID_name, cpp_parameter);
171  parameter_tor.type()=reference_type(nil_typet());
172  parameter_tor.add_source_location()=source_location;
173 
174  // Parameter declaration
175  cpp_declarationt parameter_decl;
176  parameter_decl.set(ID_type, ID_merged_type);
177  auto &sub = to_type_with_subtypes(parameter_decl.type()).subtypes();
178  sub.push_back(cppcomp.as_type());
179  irept constnd(ID_const);
180  sub.push_back(static_cast<const typet &>(constnd));
181  parameter_decl.move_to_operands(parameter_tor);
182  parameter_decl.add_source_location()=source_location;
183 
184  // Add parameter to function type
185  decl0.add(ID_type).add(ID_parameters).get_sub().push_back(parameter_decl);
186  decl0.add_source_location()=source_location;
187 
188  irept &initializers=decl0.add(ID_member_initializers);
189  initializers.id(ID_member_initializers);
190 
191  cpp_declaratort &declarator=static_cast<cpp_declaratort &>(cpctor.op0());
192  exprt &block=declarator.value();
193 
194  // First, we need to call the parent copy constructors
195  for(const auto &b : to_struct_type(symbol.type).bases())
196  {
197  DATA_INVARIANT(b.id() == ID_base, "base class expression expected");
198 
199  const symbolt &parsymb = lookup(b.type());
200 
201  if(cpp_is_pod(parsymb.type))
202  copy_parent(source_location, parsymb.base_name, param_identifier, block);
203  else
204  {
205  irep_idt ctor_name=parsymb.base_name;
206 
207  // Call the parent default copy constructor
208  const cpp_namet cppname(ctor_name, source_location);
209 
210  codet mem_init(ID_member_initializer);
211  mem_init.add_source_location()=source_location;
212  mem_init.set(ID_member, cppname);
213  mem_init.copy_to_operands(cpp_parameter.as_expr());
214  initializers.move_to_sub(mem_init);
215  }
216  }
217 
218  // Then, we add the member initializers
219  const struct_typet::componentst &components=
220  to_struct_type(symbol.type).components();
221 
222  for(const auto &mem_c : components)
223  {
224  // Take care of virtual tables
225  if(mem_c.get_bool(ID_is_vtptr))
226  {
227  const cpp_namet cppname(mem_c.get_base_name(), source_location);
228 
229  const symbolt &virtual_table_symbol_type =
230  lookup(mem_c.type().subtype().get(ID_identifier));
231 
232  const symbolt &virtual_table_symbol_var = lookup(
233  id2string(virtual_table_symbol_type.name) + "@" +
234  id2string(symbol.name));
235 
236  exprt var=virtual_table_symbol_var.symbol_expr();
237  address_of_exprt address(var);
238  assert(address.type() == mem_c.type());
239 
240  already_typechecked(address);
241 
242  exprt ptrmember(ID_ptrmember);
243  ptrmember.set(ID_component_name, mem_c.get_name());
244  ptrmember.operands().push_back(exprt("cpp-this"));
245 
246  code_assignt assign(ptrmember, address);
247  initializers.move_to_sub(assign);
248  continue;
249  }
250 
251  if(
252  mem_c.get_bool(ID_from_base) || mem_c.get_bool(ID_is_type) ||
253  mem_c.get_bool(ID_is_static) || mem_c.type().id() == ID_code)
254  {
255  continue;
256  }
257 
258  const irep_idt &mem_name = mem_c.get_base_name();
259 
260  const cpp_namet cppname(mem_name, source_location);
261 
262  codet mem_init(ID_member_initializer);
263  mem_init.set(ID_member, cppname);
264  mem_init.add_source_location()=source_location;
265 
266  exprt memberexpr(ID_member);
267  memberexpr.set(ID_component_cpp_name, cppname);
268  memberexpr.copy_to_operands(cpp_parameter.as_expr());
269  memberexpr.add_source_location()=source_location;
270 
271  if(mem_c.type().id() == ID_array)
272  memberexpr.set(ID_C_array_ini, true);
273 
274  mem_init.move_to_operands(memberexpr);
275  initializers.move_to_sub(mem_init);
276  }
277 }
278 
281  const symbolt &symbol,
282  cpp_declarationt &cpctor)
283 {
284  source_locationt source_location=symbol.type.source_location();
285 
286  source_location.set_function(
287  id2string(symbol.base_name)
288  + "& "+
289  id2string(symbol.base_name)+
290  "::operator=( const "+id2string(symbol.base_name)+"&)");
291 
292  std::string arg_name("ref");
293 
294  cpctor.add(ID_storage_spec).id(ID_cpp_storage_spec);
295  cpctor.type().id(ID_symbol_type);
296  cpctor.type().add(ID_identifier).id(symbol.name);
297  cpctor.operands().push_back(exprt(ID_cpp_declarator));
298  cpctor.add_source_location()=source_location;
299 
300  cpp_declaratort &declarator=(cpp_declaratort&) cpctor.op0();
301  declarator.add_source_location()=source_location;
302 
303  cpp_namet &declarator_name=declarator.name();
304  typet &declarator_type=declarator.type();
305 
306  declarator_type.add_source_location()=source_location;
307 
308  declarator_name.id(ID_cpp_name);
309  declarator_name.get_sub().push_back(irept(ID_operator));
310  declarator_name.get_sub().push_back(irept("="));
311 
312  declarator_type.id(ID_function_type);
313  declarator_type.subtype()=reference_type(nil_typet());
314  declarator_type.subtype().add(ID_C_qualifier).make_nil();
315 
316  exprt &args=static_cast<exprt&>(declarator.type().add(ID_parameters));
317  args.add_source_location()=source_location;
318 
319  args.get_sub().push_back(irept(ID_cpp_declaration));
320 
321  cpp_declarationt &args_decl=
322  static_cast<cpp_declarationt&>(args.get_sub().back());
323 
324  auto &args_decl_type_sub = to_type_with_subtypes(args_decl.type()).subtypes();
325 
326  args_decl.type().id(ID_merged_type);
327  args_decl_type_sub.push_back(
328  cpp_namet(symbol.base_name, source_location).as_type());
329 
330  args_decl_type_sub.push_back(typet(ID_const));
331  args_decl.operands().push_back(exprt(ID_cpp_declarator));
332  args_decl.add_source_location()=source_location;
333 
334  cpp_declaratort &args_decl_declor=
335  static_cast<cpp_declaratort&>(args_decl.operands().back());
336 
337  args_decl_declor.name() = cpp_namet(arg_name, source_location);
338  args_decl_declor.add_source_location()=source_location;
339 
340  args_decl_declor.type()=pointer_type(typet(ID_nil));
341  args_decl_declor.type().set(ID_C_reference, true);
342  args_decl_declor.value().make_nil();
343 }
344 
347  const symbolt &symbol,
348  cpp_declaratort &declarator)
349 {
350  // save source location
351  source_locationt source_location=declarator.source_location();
352  declarator.make_nil();
353 
354  declarator.value().add_source_location()=source_location;
355  declarator.value().id(ID_code);
356  declarator.value().set(ID_statement, ID_block);
357  declarator.value().type() = code_typet({}, empty_typet());
358 
359  exprt &block=declarator.value();
360 
361  std::string arg_name("ref");
362 
363  // First, we copy the parents
364  for(const auto &b : to_struct_type(symbol.type).bases())
365  {
366  DATA_INVARIANT(b.id() == ID_base, "base class expression expected");
367 
368  const symbolt &symb = lookup(b.type());
369 
370  copy_parent(source_location, symb.base_name, arg_name, block);
371  }
372 
373  // Then, we copy the members
374  for(const auto &c : to_struct_type(symbol.type).components())
375  {
376  if(
377  c.get_bool(ID_from_base) || c.get_bool(ID_is_type) ||
378  c.get_bool(ID_is_static) || c.get_bool(ID_is_vtptr) ||
379  c.type().id() == ID_code)
380  {
381  continue;
382  }
383 
384  const irep_idt &mem_name = c.get_base_name();
385 
386  if(c.type().id() == ID_array)
387  {
388  const exprt &size_expr = to_array_type(c.type()).size();
389 
390  if(size_expr.id()==ID_infinity)
391  {
392  // error().source_location=object);
393  // err << "cannot copy array of infinite size\n";
394  // throw 0;
395  continue;
396  }
397 
398  const auto size = numeric_cast<mp_integer>(size_expr);
399  CHECK_RETURN(!size.has_value());
400  CHECK_RETURN(*size >= 0);
401 
402  for(mp_integer i = 0; i < *size; ++i)
403  copy_array(source_location, mem_name, i, arg_name, block);
404  }
405  else
406  copy_member(source_location, mem_name, arg_name, block);
407  }
408 
409  // Finally we add the return statement
410  block.operands().push_back(exprt(ID_code));
411  exprt &ret_code=declarator.value().operands().back();
412  ret_code.operands().push_back(exprt(ID_dereference));
413  ret_code.op0().operands().push_back(exprt("cpp-this"));
414  ret_code.set(ID_statement, ID_return);
415  ret_code.type() = code_typet({}, empty_typet());
416 }
417 
426  const struct_typet::basest &bases,
427  const struct_typet::componentst &components,
428  const irept &initializers)
429 {
430  assert(initializers.id()==ID_member_initializers);
431 
432  forall_irep(init_it, initializers.get_sub())
433  {
434  const irept &initializer=*init_it;
435  assert(initializer.is_not_nil());
436 
437  const cpp_namet &member_name=
438  to_cpp_name(initializer.find(ID_member));
439 
440  bool has_template_args=member_name.has_template_args();
441 
442  if(has_template_args)
443  {
444  // it has to be a parent constructor
445  typet member_type=(typet&) initializer.find(ID_member);
446  typecheck_type(member_type);
447 
448  // check for a direct parent
449  bool ok=false;
450  for(const auto &b : bases)
451  {
452  if(
453  to_symbol_type(member_type).get_identifier() ==
454  to_symbol_type(b.type()).get_identifier())
455  {
456  ok=true;
457  break;
458  }
459  }
460 
461  if(!ok)
462  {
463  error().source_location=member_name.source_location();
464  error() << "invalid initializer `" << member_name.to_string()
465  << "'" << eom;
466  throw 0;
467  }
468  return;
469  }
470 
471  irep_idt base_name=member_name.get_base_name();
472  bool ok=false;
473 
474  for(const auto &c : components)
475  {
476  if(c.get_base_name() != base_name)
477  continue;
478 
479  // Data member
480  if(
481  !c.get_bool(ID_from_base) && !c.get_bool(ID_is_static) &&
482  c.type().id() != ID_code)
483  {
484  ok=true;
485  break;
486  }
487 
488  // Maybe it is a parent constructor?
489  if(c.get_bool(ID_is_type))
490  {
491  if(c.type().id() != ID_symbol_type)
492  continue;
493 
494  const symbolt &symb = lookup(to_symbol_type(c.type()).get_identifier());
495  if(symb.type.id()!=ID_struct)
496  break;
497 
498  // check for a direct parent
499  for(const auto &b : bases)
500  {
501  if(symb.name == to_symbol_type(b.type()).get_identifier())
502  {
503  ok=true;
504  break;
505  }
506  }
507  continue;
508  }
509 
510  // Parent constructor
511  if(
512  c.get_bool(ID_from_base) && !c.get_bool(ID_is_type) &&
513  !c.get_bool(ID_is_static) && c.type().id() == ID_code &&
514  to_code_type(c.type()).return_type().id() == ID_constructor)
515  {
516  typet member_type=(typet&) initializer.find(ID_member);
517  typecheck_type(member_type);
518 
519  // check for a direct parent
520  for(const auto &b : bases)
521  {
522  if(
523  member_type.get(ID_identifier) ==
524  to_symbol_type(b.type()).get_identifier())
525  {
526  ok=true;
527  break;
528  }
529  }
530  break;
531  }
532  }
533 
534  if(!ok)
535  {
536  error().source_location=member_name.source_location();
537  error() << "invalid initializer `" << base_name << "'" << eom;
538  throw 0;
539  }
540  }
541 }
542 
552  const struct_union_typet &struct_union_type,
553  irept &initializers)
554 {
555  const struct_union_typet::componentst &components=
556  struct_union_type.components();
557 
558  assert(initializers.id()==ID_member_initializers);
559 
560  irept final_initializers(ID_member_initializers);
561 
562  if(struct_union_type.id()==ID_struct)
563  {
564  // First, if we are the most-derived object, then
565  // we need to construct the virtual bases
566  std::list<irep_idt> vbases;
567  get_virtual_bases(to_struct_type(struct_union_type), vbases);
568 
569  if(!vbases.empty())
570  {
571  // TODO(tautschnig): this code doesn't seem to make much sense as the
572  // ifthenelse only gets to have two operands (instead of three)
573  codet cond(ID_ifthenelse);
574 
575  cond.copy_to_operands(cpp_namet("@most_derived").as_expr());
576 
577  code_blockt block;
578 
579  while(!vbases.empty())
580  {
581  const symbolt &symb=lookup(vbases.front());
582  if(!cpp_is_pod(symb.type))
583  {
584  // default initializer
585  const cpp_namet cppname(symb.base_name);
586 
587  codet mem_init(ID_member_initializer);
588  mem_init.set(ID_member, cppname);
589  block.move_to_sub(mem_init);
590  }
591  vbases.pop_front();
592  }
593  cond.move_to_operands(block);
594  final_initializers.move_to_sub(cond);
595  }
596 
597  // Subsequently, we need to call the non-POD parent constructors
598  for(const auto &b : to_struct_type(struct_union_type).bases())
599  {
600  DATA_INVARIANT(b.id() == ID_base, "base class expression expected");
601 
602  const symbolt &ctorsymb = lookup(b.type());
603 
604  if(cpp_is_pod(ctorsymb.type))
605  continue;
606 
607  irep_idt ctor_name=ctorsymb.base_name;
608 
609  // Check if the initialization list of the constructor
610  // explicitly calls the parent constructor.
611  bool found=false;
612 
613  forall_irep(m_it, initializers.get_sub())
614  {
615  irept initializer=*m_it;
616 
617  const cpp_namet &member_name=
618  to_cpp_name(initializer.find(ID_member));
619 
620  bool has_template_args=member_name.has_template_args();
621 
622  if(!has_template_args)
623  {
624  irep_idt base_name=member_name.get_base_name();
625 
626  // check if the initializer is a data
627  bool is_data=false;
628 
629  for(const auto &c : components)
630  {
631  if(
632  c.get_base_name() == base_name && c.type().id() != ID_code &&
633  !c.get_bool(ID_is_type))
634  {
635  is_data=true;
636  break;
637  }
638  }
639 
640  if(is_data)
641  continue;
642  }
643 
644  typet member_type=
645  static_cast<const typet&>(initializer.find(ID_member));
646 
647  typecheck_type(member_type);
648 
649  if(member_type.id() != ID_symbol_type)
650  break;
651 
652  if(
653  to_symbol_type(b.type()).get_identifier() ==
654  to_symbol_type(member_type).get_identifier())
655  {
656  final_initializers.move_to_sub(initializer);
657  found=true;
658  break;
659  }
660  }
661 
662  // Call the parent default constructor
663  if(!found)
664  {
665  const cpp_namet cppname(ctor_name);
666 
667  codet mem_init(ID_member_initializer);
668  mem_init.set(ID_member, cppname);
669  final_initializers.move_to_sub(mem_init);
670  }
671 
672  if(b.get_bool(ID_virtual))
673  {
674  // TODO(tautschnig): this code doesn't seem to make much sense as the
675  // ifthenelse only gets to have two operands (instead of three)
676  codet cond(ID_ifthenelse);
677 
678  cond.copy_to_operands(cpp_namet("@most_derived").as_expr());
679 
680  {
681  codet tmp(ID_member_initializer);
682  tmp.swap(final_initializers.get_sub().back());
683  cond.move_to_operands(tmp);
684  final_initializers.get_sub().back().swap(cond);
685  }
686  }
687  }
688  }
689 
690  // Then, we add the member initializers
691  for(const auto &c : components)
692  {
693  // Take care of virtual tables
694  if(c.get_bool(ID_is_vtptr))
695  {
696  const cpp_namet cppname(c.get_base_name(), c.source_location());
697 
698  const symbolt &virtual_table_symbol_type =
699  lookup(c.type().subtype().get(ID_identifier));
700 
701  const symbolt &virtual_table_symbol_var =
702  lookup(id2string(virtual_table_symbol_type.name) + "@" +
703  id2string(struct_union_type.get(ID_name)));
704 
705  exprt var=virtual_table_symbol_var.symbol_expr();
706  address_of_exprt address(var);
707  assert(address.type() == c.type());
708 
709  already_typechecked(address);
710 
711  exprt ptrmember(ID_ptrmember);
712  ptrmember.set(ID_component_name, c.get_name());
713  ptrmember.operands().push_back(exprt("cpp-this"));
714 
715  code_assignt assign(ptrmember, address);
716  final_initializers.move_to_sub(assign);
717  continue;
718  }
719 
720  if(
721  c.get_bool(ID_from_base) || c.type().id() == ID_code ||
722  c.get_bool(ID_is_type) || c.get_bool(ID_is_static))
723  {
724  continue;
725  }
726 
727  const irep_idt &mem_name = c.get_base_name();
728 
729  // Check if the initialization list of the constructor
730  // explicitly initializes the data member
731  bool found=false;
732  Forall_irep(m_it, initializers.get_sub())
733  {
734  irept &initializer=*m_it;
735 
736  if(initializer.get(ID_member)!=ID_cpp_name)
737  continue;
738  cpp_namet &member_name=(cpp_namet&) initializer.add(ID_member);
739 
740  if(member_name.has_template_args())
741  continue; // base-type initializer
742 
743  irep_idt base_name=member_name.get_base_name();
744 
745  if(mem_name==base_name)
746  {
747  final_initializers.move_to_sub(initializer);
748  found=true;
749  break;
750  }
751  }
752 
753  // If the data member is a reference, it must be explicitly
754  // initialized
755  if(
756  !found && c.type().id() == ID_pointer &&
757  c.type().get_bool(ID_C_reference))
758  {
759  error().source_location = c.source_location();
760  error() << "reference must be explicitly initialized" << eom;
761  throw 0;
762  }
763 
764  // If the data member is not POD and is not explicitly initialized,
765  // then its default constructor is called.
766  if(!found && !cpp_is_pod(c.type()))
767  {
768  cpp_namet cppname(mem_name);
769 
770  codet mem_init(ID_member_initializer);
771  mem_init.set(ID_member, cppname);
772  final_initializers.move_to_sub(mem_init);
773  }
774  }
775 
776  initializers.swap(final_initializers);
777 }
778 
781 bool cpp_typecheckt::find_cpctor(const symbolt &symbol) const
782 {
783  for(const auto &component : to_struct_type(symbol.type).components())
784  {
785  // Skip non-ctor
786  if(component.type().id()!=ID_code ||
787  to_code_type(component.type()).return_type().id() !=ID_constructor)
788  continue;
789 
790  // Skip inherited constructor
791  if(component.get_bool(ID_from_base))
792  continue;
793 
794  const code_typet &code_type=to_code_type(component.type());
795 
796  const code_typet::parameterst &parameters=code_type.parameters();
797 
798  // First parameter is the 'this' pointer. Therefore, copy
799  // constructors have at least two parameters
800  if(parameters.size() < 2)
801  continue;
802 
803  const code_typet::parametert &parameter1=parameters[1];
804 
805  const typet &parameter1_type=parameter1.type();
806 
807  if(!is_reference(parameter1_type))
808  continue;
809 
810  if(parameter1_type.subtype().get(ID_identifier)!=symbol.name)
811  continue;
812 
813  bool defargs=true;
814  for(std::size_t i=2; i<parameters.size(); i++)
815  {
816  if(parameters[i].default_value().is_nil())
817  {
818  defargs=false;
819  break;
820  }
821  }
822 
823  if(defargs)
824  return true;
825  }
826 
827  return false;
828 }
829 
830 bool cpp_typecheckt::find_assignop(const symbolt &symbol) const
831 {
832  const struct_typet &struct_type=to_struct_type(symbol.type);
833  const struct_typet::componentst &components=struct_type.components();
834 
835  for(const auto &component : components)
836  {
837  if(component.get_base_name() != "operator=")
838  continue;
839 
840  if(component.get_bool(ID_is_static))
841  continue;
842 
843  if(component.get_bool(ID_from_base))
844  continue;
845 
846  const code_typet &code_type=to_code_type(component.type());
847 
848  const code_typet::parameterst &args=code_type.parameters();
849 
850  if(args.size()!=2)
851  continue;
852 
853  const code_typet::parametert &arg1=args[1];
854 
855  const typet &arg1_type=arg1.type();
856 
857  if(!is_reference(arg1_type))
858  continue;
859 
860  if(arg1_type.subtype().get(ID_identifier)!=symbol.name)
861  continue;
862 
863  return true;
864  }
865 
866  return false;
867 }
exprt::copy_to_operands
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition: expr.h:123
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:205
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:35
code_blockt
A codet representing sequential composition of program statements.
Definition: std_code.h:150
exprt::move_to_operands
void move_to_operands(exprt &expr)
Move the given argument to the end of exprt's operands.
Definition: expr.cpp:29
typet::subtype
const typet & subtype() const
Definition: type.h:38
arith_tools.h
source_locationt::set_function
void set_function(const irep_idt &function)
Definition: source_location.h:122
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:349
DATA_INVARIANT
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:485
irept::move_to_sub
void move_to_sub(irept &irep)
Definition: irep.cpp:203
already_typechecked
void already_typechecked(irept &irep)
Definition: cpp_util.h:18
irept::make_nil
void make_nil()
Definition: irep.h:315
typet
The type of an expression, extends irept.
Definition: type.h:27
code_typet::parameterst
std::vector< parametert > parameterst
Definition: std_types.h:754
struct_union_typet
Base type for structs and unions.
Definition: std_types.h:114
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
dereference_exprt
Operator to dereference a pointer.
Definition: std_expr.h:3355
mp_integer
BigInt mp_integer
Definition: mp_arith.h:22
irept::add
irept & add(const irep_namet &name)
Definition: irep.cpp:305
nil_typet
The NIL type, i.e., an invalid type, no value.
Definition: std_types.h:39
cpp_declaratort::name
cpp_namet & name()
Definition: cpp_declarator.h:36
irept::find
const irept & find(const irep_namet &name) const
Definition: irep.cpp:284
to_type_with_subtypes
const type_with_subtypest & to_type_with_subtypes(const typet &type)
Definition: type.h:206
cpp_typecheckt::default_assignop_value
void default_assignop_value(const symbolt &symbol, cpp_declaratort &declarator)
Generate code for the implicit default assignment operator.
Definition: cpp_typecheck_constructor.cpp:346
exprt
Base class for all expressions.
Definition: expr.h:54
struct_union_typet::componentst
std::vector< componentt > componentst
Definition: std_types.h:203
symbolt::base_name
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
exprt::op0
exprt & op0()
Definition: expr.h:84
component
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:173
messaget::eom
static eomt eom
Definition: message.h:284
symbol_typet::get_identifier
const irep_idt & get_identifier() const
Definition: std_types.h:75
index_type
bitvector_typet index_type()
Definition: c_types.cpp:16
Forall_irep
#define Forall_irep(it, irep)
Definition: irep.h:66
cpp_declarationt::declarators
const declaratorst & declarators() const
Definition: cpp_declaration.h:64
cpp_typecheckt::cpp_is_pod
bool cpp_is_pod(const typet &type) const
Definition: cpp_is_pod.cpp:14
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:68
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:166
cpp_typecheckt::typecheck_type
void typecheck_type(typet &) override
Definition: cpp_typecheck_type.cpp:23
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:173
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:982
cpp_typecheckt::default_ctor
void default_ctor(const source_locationt &source_location, const irep_idt &base_name, cpp_declarationt &ctor) const
Generate code for implicit default constructors.
Definition: cpp_typecheck_constructor.cpp:120
copy_parent
static void copy_parent(const source_locationt &source_location, const irep_idt &parent_base_name, const irep_idt &arg_name, exprt &block)
Generate code to copy the parent.
Definition: cpp_typecheck_constructor.cpp:27
messaget::error
mstreamt & error() const
Definition: message.h:386
empty_typet
The empty type.
Definition: std_types.h:48
cpp_typecheckt::get_virtual_bases
void get_virtual_bases(const struct_typet &type, std::list< irep_idt > &vbases) const
Definition: cpp_typecheck_compound_type.cpp:1655
cpp_util.h
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
messaget::mstreamt::source_location
source_locationt source_location
Definition: message.h:236
typet::source_location
const source_locationt & source_location() const
Definition: type.h:62
cpp_typecheckt::check_member_initializers
void check_member_initializers(const struct_typet::basest &bases, const struct_typet::componentst &components, const irept &initializers)
Check a constructor initialization-list.
Definition: cpp_typecheck_constructor.cpp:425
exprt::op1
exprt & op1()
Definition: expr.h:87
struct_typet::bases
const basest & bases() const
Get the collection of base classes/structs.
Definition: std_types.h:303
pointer_type
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:243
irept::swap
void swap(irept &irep)
Definition: irep.h:303
code_typet
Base type of functions.
Definition: std_types.h:751
cpp_declarationt
Definition: cpp_declaration.h:23
irept::id
const irep_idt & id() const
Definition: irep.h:259
struct_typet::basest
std::vector< baset > basest
Definition: std_types.h:300
copy_array
static void copy_array(const source_locationt &source_location, const irep_idt &member_base_name, mp_integer i, const irep_idt &arg_name, exprt &block)
Generate code to copy the member.
Definition: cpp_typecheck_constructor.cpp:88
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:893
typet::add_source_location
source_locationt & add_source_location()
Definition: type.h:67
std_code.h
cpp_typecheck.h
to_symbol_type
const symbol_typet & to_symbol_type(const typet &type)
Cast a typet to a symbol_typet.
Definition: std_types.h:98
source_locationt
Definition: source_location.h:20
cpp_typecheckt::full_member_initialization
void full_member_initialization(const struct_union_typet &struct_union_type, irept &initializers)
Build the full initialization list of the constructor.
Definition: cpp_typecheck_constructor.cpp:551
copy_member
static void copy_member(const source_locationt &source_location, const irep_idt &member_base_name, const irep_idt &arg_name, exprt &block)
Generate code to copy the member.
Definition: cpp_typecheck_constructor.cpp:58
reference_type
reference_typet reference_type(const typet &subtype)
Definition: c_types.cpp:248
forall_irep
#define forall_irep(it, irep)
Definition: irep.h:62
cpp_namet::has_template_args
bool has_template_args() const
Definition: cpp_name.h:122
struct_typet
Structure type, corresponds to C style structs.
Definition: std_types.h:276
is_reference
bool is_reference(const typet &type)
Returns true if the type is a reference.
Definition: std_types.cpp:132
irept::get
const irep_idt & get(const irep_namet &name) const
Definition: irep.cpp:212
symbolt
Symbol table entry.
Definition: symbol.h:27
irept::set
void set(const irep_namet &name, const irep_idt &value)
Definition: irep.h:286
cpp_namet::as_expr
const exprt & as_expr() const
Definition: cpp_name.h:133
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:123
c_typecheck_baset::return_type
typet return_type
Definition: c_typecheck_base.h:152
irept::get_sub
subt & get_sub()
Definition: irep.h:317
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:1048
code_typet::parametert
Definition: std_types.h:788
cpp_declaratort::value
exprt & value()
Definition: cpp_declarator.h:42
irept
Base class for tree-like data structures with sharing.
Definition: irep.h:156
cpp_typecheckt::find_assignop
bool find_assignop(const symbolt &symbol) const
Definition: cpp_typecheck_constructor.cpp:830
exprt::operands
operandst & operands()
Definition: expr.h:78
index_exprt
Array index operator.
Definition: std_expr.h:1595
address_of_exprt
Operator to return the address of an object.
Definition: std_expr.h:3255
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:233
code_assignt
A codet representing an assignment in the program.
Definition: std_code.h:256
cpp_namet::get_base_name
irep_idt get_base_name() const
Definition: cpp_name.cpp:17
cpp_typecheckt::find_cpctor
bool find_cpctor(const symbolt &symbol) const
Definition: cpp_typecheck_constructor.cpp:781
cpp_typecheckt::default_assignop
void default_assignop(const symbolt &symbol, cpp_declarationt &cpctor)
Generate declaration of the implicit default assignment operator.
Definition: cpp_typecheck_constructor.cpp:280
cpp_typecheckt::default_cpctor
void default_cpctor(const symbolt &, cpp_declarationt &cpctor) const
Generate code for implicit default copy constructor.
Definition: cpp_typecheck_constructor.cpp:144
std_expr.h
cpp_namet
Definition: cpp_name.h:16
exprt::source_location
const source_locationt & source_location() const
Definition: expr.h:228
c_types.h
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
cpp_declaratort
Definition: cpp_declarator.h:19
side_effect_exprt
An expression containing a side effect.
Definition: std_code.h:1560
to_cpp_name
cpp_namet & to_cpp_name(irept &cpp_name)
Definition: cpp_name.h:144
code_expressiont
codet representation of an expression statement.
Definition: std_code.h:1504
cpp_namet::as_type
const typet & as_type() const
Definition: cpp_name.h:138
codet
Data structure for representing an arbitrary statement in a program.
Definition: std_code.h:34
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:470