CBMC
cpp_typecheck_resolve.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_resolve.h"
13 
14 #ifdef DEBUG
15 #include <iostream>
16 #endif
17 
18 #include <algorithm>
19 
20 #include <util/arith_tools.h>
21 #include <util/c_types.h>
23 #include <util/prefix.h>
24 #include <util/simplify_expr.h>
25 #include <util/std_expr.h>
26 #include <util/string_constant.h>
27 
29 #include <ansi-c/merged_type.h>
30 
31 #include "cpp_convert_type.h"
32 #include "cpp_type2name.h"
33 #include "cpp_typecheck.h"
34 #include "cpp_typecheck_fargs.h"
35 #include "cpp_util.h"
36 
38  cpp_typecheck(_cpp_typecheck),
39  original_scope(nullptr) // set in resolve_scope()
40 {
41 }
42 
44  const cpp_scopest::id_sett &id_set,
45  const cpp_typecheck_fargst &fargs,
46  resolve_identifierst &identifiers)
47 {
48  for(const auto &id_ptr : id_set)
49  {
50  const cpp_idt &identifier = *id_ptr;
51  exprt e=convert_identifier(identifier, fargs);
52 
53  if(e.is_not_nil())
54  {
55  if(e.id()==ID_type)
56  assert(e.type().is_not_nil());
57 
58  identifiers.push_back(e);
59  }
60  }
61 }
62 
64  resolve_identifierst &identifiers,
65  const cpp_template_args_non_tct &template_args,
66  const cpp_typecheck_fargst &fargs)
67 {
68  resolve_identifierst old_identifiers;
69  old_identifiers.swap(identifiers);
70 
71  for(const auto &old_id : old_identifiers)
72  {
73  exprt e = old_id;
74  apply_template_args(e, template_args, fargs);
75 
76  if(e.is_not_nil())
77  {
78  if(e.id()==ID_type)
79  assert(e.type().is_not_nil());
80 
81  identifiers.push_back(e);
82  }
83  }
84 }
85 
88  resolve_identifierst &identifiers,
89  const cpp_typecheck_fargst &fargs)
90 {
91  resolve_identifierst old_identifiers;
92  old_identifiers.swap(identifiers);
93 
94  for(const auto &old_id : old_identifiers)
95  {
96  exprt e = guess_function_template_args(old_id, fargs);
97 
98  if(e.is_not_nil())
99  {
100  assert(e.id()!=ID_type);
101  identifiers.push_back(e);
102  }
103  }
104 
105  disambiguate_functions(identifiers, fargs);
106 
107  // there should only be one left, or we have failed to disambiguate
108  if(identifiers.size()==1)
109  {
110  // instantiate that one
111  exprt e=*identifiers.begin();
112  assert(e.id()==ID_template_function_instance);
113 
114  const symbolt &template_symbol=
115  cpp_typecheck.lookup(e.type().get(ID_C_template));
116 
117  const cpp_template_args_tct &template_args=
118  to_cpp_template_args_tc(e.type().find(ID_C_template_arguments));
119 
120  // Let's build the instance.
121 
122  const symbolt &new_symbol=
125  template_symbol,
126  template_args,
127  template_args);
128 
129  identifiers.clear();
130  identifiers.push_back(
131  symbol_exprt(new_symbol.name, new_symbol.type));
132  }
133 }
134 
136  resolve_identifierst &identifiers)
137 {
138  resolve_identifierst old_identifiers;
139  old_identifiers.swap(identifiers);
140 
141  for(const auto &old_id : old_identifiers)
142  {
143  if(!cpp_typecheck.follow(old_id.type()).get_bool(ID_is_template))
144  identifiers.push_back(old_id);
145  }
146 }
147 
149  resolve_identifierst &identifiers)
150 {
151  resolve_identifierst old_identifiers;
152  old_identifiers.swap(identifiers);
153 
154  std::set<irep_idt> ids;
155  std::set<exprt> other;
156 
157  for(const auto &old_id : old_identifiers)
158  {
159  irep_idt id;
160 
161  if(old_id.id() == ID_symbol)
162  id = to_symbol_expr(old_id).get_identifier();
163  else if(old_id.id() == ID_type && old_id.type().id() == ID_struct_tag)
164  id = to_struct_tag_type(old_id.type()).get_identifier();
165  else if(old_id.id() == ID_type && old_id.type().id() == ID_union_tag)
166  id = to_union_tag_type(old_id.type()).get_identifier();
167 
168  if(id.empty())
169  {
170  if(other.insert(old_id).second)
171  identifiers.push_back(old_id);
172  }
173  else
174  {
175  if(ids.insert(id).second)
176  identifiers.push_back(old_id);
177  }
178  }
179 }
180 
182  const cpp_idt &identifier)
183 {
184 #ifdef DEBUG
185  std::cout << "RESOLVE MAP:\n";
186  cpp_typecheck.template_map.print(std::cout);
187 #endif
188 
189  // look up the parameter in the template map
191 
192  if(e.is_nil() ||
193  (e.id()==ID_type && e.type().is_nil()))
194  {
196  cpp_typecheck.error() << "internal error: template parameter "
197  << "without instance:\n"
198  << identifier << messaget::eom;
199  throw 0;
200  }
201 
203 
204  return e;
205 }
206 
208  const cpp_idt &identifier,
209  const cpp_typecheck_fargst &fargs)
210 {
212  return convert_template_parameter(identifier);
213 
214  exprt e;
215 
216  if(identifier.is_member &&
217  !identifier.is_constructor &&
218  !identifier.is_static_member)
219  {
220  // a regular struct or union member
221 
222  const symbolt &compound_symbol=
224 
225  assert(compound_symbol.type.id()==ID_struct ||
226  compound_symbol.type.id()==ID_union);
227 
228  const struct_union_typet &struct_union_type=
229  to_struct_union_type(compound_symbol.type);
230 
231  const exprt &component =
232  struct_union_type.get_component(identifier.identifier);
233 
234  const typet &type=component.type();
235  assert(type.is_not_nil());
236 
238  {
239  e=type_exprt(type);
240  }
241  else if(identifier.id_class==cpp_scopet::id_classt::SYMBOL)
242  {
243  // A non-static, non-type member.
244  // There has to be an object.
245  e=exprt(ID_member);
246  e.set(ID_component_name, identifier.identifier);
248 
249  exprt object;
250  object.make_nil();
251 
252  #if 0
253  std::cout << "I: " << identifier.class_identifier
254  << " "
256  this_class_identifier << '\n';
257  #endif
258 
259  const exprt &this_expr=
261 
262  if(fargs.has_object)
263  {
264  // the object is given to us in fargs
265  assert(!fargs.operands.empty());
266  object=fargs.operands.front();
267  }
268  else if(this_expr.is_not_nil())
269  {
270  // use this->...
271  assert(this_expr.type().id()==ID_pointer);
272  object =
273  exprt(ID_dereference, to_pointer_type(this_expr.type()).base_type());
274  object.copy_to_operands(this_expr);
275  object.type().set(
276  ID_C_constant,
277  to_pointer_type(this_expr.type())
278  .base_type()
279  .get_bool(ID_C_constant));
280  object.set(ID_C_lvalue, true);
281  object.add_source_location()=source_location;
282  }
283 
284  // check if the member can be applied to the object
285  typet object_type=cpp_typecheck.follow(object.type());
286 
287  if(object_type.id()==ID_struct ||
288  object_type.id()==ID_union)
289  {
290  if(!has_component_rec(
291  to_struct_union_type(object_type),
292  identifier.identifier,
293  cpp_typecheck))
294  object.make_nil(); // failed!
295  }
296  else
297  object.make_nil();
298 
299  if(object.is_not_nil())
300  {
301  // we got an object
302  e.add_to_operands(std::move(object));
303 
304  bool old_value=cpp_typecheck.disable_access_control;
308  }
309  else
310  {
311  // this has to be a method or form a pointer-to-member expression
312  if(identifier.is_method)
314  else
315  {
316  e.id(ID_ptrmember);
318  exprt("cpp-this", pointer_type(compound_symbol.type)));
319  e.type() = type;
320  }
321  }
322  }
323  }
324  else
325  {
326  const symbolt &symbol=
327  cpp_typecheck.lookup(identifier.identifier);
328 
329  if(symbol.is_type)
330  {
331  e.make_nil();
332 
333  if(symbol.is_macro) // includes typedefs
334  {
335  e = type_exprt(symbol.type);
336  assert(symbol.type.is_not_nil());
337  }
338  else if(symbol.type.id()==ID_c_enum)
339  {
340  e = type_exprt(c_enum_tag_typet(symbol.name));
341  }
342  else if(symbol.type.id() == ID_struct)
343  {
344  e = type_exprt(struct_tag_typet(symbol.name));
345  }
346  else if(symbol.type.id() == ID_union)
347  {
348  e = type_exprt(union_tag_typet(symbol.name));
349  }
350  }
351  else if(symbol.is_macro)
352  {
353  e=symbol.value;
354  assert(e.is_not_nil());
355  }
356  else
357  {
358  bool constant = symbol.type.get_bool(ID_C_constant);
359 
360  if(
361  constant && symbol.value.is_not_nil() && is_number(symbol.type) &&
362  symbol.value.id() == ID_constant)
363  {
364  e=symbol.value;
365  }
366  else
367  {
368  e=cpp_symbol_expr(symbol);
369  }
370  }
371  }
372 
374 
375  return e;
376 }
377 
379  resolve_identifierst &identifiers,
380  const wantt want)
381 {
382  resolve_identifierst old_identifiers;
383  old_identifiers.swap(identifiers);
384 
385  for(const auto &old_id : old_identifiers)
386  {
387  bool match=false;
388 
389  switch(want)
390  {
391  case wantt::TYPE:
392  match = (old_id.id() == ID_type);
393  break;
394 
395  case wantt::VAR:
396  match = (old_id.id() != ID_type);
397  break;
398 
399  case wantt::BOTH:
400  match=true;
401  break;
402 
403  default:
404  UNREACHABLE;
405  }
406 
407  if(match)
408  identifiers.push_back(old_id);
409  }
410 }
411 
413  resolve_identifierst &identifiers,
414  const cpp_typecheck_fargst &fargs)
415 {
416  if(!fargs.in_use)
417  return;
418 
419  resolve_identifierst old_identifiers;
420  old_identifiers.swap(identifiers);
421 
422  identifiers.clear();
423 
424  // put in the ones that match precisely
425  for(const auto &old_id : old_identifiers)
426  {
427  unsigned distance;
428  if(disambiguate_functions(old_id, distance, fargs))
429  if(distance<=0)
430  identifiers.push_back(old_id);
431  }
432 }
433 
435  resolve_identifierst &identifiers,
436  const cpp_typecheck_fargst &fargs)
437 {
438  resolve_identifierst old_identifiers;
439  old_identifiers.swap(identifiers);
440 
441  // sort according to distance
442  std::multimap<std::size_t, exprt> distance_map;
443 
444  for(const auto &old_id : old_identifiers)
445  {
446  unsigned args_distance;
447 
448  if(disambiguate_functions(old_id, args_distance, fargs))
449  {
450  std::size_t template_distance=0;
451 
452  if(!old_id.type().get(ID_C_template).empty())
453  template_distance = old_id.type()
454  .find(ID_C_template_arguments)
455  .find(ID_arguments)
456  .get_sub()
457  .size();
458 
459  // we give strong preference to functions that have
460  // fewer template arguments
461  std::size_t total_distance=
462  // NOLINTNEXTLINE(whitespace/operators)
463  1000*template_distance+args_distance;
464 
465  distance_map.insert({total_distance, old_id});
466  }
467  }
468 
469  old_identifiers.clear();
470 
471  // put in the top ones
472  if(!distance_map.empty())
473  {
474  auto range = distance_map.equal_range(distance_map.begin()->first);
475  for(auto it = range.first; it != range.second; ++it)
476  old_identifiers.push_back(it->second);
477  }
478 
479  if(old_identifiers.size() > 1 && fargs.in_use)
480  {
481  // try to further disambiguate functions
482 
483  for(resolve_identifierst::const_iterator old_it = old_identifiers.begin();
484  old_it != old_identifiers.end();
485  ++old_it)
486  {
487 #if 0
488  std::cout << "I1: " << old_it->get(ID_identifier) << '\n';
489 #endif
490 
491  if(old_it->type().id() != ID_code)
492  {
493  identifiers.push_back(*old_it);
494  continue;
495  }
496 
497  const code_typet &f1 = to_code_type(old_it->type());
498 
499  for(resolve_identifierst::const_iterator resolve_it = old_it + 1;
500  resolve_it != old_identifiers.end();
501  ++resolve_it)
502  {
503  if(resolve_it->type().id() != ID_code)
504  continue;
505 
506  const code_typet &f2 = to_code_type(resolve_it->type());
507 
508  // TODO: may fail when using ellipsis
509  assert(f1.parameters().size() == f2.parameters().size());
510 
511  bool f1_better=true;
512  bool f2_better=true;
513 
514  for(std::size_t i=0;
515  i<f1.parameters().size() && (f1_better || f2_better);
516  i++)
517  {
518  typet type1=f1.parameters()[i].type();
519  typet type2=f2.parameters()[i].type();
520 
521  if(type1 == type2)
522  continue;
523 
524  if(is_reference(type1) != is_reference(type2))
525  continue;
526 
527  if(type1.id()==ID_pointer)
528  {
529  typet tmp = to_pointer_type(type1).base_type();
530  type1=tmp;
531  }
532 
533  if(type2.id()==ID_pointer)
534  {
535  typet tmp = to_pointer_type(type2).base_type();
536  type2=tmp;
537  }
538 
539  const typet &followed1=cpp_typecheck.follow(type1);
540  const typet &followed2=cpp_typecheck.follow(type2);
541 
542  if(followed1.id() != ID_struct || followed2.id() != ID_struct)
543  continue;
544 
545  const struct_typet &struct1=to_struct_type(followed1);
546  const struct_typet &struct2=to_struct_type(followed2);
547 
548  if(f1_better && cpp_typecheck.subtype_typecast(struct1, struct2))
549  {
550  f2_better=false;
551  }
552  else if(f2_better && cpp_typecheck.subtype_typecast(struct2, struct1))
553  {
554  f1_better=false;
555  }
556  }
557 
558  if(!f1_better || f2_better)
559  identifiers.push_back(*resolve_it);
560  }
561  }
562  }
563  else
564  {
565  identifiers.swap(old_identifiers);
566  }
567 
568  remove_duplicates(identifiers);
569 }
570 
572  resolve_identifierst &identifiers)
573 {
574  resolve_identifierst new_identifiers;
575 
576  for(const auto &identifier : identifiers)
577  {
578  if(identifier.id() != ID_type)
579  {
580  // already an expression
581  new_identifiers.push_back(identifier);
582  continue;
583  }
584 
585  const typet &symbol_type = cpp_typecheck.follow(identifier.type());
586 
587  // is it a POD?
588 
589  if(cpp_typecheck.cpp_is_pod(symbol_type))
590  {
591  // there are two pod constructors:
592 
593  // 1. no arguments, default initialization
594  {
595  const code_typet t1({}, identifier.type());
596  exprt pod_constructor1(ID_pod_constructor, t1);
597  new_identifiers.push_back(pod_constructor1);
598  }
599 
600  // 2. one argument, copy/conversion
601  {
602  const code_typet t2(
603  {code_typet::parametert(identifier.type())}, identifier.type());
604  exprt pod_constructor2(ID_pod_constructor, t2);
605  new_identifiers.push_back(pod_constructor2);
606  }
607 
608  // enums, in addition, can also be constructed from int
609  if(symbol_type.id()==ID_c_enum_tag)
610  {
611  const code_typet t3(
612  {code_typet::parametert(signed_int_type())}, identifier.type());
613  exprt pod_constructor3(ID_pod_constructor, t3);
614  new_identifiers.push_back(pod_constructor3);
615  }
616  }
617  else if(symbol_type.id()==ID_struct)
618  {
619  const struct_typet &struct_type=to_struct_type(symbol_type);
620 
621  // go over components
622  for(const auto &component : struct_type.components())
623  {
624  const typet &type=component.type();
625 
626  if(component.get_bool(ID_from_base))
627  continue;
628 
629  if(
630  type.id() == ID_code &&
631  to_code_type(type).return_type().id() == ID_constructor)
632  {
633  const symbolt &symb =
634  cpp_typecheck.lookup(component.get_name());
635  exprt e=cpp_symbol_expr(symb);
636  e.type()=type;
637  new_identifiers.push_back(e);
638  }
639  }
640  }
641  }
642 
643  identifiers.swap(new_identifiers);
644 }
645 
647  exprt &argument,
648  const cpp_typecheck_fargst &fargs)
649 {
650  if(argument.id() == ID_ambiguous) // could come from a template parameter
651  {
652  // this must be resolved in the template scope
655 
656  argument = resolve(to_cpp_name(argument.type()), wantt::VAR, fargs, false);
657  }
658 }
659 
661  const irep_idt &base_name,
662  const cpp_typecheck_fargst &fargs,
663  const cpp_template_args_non_tct &template_args)
664 {
665  exprt dest;
666 
667  const cpp_template_args_non_tct::argumentst &arguments=
668  template_args.arguments();
669 
670  if(base_name==ID_unsignedbv ||
671  base_name==ID_signedbv)
672  {
673  if(arguments.size()!=1)
674  {
677  << base_name << " expects one template argument, but got "
678  << arguments.size() << messaget::eom;
679  throw 0;
680  }
681 
682  exprt argument=arguments.front(); // copy
683 
684  if(argument.id()==ID_type)
685  {
688  << base_name << " expects one integer template argument, "
689  << "but got type" << messaget::eom;
690  throw 0;
691  }
692 
693  resolve_argument(argument, fargs);
694 
695  const auto i = numeric_cast<mp_integer>(argument);
696  if(!i.has_value())
697  {
699  cpp_typecheck.error() << "template argument must be constant"
700  << messaget::eom;
701  throw 0;
702  }
703 
704  if(*i < 1)
705  {
708  << "template argument must be greater than zero"
709  << messaget::eom;
710  throw 0;
711  }
712 
713  dest=type_exprt(typet(base_name));
714  dest.type().set(ID_width, integer2string(*i));
715  }
716  else if(base_name==ID_fixedbv)
717  {
718  if(arguments.size()!=2)
719  {
722  << base_name << " expects two template arguments, but got "
723  << arguments.size() << messaget::eom;
724  throw 0;
725  }
726 
727  exprt argument0=arguments[0];
728  resolve_argument(argument0, fargs);
729  exprt argument1=arguments[1];
730  resolve_argument(argument1, fargs);
731 
732  if(argument0.id()==ID_type)
733  {
736  << base_name << " expects two integer template arguments, "
737  << "but got type" << messaget::eom;
738  throw 0;
739  }
740 
741  if(argument1.id()==ID_type)
742  {
745  << base_name << " expects two integer template arguments, "
746  << "but got type" << messaget::eom;
747  throw 0;
748  }
749 
750  const auto width = numeric_cast<mp_integer>(argument0);
751 
752  if(!width.has_value())
753  {
755  cpp_typecheck.error() << "template argument must be constant"
756  << messaget::eom;
757  throw 0;
758  }
759 
760  const auto integer_bits = numeric_cast<mp_integer>(argument1);
761 
762  if(!integer_bits.has_value())
763  {
765  cpp_typecheck.error() << "template argument must be constant"
766  << messaget::eom;
767  throw 0;
768  }
769 
770  if(*width < 1)
771  {
774  << "template argument must be greater than zero"
775  << messaget::eom;
776  throw 0;
777  }
778 
779  if(*integer_bits < 0)
780  {
783  << "template argument must be greater or equal zero"
784  << messaget::eom;
785  throw 0;
786  }
787 
788  if(*integer_bits > *width)
789  {
792  << "template argument must be smaller or equal width"
793  << messaget::eom;
794  throw 0;
795  }
796 
797  dest=type_exprt(typet(base_name));
798  dest.type().set(ID_width, integer2string(*width));
799  dest.type().set(ID_integer_bits, integer2string(*integer_bits));
800  }
801  else if(base_name==ID_integer)
802  {
803  if(!arguments.empty())
804  {
807  << base_name << " expects no template arguments"
808  << messaget::eom;
809  throw 0;
810  }
811 
812  dest=type_exprt(typet(base_name));
813  }
814  else if(has_prefix(id2string(base_name), "constant_infinity"))
815  {
816  // ok, but type missing
817  dest=exprt(ID_infinity, size_type());
818  }
819  else if(base_name=="dump_scopes")
820  {
821  dest=exprt(ID_constant, typet(ID_empty));
822  cpp_typecheck.warning() << "Scopes in location "
826  }
827  else if(base_name=="current_scope")
828  {
829  dest=exprt(ID_constant, typet(ID_empty));
830  cpp_typecheck.warning() << "Scope in location " << source_location
831  << ": " << original_scope->prefix
832  << messaget::eom;
833  }
834  else if(base_name == ID_size_t)
835  {
836  dest=type_exprt(size_type());
837  }
838  else if(base_name == ID_ssize_t)
839  {
841  }
842  else
843  {
845  cpp_typecheck.error() << "unknown built-in identifier: "
846  << base_name << messaget::eom;
847  throw 0;
848  }
849 
850  return dest;
851 }
852 
857  const cpp_namet &cpp_name,
858  irep_idt &base_name,
859  cpp_template_args_non_tct &template_args)
860 {
861  assert(!cpp_name.get_sub().empty());
862 
864  source_location=cpp_name.source_location();
865 
866  irept::subt::const_iterator pos=cpp_name.get_sub().begin();
867 
868  bool recursive=true;
869 
870  // check if we need to go to the root scope
871  if(pos->id()=="::")
872  {
873  pos++;
875  recursive=false;
876  }
877 
878  std::string final_base_name;
879  template_args.make_nil();
880 
881  while(pos!=cpp_name.get_sub().end())
882  {
883  if(pos->id()==ID_name)
884  final_base_name+=pos->get_string(ID_identifier);
885  else if(pos->id()==ID_template_args)
886  template_args=to_cpp_template_args_non_tc(*pos);
887  else if(pos->id()=="::")
888  {
889  if(template_args.is_not_nil())
890  {
891  const auto id_set = cpp_typecheck.cpp_scopes.current_scope().lookup(
892  final_base_name,
895 
896 #ifdef DEBUG
897  std::cout << "S: "
899  << '\n';
901  std::cout << "X: " << id_set.size() << '\n';
902 #endif
903  struct_tag_typet instance =
904  disambiguate_template_classes(final_base_name, id_set, template_args);
905 
907 
908  // the "::" triggers template elaboration
910 
913 
914  template_args.make_nil();
915  }
916  else
917  {
919  final_base_name,
921 
922  filter_for_named_scopes(id_set);
923 
924  if(id_set.empty())
925  {
929  << "scope '" << final_base_name << "' not found" << messaget::eom;
930  throw 0;
931  }
932  else if(id_set.size()>=2)
933  {
936  cpp_typecheck.error() << "scope '" << final_base_name
937  << "' is ambiguous" << messaget::eom;
938  throw 0;
939  }
940 
941  assert(id_set.size()==1);
942 
943  cpp_typecheck.cpp_scopes.go_to(**id_set.begin());
944 
945  // the "::" triggers template elaboration
947  {
948  struct_tag_typet instance(
951  }
952  }
953 
954  // we start from fresh
955  final_base_name.clear();
956  }
957  else if(pos->id()==ID_operator)
958  {
959  final_base_name+="operator";
960 
961  irept::subt::const_iterator next=pos+1;
962  assert(next != cpp_name.get_sub().end());
963 
964  if(
965  next->id() == ID_cpp_name || next->id() == ID_pointer ||
966  next->id() == ID_int || next->id() == ID_char ||
967  next->id() == ID_c_bool || next->id() == ID_merged_type)
968  {
969  // it's a cast operator
970  irept next_ir=*next;
971  typet op_name;
972  op_name.swap(next_ir);
973  cpp_typecheck.typecheck_type(op_name);
974  final_base_name+="("+cpp_type2name(op_name)+")";
975  pos++;
976  }
977  }
978  else
979  final_base_name+=pos->id_string();
980 
981  pos++;
982  }
983 
984  base_name=final_base_name;
985 
987 }
988 
991  const irep_idt &base_name,
992  const cpp_scopest::id_sett &id_set,
993  const cpp_template_args_non_tct &full_template_args)
994 {
995  if(id_set.empty())
996  {
999  cpp_typecheck.error() << "template scope '" << base_name << "' not found"
1000  << messaget::eom;
1001  throw 0;
1002  }
1003 
1004  std::set<irep_idt> primary_templates;
1005 
1006  for(const auto &id_ptr : id_set)
1007  {
1008  const irep_idt id = id_ptr->identifier;
1009  const symbolt &s=cpp_typecheck.lookup(id);
1010  if(!s.type.get_bool(ID_is_template))
1011  continue;
1012  const cpp_declarationt &cpp_declaration=to_cpp_declaration(s.type);
1013  if(!cpp_declaration.is_class_template())
1014  continue;
1015  irep_idt specialization_of=cpp_declaration.get_specialization_of();
1016  if(!specialization_of.empty())
1017  primary_templates.insert(specialization_of);
1018  else
1019  primary_templates.insert(id);
1020  }
1021 
1022  assert(!primary_templates.empty());
1023 
1024  if(primary_templates.size()>=2)
1025  {
1028  cpp_typecheck.error() << "template scope '" << base_name << "' is ambiguous"
1029  << messaget::eom;
1030  throw 0;
1031  }
1032 
1033  const symbolt &primary_template_symbol=
1034  cpp_typecheck.lookup(*primary_templates.begin());
1035 
1036  // We typecheck the template arguments in the context
1037  // of the original scope!
1038  cpp_template_args_tct full_template_args_tc;
1039 
1040  {
1042 
1044 
1045  // use template type of 'primary template'
1046  full_template_args_tc=
1049  primary_template_symbol,
1050  full_template_args);
1051 
1052  for(auto &arg : full_template_args_tc.arguments())
1053  {
1054  if(arg.id() == ID_type)
1055  continue;
1056  if(arg.id() == ID_symbol)
1057  {
1058  const symbol_exprt &s = to_symbol_expr(arg);
1059  const symbolt &symbol = cpp_typecheck.lookup(s.get_identifier());
1060 
1061  if(
1062  cpp_typecheck.cpp_is_pod(symbol.type) &&
1063  symbol.type.get_bool(ID_C_constant))
1064  {
1065  arg = symbol.value;
1066  }
1067  }
1068  simplify(arg, cpp_typecheck);
1069  }
1070 
1071  // go back to where we used to be
1072  }
1073 
1074  // find any matches
1075 
1076  std::vector<matcht> matches;
1077 
1078  // the baseline
1079  matches.push_back(
1080  matcht(full_template_args_tc, full_template_args_tc,
1081  primary_template_symbol.name));
1082 
1083  for(const auto &id_ptr : id_set)
1084  {
1085  const irep_idt id = id_ptr->identifier;
1086  const symbolt &s=cpp_typecheck.lookup(id);
1087 
1088  if(s.type.get(ID_specialization_of).empty())
1089  continue;
1090 
1091  const cpp_declarationt &cpp_declaration=
1093 
1094  const cpp_template_args_non_tct &partial_specialization_args=
1095  cpp_declaration.partial_specialization_args();
1096 
1097  // alright, set up template arguments as 'unassigned'
1098 
1101 
1103  cpp_declaration.template_type());
1104 
1105  // iterate over template instance
1106  assert(full_template_args_tc.arguments().size()==
1107  partial_specialization_args.arguments().size());
1108 
1109  // we need to do this in the right scope
1110 
1111  cpp_scopet *template_scope=
1112  static_cast<cpp_scopet *>(
1114 
1115  if(template_scope==nullptr)
1116  {
1118  cpp_typecheck.error() << "template identifier: " << id << '\n'
1119  << "class template instantiation error"
1120  << messaget::eom;
1121  throw 0;
1122  }
1123 
1124  // enter the scope of the template
1125  cpp_typecheck.cpp_scopes.go_to(*template_scope);
1126 
1127  for(std::size_t i=0; i<full_template_args_tc.arguments().size(); i++)
1128  {
1129  if(full_template_args_tc.arguments()[i].id()==ID_type)
1130  guess_template_args(partial_specialization_args.arguments()[i].type(),
1131  full_template_args_tc.arguments()[i].type());
1132  else
1133  guess_template_args(partial_specialization_args.arguments()[i],
1134  full_template_args_tc.arguments()[i]);
1135  }
1136 
1137  // see if that has worked out
1138 
1139  cpp_template_args_tct guessed_template_args=
1141  cpp_declaration.template_type());
1142 
1143  if(!guessed_template_args.has_unassigned())
1144  {
1145  // check: we can now typecheck the partial_specialization_args
1146 
1147  cpp_template_args_tct partial_specialization_args_tc=
1150  primary_template_symbol,
1151  partial_specialization_args);
1152 
1153  // if these match the arguments, we have a match
1154 
1155  assert(partial_specialization_args_tc.arguments().size()==
1156  full_template_args_tc.arguments().size());
1157 
1158  if(partial_specialization_args_tc==
1159  full_template_args_tc)
1160  {
1161  matches.push_back(matcht(
1162  guessed_template_args, full_template_args_tc, id));
1163  }
1164  }
1165  }
1166 
1167  assert(!matches.empty());
1168 
1169  std::sort(matches.begin(), matches.end());
1170 
1171  #if 0
1172  for(std::vector<matcht>::const_iterator
1173  m_it=matches.begin();
1174  m_it!=matches.end();
1175  m_it++)
1176  {
1177  std::cout << "M: " << m_it->cost
1178  << " " << m_it->id << '\n';
1179  }
1180 
1181  std::cout << '\n';
1182  #endif
1183 
1184  const matcht &match=*matches.begin();
1185 
1186  const symbolt &choice=
1187  cpp_typecheck.lookup(match.id);
1188 
1189  #if 0
1190  // build instance
1191  const symbolt &instance=
1194  choice,
1195  match.specialization_args,
1196  match.full_args);
1197 
1198  if(instance.type.id()!=ID_struct)
1199  {
1201  cpp_typecheck.error() << "template '"
1202  << base_name << "' is not a class" << messaget::eom;
1203  throw 0;
1204  }
1205 
1206  struct_tag_typet result(instance.name);
1208 
1209  return result;
1210  #else
1211 
1212  // build instance
1213  const symbolt &instance=
1216  choice,
1217  match.specialization_args,
1218  match.full_args);
1219 
1220  struct_tag_typet result(instance.name);
1222 
1223  return result;
1224  #endif
1225 }
1226 
1228  const cpp_namet &cpp_name)
1229 {
1230  irep_idt base_name;
1231  cpp_template_args_non_tct template_args;
1232  template_args.make_nil();
1233 
1235  resolve_scope(cpp_name, base_name, template_args);
1236 
1237  bool qualified=cpp_name.is_qualified();
1238 
1239  auto id_set = cpp_typecheck.cpp_scopes.current_scope().lookup(
1240  base_name, qualified ? cpp_scopet::QUALIFIED : cpp_scopet::RECURSIVE);
1241 
1242  filter_for_namespaces(id_set);
1243 
1244  if(id_set.empty())
1245  {
1247  cpp_typecheck.error() << "namespace '" << base_name << "' not found"
1248  << messaget::eom;
1249  throw 0;
1250  }
1251  else if(id_set.size()==1)
1252  {
1253  cpp_idt &id=**id_set.begin();
1254  return (cpp_scopet &)id;
1255  }
1256  else
1257  {
1259  cpp_typecheck.error() << "namespace '" << base_name << "' is ambiguous"
1260  << messaget::eom;
1261  throw 0;
1262  }
1263 }
1264 
1266  const irep_idt &base_name,
1267  const resolve_identifierst &identifiers,
1268  std::ostream &out)
1269 {
1270  for(const auto &id_expr : identifiers)
1271  {
1272  out << " ";
1273 
1274  if(id_expr.id()==ID_type)
1275  {
1276  out << "type " << cpp_typecheck.to_string(id_expr.type());
1277  }
1278  else
1279  {
1280  irep_idt id;
1281 
1282  if(id_expr.type().get_bool(ID_is_template))
1283  out << "template ";
1284 
1285  if(id_expr.id()==ID_member)
1286  {
1287  out << "member ";
1288  id="."+id2string(base_name);
1289  }
1290  else if(id_expr.id() == ID_pod_constructor)
1291  {
1292  out << "constructor ";
1293  id.clear();
1294  }
1295  else if(id_expr.id()==ID_template_function_instance)
1296  {
1297  out << "symbol ";
1298  }
1299  else
1300  {
1301  out << "symbol ";
1302  id=cpp_typecheck.to_string(id_expr);
1303  }
1304 
1305  if(id_expr.type().get_bool(ID_is_template))
1306  {
1307  }
1308  else if(id_expr.type().id()==ID_code)
1309  {
1310  const code_typet &code_type=to_code_type(id_expr.type());
1311  const typet &return_type=code_type.return_type();
1312  const code_typet::parameterst &parameters=code_type.parameters();
1313  out << cpp_typecheck.to_string(return_type);
1314  out << " " << id << "(";
1315 
1316  bool first = true;
1317 
1318  for(const auto &parameter : parameters)
1319  {
1320  const typet &parameter_type = parameter.type();
1321 
1322  if(first)
1323  first = false;
1324  else
1325  out << ", ";
1326 
1327  out << cpp_typecheck.to_string(parameter_type);
1328  }
1329 
1330  if(code_type.has_ellipsis())
1331  {
1332  if(!parameters.empty())
1333  out << ", ";
1334  out << "...";
1335  }
1336 
1337  out << ")";
1338  }
1339  else
1340  out << id << ": " << cpp_typecheck.to_string(id_expr.type());
1341 
1342  if(id_expr.id()==ID_symbol)
1343  {
1344  const symbolt &symbol=cpp_typecheck.lookup(to_symbol_expr(id_expr));
1345  out << " (" << symbol.location << ")";
1346  }
1347  else if(id_expr.id()==ID_template_function_instance)
1348  {
1349  const symbolt &symbol=
1350  cpp_typecheck.lookup(id_expr.type().get(ID_C_template));
1351  out << " (" << symbol.location << ")";
1352  }
1353  }
1354 
1355  out << '\n';
1356  }
1357 }
1358 
1360  const cpp_namet &cpp_name,
1361  const wantt want,
1362  const cpp_typecheck_fargst &fargs,
1363  bool fail_with_exception)
1364 {
1365  irep_idt base_name;
1366  cpp_template_args_non_tct template_args;
1367  template_args.make_nil();
1368 
1371 
1372  // this changes the scope
1373  resolve_scope(cpp_name, base_name, template_args);
1374 
1375 #ifdef DEBUG
1376  std::cout << "base name: " << base_name << '\n';
1377  std::cout << "template args: " << template_args.pretty() << '\n';
1378  std::cout << "original-scope: " << original_scope->prefix << '\n';
1379  std::cout << "scope: " << cpp_typecheck.cpp_scopes.current_scope().prefix
1380  << '\n';
1381 #endif
1382 
1383  bool qualified=cpp_name.is_qualified();
1384 
1385  // do __CPROVER scope
1386  if(qualified)
1387  {
1389  return do_builtin(base_name, fargs, template_args);
1390  }
1391  else
1392  {
1393  if(base_name=="__func__" ||
1394  base_name=="__FUNCTION__" ||
1395  base_name=="__PRETTY_FUNCTION__")
1396  {
1397  // __func__ is an ANSI-C standard compliant hack to get the function name
1398  // __FUNCTION__ and __PRETTY_FUNCTION__ are GCC-specific
1401  return std::move(s);
1402  }
1403  }
1404 
1405  cpp_scopest::id_sett id_set;
1406 
1407  cpp_scopet::lookup_kindt lookup_kind=
1409 
1410  if(template_args.is_nil())
1411  {
1412  id_set =
1413  cpp_typecheck.cpp_scopes.current_scope().lookup(base_name, lookup_kind);
1414 
1415  if(id_set.empty() && !cpp_typecheck.builtin_factory(base_name))
1416  {
1417  cpp_idt &builtin_id =
1419  builtin_id.identifier = base_name;
1420  builtin_id.id_class = cpp_idt::id_classt::SYMBOL;
1421 
1422  id_set.insert(&builtin_id);
1423  }
1424  }
1425  else
1427  base_name, lookup_kind, cpp_idt::id_classt::TEMPLATE);
1428 
1429  // Argument-dependent name lookup
1430  #if 0
1431  // not clear what this is good for
1432  if(!qualified && !fargs.has_object)
1433  resolve_with_arguments(id_set, base_name, fargs);
1434  #endif
1435 
1436  if(id_set.empty())
1437  {
1438  if(!fail_with_exception)
1439  return nil_exprt();
1440 
1443 
1444  if(qualified)
1445  {
1446  cpp_typecheck.error() << "symbol '" << base_name << "' not found";
1447 
1449  cpp_typecheck.error() << " in root scope";
1450  else
1452  << " in scope '" << cpp_typecheck.cpp_scopes.current_scope().prefix
1453  << "'";
1454  }
1455  else
1456  {
1457  cpp_typecheck.error() << "symbol '" << base_name << "' is unknown";
1458  }
1459 
1461  // cpp_typecheck.cpp_scopes.get_root_scope().print(std::cout);
1462  // cpp_typecheck.cpp_scopes.current_scope().print(std::cout);
1463  throw 0;
1464  }
1465 
1466  resolve_identifierst identifiers;
1467 
1468  if(template_args.is_not_nil())
1469  {
1470  // first figure out if we are doing functions/methods or
1471  // classes
1472  bool have_classes=false, have_methods=false;
1473 
1474  for(const auto &id_ptr : id_set)
1475  {
1476  const irep_idt id = id_ptr->identifier;
1477  const symbolt &s=cpp_typecheck.lookup(id);
1478  assert(s.type.get_bool(ID_is_template));
1480  have_classes=true;
1481  else
1482  have_methods=true;
1483  }
1484 
1485  if(want==wantt::BOTH && have_classes && have_methods)
1486  {
1487  if(!fail_with_exception)
1488  return nil_exprt();
1489 
1492  cpp_typecheck.error() << "template symbol '" << base_name
1493  << "' is ambiguous" << messaget::eom;
1494  throw 0;
1495  }
1496 
1497  if(want==wantt::TYPE || have_classes)
1498  {
1499  typet instance=
1500  disambiguate_template_classes(base_name, id_set, template_args);
1501 
1503 
1504  identifiers.push_back(exprt(ID_type, instance));
1505  }
1506  else
1507  {
1508  // methods and functions
1510  id_set, fargs, identifiers);
1511 
1513  identifiers, template_args, fargs);
1514  }
1515  }
1516  else
1517  {
1519  id_set, fargs, identifiers);
1520  }
1521 
1522  // change types into constructors if we want a constructor
1523  if(want==wantt::VAR)
1524  make_constructors(identifiers);
1525 
1526  filter(identifiers, want);
1527 
1528 #ifdef DEBUG
1529  std::cout << "P0 " << base_name << " " << identifiers.size() << '\n';
1530  show_identifiers(base_name, identifiers, std::cout);
1531  std::cout << '\n';
1532 #endif
1533 
1534  exprt result;
1535 
1536  // We disambiguate functions
1537  resolve_identifierst new_identifiers=identifiers;
1538 
1539  remove_templates(new_identifiers);
1540 
1541 #ifdef DEBUG
1542  std::cout << "P1 " << base_name << " " << new_identifiers.size() << '\n';
1543  show_identifiers(base_name, new_identifiers, std::cout);
1544  std::cout << '\n';
1545 #endif
1546 
1547  // we only want _exact_ matches, without templates!
1548  exact_match_functions(new_identifiers, fargs);
1549 
1550 #ifdef DEBUG
1551  std::cout << "P2 " << base_name << " " << new_identifiers.size() << '\n';
1552  show_identifiers(base_name, new_identifiers, std::cout);
1553  std::cout << '\n';
1554 #endif
1555 
1556  // no exact matches? Try again with function template guessing.
1557  if(new_identifiers.empty())
1558  {
1559  new_identifiers=identifiers;
1560 
1561  if(template_args.is_nil())
1562  {
1563  guess_function_template_args(new_identifiers, fargs);
1564 
1565  if(new_identifiers.empty())
1566  new_identifiers=identifiers;
1567  }
1568 
1569  disambiguate_functions(new_identifiers, fargs);
1570 
1571 #ifdef DEBUG
1572  std::cout << "P3 " << base_name << " " << new_identifiers.size() << '\n';
1573  show_identifiers(base_name, new_identifiers, std::cout);
1574  std::cout << '\n';
1575 #endif
1576  }
1577  else
1578  remove_duplicates(new_identifiers);
1579 
1580 #ifdef DEBUG
1581  std::cout << "P4 " << base_name << " " << new_identifiers.size() << '\n';
1582  show_identifiers(base_name, new_identifiers, std::cout);
1583  std::cout << '\n';
1584 #endif
1585 
1586  if(new_identifiers.size()==1)
1587  {
1588  result=*new_identifiers.begin();
1589  }
1590  else
1591  {
1592  // nothing or too many
1593  if(!fail_with_exception)
1594  return nil_exprt();
1595 
1596  if(new_identifiers.empty())
1597  {
1600  << "found no match for symbol '" << base_name << "', candidates are:\n";
1601  show_identifiers(base_name, identifiers, cpp_typecheck.error());
1602  }
1603  else
1604  {
1607  << "symbol '" << base_name << "' does not uniquely resolve:\n";
1608  show_identifiers(base_name, new_identifiers, cpp_typecheck.error());
1609 
1610 #ifdef DEBUG
1611  exprt e1=*new_identifiers.begin();
1612  exprt e2=*(++new_identifiers.begin());
1613  cpp_typecheck.error() << "e1==e2: " << (e1 == e2) << '\n';
1615  << "e1.type==e2.type: " << (e1.type() == e2.type()) << '\n';
1617  << "e1.id()==e2.id(): " << (e1.id() == e2.id()) << '\n';
1619  << "e1.iden==e2.iden: "
1620  << (e1.get(ID_identifier) == e2.get(ID_identifier)) << '\n';
1621  cpp_typecheck.error() << "e1.iden:: " << e1.get(ID_identifier) << '\n';
1622  cpp_typecheck.error() << "e2.iden:: " << e2.get(ID_identifier) << '\n';
1623 #endif
1624  }
1625 
1626  if(fargs.in_use)
1627  {
1628  cpp_typecheck.error() << "\nargument types:\n";
1629 
1630  for(const auto &op : fargs.operands)
1631  {
1633  << " " << cpp_typecheck.to_string(op.type()) << '\n';
1634  }
1635  }
1636 
1637  if(!cpp_typecheck.instantiation_stack.empty())
1638  {
1640  }
1641 
1643  throw 0;
1644  }
1645 
1646  // we do some checks before we return
1647  if(result.get_bool(ID_C_not_accessible))
1648  {
1649  #if 0
1650  if(!fail_with_exception)
1651  return nil_exprt();
1652 
1654  cpp_typecheck.str
1655  << "error: member '" << result.get(ID_component_name)
1656  << "' is not accessible";
1657  throw 0;
1658  #endif
1659  }
1660 
1661  switch(want)
1662  {
1663  case wantt::VAR:
1664  if(result.id()==ID_type && !cpp_typecheck.cpp_is_pod(result.type()))
1665  {
1666  if(!fail_with_exception)
1667  return nil_exprt();
1668 
1670 
1672  << "error: expected expression, but got type '"
1673  << cpp_typecheck.to_string(result.type()) << "'" << messaget::eom;
1674 
1675  throw 0;
1676  }
1677  break;
1678 
1679  case wantt::TYPE:
1680  if(result.id()!=ID_type)
1681  {
1682  if(!fail_with_exception)
1683  return nil_exprt();
1684 
1686 
1688  << "error: expected type, but got expression '"
1689  << cpp_typecheck.to_string(result) << "'" << messaget::eom;
1690 
1691  throw 0;
1692  }
1693  break;
1694 
1695  case wantt::BOTH:
1696  break;
1697  }
1698 
1699  return result;
1700 }
1701 
1703  const exprt &template_expr,
1704  const exprt &desired_expr)
1705 {
1706  if(template_expr.id()==ID_cpp_name)
1707  {
1708  const cpp_namet &cpp_name=
1709  to_cpp_name(template_expr);
1710 
1711  if(!cpp_name.is_qualified())
1712  {
1714 
1715  cpp_template_args_non_tct template_args;
1716  irep_idt base_name;
1717  resolve_scope(cpp_name, base_name, template_args);
1718 
1719  const auto id_set = cpp_typecheck.cpp_scopes.current_scope().lookup(
1720  base_name, cpp_scopet::RECURSIVE);
1721 
1722  // alright, rummage through these
1723  for(const auto &id_ptr : id_set)
1724  {
1725  const cpp_idt &id = *id_ptr;
1726  // template parameter?
1728  {
1729  // see if unassigned
1730  exprt &e=cpp_typecheck.template_map.expr_map[id.identifier];
1731  if(e.id()==ID_unassigned)
1732  {
1733  typet old_type=e.type();
1734  e = typecast_exprt::conditional_cast(desired_expr, old_type);
1735  }
1736  }
1737  }
1738  }
1739  }
1740 }
1741 
1743  const typet &template_type,
1744  const typet &desired_type)
1745 {
1746  // look at
1747  // http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/
1748  // com.ibm.xlcpp8a.doc/language/ref/template_argument_deduction.htm
1749 
1750  // T
1751  // const T
1752  // volatile T
1753  // T&
1754  // T*
1755  // T[10]
1756  // A<T>
1757  // C(*)(T)
1758  // T(*)()
1759  // T(*)(U)
1760  // T C::*
1761  // C T::*
1762  // T U::*
1763  // T (C::*)()
1764  // C (T::*)()
1765  // D (C::*)(T)
1766  // C (T::*)(U)
1767  // T (C::*)(U)
1768  // T (U::*)()
1769  // T (U::*)(V)
1770  // E[10][i]
1771  // B<i>
1772  // TT<T>
1773  // TT<i>
1774  // TT<C>
1775 
1776  #if 0
1777  std::cout << "TT: " << template_type.pretty() << '\n';
1778  std::cout << "DT: " << desired_type.pretty() << '\n';
1779  #endif
1780 
1781  if(template_type.id()==ID_cpp_name)
1782  {
1783  // we only care about cpp_names that are template parameters!
1784  const cpp_namet &cpp_name=to_cpp_name(template_type);
1785 
1787 
1788  if(cpp_name.has_template_args())
1789  {
1790  // this could be something like my_template<T>, and we need
1791  // to match 'T'. Then 'desired_type' has to be a template instance.
1792 
1793  // TODO
1794  }
1795  else
1796  {
1797  // template parameters aren't qualified
1798  if(!cpp_name.is_qualified())
1799  {
1800  irep_idt base_name;
1801  cpp_template_args_non_tct template_args;
1802  resolve_scope(cpp_name, base_name, template_args);
1803 
1804  const auto id_set = cpp_typecheck.cpp_scopes.current_scope().lookup(
1805  base_name, cpp_scopet::RECURSIVE);
1806 
1807  // alright, rummage through these
1808  for(const auto &id_ptr : id_set)
1809  {
1810  const cpp_idt &id = *id_ptr;
1811 
1812  // template argument?
1814  {
1815  // see if unassigned
1816  typet &t=cpp_typecheck.template_map.type_map[id.identifier];
1817  if(t.id()==ID_unassigned)
1818  {
1819  t=desired_type;
1820 
1821  // remove const, volatile (these can be added in the call)
1822  t.remove(ID_C_constant);
1823  t.remove(ID_C_volatile);
1824  #if 0
1825  std::cout << "ASSIGN " << id.identifier << " := "
1826  << cpp_typecheck.to_string(desired_type) << '\n';
1827  #endif
1828  }
1829  }
1830  }
1831  }
1832  }
1833  }
1834  else if(template_type.id()==ID_merged_type)
1835  {
1836  // look at subtypes
1837  for(const auto &t : to_merged_type(template_type).subtypes())
1838  {
1839  guess_template_args(t, desired_type);
1840  }
1841  }
1842  else if(is_reference(template_type) ||
1843  is_rvalue_reference(template_type))
1844  {
1846  to_reference_type(template_type).base_type(), desired_type);
1847  }
1848  else if(template_type.id()==ID_pointer)
1849  {
1850  if(desired_type.id() == ID_pointer)
1852  to_pointer_type(template_type).base_type(),
1853  to_pointer_type(desired_type).base_type());
1854  }
1855  else if(template_type.id()==ID_array)
1856  {
1857  if(desired_type.id() == ID_array)
1858  {
1859  // look at subtype first
1861  to_array_type(template_type).element_type(),
1862  to_array_type(desired_type).element_type());
1863 
1864  // size (e.g., buffer size guessing)
1866  to_array_type(template_type).size(),
1867  to_array_type(desired_type).size());
1868  }
1869  }
1870 }
1871 
1874  const exprt &expr,
1875  const cpp_typecheck_fargst &fargs)
1876 {
1877  typet tmp = cpp_typecheck.follow(expr.type());
1878 
1879  if(!tmp.get_bool(ID_is_template))
1880  return nil_exprt(); // not a template
1881 
1882  assert(expr.id()==ID_symbol);
1883 
1884  // a template is always a declaration
1885  const cpp_declarationt &cpp_declaration=
1886  to_cpp_declaration(tmp);
1887 
1888  // Class templates require explicit template arguments,
1889  // no guessing!
1890  if(cpp_declaration.is_class_template())
1891  return nil_exprt();
1892 
1893  // we need function arguments for guessing
1894  if(fargs.operands.empty())
1895  return nil_exprt(); // give up
1896 
1897  // We need to guess in the case of function templates!
1898 
1899  irep_idt template_identifier=
1901 
1902  const symbolt &template_symbol=
1903  cpp_typecheck.lookup(template_identifier);
1904 
1905  // alright, set up template arguments as 'unassigned'
1906 
1908 
1910  cpp_declaration.template_type());
1911 
1912  // there should be exactly one declarator
1913  assert(cpp_declaration.declarators().size()==1);
1914 
1915  const cpp_declaratort &function_declarator=
1916  cpp_declaration.declarators().front();
1917 
1918  // and that needs to have function type
1919  if(function_declarator.type().id()!=ID_function_type)
1920  {
1923  << "expected function type for function template"
1924  << messaget::eom;
1925  throw 0;
1926  }
1927 
1928  cpp_save_scopet cpp_saved_scope(cpp_typecheck.cpp_scopes);
1929 
1930  // we need the template scope
1931  cpp_scopet *template_scope=
1932  static_cast<cpp_scopet *>(
1933  cpp_typecheck.cpp_scopes.id_map[template_identifier]);
1934 
1935  if(template_scope==nullptr)
1936  {
1938  cpp_typecheck.error() << "template identifier: "
1939  << template_identifier << '\n'
1940  << "function template instantiation error"
1941  << messaget::eom;
1942  throw 0;
1943  }
1944 
1945  // enter the scope of the template
1946  cpp_typecheck.cpp_scopes.go_to(*template_scope);
1947 
1948  // walk through the function parameters
1949  const irept::subt &parameters=
1950  function_declarator.type().find(ID_parameters).get_sub();
1951 
1952  exprt::operandst::const_iterator it=fargs.operands.begin();
1953  for(const auto &parameter : parameters)
1954  {
1955  if(it==fargs.operands.end())
1956  break;
1957 
1958  if(parameter.id()==ID_cpp_declaration)
1959  {
1960  const cpp_declarationt &arg_declaration=
1961  to_cpp_declaration(parameter);
1962 
1963  // again, there should be one declarator
1964  assert(arg_declaration.declarators().size()==1);
1965 
1966  // turn into type
1967  typet arg_type=
1968  arg_declaration.declarators().front().
1969  merge_type(arg_declaration.type());
1970 
1971  // We only convert the arg_type,
1972  // and don't typecheck it -- that could cause all
1973  // sorts of trouble.
1975 
1976  guess_template_args(arg_type, it->type());
1977  }
1978 
1979  ++it;
1980  }
1981 
1982  // see if that has worked out
1983 
1984  cpp_template_args_tct template_args=
1986  cpp_declaration.template_type());
1987 
1988  if(template_args.has_unassigned())
1989  return nil_exprt(); // give up
1990 
1991  // Build the type of the function.
1992 
1993  typet function_type=
1994  function_declarator.merge_type(cpp_declaration.type());
1995 
1996  cpp_typecheck.typecheck_type(function_type);
1997 
1998  // Remember that this was a template
1999 
2000  function_type.set(ID_C_template, template_symbol.name);
2001  function_type.set(ID_C_template_arguments, template_args);
2002 
2003  // Seems we got an instance for all parameters. Let's return that.
2004 
2005  exprt template_function_instance(
2006  ID_template_function_instance, function_type);
2007 
2008  return template_function_instance;
2009 }
2010 
2012  exprt &expr,
2013  const cpp_template_args_non_tct &template_args_non_tc,
2014  const cpp_typecheck_fargst &fargs)
2015 {
2016  if(expr.id()!=ID_symbol)
2017  return; // templates are always symbols
2018 
2019  const symbolt &template_symbol =
2021 
2022  if(!template_symbol.type.get_bool(ID_is_template))
2023  return;
2024 
2025  #if 0
2026  if(template_args_non_tc.is_nil())
2027  {
2028  // no arguments, need to guess
2029  guess_function_template_args(expr, fargs);
2030  return;
2031  }
2032  #endif
2033 
2034  // We typecheck the template arguments in the context
2035  // of the original scope!
2036  cpp_template_args_tct template_args_tc;
2037 
2038  {
2040 
2042 
2043  template_args_tc=
2046  template_symbol,
2047  template_args_non_tc);
2048  // go back to where we used to be
2049  }
2050 
2051  // We never try 'unassigned' template arguments.
2052  if(template_args_tc.has_unassigned())
2053  UNREACHABLE;
2054 
2055  // a template is always a declaration
2056  const cpp_declarationt &cpp_declaration=
2057  to_cpp_declaration(template_symbol.type);
2058 
2059  // is it a class template or function template?
2060  if(cpp_declaration.is_class_template())
2061  {
2062  const symbolt &new_symbol=
2065  template_symbol,
2066  template_args_tc,
2067  template_args_tc);
2068 
2069  expr = type_exprt(struct_tag_typet(new_symbol.name));
2071  }
2072  else
2073  {
2074  // must be a function, maybe method
2075  const symbolt &new_symbol=
2078  template_symbol,
2079  template_args_tc,
2080  template_args_tc);
2081 
2082  // check if it is a method
2083  const code_typet &code_type=to_code_type(new_symbol.type);
2084 
2085  if(
2086  !code_type.parameters().empty() &&
2087  code_type.parameters().front().get_this())
2088  {
2089  // do we have an object?
2090  if(fargs.has_object)
2091  {
2092  const symbolt &type_symb=
2094  fargs.operands.begin()->type().get(ID_identifier));
2095 
2096  assert(type_symb.type.id()==ID_struct);
2097 
2098  const struct_typet &struct_type=
2099  to_struct_type(type_symb.type);
2100 
2101  DATA_INVARIANT(struct_type.has_component(new_symbol.name),
2102  "method should exist in struct");
2103 
2104  member_exprt member(
2105  *fargs.operands.begin(),
2106  new_symbol.name,
2107  code_type);
2109  expr.swap(member);
2110  return;
2111  }
2112  }
2113 
2114  expr=cpp_symbol_expr(new_symbol);
2116  }
2117 }
2118 
2120  const exprt &expr,
2121  unsigned &args_distance,
2122  const cpp_typecheck_fargst &fargs)
2123 {
2124  args_distance=0;
2125 
2126  if(expr.type().id()!=ID_code || !fargs.in_use)
2127  return true;
2128 
2129  const code_typet &type=to_code_type(expr.type());
2130 
2131  if(expr.id()==ID_member ||
2132  type.return_type().id() == ID_constructor)
2133  {
2134  // if it's a member, but does not have an object yet,
2135  // we add one
2136  if(!fargs.has_object)
2137  {
2138  const code_typet::parameterst &parameters=type.parameters();
2139  const code_typet::parametert &parameter=parameters.front();
2140 
2141  INVARIANT(parameter.get_this(), "first parameter should be `this'");
2142 
2143  if(type.return_type().id() == ID_constructor)
2144  {
2145  // it's a constructor
2146  const typet &object_type =
2147  to_pointer_type(parameter.type()).base_type();
2148  symbol_exprt object(irep_idt(), object_type);
2149  object.set(ID_C_lvalue, true);
2150 
2151  cpp_typecheck_fargst new_fargs(fargs);
2152  new_fargs.add_object(object);
2153  return new_fargs.match(type, args_distance, cpp_typecheck);
2154  }
2155  else
2156  {
2157  if(
2158  expr.type().get_bool(ID_C_is_operator) &&
2159  fargs.operands.size() == parameters.size())
2160  {
2161  return fargs.match(type, args_distance, cpp_typecheck);
2162  }
2163 
2164  cpp_typecheck_fargst new_fargs(fargs);
2165  new_fargs.add_object(to_member_expr(expr).compound());
2166 
2167  return new_fargs.match(type, args_distance, cpp_typecheck);
2168  }
2169  }
2170  }
2171  else if(fargs.has_object)
2172  {
2173  // if it's not a member then we shall remove the object
2174  cpp_typecheck_fargst new_fargs(fargs);
2175  new_fargs.remove_object();
2176 
2177  return new_fargs.match(type, args_distance, cpp_typecheck);
2178  }
2179 
2180  return fargs.match(type, args_distance, cpp_typecheck);
2181 }
2182 
2184  cpp_scopest::id_sett &id_set)
2185 {
2186  cpp_scopest::id_sett new_set;
2187 
2188  // std::cout << "FILTER\n";
2189 
2190  // We only want scopes!
2191  for(const auto &id_ptr : id_set)
2192  {
2193  cpp_idt &id = *id_ptr;
2194 
2195  if(id.is_class() || id.is_enum() || id.is_namespace())
2196  {
2197  // std::cout << "X1\n";
2198  assert(id.is_scope);
2199  new_set.insert(&id);
2200  }
2201  else if(id.is_typedef())
2202  {
2203  // std::cout << "X2\n";
2204  irep_idt identifier=id.identifier;
2205 
2206  if(id.is_member)
2207  continue;
2208 
2209  while(true)
2210  {
2211  const symbolt &symbol=cpp_typecheck.lookup(identifier);
2212  assert(symbol.is_type);
2213 
2214  // todo? maybe do enum here, too?
2215  if(symbol.type.id()==ID_struct)
2216  {
2217  // this is a scope, too!
2218  cpp_idt &class_id=
2219  cpp_typecheck.cpp_scopes.get_id(identifier);
2220 
2221  assert(class_id.is_scope);
2222  new_set.insert(&class_id);
2223  break;
2224  }
2225  else
2226  break;
2227  }
2228  }
2229  else if(id.id_class==cpp_scopet::id_classt::TEMPLATE)
2230  {
2231  // std::cout << "X3\n";
2232  #if 0
2233  const symbolt &symbol=
2234  cpp_typecheck.lookup(id.identifier);
2235 
2236  // Template struct? Really needs arguments to be a scope!
2237  if(symbol.type.id() == ID_struct)
2238  {
2239  id.print(std::cout);
2240  assert(id.is_scope);
2241  new_set.insert(&id);
2242  }
2243  #endif
2244  }
2245  else if(id.id_class==cpp_scopet::id_classt::TEMPLATE_PARAMETER)
2246  {
2247  // std::cout << "X4\n";
2248  // a template parameter may evaluate to be a scope: it could
2249  // be instantiated with a class/struct/union/enum
2250  exprt e=cpp_typecheck.template_map.lookup(id.identifier);
2251 
2252  #if 0
2253  cpp_typecheck.template_map.print(std::cout);
2254  std::cout << "S: " << cpp_typecheck.cpp_scopes.current_scope().identifier
2255  << '\n';
2256  std::cout << "P: "
2258  << '\n';
2259  std::cout << "I: " << id.identifier << '\n';
2260  std::cout << "E: " << e.pretty() << '\n';
2261  #endif
2262 
2263  if(e.id()!=ID_type)
2264  continue; // expressions are definitively not a scope
2265 
2266  if(e.type().id() == ID_template_parameter_symbol_type)
2267  {
2268  auto type = to_template_parameter_symbol_type(e.type());
2269 
2270  while(true)
2271  {
2272  irep_idt identifier=type.get_identifier();
2273 
2274  const symbolt &symbol=cpp_typecheck.lookup(identifier);
2275  assert(symbol.is_type);
2276 
2277  if(symbol.type.id() == ID_template_parameter_symbol_type)
2278  type = to_template_parameter_symbol_type(symbol.type);
2279  else if(symbol.type.id()==ID_struct ||
2280  symbol.type.id()==ID_union ||
2281  symbol.type.id()==ID_c_enum)
2282  {
2283  // this is a scope, too!
2284  cpp_idt &class_id=
2285  cpp_typecheck.cpp_scopes.get_id(identifier);
2286 
2287  assert(class_id.is_scope);
2288  new_set.insert(&class_id);
2289  break;
2290  }
2291  else // give up
2292  break;
2293  }
2294  }
2295  }
2296  }
2297 
2298  id_set.swap(new_set);
2299 }
2300 
2302  cpp_scopest::id_sett &id_set)
2303 {
2304  // we only want namespaces
2305  for(cpp_scopest::id_sett::iterator
2306  it=id_set.begin();
2307  it!=id_set.end();
2308  ) // no it++
2309  {
2310  if((*it)->is_namespace())
2311  it++;
2312  else
2313  {
2314  cpp_scopest::id_sett::iterator old(it);
2315  it++;
2316  id_set.erase(old);
2317  }
2318  }
2319 }
2320 
2322  cpp_scopest::id_sett &id_set,
2323  const irep_idt &base_name,
2324  const cpp_typecheck_fargst &fargs)
2325 {
2326  // not clear what this is good for
2327  for(const auto &arg : fargs.operands)
2328  {
2329  const typet &final_type=cpp_typecheck.follow(arg.type());
2330 
2331  if(final_type.id()!=ID_struct && final_type.id()!=ID_union)
2332  continue;
2333 
2334  cpp_scopet &scope=
2335  cpp_typecheck.cpp_scopes.get_scope(final_type.get(ID_name));
2336  const auto tmp_set = scope.lookup(base_name, cpp_scopet::SCOPE_ONLY);
2337  id_set.insert(tmp_set.begin(), tmp_set.end());
2338  }
2339 }
to_union_tag_type
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:202
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:155
tag_typet::get_identifier
const irep_idt & get_identifier() const
Definition: std_types.h:410
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:147
cpp_typecheck_resolvet::filter
void filter(resolve_identifierst &identifiers, const wantt want)
Definition: cpp_typecheck_resolve.cpp:378
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
cpp_idt::class_identifier
irep_idt class_identifier
Definition: cpp_id.h:75
source_locationt::get_function
const irep_idt & get_function() const
Definition: source_location.h:55
code_typet::has_ellipsis
bool has_ellipsis() const
Definition: std_types.h:611
typecast_exprt::conditional_cast
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2025
cpp_scopet::get_parent
cpp_scopet & get_parent() const
Definition: cpp_scope.h:88
template_mapt::build_unassigned
void build_unassigned(const template_typet &template_type)
Definition: template_map.cpp:214
cpp_typecheck_resolvet::matcht
Definition: cpp_typecheck_resolve.h:144
cpp_scopet
Definition: cpp_scope.h:20
cpp_typecheckt::elaborate_class_template
void elaborate_class_template(const typet &type)
elaborate class template instances
Definition: cpp_instantiate_template.cpp:221
arith_tools.h
is_number
bool is_number(const typet &type)
Returns true if the type is a rational, real, integer, natural, complex, unsignedbv,...
Definition: mathematical_types.cpp:17
symbolt::is_macro
bool is_macro
Definition: symbol.h:61
cpp_typecheck_fargst
Definition: cpp_typecheck_fargs.h:21
struct_union_typet::get_component
const componentt & get_component(const irep_idt &component_name) const
Get the reference to a component with given name.
Definition: std_types.cpp:63
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
cpp_typecheck_resolvet::convert_identifier
exprt convert_identifier(const cpp_idt &id, const cpp_typecheck_fargst &fargs)
Definition: cpp_typecheck_resolve.cpp:207
cpp_typecheck_resolvet::show_identifiers
void show_identifiers(const irep_idt &base_name, const resolve_identifierst &identifiers, std::ostream &out)
Definition: cpp_typecheck_resolve.cpp:1265
cpp_save_scopet
Definition: cpp_scopes.h:127
cpp_scopest::id_map
id_mapt id_map
Definition: cpp_scopes.h:68
cpp_typecheck_resolvet::wantt
wantt
Definition: cpp_typecheck_resolve.h:29
cpp_idt::id_classt::TEMPLATE
@ TEMPLATE
to_struct_union_type
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition: std_types.h:214
pos
literalt pos(literalt a)
Definition: literal.h:194
cpp_typecheckt::cpp_scopes
cpp_scopest cpp_scopes
Definition: cpp_typecheck.h:104
cpp_idt::this_expr
exprt this_expr
Definition: cpp_id.h:76
cpp_scopet::lookup
id_sett lookup(const irep_idt &base_name_to_lookup, lookup_kindt kind)
Definition: cpp_scope.h:32
irept::make_nil
void make_nil()
Definition: irep.h:454
cpp_scopet::QUALIFIED
@ QUALIFIED
Definition: cpp_scope.h:30
typet
The type of an expression, extends irept.
Definition: type.h:28
code_typet::parameterst
std::vector< parametert > parameterst
Definition: std_types.h:541
cpp_typecheckt::show_instantiation_stack
void show_instantiation_stack(std::ostream &)
Definition: cpp_instantiate_template.cpp:90
to_cpp_template_args_non_tc
cpp_template_args_non_tct & to_cpp_template_args_non_tc(irept &irep)
Definition: cpp_template_args.h:48
irept::pretty
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:495
to_cpp_declaration
cpp_declarationt & to_cpp_declaration(irept &irep)
Definition: cpp_declaration.h:146
irept::find
const irept & find(const irep_idt &name) const
Definition: irep.cpp:106
cpp_typecheck_fargs.h
struct_union_typet
Base type for structs and unions.
Definition: std_types.h:61
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
cpp_typecheck_resolvet::resolve_identifierst
std::vector< exprt > resolve_identifierst
Definition: cpp_typecheck_resolve.h:51
merged_type.h
cpp_typecheck_fargst::match
bool match(const code_typet &code_type, unsigned &distance, cpp_typecheckt &cpp_typecheck) const
Definition: cpp_typecheck_fargs.cpp:36
cpp_idt::identifier
irep_idt identifier
Definition: cpp_id.h:72
cpp_typecheck_fargst::operands
exprt::operandst operands
Definition: cpp_typecheck_fargs.h:25
cpp_type2name.h
prefix.h
cpp_typecheck_resolve.h
cpp_typecheckt::builtin_factory
bool builtin_factory(const irep_idt &)
Definition: cpp_typecheck.cpp:332
cpp_typecheck_resolvet::disambiguate_template_classes
struct_tag_typet disambiguate_template_classes(const irep_idt &base_name, const cpp_scopest::id_sett &id_set, const cpp_template_args_non_tct &template_args)
disambiguate partial specialization
Definition: cpp_typecheck_resolve.cpp:990
cpp_typecheckt::typecheck_expr_member
void typecheck_expr_member(exprt &) override
Definition: cpp_typecheck_expr.cpp:290
cpp_scopest::get_scope
cpp_scopet & get_scope(const irep_idt &identifier)
Definition: cpp_scopes.h:80
string_constant.h
exprt
Base class for all expressions.
Definition: expr.h:55
cpp_declarationt::partial_specialization_args
cpp_template_args_non_tct & partial_specialization_args()
Definition: cpp_declaration.h:106
cpp_typecheckt::class_template_symbol
const symbolt & class_template_symbol(const source_locationt &source_location, const symbolt &template_symbol, const cpp_template_args_tct &specialization_template_args, const cpp_template_args_tct &full_template_args)
Definition: cpp_instantiate_template.cpp:146
struct_tag_typet
A struct tag type, i.e., struct_typet with an identifier.
Definition: std_types.h:448
component
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:76
cpp_typecheckt::instantiation_stack
instantiation_stackt instantiation_stack
Definition: cpp_typecheck.h:177
irep_idt
dstringt irep_idt
Definition: irep.h:37
template_mapt::build_template_args
cpp_template_args_tct build_template_args(const template_typet &template_type) const
Definition: template_map.cpp:236
cpp_scopet::SCOPE_ONLY
@ SCOPE_ONLY
Definition: cpp_scope.h:30
cpp_typecheck_resolvet::cpp_typecheck
cpp_typecheckt & cpp_typecheck
Definition: cpp_typecheck_resolve.h:47
messaget::eom
static eomt eom
Definition: message.h:297
cpp_template_args_tct
Definition: cpp_template_args.h:64
cpp_declarationt::is_class_template
bool is_class_template() const
Definition: cpp_declaration.h:55
cpp_declarationt::get_specialization_of
irep_idt get_specialization_of() const
Definition: cpp_declaration.h:123
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
string_constantt
Definition: string_constant.h:14
is_rvalue_reference
bool is_rvalue_reference(const typet &type)
Returns if the type is an R value reference.
Definition: std_types.cpp:150
template_mapt::expr_map
expr_mapt expr_map
Definition: template_map.h:32
cpp_idt
Definition: cpp_id.h:22
union_tag_typet
A union tag type, i.e., union_typet with an identifier.
Definition: c_types.h:176
cpp_typecheck
bool cpp_typecheck(cpp_parse_treet &cpp_parse_tree, symbol_tablet &symbol_table, const std::string &module, message_handlert &message_handler)
Definition: cpp_typecheck.cpp:87
cpp_declarationt::declarators
const declaratorst & declarators() const
Definition: cpp_declaration.h:62
cpp_scopest::get_root_scope
cpp_scopet & get_root_scope()
Definition: cpp_scopes.h:93
template_mapt::lookup
exprt lookup(const irep_idt &identifier) const
Definition: template_map.cpp:93
cpp_typecheck_resolvet::original_scope
cpp_scopet * original_scope
Definition: cpp_typecheck_resolve.h:49
irept::get
const irep_idt & get(const irep_idt &name) const
Definition: irep.cpp:45
cpp_typecheck_resolvet::wantt::TYPE
@ TYPE
cpp_typecheck_resolvet::matcht::full_args
cpp_template_args_tct full_args
Definition: cpp_typecheck_resolve.h:148
cpp_idt::is_scope
bool is_scope
Definition: cpp_id.h:43
mathematical_types.h
cpp_typecheckt::cpp_is_pod
bool cpp_is_pod(const typet &type) const
Definition: cpp_is_pod.cpp:16
cpp_idt::is_method
bool is_method
Definition: cpp_id.h:42
to_merged_type
const merged_typet & to_merged_type(const typet &type)
conversion to merged_typet
Definition: merged_type.h:29
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
to_cpp_template_args_tc
cpp_template_args_tct & to_cpp_template_args_tc(irept &irep)
Definition: cpp_template_args.h:82
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
cpp_typecheck_fargst::has_object
bool has_object
Definition: cpp_typecheck_fargs.h:24
cpp_typecheckt::typecheck_type
void typecheck_type(typet &) override
Definition: cpp_typecheck_type.cpp:23
has_component_rec
bool has_component_rec(const typet &type, const irep_idt &component_name, const namespacet &ns)
Definition: anonymous_member.cpp:74
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
cpp_typecheck_resolvet::guess_function_template_args
void guess_function_template_args(resolve_identifierst &identifiers, const cpp_typecheck_fargst &fargs)
guess arguments of function templates
Definition: cpp_typecheck_resolve.cpp:87
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
messaget::error
mstreamt & error() const
Definition: message.h:399
cpp_idt::id_classt::SYMBOL
@ SYMBOL
signed_int_type
signedbv_typet signed_int_type()
Definition: c_types.cpp:40
has_prefix
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
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:510
cpp_util.h
cpp_idt::id_classt::TEMPLATE_PARAMETER
@ TEMPLATE_PARAMETER
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
cpp_scopest::current_scope
cpp_scopet & current_scope()
Definition: cpp_scopes.h:32
cpp_template_args_baset::arguments
argumentst & arguments()
Definition: cpp_template_args.h:31
cpp_saved_template_mapt
Definition: template_map.h:70
messaget::mstreamt::source_location
source_locationt source_location
Definition: message.h:247
get_identifier
static optionalt< smt_termt > get_identifier(const exprt &expr, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_handle_identifiers, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_identifiers)
Definition: smt2_incremental_decision_procedure.cpp:328
template_mapt::print
void print(std::ostream &out) const
Definition: template_map.cpp:136
irept::set
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:420
cpp_typecheck_resolvet::remove_duplicates
void remove_duplicates(resolve_identifierst &identifiers)
Definition: cpp_typecheck_resolve.cpp:148
cpp_scopest::id_sett
std::set< cpp_idt * > id_sett
Definition: cpp_scopes.h:30
exprt::find_source_location
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition: expr.cpp:165
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
cpp_typecheck_resolvet::resolve_namespace
cpp_scopet & resolve_namespace(const cpp_namet &cpp_name)
Definition: cpp_typecheck_resolve.cpp:1227
cpp_symbol_expr
symbol_exprt cpp_symbol_expr(const symbolt &symbol)
Definition: cpp_util.cpp:14
nil_exprt
The NIL expression.
Definition: std_expr.h:3025
cpp_idt::is_constructor
bool is_constructor
Definition: cpp_id.h:43
cpp_idt::is_member
bool is_member
Definition: cpp_id.h:42
cpp_typecheck_resolvet::cpp_typecheck_resolvet
cpp_typecheck_resolvet(class cpp_typecheckt &_cpp_typecheck)
Definition: cpp_typecheck_resolve.cpp:37
signed_size_type
signedbv_typet signed_size_type()
Definition: c_types.cpp:84
simplify
bool simplify(exprt &expr, const namespacet &ns)
Definition: simplify_expr.cpp:2926
cpp_typecheck_resolvet::matcht::specialization_args
cpp_template_args_tct specialization_args
Definition: cpp_typecheck_resolve.h:147
cpp_typecheck_resolvet::wantt::BOTH
@ BOTH
to_pointer_type
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:79
to_template_parameter_symbol_type
const template_parameter_symbol_typet & to_template_parameter_symbol_type(const typet &type)
Cast a typet to a template_parameter_symbol_typet.
Definition: cpp_template_parameter.h:94
to_reference_type
const reference_typet & to_reference_type(const typet &type)
Cast a typet to a reference_typet.
Definition: pointer_expr.h:148
pointer_type
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:253
irept::swap
void swap(irept &irep)
Definition: irep.h:442
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:222
cpp_typecheck_fargst::in_use
bool in_use
Definition: cpp_typecheck_fargs.h:24
cpp_typecheckt::subtype_typecast
bool subtype_typecast(const struct_typet &from, const struct_typet &to) const
Definition: cpp_typecheck_compound_type.cpp:1687
code_typet
Base type of functions.
Definition: std_types.h:538
cpp_typecheckt
Definition: cpp_typecheck.h:39
cpp_convert_type.h
cpp_declarationt
Definition: cpp_declaration.h:21
struct_union_typet::has_component
bool has_component(const irep_idt &component_name) const
Definition: std_types.h:157
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
to_struct_tag_type
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:474
dstringt::empty
bool empty() const
Definition: dstring.h:88
cpp_typecheck_fargst::add_object
void add_object(const exprt &expr)
Definition: cpp_typecheck_fargs.h:50
cpp_typecheck_resolvet::filter_for_named_scopes
void filter_for_named_scopes(cpp_scopest::id_sett &id_set)
Definition: cpp_typecheck_resolve.cpp:2183
cpp_typecheck_resolvet::resolve
exprt resolve(const cpp_namet &cpp_name, const wantt want, const cpp_typecheck_fargst &fargs, bool fail_with_exception=true)
Definition: cpp_typecheck_resolve.cpp:1359
cpp_typecheck_fargst::remove_object
void remove_object()
Definition: cpp_typecheck_fargs.h:57
cpp_scopest::go_to
void go_to(cpp_idt &id)
Definition: cpp_scopes.h:103
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:655
cpp_typecheck_resolvet::matcht::id
irep_idt id
Definition: cpp_typecheck_resolve.h:149
typet::add_source_location
source_locationt & add_source_location()
Definition: type.h:95
code_typet::parametert::get_this
bool get_this() const
Definition: std_types.h:600
cpp_typecheck_resolvet::remove_templates
void remove_templates(resolve_identifierst &identifiers)
Definition: cpp_typecheck_resolve.cpp:135
cpp_typecheck.h
cpp_namet::is_qualified
bool is_qualified() const
Definition: cpp_name.h:109
cpp_typecheck_resolvet::resolve_argument
void resolve_argument(exprt &argument, const cpp_typecheck_fargst &fargs)
Definition: cpp_typecheck_resolve.cpp:646
cpp_scopet::RECURSIVE
@ RECURSIVE
Definition: cpp_scope.h:30
sharing_treet< irept, forward_list_as_mapt< irep_idt, irept > >::subt
typename dt::subt subt
Definition: irep.h:160
cpp_template_args_non_tct
Definition: cpp_template_args.h:44
cpp_typecheck_resolvet::exact_match_functions
void exact_match_functions(resolve_identifierst &identifiers, const cpp_typecheck_fargst &fargs)
Definition: cpp_typecheck_resolve.cpp:412
cpp_scopest::go_to_root_scope
void go_to_root_scope()
Definition: cpp_scopes.h:98
cpp_convert_plain_type
void cpp_convert_plain_type(typet &type, message_handlert &message_handler)
Definition: cpp_convert_type.cpp:328
simplify_expr.h
symbolt::clear
void clear()
Zero initialise a symbol object.
Definition: symbol.h:75
cpp_typecheckt::typecheck_template_args
cpp_template_args_tct typecheck_template_args(const source_locationt &source_location, const symbolt &template_symbol, const cpp_template_args_non_tct &template_args)
Definition: cpp_typecheck_template.cpp:826
cpp_typecheck_resolvet::guess_template_args
void guess_template_args(const typet &template_parameter, const typet &desired_type)
Definition: cpp_typecheck_resolve.cpp:1742
cpp_typecheck_resolvet::convert_template_parameter
exprt convert_template_parameter(const cpp_idt &id)
Definition: cpp_typecheck_resolve.cpp:181
member_exprt
Extract member of struct or union.
Definition: std_expr.h:2793
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
messaget::get_message_handler
message_handlert & get_message_handler()
Definition: message.h:184
type_exprt
An expression denoting a type.
Definition: std_expr.h:2905
cpp_namet::has_template_args
bool has_template_args() const
Definition: cpp_name.h:124
is_reference
bool is_reference(const typet &type)
Returns true if the type is a reference.
Definition: std_types.cpp:143
struct_typet
Structure type, corresponds to C style structs.
Definition: std_types.h:230
cpp_namet::source_location
const source_locationt & source_location() const
Definition: cpp_name.h:73
c_enum_tag_typet
C enum tag type, i.e., c_enum_typet with an identifier.
Definition: c_types.h:318
cpp_idt::id_classt::TYPEDEF
@ TYPEDEF
cpp_idt::is_static_member
bool is_static_member
Definition: cpp_id.h:42
cpp_typecheckt::instantiate_template
const symbolt & instantiate_template(const source_locationt &source_location, const symbolt &symbol, const cpp_template_args_tct &specialization_template_args, const cpp_template_args_tct &full_template_args, const typet &specialization=uninitialized_typet{})
Definition: cpp_instantiate_template.cpp:250
cpp_typecheck_resolvet::resolve_scope
cpp_scopet & resolve_scope(const cpp_namet &cpp_name, irep_idt &base_name, cpp_template_args_non_tct &template_args)
Definition: cpp_typecheck_resolve.cpp:856
cpp_type2name
std::string cpp_type2name(const typet &type)
Definition: cpp_type2name.cpp:101
namespace_baset::follow
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:49
symbolt::location
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
symbolt
Symbol table entry.
Definition: symbol.h:27
cpp_typecheck_resolvet::convert_identifiers
void convert_identifiers(const cpp_scopest::id_sett &id_set, const cpp_typecheck_fargst &fargs, resolve_identifierst &identifiers)
Definition: cpp_typecheck_resolve.cpp:43
cpp_scopet::is_root_scope
bool is_root_scope() const
Definition: cpp_scope.h:77
symbolt::is_type
bool is_type
Definition: symbol.h:61
cpp_idt::id_class
id_classt id_class
Definition: cpp_id.h:45
template_mapt::type_map
type_mapt type_map
Definition: template_map.h:31
pointer_typet::base_type
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
irept::get_sub
subt & get_sub()
Definition: irep.h:456
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
code_typet::parametert
Definition: std_types.h:555
exprt::add_to_operands
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:162
cpp_typecheck_resolvet::wantt::VAR
@ VAR
cpp_idt::prefix
std::string prefix
Definition: cpp_id.h:79
cpp_typecheck_resolvet::apply_template_args
void apply_template_args(resolve_identifierst &identifiers, const cpp_template_args_non_tct &template_args, const cpp_typecheck_fargst &fargs)
Definition: cpp_typecheck_resolve.cpp:63
code_typet::return_type
const typet & return_type() const
Definition: std_types.h:645
to_member_expr
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2886
cpp_template_args_tct::has_unassigned
bool has_unassigned() const
Definition: cpp_template_args.h:67
irept
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition: irep.h:359
anonymous_member.h
cpp_typecheckt::to_string
std::string to_string(const typet &) override
Definition: cpp_typecheck.cpp:82
cpp_template_args_baset::argumentst
exprt::operandst argumentst
Definition: cpp_template_args.h:29
cpp_scopet::lookup_kindt
lookup_kindt
Definition: cpp_scope.h:30
irept::remove
void remove(const irep_idt &name)
Definition: irep.cpp:96
cpp_typecheck_resolvet::disambiguate_functions
void disambiguate_functions(resolve_identifierst &identifiers, const cpp_typecheck_fargst &fargs)
Definition: cpp_typecheck_resolve.cpp:434
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:216
cpp_typecheck_resolvet::filter_for_namespaces
void filter_for_namespaces(cpp_scopest::id_sett &id_set)
Definition: cpp_typecheck_resolve.cpp:2301
size_type
unsignedbv_typet size_type()
Definition: c_types.cpp:68
cpp_idt::print
void print(std::ostream &out, unsigned indent=0) const
Definition: cpp_id.cpp:31
cpp_typecheck_resolvet::do_builtin
exprt do_builtin(const irep_idt &base_name, const cpp_typecheck_fargst &fargs, const cpp_template_args_non_tct &template_args)
Definition: cpp_typecheck_resolve.cpp:660
cpp_typecheckt::template_map
template_mapt template_map
Definition: cpp_typecheck.h:223
messaget::warning
mstreamt & warning() const
Definition: message.h:404
cpp_scopest::get_id
cpp_idt & get_id(const irep_idt &identifier)
Definition: cpp_scopes.h:72
std_expr.h
cpp_namet
Definition: cpp_name.h:16
exprt::source_location
const source_locationt & source_location() const
Definition: expr.h:211
c_types.h
cpp_typecheckt::disable_access_control
bool disable_access_control
Definition: cpp_typecheck.h:589
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
cpp_typecheck_resolvet::resolve_with_arguments
void resolve_with_arguments(cpp_scopest::id_sett &id_set, const irep_idt &base_name, const cpp_typecheck_fargst &fargs)
Definition: cpp_typecheck_resolve.cpp:2321
irept::get_bool
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:58
cpp_declaratort
Definition: cpp_declarator.h:19
cpp_typecheck_resolvet::make_constructors
void make_constructors(resolve_identifierst &identifiers)
Definition: cpp_typecheck_resolve.cpp:571
dstringt::size
size_t size() const
Definition: dstring.h:120
cpp_typecheck_resolvet::source_location
source_locationt source_location
Definition: cpp_typecheck_resolve.h:48
to_cpp_name
cpp_namet & to_cpp_name(irept &cpp_name)
Definition: cpp_name.h:148
validation_modet::INVARIANT
@ INVARIANT
cpp_declarationt::template_type
template_typet & template_type()
Definition: cpp_declaration.h:96
cpp_scopet::insert
cpp_idt & insert(const irep_idt &_base_name)
Definition: cpp_scope.h:52
cpp_declaratort::merge_type
typet merge_type(const typet &declaration_type) const
Definition: cpp_declarator.cpp:27
integer2string
const std::string integer2string(const mp_integer &n, unsigned base)
Definition: mp_arith.cpp:103