32 for(std::size_t i=0; i<new_parameters.size(); i++)
34 if(i<old_parameters.size() &&
35 old_parameters[i].has_default_argument() &&
36 !new_parameters[i].has_default_argument())
39 new_parameters[i].default_argument()=old_parameters[i].default_argument();
57 static_cast<const cpp_namet &
>(type.find(ID_tag));
62 error() <<
"class templates must not be anonymous" <<
eom;
69 error() <<
"simple name expected as class template tag" <<
eom;
80 base_name, template_type, partial_specialization_args);
95 const symbolt &previous=
lookup((*id_set.begin())->identifier);
96 if(previous.
name!=symbol_name || id_set.
size()>1)
99 str <<
"template declaration of `" << base_name.
c_str()
100 <<
" does not match previous declaration\n";
101 str <<
"location of previous definition: " << previous.
location;
110 symbol_tablet::symbolst::iterator previous_symbol=
119 bool previous_has_body=
123 if(has_body && previous_has_body)
126 error() <<
"template struct `" << base_name
127 <<
"' defined previously\n" 128 <<
"location of previous definition: " 129 << previous_symbol->second.location <<
eom;
141 previous_symbol->second.type.swap(declaration);
144 std::cout <<
"*****\n";
146 std::cout <<
"*****\n";
147 std::cout <<
"II: " << symbol_name <<
'\n';
173 symbol.
name=symbol_name;
189 error() <<
"cpp_typecheckt::typecheck_compound_type: " 190 <<
"symbol_table.move() failed" 224 error() <<
"function template must have simple name" <<
eom;
233 declarator.merge_type(declaration.
type());
243 bool has_value=declarator.find(ID_value).is_not_nil();
247 symbol_tablet::symbolst::iterator previous_symbol=
252 bool previous_has_value =
256 if(has_value && previous_has_value)
259 error() <<
"function template symbol `" << base_name
260 <<
"' declared previously\n" 261 <<
"location of previous definition: " 262 << previous_symbol->second.location <<
eom;
268 previous_symbol->second.type.swap(declaration);
278 symbol.
name=symbol_name;
293 error() <<
"cpp_typecheckt::typecheck_compound_type: " 294 <<
"symbol_table.move() failed" 324 if(cpp_name.
get_sub().size()==4 &&
325 cpp_name.
get_sub()[0].id()==ID_name &&
326 cpp_name.
get_sub()[1].id()==ID_template_args &&
327 cpp_name.
get_sub()[2].id()==
"::" &&
328 cpp_name.
get_sub()[3].id()==ID_name)
331 else if(cpp_name.
get_sub().size()==5 &&
332 cpp_name.
get_sub()[0].id()==ID_name &&
333 cpp_name.
get_sub()[1].id()==ID_template_args &&
334 cpp_name.
get_sub()[2].id()==
"::" &&
335 cpp_name.
get_sub()[3].id()==ID_operator)
342 error() <<
"bad template name" <<
eom;
350 cpp_name.
get_sub().front().get(ID_identifier),
359 error() <<
"class template `" 360 << cpp_name.
get_sub().front().get(ID_identifier)
361 <<
"' not found" <<
eom;
364 else if(id_set.size()>1)
367 error() <<
"class template `" 368 << cpp_name.
get_sub().front().get(ID_identifier)
369 <<
"' is ambiguous" <<
eom;
376 error() <<
"class template `" 377 << cpp_name.
get_sub().front().get(ID_identifier)
378 <<
"' is not a template" <<
eom;
382 const cpp_idt &cpp_id=**(id_set.begin());
387 template_symbol.
value.
add(
"template_methods"));
394 const irept &instantiated_with =
395 template_symbol.
value.
add(
"instantiated_with");
397 for(std::size_t i=0; i<instantiated_with.
get_sub().size(); i++)
401 instantiated_with.
get_sub()[i]);
415 decl_tmp.
remove(ID_template_type);
416 decl_tmp.
remove(ID_is_template);
428 std::string identifier=
436 for(template_typet::template_parameterst::const_iterator
444 if(it->id()==ID_type)
445 identifier+=
"Type"+std::to_string(counter);
447 identifier+=
"Non_Type"+std::to_string(counter);
454 if(!partial_specialization_args.
arguments().empty())
456 identifier+=
"_specialized_to_<";
459 for(cpp_template_args_non_tct::argumentst::const_iterator
460 it=partial_specialization_args.
arguments().begin();
461 it!=partial_specialization_args.
arguments().end();
470 if(it->id()==ID_type || it->id()==
"ambiguous")
485 const typet &function_type)
489 std::string identifier=
491 partial_specialization_args);
506 assert(type.
id()==ID_struct);
511 if(cpp_name.is_qualified())
514 error() <<
"qualifiers not expected here" <<
eom;
518 if(cpp_name.get_sub().size()!=2 ||
519 cpp_name.get_sub()[0].id()!=ID_name ||
520 cpp_name.get_sub()[1].id()!=ID_template_args)
525 error() <<
"bad template-class-specialization name" <<
eom;
530 cpp_name.get_sub()[0].get(ID_identifier);
546 for(cpp_scopest::id_sett::iterator
551 cpp_scopest::id_sett::iterator next=it;
554 if(
lookup((*it)->identifier).type.
555 find(
"specialization_of").is_not_nil())
565 error() <<
"class template `" << base_name <<
"' not found" <<
eom;
568 else if(id_set.size()>1)
571 error() <<
"class template `" << base_name <<
"' is ambiguous" 576 symbol_tablet::symbolst::iterator s_it=
581 symbolt &template_symbol=s_it->second;
583 if(!template_symbol.type.get_bool(ID_is_template))
586 error() <<
"expected a template" <<
eom;
598 template_args_non_tc);
603 cpp_name.source_location(),
626 declaration.
declarators().front().type().id()!=ID_function_type)
629 error() <<
"expected function template specialization" <<
eom;
640 error() <<
"qualifiers not expected here" <<
eom;
647 assert(!cpp_name.
get_sub().empty());
649 if(cpp_name.
get_sub().back().id()==ID_template_args)
652 if(cpp_name.
get_sub().size()!=2 ||
653 cpp_name.
get_sub()[0].id()!=ID_name ||
654 cpp_name.
get_sub()[1].id()!=ID_template_args)
659 error() <<
"bad template-function-specialization name" <<
eom;
663 std::string base_name=
664 cpp_name.
get_sub()[0].get(ID_identifier).c_str();
673 error() <<
"template function `" << base_name <<
"' not found" 677 else if(id_set.size()>1)
680 error() <<
"template function `" << base_name
681 <<
"' is ambiguous" <<
eom;
685 const symbolt &template_symbol=
686 lookup((*id_set.begin())->identifier);
696 typet specialization;
697 specialization.
swap(declarator);
713 new_declaration.
remove(ID_template_type);
714 new_declaration.
remove(ID_is_template);
715 new_declaration.
set(ID_C_template,
"");
726 assert(type.
id()==ID_template);
744 unsigned anon_count=0;
746 for(template_typet::template_parameterst::iterator
747 it=parameters.begin();
748 it!=parameters.end();
751 exprt ¶meter=*it;
754 declaration.
swap(static_cast<cpp_declarationt &>(parameter));
764 if(declarator.name().is_nil())
767 name.
set(ID_identifier,
"anon#"+std::to_string(++anon_count));
769 declarator.name().get_sub().push_back(name);
774 if(declarator.name().get_sub().size()!=1 ||
775 declarator.name().get_sub().front().id()!=ID_name)
778 error() <<
"template parameter must be simple name" <<
eom;
784 irep_idt base_name=declarator.name().get_sub().front().get(ID_identifier);
793 if(declaration.
get_bool(ID_is_type))
796 parameter.
type().
set(ID_identifier, identifier);
810 if(declarator.value().is_not_nil())
811 parameter.
add(ID_C_default_value)=declarator.value();
823 exprt default_value=declarator.value();
827 cpp_declarator_converter.
convert(declaration, declarator);
840 parameter.
add(ID_C_default_value)=default_value;
849 return template_scope;
856 const symbolt &template_symbol,
860 assert(template_args.
id()!=ID_already_typechecked);
875 template_type.template_parameters();
877 if(parameters.size()<args.size())
880 error() <<
"too many template arguments (expected " 881 << parameters.size() <<
", but got " 882 << args.size() <<
")" <<
eom;
891 for(std::size_t i=0; i<parameters.size(); i++)
903 error() <<
"not enough template arguments (expected " 904 << parameters.size() <<
", but got " << args.size()
919 assert(i<args.size());
923 if(parameter.
id()==ID_type)
925 if(arg.id()==ID_type)
929 else if(arg.id()==
"ambiguous")
933 arg=
exprt(ID_type, t);
938 error() <<
"expected type, but got expression" <<
eom;
944 if(arg.id()==ID_type)
947 error() <<
"expected expression, but got type" <<
eom;
950 else if(arg.id()==
"ambiguous")
966 template_scope!=
nullptr,
968 "template_scope is null");
990 assert(args.size()==parameters.size());
1003 error() <<
"invalid use of 'virtual' in template declaration" 1011 error() <<
"template declaration for typedef" <<
eom;
1029 error() <<
"class template not expected to have declarators" 1035 if(type.
id()!=ID_struct)
1038 error() <<
"expected class template" <<
eom;
1045 if((static_cast<const cpp_namet &>(
1046 type.
find(ID_tag))).has_template_args())
1063 error() <<
"non-class template is expected to have a declarator"
C++ Language Type Checking.
The type of an expression.
irep_idt name
The unique identifier.
#define INVARIANT_STRUCTURED(CONDITION, TYPENAME,...)
void set(const template_parametert ¶meter, const exprt &value)
virtual bool lookup(const irep_idt &name, const symbolt *&symbol) const
void typecheck_type(typet &type)
const std::string & id2string(const irep_idt &d)
std::vector< template_parametert > template_parameterst
std::set< cpp_idt * > id_sett
template_parameterst & template_parameters()
void lookup(const irep_idt &base_name, lookup_kindt kind, id_sett &id_set)
void convert_non_template_declaration(cpp_declarationt &declaration)
irep_idt mode
Language mode.
exprt::operandst argumentst
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))
class cpp_scopet & new_scope(const irep_idt &new_scope_name)
cpp_template_args_tct typecheck_template_args(const source_locationt &source_location, const symbolt &template_symbol, const cpp_template_args_non_tct &template_args)
void copy_to_operands(const exprt &expr)
void convert_template_function_or_member_specialization(cpp_declarationt &declaration)
cpp_namet & to_cpp_name(irept &cpp_name)
cpp_scopet & get_parent() const
cpp_template_args_non_tct & partial_specialization_args()
exprt value
Initial value of symbol.
cpp_idt & put_into_scope(const symbolt &symbol, cpp_scopet &scope, bool is_friend=false)
template_mapt template_map
irep_idt module
Name of module the symbol belongs to.
irep_idt pretty_name
Language-specific display name.
bool is_simple_name() const
virtual void implicit_typecast(exprt &expr, const typet &type)
Symbol table entry.This is a symbol in the symbol table, stored in an object of type symbol_tablet...
void build(const template_typet &template_type, const cpp_template_args_tct &template_args)
static mstreamt & eom(mstreamt &m)
std::string class_template_identifier(const irep_idt &base_name, const template_typet &template_type, const cpp_template_args_non_tct &partial_specialization_args)
bool get_bool(const irep_namet &name) const
void typecheck_class_template(cpp_declarationt &declaration)
cpp_scopet & typecheck_template_parameters(template_typet &type)
cpp_template_args_non_tct & to_cpp_template_args_non_tc(irept &irep)
bool has_default_argument() const
bool is_qualified() const
const cpp_member_spect & member_spec() const
virtual void typecheck_expr(exprt &expr)
void convert(cpp_linkage_spect &)
void swap(template_mapt &template_map)
symbol_tablet & symbol_table
bool is_class_template() const
const irep_idt & id() const
const source_locationt & source_location() const
class symbol_exprt symbol_expr() const
produces a symbol_exprt for a symbol
const declaratorst & declarators() const
void salvage_default_arguments(const template_typet &old_type, template_typet &new_type)
const source_locationt & find_source_location() const
bool has_template_args() const
source_locationt source_location
std::string function_template_identifier(const irep_idt &base_name, const template_typet &template_type, const typet &function_type)
void set_specialization_of(const irep_idt &id)
std::string cpp_type2name(const typet &type)
Base class for tree-like data structures with sharing.
void convert_template_declaration(cpp_declarationt &declaration)
void typecheck_function_template(cpp_declarationt &declaration)
typecheck function templates
C++ Language Type Checking.
C++ Language Type Checking.
bool move(symbolt &symbol, symbolt *&new_symbol)
Move a symbol into the symbol table.
const source_locationt & source_location() const
irep_idt get_base_name() const
bool is_template_parameter
typet type
Type of symbol.
source_locationt location
Source code location of definition of symbol.
cpp_declarationt & to_cpp_declaration(irept &irep)
Base class for all expressions.
void convert_class_template_specialization(cpp_declarationt &declaration)
irep_idt base_name
Base (non-scoped) name.
cpp_scopet & current_scope()
unsigned template_counter
symbolt & convert(const typet &type, const cpp_storage_spect &storage_spec, const cpp_member_spect &member_spec, cpp_declaratort &declarator)
source_locationt & add_source_location()
const source_locationt & source_location() const
irept & add(const irep_namet &name)
void cpp_convert_plain_type(typet &type)
source_locationt & add_source_location()
std::string cpp_expr2name(const exprt &expr)
Expression to hold a symbol (variable)
const char * c_str() const
void remove(const irep_namet &name)
void typecheck_class_template_member(cpp_declarationt &declaration)
typecheck class template members; these can be methods or static members
template_typet & template_type()
Generic exception types primarily designed for use with invariants.
cpp_idt & insert(const irep_idt &_base_name)
std::set< cpp_idt * > id_sett
const irept & find(const irep_namet &name) const
void set(const irep_namet &name, const irep_idt &value)
bool simplify(exprt &expr, const namespacet &ns)
exprt & default_argument()