30 if(type.
id()==ID_const)
32 else if(type.
id()==ID_merged_type)
46 if(type.
id()==ID_volatile)
48 else if(type.
id()==ID_merged_type)
63 bool tag_only_declaration)
79 if(has_body || tag_only_declaration)
89 for(
const auto &
id :
id_set)
91 return static_cast<cpp_scopet &>(id->get_parent());
106 type.
remove(ID_C_constant);
107 type.
remove(ID_C_volatile);
108 type.
remove(ID_C_restricted);
115 bool tag_only_declaration=type.
get_bool(ID_C_tag_only_declaration);
122 base_name=std::string(
"#anon_")+std::to_string(++
anon_counter);
123 type.
set(ID_C_is_anonymous,
true);
137 if(type.
get_bool(ID_C_is_anonymous))
140 dest_scope=&
tag_scope(base_name, has_body, tag_only_declaration);
148 &cpp_typecheck_resolve.
resolve_scope(cpp_name, base_name, t_args);
162 symbol_tablet::symbolst::iterator previous_symbol=
169 symbolt &symbol=previous_symbol->second;
186 error() <<
"error: compound tag `" << base_name
187 <<
"' declared previously\n" 188 <<
"location of previous definition: " 199 symbol.
name=symbol_name;
221 error() <<
"cpp_typecheckt::typecheck_compound_type: " 222 <<
"symbol_table.move() failed" <<
eom;
234 id.class_identifier=new_symbol->
name;
248 typet symbol_type(ID_symbol);
249 symbol_type.
set(ID_identifier, symbol_name);
250 qualifiers.
write(symbol_type);
251 type.
swap(symbol_type);
264 bool is_cast_operator=
265 declaration.
type().
id()==
"cpp-cast-operator";
270 declarator.
name().
get_sub().front().id()==ID_operator);
305 error() <<
"declarator in compound needs to be simple name" 310 bool is_method=!is_typedef && final_type.
id()==ID_code;
317 final_type.
set(ID_C_member_name, symbol.
name);
321 if(is_virtual && !is_method)
324 error() <<
"only methods can be virtual" <<
eom;
328 if(is_inline && !is_method)
331 error() <<
"only methods can be inlined" <<
eom;
335 if(is_virtual && is_static)
338 error() <<
"static methods cannot be virtual" <<
eom;
342 if(is_cast_operator && is_static)
345 error() <<
"cast operators cannot be static`" <<
eom;
349 if(is_constructor && is_virtual)
352 error() <<
"constructors cannot be virtual" <<
eom;
356 if(!is_constructor && is_explicit)
359 error() <<
"only constructors can be explicit" <<
eom;
367 error() <<
"member function must return a value or void" <<
eom;
375 error() <<
"destructor with wrong name" <<
eom;
388 is_method || is_static)
399 identifier=base_name;
402 component.
set(ID_name, identifier);
403 component.
type()=final_type;
404 component.
set(ID_access, access);
405 component.
set(ID_base_name, base_name);
406 component.
set(ID_pretty_name, base_name);
411 component.
set(
"is_operator",
true);
412 component.
type().
set(
"#is_operator",
true);
416 component.
set(
"is_cast_operator",
true);
419 component.
set(
"is_explicit",
true);
422 const typet &method_qualifier=
423 static_cast<const typet &
>(declarator.
add(ID_method_qualifier));
427 component.
set(ID_is_static,
true);
428 component.
type().
set(
"#is_static",
true);
432 component.
set(
"is_type",
true);
435 component.
set(
"is_mutable",
true);
445 std::string virtual_name=
449 static_cast<const typet &>(component.
find(ID_type))));
452 virtual_name+=
"$const";
455 virtual_name+=
"$virtual";
457 if(component.
type().
get(ID_return_type)==ID_destructor)
458 virtual_name=
"@dtor";
461 std::set<irep_idt> virtual_bases;
463 for(
const auto &comp : components)
465 if(comp.get_bool(ID_is_virtual))
467 if(comp.get(
"virtual_name")==virtual_name)
482 symbol.
name, component, initializers,
483 method_qualifier, value);
485 if(!value.
is_nil() && !is_static)
488 error() <<
"no initialization allowed here" <<
eom;
494 component.
type().
set(ID_C_is_virtual,
true);
495 component.
type().
set(
"#virtual_name", virtual_name);
507 error() <<
"expected 0 to mark pure virtual method, got " 511 component.
set(
"is_pure_virtual",
true);
526 symbol_tablet::symbolst::iterator vtit =
533 vt_symb_type.
name= vt_name;
536 vt_symb_type.
mode=ID_cpp;
551 compo.
set(ID_base_name,
"@vtable_pointer");
555 compo.
set(
"is_vtptr",
true);
556 compo.
set(ID_access, ID_public);
557 components.push_back(compo);
561 assert(vtit->second.type.id()==ID_struct);
566 component.
set(
"virtual_name", virtual_name);
567 component.
set(
"is_virtual", is_virtual);
573 vt_entry.
set(ID_base_name, virtual_name);
574 vt_entry.
set(ID_pretty_name, virtual_name);
575 vt_entry.
set(ID_access, ID_public);
577 virtual_table.components().push_back(vt_entry);
580 while(!virtual_bases.empty())
582 irep_idt virtual_base=*virtual_bases.begin();
590 func_symb.
mode=ID_cpp;
603 for(
auto &arg : args)
607 if(base_name.
empty())
608 base_name=
"arg"+std::to_string(i++);
614 arg_symb.
mode=ID_cpp;
618 arg.
set(ID_C_identifier, arg_symb.
name);
631 args[0].
get(ID_C_identifier)).symbol_expr();
640 expr_call.
arguments().reserve(args.size());
641 expr_call.
arguments().push_back(late_cast);
643 for(
unsigned i=1; i < args.size(); i++)
647 args[i].
get(ID_C_identifier)).symbol_expr());
657 code_func.
arguments().reserve(args.size());
658 code_func.
arguments().push_back(late_cast);
660 for(
unsigned i=1; i < args.size(); i++)
664 args[i].
get(ID_C_identifier)).symbol_expr());
667 func_symb.
value=code_func;
675 components.push_back(new_compo);
684 virtual_bases.erase(virtual_bases.begin());
689 if(is_static && !is_method)
694 static_symbol.
name=identifier;
695 static_symbol.
type=component.
type();
709 error() <<
"redeclaration of static member `" 735 ops.push_back(value);
749 components.push_back(component);
755 if(type.
id()==ID_array)
774 if(base_name.
empty())
777 if(compound.
type().
id()==ID_code)
788 compound.
find(ID_type).
get(ID_return_type)==ID_constructor;
790 id.is_static_member=compound.
get_bool(ID_is_static);
815 for(
const auto &id_it :
id_set)
821 if(!
id.is_class() && !
id.is_enum())
824 error() <<
"`" << base_name
825 <<
"' already in compound scope" <<
eom;
839 id.is_static_member=compound.
get_bool(ID_is_static);
854 error() <<
"friend template not supported" <<
eom;
864 if(ftype.
id()!=ID_struct && ftype.
id()!=ID_union)
867 error() <<
"unexpected friend" <<
eom;
874 error() <<
"friend declaration must not have compound body" <<
eom;
893 bool has_value=sub_it.value().is_not_nil();
934 assert(symbol.
type.
id()==ID_struct ||
935 symbol.
type.
id()==ID_union);
941 if(!type.find(ID_bases).get_sub().empty())
943 if(type.id()==ID_union)
946 error() <<
"union types must not have bases" <<
eom;
953 exprt &body=
static_cast<exprt &
>(type.add(ID_body));
960 type.get_bool(ID_C_class)?ID_private:ID_public;
962 bool found_ctor=
false;
963 bool found_dtor=
false;
969 if(it->id()==ID_cpp_declaration)
983 declaration.
set(ID_C_access, access);
994 if(declaration.
type().
id()==ID_struct ||
995 declaration.
type().
id()==ID_union ||
996 declaration.
type().
id()==ID_c_enum)
998 declaration.
type().
set(ID_C_tag_only_declaration,
true);
1011 error() <<
"invalid storage class specified for field" <<
eom;
1019 final_type.
get_bool(ID_C_is_anonymous))
1022 if(final_type.
id()!=ID_union &&
1023 final_type.
id()!=ID_struct)
1026 error() <<
"member declaration does not declare anything" 1032 declaration, access, components);
1053 declaration, declarator, components,
1054 access, is_static, is_typedef, is_mutable);
1057 else if(it->id()==
"cpp-public")
1059 else if(it->id()==
"cpp-private")
1061 else if(it->id()==
"cpp-protected")
1062 access=ID_protected;
1080 dtor,
dtor.declarators()[0], components,
1081 ID_public,
false,
false,
false);
1085 if(symbol.
type.
id()==ID_struct)
1091 exprt cpp_public(
"cpp-public");
1102 type.get_bool(ID_C_class)?ID_private:ID_public;
1108 if(it->id()==ID_cpp_declaration)
1120 declarator.name().get_base_name();
1123 if(declarator.value().is_not_nil())
1125 if(declarator.find(ID_member_initializers).is_nil())
1126 declarator.set(ID_member_initializers, ID_member_initializers);
1131 declarator.member_initializers());
1135 declarator.member_initializers());
1147 declaration, declarator, components,
1148 access, is_static, is_typedef, is_mutable);
1151 else if(it->id()==
"cpp-public")
1153 else if(it->id()==
"cpp-private")
1155 else if(it->id()==
"cpp-protected")
1156 access=ID_protected;
1174 exprt value(
"cpp_not_typechecked");
1175 value.copy_to_operands(cpctor.
declarators()[0].value());
1181 ID_public,
false,
false,
false);
1201 ID_public,
false,
false,
false);
1210 irept &initializers,
1214 bool is_constructor=
1215 type.
find(ID_return_type).
id()==ID_constructor;
1218 if(!initializers.
get_sub().empty())
1222 initializers.
find(ID_C_source_location));
1227 error() <<
"only constructors are allowed to " 1228 <<
"have member initializers" <<
eom;
1235 error() <<
"only constructors with body are allowed to " 1236 <<
"have member initializers" <<
eom;
1242 exprt::operandst::iterator o_it=value.
operands().begin();
1245 o_it=value.
operands().insert(o_it, static_cast<const exprt &>(*it));
1252 const irep_idt &compound_identifier,
1254 irept &initializers,
1255 const typet &method_qualifier,
1262 if(component.
get_bool(ID_is_static))
1264 if(!method_qualifier.
id().
empty())
1267 error() <<
"method is static -- no qualifiers allowed" <<
eom;
1274 compound_identifier,
1296 type.
set(ID_C_inlined,
true);
1298 symbol.
name=identifier;
1314 error() <<
"failed to insert new method symbol: " 1315 << symbol.
name <<
"\n" 1316 <<
"name of previous symbol: " 1317 << new_symbol->
name <<
"\n" 1318 <<
"location of previous symbol: " 1336 const typet &method_qualifier)
1352 subtype.
set(ID_C_constant,
true);
1355 subtype.
set(ID_C_volatile,
true);
1361 const symbolt &struct_union_symbol)
1373 for(
const auto &comp : struct_union_components)
1375 if(comp.type().id()==ID_code)
1378 error() <<
"anonymous struct/union member `" 1380 <<
"' shall not have function members" <<
eom;
1384 if(comp.get_anonymous())
1386 const symbolt &symbol=
lookup(comp.type().get(ID_identifier));
1392 const irep_idt &base_name=comp.get_base_name();
1397 error() <<
"`" << base_name <<
"' already in scope" <<
eom;
1403 id.identifier=comp.get_name();
1404 id.class_identifier=struct_union_symbol.
name;
1422 error() <<
"storage class is not allowed here" <<
eom;
1429 error() <<
"anonymous struct/union member is not POD" <<
eom;
1434 irep_idt base_name=
"#anon_member"+std::to_string(components.size());
1440 typet symbol_type(ID_symbol);
1441 symbol_type.
set(ID_identifier, struct_union_symbol.
name);
1444 component.
set(ID_name, identifier);
1445 component.
type()=symbol_type;
1452 components.push_back(component);
1458 struct_union_symbol.
type.
set(
"#unnamed_object", base_name);
1463 const exprt &
object,
1469 assert(followed_type.
id()==ID_struct ||
1470 followed_type.
id()==ID_union);
1476 final_type.components();
1478 for(
const auto &component : components)
1480 exprt tmp(ID_member, component.type());
1481 tmp.
set(ID_component_name, component.get_name());
1482 tmp.add_source_location()=source_location;
1483 tmp.copy_to_operands(
object);
1485 if(component.get_name()==component_name)
1494 member.
set(
"#not_accessible",
true);
1495 member.
set(ID_C_access, component.get(ID_access));
1501 str <<
"error: member `" << component_name
1502 <<
"' is not accessible (" << component.get(ID_access) <<
")";
1503 str <<
"\nstruct name: " << final_type.get(ID_name);
1509 if(
object.get_bool(ID_C_lvalue))
1510 member.
set(ID_C_lvalue,
true);
1512 if(
object.type().get_bool(ID_C_constant) &&
1513 !component.get_bool(
"is_mutable"))
1514 member.
type().
set(ID_C_constant,
true);
1525 const typet &component_type=
follow(component.type());
1527 if(component_type.
id()==ID_union ||
1528 component_type.
id()==ID_struct)
1531 if(
get_component(source_location, tmp, component_name, member))
1537 str <<
"error: member `" << component_name
1538 <<
"' is not accessible";
1543 if(
object.get_bool(ID_C_lvalue))
1544 member.
set(ID_C_lvalue,
true);
1546 if(
object.get_bool(ID_C_constant) &&
1547 !component.get_bool(
"is_mutable"))
1548 member.
type().
set(ID_C_constant,
true);
1566 if(access==
"noaccess")
1569 if(access==ID_public)
1572 assert(access==ID_private ||
1573 access==ID_protected);
1576 struct_union_type.
get(ID_name);
1604 const irept &friend_symb=*f_it;
1628 std::set<irep_idt> &set_bases)
const 1634 assert(it->id()==ID_base);
1635 assert(it->get(ID_type)==ID_symbol);
1640 set_bases.insert(base.get(ID_name));
1647 std::list<irep_idt> &vbases)
const 1649 if(std::find(vbases.begin(), vbases.end(), type.
get(ID_name))!=vbases.end())
1656 assert(it->id()==ID_base);
1657 assert(it->get(ID_type)==ID_symbol);
1662 if(it->get_bool(ID_virtual))
1663 vbases.push_back(base.get(ID_name));
1673 if(from.
get(ID_name)==to.
get(ID_name))
1676 std::set<irep_idt> bases;
1680 return bases.find(to.
get(ID_name))!=bases.end();
1685 const typet &dest_type)
1689 assert(src_type.
id()== ID_pointer);
1690 assert(dest_type.
id()== ID_pointer);
C++ Language Type Checking.
const irep_idt & get_name() const
The type of an expression.
irep_idt name
The unique identifier.
void add_anonymous_members_to_scope(const symbolt &struct_union_symbol)
#define forall_subtypes(it, type)
const typet & follow(const typet &src) const
bool find_cpctor(const symbolt &symbol) const
void check_fixed_size_array(typet &type)
check that an array has fixed size
virtual bool lookup(const irep_idt &name, const symbolt *&symbol) const
codet dtor(const symbolt &symb)
produces destructor code for a class object
void typecheck_type(typet &type)
const std::string & id2string(const irep_idt &d)
pointer_typet pointer_type(const typet &subtype)
const cpp_storage_spect & storage_spec() const
std::set< cpp_idt * > id_sett
void lookup(const irep_idt &base_name, lookup_kindt kind, id_sett &id_set)
static bool has_const(const typet &type)
bool is_destructor() const
std::vector< irept > subt
irep_idt mode
Language mode.
void move_to_sub(irept &irep)
void name_anon_struct_union()
void get_bases(const struct_typet &type, std::set< irep_idt > &set_bases) const
void set_base_name(const irep_idt &base_name)
void set_name(const irep_idt &name)
void full_member_initialization(const struct_union_typet &struct_union_type, irept &initializers)
Build the full initialization list of the constructor.
bool check_component_access(const struct_union_typet::componentt &component, const struct_union_typet &struct_union_type)
cpp_namet & to_cpp_name(irept &cpp_name)
std::vector< componentt > componentst
void move_to_operands(exprt &expr)
cpp_scopet & get_parent() const
std::vector< parametert > parameterst
exprt value
Initial value of symbol.
const componentst & components() const
cpp_idt & put_into_scope(const symbolt &symbol, cpp_scopet &scope, bool is_friend=false)
irep_idt module
Name of module the symbol belongs to.
irep_idt pretty_name
Language-specific display name.
void default_dtor(const symbolt &symb, cpp_declarationt &dtor)
Note:
void move_member_initializers(irept &initializers, const typet &type, exprt &value)
void add_this_to_method_type(const irep_idt &compound_identifier, typet &method_type, const typet &method_qualifier)
cpp_scopet & get_global_scope()
bool is_simple_name() const
typet merge_type(const typet &declaration_type) const
Symbol table entry.This is a symbol in the symbol table, stored in an object of type symbol_tablet...
static mstreamt & eom(mstreamt &m)
void check_member_initializers(const irept &bases, const struct_typet::componentst &components, const irept &initializers)
Check a constructor initialization-list.
bool get_bool(const irep_namet &name) const
const cpp_member_spect & member_spec() const
void set_inline(bool value)
void set_base_name(const irep_idt &name)
void typecheck_compound_declarator(const symbolt &symbol, const cpp_declarationt &declaration, cpp_declaratort &declarator, struct_typet::componentst &components, const irep_idt &access, bool is_static, bool is_typedef, bool is_mutable)
symbol_tablet & symbol_table
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a generic typet to a struct_union_typet.
const irep_idt & get_base_name() const
void add_method_body(symbolt *_method_symbol)
const irep_idt & id() const
const source_locationt & source_location() const
const array_typet & to_array_type(const typet &type)
Cast a generic typet to an array_typet.
const irep_idt & get_base_name() const
void elaborate_class_template(const typet &type)
elaborate class template instances
class code_blockt & make_block()
const declaratorst & declarators() const
source_locationt & location()
A reference into the symbol table.
source_locationt source_location
bool cpp_is_pod(const typet &type) const
void set_access(const irep_idt &access)
void typecheck_friend_declaration(symbolt &symbol, cpp_declarationt &cpp_declaration)
void write(typet &src) const
const irep_idt & get(const irep_namet &name) const
void go_to_global_scope()
void typecheck_member_function(const irep_idt &compound_identifier, struct_typet::componentt &component, irept &initializers, const typet &method_qualifier, exprt &value)
void do_virtual_table(const symbolt &symbol)
std::string cpp_type2name(const typet &type)
namespacet(const symbol_tablet &_symbol_table)
const exprt & size() const
Base class for tree-like data structures with sharing.
void convert_template_declaration(cpp_declarationt &declaration)
C++ Language Type Checking.
bool is_constructor() const
bool move(symbolt &symbol, symbolt *&new_symbol)
Move a symbol into the symbol table.
void default_assignop(const symbolt &symbol, cpp_declarationt &cpctor)
Generate declaration of the implicit default assignment operator.
bool has_operands() const
void default_cpctor(const symbolt &, cpp_declarationt &cpctor) const
Generate code for implicit default copy constructor.
void make_ptr_typecast(exprt &expr, const typet &dest_type)
std::vector< exprt > operandst
const struct_typet & to_struct_type(const typet &type)
Cast a generic typet to a struct_typet.
const source_locationt & source_location() const
irep_idt get_base_name() const
cpp_scopet & set_scope(const irep_idt &identifier)
A function call side effect.
bool get_component(const source_locationt &source_location, const exprt &object, const irep_idt &component_name, exprt &member)
irep_idt function_identifier(const typet &type)
for function overloading
typet type
Type of symbol.
source_locationt location
Source code location of definition of symbol.
cpp_declarationt & to_cpp_declaration(irept &irep)
void set_identifier(const irep_idt &identifier)
bool subtype_typecast(const struct_typet &from, const struct_typet &to) const
void typecheck_compound_bases(struct_typet &type)
Base type of C structs and unions, and C++ classes.
void default_ctor(const source_locationt &source_location, const irep_idt &base_name, cpp_declarationt &ctor) const
Generate code for implicit default constructors.
bool find_assignop(const symbolt &symbol) const
Base class for all expressions.
void get_virtual_bases(const struct_typet &type, std::list< irep_idt > &vbases) const
bool contains(const irep_idt &base_name)
const parameterst & parameters() const
irep_idt base_name
Base (non-scoped) name.
cpp_scopet & current_scope()
irept & member_initializers()
void set_pretty_name(const irep_idt &name)
symbolt & convert(const typet &type, const cpp_storage_spect &storage_spec, const cpp_member_spect &member_spec, cpp_declaratort &declarator)
const source_locationt & source_location() const
virtual void make_constant_index(exprt &expr)
irept & add(const irep_namet &name)
void typecheck_compound_type(struct_union_typet &type)
const std::string & get_string(const irep_namet &name) const
exprt::operandst & arguments()
const code_typet & to_code_type(const typet &type)
Cast a generic typet to a code_typet.
void set_identifier(const irep_idt &identifier)
dynamic_initializationst dynamic_initializations
const std::string & id_string() const
bool disable_access_control
#define Forall_operands(it, expr)
source_locationt & add_source_location()
const codet & to_code(const exprt &expr)
void typecheck_compound_body(symbolt &symbol)
Expression to hold a symbol (variable)
void set_anonymous(bool anonymous)
cpp_scopet & get_scope(const irep_idt &identifier)
const char * c_str() const
virtual void do_initializer(exprt &initializer, const typet &type, bool force_constant)
void put_compound_into_scope(const struct_union_typet::componentt &component)
A statement in a programming language.
exprt cpp_symbol_expr(const symbolt &symbol)
void remove(const irep_namet &name)
const typet & subtype() const
static bool has_volatile(const typet &type)
bool is_root_scope() const
void convert_anon_struct_union_member(const cpp_declarationt &declaration, const irep_idt &access, struct_typet::componentst &components)
cpp_idt & insert(const irep_idt &_base_name)
std::set< cpp_idt * > id_sett
void make_typecast(const typet &_type)
const irept & find(const irep_namet &name) const
cpp_scopet & tag_scope(const irep_idt &_base_name, bool has_body, bool tag_only_declaration)
const typet & return_type() const
codet cpp_constructor(const source_locationt &source_location, const exprt &object, const exprt::operandst &operands)
bool is_template_scope() const
void set(const irep_namet &name, const irep_idt &value)
bool simplify(exprt &expr, const namespacet &ns)
cpp_scopet & resolve_scope(const cpp_namet &cpp_name, irep_idt &base_name, cpp_template_args_non_tct &template_args)
#define forall_irep(it, irep)