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