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