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