diff --git a/src/cpp/cpp_declarator_converter.cpp b/src/cpp/cpp_declarator_converter.cpp index 13c23af732a..6b773c072e0 100644 --- a/src/cpp/cpp_declarator_converter.cpp +++ b/src/cpp/cpp_declarator_converter.cpp @@ -152,20 +152,16 @@ symbolt &cpp_declarator_convertert::convert( irep_idt identifier=symbol_expr.type().get(ID_identifier); const symbolt &symb=cpp_typecheck.lookup(identifier); - const typet &type = symb.type; - assert(type.id()==ID_struct); + const struct_typet &type = to_struct_type(symb.type); if(declarator.find(ID_member_initializers).is_nil()) declarator.set(ID_member_initializers, ID_member_initializers); cpp_typecheck.check_member_initializers( - type.find(ID_bases), - to_struct_type(type).components(), - declarator.member_initializers()); + type.bases(), type.components(), declarator.member_initializers()); cpp_typecheck.full_member_initialization( - to_struct_type(type), - declarator.member_initializers()); + type, declarator.member_initializers()); } if(!storage_spec.is_extern()) diff --git a/src/cpp/cpp_exception_id.cpp b/src/cpp/cpp_exception_id.cpp index f06f221f3c5..7899d03f999 100644 --- a/src/cpp/cpp_exception_id.cpp +++ b/src/cpp/cpp_exception_id.cpp @@ -12,6 +12,7 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include "cpp_exception_id.h" #include +#include /// turns a type into a list of relevant exception IDs void cpp_exception_list_rec( @@ -48,13 +49,8 @@ void cpp_exception_list_rec( dest.push_back("struct_"+src.get_string(ID_tag)); // now do any bases, recursively - const irept::subt &bases=src.find(ID_bases).get_sub(); - - forall_irep(it, bases) - { - const typet &type=static_cast(it->find(ID_type)); - cpp_exception_list_rec(type, ns, suffix, dest); - } + for(const auto &b : to_struct_type(src).bases()) + cpp_exception_list_rec(b.type(), ns, suffix, dest); } else { diff --git a/src/cpp/cpp_typecheck.h b/src/cpp/cpp_typecheck.h index 1c38c0fce2f..9fbd7268dbf 100644 --- a/src/cpp/cpp_typecheck.h +++ b/src/cpp/cpp_typecheck.h @@ -262,7 +262,7 @@ class cpp_typecheckt:public c_typecheck_baset codet dtor(const symbolt &symb); void check_member_initializers( - const irept &bases, + const struct_typet::basest &bases, const struct_typet::componentst &components, const irept &initializers); diff --git a/src/cpp/cpp_typecheck_bases.cpp b/src/cpp/cpp_typecheck_bases.cpp index c916eb0f290..65fba0fe523 100644 --- a/src/cpp/cpp_typecheck_bases.cpp +++ b/src/cpp/cpp_typecheck_bases.cpp @@ -141,19 +141,18 @@ void cpp_typecheckt::add_base_components( vbases.insert(from_name); // look at the the parents of the base type - forall_irep(it, from.find(ID_bases).get_sub()) + for(const auto &b : from.bases()) { - irep_idt sub_access=it->get(ID_access); + irep_idt sub_access = b.get(ID_access); if(access==ID_private) sub_access=ID_private; else if(access==ID_protected && sub_access!=ID_private) sub_access=ID_protected; - const symbolt &symb= - lookup(it->find(ID_type).get(ID_identifier)); + const symbolt &symb = lookup(to_symbol_type(b.type()).get_identifier()); - bool is_virtual=it->get_bool(ID_virtual); + const bool is_virtual = b.get_bool(ID_virtual); // recursive call add_base_components( diff --git a/src/cpp/cpp_typecheck_compound_type.cpp b/src/cpp/cpp_typecheck_compound_type.cpp index af0e30800df..103d5858217 100644 --- a/src/cpp/cpp_typecheck_compound_type.cpp +++ b/src/cpp/cpp_typecheck_compound_type.cpp @@ -1135,10 +1135,18 @@ void cpp_typecheckt::typecheck_compound_body(symbolt &symbol) if(declarator.find(ID_member_initializers).is_nil()) declarator.set(ID_member_initializers, ID_member_initializers); - check_member_initializers( - type.add(ID_bases), - type.components(), - declarator.member_initializers()); + if(type.id() == ID_union) + { + check_member_initializers( + {}, type.components(), declarator.member_initializers()); + } + else + { + check_member_initializers( + to_struct_type(type).bases(), + type.components(), + declarator.member_initializers()); + } full_member_initialization( type, @@ -1634,15 +1642,12 @@ void cpp_typecheckt::get_bases( const struct_typet &type, std::set &set_bases) const { - const irept::subt &bases=type.find(ID_bases).get_sub(); - - forall_irep(it, bases) + for(const auto &b : type.bases()) { - assert(it->id()==ID_base); - assert(it->get(ID_type) == ID_symbol_type); + DATA_INVARIANT(b.id() == ID_base, "base class expression expected"); - const struct_typet &base= - to_struct_type(lookup(it->find(ID_type).get(ID_identifier)).type); + const struct_typet &base = + to_struct_type(lookup(to_symbol_type(b.type()).get_identifier()).type); set_bases.insert(base.get(ID_name)); get_bases(base, set_bases); @@ -1656,17 +1661,14 @@ void cpp_typecheckt::get_virtual_bases( if(std::find(vbases.begin(), vbases.end(), type.get(ID_name))!=vbases.end()) return; - const irept::subt &bases=type.find(ID_bases).get_sub(); - - forall_irep(it, bases) + for(const auto &b : type.bases()) { - assert(it->id()==ID_base); - assert(it->get(ID_type) == ID_symbol_type); + DATA_INVARIANT(b.id() == ID_base, "base class expression expected"); - const struct_typet &base= - to_struct_type(lookup(it->find(ID_type).get(ID_identifier)).type); + const struct_typet &base = + to_struct_type(lookup(to_symbol_type(b.type()).get_identifier()).type); - if(it->get_bool(ID_virtual)) + if(b.get_bool(ID_virtual)) vbases.push_back(base.get(ID_name)); get_virtual_bases(base, vbases); diff --git a/src/cpp/cpp_typecheck_constructor.cpp b/src/cpp/cpp_typecheck_constructor.cpp index f9784bc9a42..d4a51223886 100644 --- a/src/cpp/cpp_typecheck_constructor.cpp +++ b/src/cpp/cpp_typecheck_constructor.cpp @@ -186,14 +186,11 @@ void cpp_typecheckt::default_cpctor( exprt &block=declarator.value(); // First, we need to call the parent copy constructors - const irept &bases=symbol.type.find(ID_bases); - forall_irep(parent_it, bases.get_sub()) + for(const auto &b : to_struct_type(symbol.type).bases()) { - assert(parent_it->id()==ID_base); - assert(parent_it->get(ID_type) == ID_symbol_type); + DATA_INVARIANT(b.id() == ID_base, "base class expression expected"); - const symbolt &parsymb= - lookup(parent_it->find(ID_type).get(ID_identifier)); + const symbolt &parsymb = lookup(to_symbol_type(b.type()).get_identifier()); if(cpp_is_pod(parsymb.type)) copy_parent(source_location, parsymb.base_name, param_identifier, block); @@ -358,15 +355,11 @@ void cpp_typecheckt::default_assignop_value( std::string arg_name("ref"); // First, we copy the parents - const irept &bases=symbol.type.find(ID_bases); - - forall_irep(parent_it, bases.get_sub()) + for(const auto &b : to_struct_type(symbol.type).bases()) { - assert(parent_it->id()==ID_base); - assert(parent_it->get(ID_type) == ID_symbol_type); + DATA_INVARIANT(b.id() == ID_base, "base class expression expected"); - const symbolt &symb= - lookup(parent_it->find(ID_type).get(ID_identifier)); + const symbolt &symb = lookup(to_symbol_type(b.type()).get_identifier()); copy_parent(source_location, symb.base_name, arg_name, block); } @@ -426,7 +419,7 @@ void cpp_typecheckt::default_assignop_value( /// \return If an invalid initializer is found, then the method outputs an error /// message and throws a 0 exception. void cpp_typecheckt::check_member_initializers( - const irept &bases, + const struct_typet::basest &bases, const struct_typet::componentst &components, const irept &initializers) { @@ -450,12 +443,11 @@ void cpp_typecheckt::check_member_initializers( // check for a direct parent bool ok=false; - forall_irep(parent_it, bases.get_sub()) + for(const auto &b : bases) { - assert(parent_it->get(ID_type) == ID_symbol_type); - - if(member_type.get(ID_identifier) - ==parent_it->find(ID_type).get(ID_identifier)) + if( + to_symbol_type(member_type).get_identifier() == + to_symbol_type(b.type()).get_identifier()) { ok=true; break; @@ -500,10 +492,9 @@ void cpp_typecheckt::check_member_initializers( break; // check for a direct parent - forall_irep(parent_it, bases.get_sub()) + for(const auto &b : bases) { - assert(parent_it->get(ID_type) == ID_symbol_type); - if(symb.name==parent_it->find(ID_type).get(ID_identifier)) + if(symb.name == to_symbol_type(b.type()).get_identifier()) { ok=true; break; @@ -522,12 +513,11 @@ void cpp_typecheckt::check_member_initializers( typecheck_type(member_type); // check for a direct parent - forall_irep(parent_it, bases.get_sub()) + for(const auto &b : bases) { - assert(parent_it->get(ID_type) == ID_symbol_type); - - if(member_type.get(ID_identifier)== - parent_it->find(ID_type).get(ID_identifier)) + if( + member_type.get(ID_identifier) == + to_symbol_type(b.type()).get_identifier()) { ok=true; break; @@ -600,16 +590,13 @@ void cpp_typecheckt::full_member_initialization( final_initializers.move_to_sub(cond); } - const irept &bases=struct_union_type.find(ID_bases); - // Subsequently, we need to call the non-POD parent constructors - forall_irep(parent_it, bases.get_sub()) + for(const auto &b : to_struct_type(struct_union_type).bases()) { - assert(parent_it->id()==ID_base); - assert(parent_it->get(ID_type) == ID_symbol_type); + DATA_INVARIANT(b.id() == ID_base, "base class expression expected"); - const symbolt &ctorsymb= - lookup(parent_it->find(ID_type).get(ID_identifier)); + const symbolt &ctorsymb = + lookup(to_symbol_type(b.type()).get_identifier()); if(cpp_is_pod(ctorsymb.type)) continue; @@ -659,8 +646,9 @@ void cpp_typecheckt::full_member_initialization( if(member_type.id() != ID_symbol_type) break; - if(parent_it->find(ID_type).get(ID_identifier)== - member_type.get(ID_identifier)) + if( + to_symbol_type(b.type()).get_identifier() == + to_symbol_type(member_type).get_identifier()) { final_initializers.move_to_sub(initializer); found=true; @@ -678,7 +666,7 @@ void cpp_typecheckt::full_member_initialization( final_initializers.move_to_sub(mem_init); } - if(parent_it->get_bool(ID_virtual)) + if(b.get_bool(ID_virtual)) { // TODO(tautschnig): this code doesn't seem to make much sense as the // ifthenelse only gets to have two operands (instead of three) diff --git a/src/cpp/cpp_typecheck_destructor.cpp b/src/cpp/cpp_typecheck_destructor.cpp index 8ec66f61ef2..d80cffd33b2 100644 --- a/src/cpp/cpp_typecheck_destructor.cpp +++ b/src/cpp/cpp_typecheck_destructor.cpp @@ -130,17 +130,18 @@ codet cpp_typecheckt::dtor(const symbolt &symbol) block.move_to_operands(dtor_code.value()); } - const irept::subt &bases=symbol.type.find(ID_bases).get_sub(); + if(symbol.type.id() == ID_union) + return block; + + const auto &bases = to_struct_type(symbol.type).bases(); // call the base destructors in the reverse order - for(irept::subt::const_reverse_iterator - bit=bases.rbegin(); - bit!=bases.rend(); + for(class_typet::basest::const_reverse_iterator bit = bases.rbegin(); + bit != bases.rend(); bit++) { - assert(bit->id()==ID_base); - assert(bit->find(ID_type).id() == ID_symbol_type); - const symbolt &psymb = lookup(bit->find(ID_type).get(ID_identifier)); + DATA_INVARIANT(bit->id() == ID_base, "base class expression expected"); + const symbolt &psymb = lookup(to_symbol_type(bit->type()).get_identifier()); symbol_exprt this_ptr(ID_this, pointer_type(symbol.type)); dereference_exprt object(this_ptr, psymb.type); diff --git a/src/cpp/cpp_typecheck_expr.cpp b/src/cpp/cpp_typecheck_expr.cpp index 0839de873c3..25b6b1337f2 100644 --- a/src/cpp/cpp_typecheck_expr.cpp +++ b/src/cpp/cpp_typecheck_expr.cpp @@ -33,11 +33,12 @@ bool cpp_typecheckt::find_parent( const irep_idt &base_name, irep_idt &identifier) { - forall_irep(bit, symb.type.find(ID_bases).get_sub()) + for(const auto &b : to_struct_type(symb.type).bases()) { - if(lookup(bit->find(ID_type).get(ID_identifier)).base_name == base_name) + const irep_idt &id = to_symbol_type(b.type()).get_identifier(); + if(lookup(id).base_name == base_name) { - identifier=bit->find(ID_type).get(ID_identifier); + identifier = id; return true; } } diff --git a/src/goto-programs/class_hierarchy.cpp b/src/goto-programs/class_hierarchy.cpp index 99d92c33694..3e4ecf96589 100644 --- a/src/goto-programs/class_hierarchy.cpp +++ b/src/goto-programs/class_hierarchy.cpp @@ -43,9 +43,9 @@ void class_hierarchy_grapht::populate(const symbol_tablet &symbol_table) { if(symbol_pair.second.is_type && symbol_pair.second.type.id() == ID_struct) { - const class_typet &class_type = to_class_type(symbol_pair.second.type); + const struct_typet &struct_type = to_struct_type(symbol_pair.second.type); - for(const auto &base : class_type.bases()) + for(const auto &base : struct_type.bases()) { const irep_idt &parent = to_symbol_type(base.type()).get_identifier(); if(!parent.empty()) @@ -157,11 +157,9 @@ void class_hierarchyt::operator()(const symbol_tablet &symbol_table) class_map[symbol_pair.first].is_abstract = struct_type.get_bool(ID_abstract); - const irept::subt &bases = struct_type.find(ID_bases).get_sub(); - - for(const auto &base : bases) + for(const auto &base : struct_type.bases()) { - irep_idt parent = base.find(ID_type).get(ID_identifier); + const irep_idt &parent = to_symbol_type(base.type()).get_identifier(); if(parent.empty()) continue; diff --git a/src/util/std_types.h b/src/util/std_types.h index da69871144f..c4b18bbbc6f 100644 --- a/src/util/std_types.h +++ b/src/util/std_types.h @@ -280,6 +280,67 @@ class struct_typet:public struct_union_typet } bool is_prefix_of(const struct_typet &other) const; + + /// A struct may be a class, where members may have access restrictions. + bool is_class() const + { + return get_bool(ID_C_class); + } + + /// Base class or struct that a class or struct inherits from. + class baset : public exprt + { + public: + baset() : exprt(ID_base) + { + } + + explicit baset(const typet &base) : exprt(ID_base, base) + { + } + }; + + typedef std::vector basest; + + /// Get the collection of base classes/structs. + const basest &bases() const + { + return (const basest &)find(ID_bases).get_sub(); + } + + /// Get the collection of base classes/structs. + basest &bases() + { + return (basest &)add(ID_bases).get_sub(); + } + + /// Add a base class/struct + /// \param base: Type of case/class struct to be added. + void add_base(const symbol_typet &base) + { + bases().push_back(baset(base)); + } + + /// Return the base with the given name, if exists. + /// \param id The name of the base we are looking for. + /// \return The base if exists. + optionalt get_base(const irep_idt &id) const + { + for(const auto &b : bases()) + { + if(to_symbol_type(b.type()).get_identifier() == id) + return b; + } + return {}; + } + + /// Test whether `id` is a base class/struct. + /// \param id: symbol type name + /// \return True if, and only if, the symbol type `id` is a base class/struct. + bool has_base(const irep_idt &id) const + { + return get_base(id).has_value(); + } }; /// Check whether a reference to a typet is a \ref struct_typet. @@ -336,53 +397,6 @@ class class_typet:public struct_typet return (methodst &)(add(ID_methods).get_sub()); } - class baset:public exprt - { - public: - baset():exprt(ID_base) - { - } - - explicit baset(const typet &base):exprt(ID_base, base) - { - } - }; - - typedef std::vector basest; - - const basest &bases() const - { - return (const basest &)find(ID_bases).get_sub(); - } - - basest &bases() - { - return (basest &)add(ID_bases).get_sub(); - } - - void add_base(const typet &base) - { - bases().push_back(baset(base)); - } - - /// Return the base with the given name, if exists. - /// \param id The name of the base we are looking for. - /// \return The base if exists. - optionalt get_base(const irep_idt &id) const - { - for(const auto &b : bases()) - { - if(to_symbol_type(b.type()).get_identifier() == id) - return b; - } - return {}; - } - - bool has_base(const irep_idt &id) const - { - return get_base(id).has_value(); - } - bool is_abstract() const { return get_bool(ID_abstract);