diff --git a/src/cpp/cpp_constructor.cpp b/src/cpp/cpp_constructor.cpp index 205ec052dd8..b10f5cdfe55 100644 --- a/src/cpp/cpp_constructor.cpp +++ b/src/cpp/cpp_constructor.cpp @@ -30,10 +30,9 @@ std::optional cpp_typecheckt::cpp_constructor( elaborate_class_template(object_tc.type()); - typet tmp_type(follow(object_tc.type())); - CHECK_RETURN(!is_reference(tmp_type)); + CHECK_RETURN(!is_reference(object_tc.type())); - if(tmp_type.id()==ID_array) + if(object_tc.type().id() == ID_array) { // We allow only one operand and it must be tagged with '#array_ini'. // Note that the operand is an array that is used for copy-initialization. @@ -53,11 +52,10 @@ std::optional cpp_typecheckt::cpp_constructor( operands.empty() || operands.size() == 1, "array constructor must have at most one operand"); - if(operands.empty() && cpp_is_pod(tmp_type)) + if(operands.empty() && cpp_is_pod(object_tc.type())) return {}; - const exprt &size_expr= - to_array_type(tmp_type).size(); + const exprt &size_expr = to_array_type(object_tc.type()).size(); if(size_expr.id() == ID_infinity) return {}; // don't initialize @@ -74,7 +72,7 @@ std::optional cpp_typecheckt::cpp_constructor( throw 0; } - /*if(cpp_is_pod(tmp_type)) + /*if(cpp_is_pod(object_tc.type())) { code_expressiont new_code; exprt op_tc=operands.front(); @@ -119,7 +117,7 @@ std::optional cpp_typecheckt::cpp_constructor( return std::move(new_code); } } - else if(cpp_is_pod(tmp_type)) + else if(cpp_is_pod(object_tc.type())) { exprt::operandst operands_tc=operands; @@ -152,11 +150,11 @@ std::optional cpp_typecheckt::cpp_constructor( throw 0; } } - else if(tmp_type.id()==ID_union) + else if(object_tc.type().id() == ID_union_tag) { UNREACHABLE; // Todo: union } - else if(tmp_type.id()==ID_struct) + else if(object_tc.type().id() == ID_struct_tag) { exprt::operandst operands_tc=operands; @@ -166,8 +164,8 @@ std::optional cpp_typecheckt::cpp_constructor( add_implicit_dereference(op); } - const struct_typet &struct_type= - to_struct_type(tmp_type); + const struct_typet &struct_type = + follow_tag(to_struct_tag_type(object_tc.type())); // set most-derived bits code_blockt block; diff --git a/src/cpp/cpp_destructor.cpp b/src/cpp/cpp_destructor.cpp index 5f2ee3dbe16..a03364ccb0e 100644 --- a/src/cpp/cpp_destructor.cpp +++ b/src/cpp/cpp_destructor.cpp @@ -22,17 +22,15 @@ std::optional cpp_typecheckt::cpp_destructor( { elaborate_class_template(object.type()); - typet tmp_type(follow(object.type())); - CHECK_RETURN(!is_reference(tmp_type)); + CHECK_RETURN(!is_reference(object.type())); // PODs don't need a destructor - if(cpp_is_pod(tmp_type)) + if(cpp_is_pod(object.type())) return {}; - if(tmp_type.id()==ID_array) + if(object.type().id() == ID_array) { - const exprt &size_expr= - to_array_type(tmp_type).size(); + const exprt &size_expr = to_array_type(object.type()).size(); if(size_expr.id() == ID_infinity) return {}; // don't initialize @@ -70,8 +68,8 @@ std::optional cpp_typecheckt::cpp_destructor( } else { - const struct_typet &struct_type= - to_struct_type(tmp_type); + const struct_typet &struct_type = + follow_tag(to_struct_tag_type(object.type())); // enter struct scope cpp_save_scopet save_scope(cpp_scopes); diff --git a/src/cpp/cpp_typecheck.cpp b/src/cpp/cpp_typecheck.cpp index 6f888c1cb79..a6dd67ba4b8 100644 --- a/src/cpp/cpp_typecheck.cpp +++ b/src/cpp/cpp_typecheck.cpp @@ -67,9 +67,9 @@ const struct_typet &cpp_typecheckt::this_struct_type() CHECK_RETURN(this_expr.is_not_nil()); CHECK_RETURN(this_expr.type().id() == ID_pointer); - const typet &t = follow(to_pointer_type(this_expr.type()).base_type()); - CHECK_RETURN(t.id() == ID_struct); - return to_struct_type(t); + const typet &t = to_pointer_type(this_expr.type()).base_type(); + CHECK_RETURN(t.id() == ID_struct_tag); + return follow_tag(to_struct_tag_type(t)); } std::string cpp_typecheckt::to_string(const exprt &expr) diff --git a/src/cpp/cpp_typecheck.h b/src/cpp/cpp_typecheck.h index 0e64a2f38cb..60f59a0b10d 100644 --- a/src/cpp/cpp_typecheck.h +++ b/src/cpp/cpp_typecheck.h @@ -25,6 +25,9 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include #include +class pointer_typet; +class reference_typet; + bool cpp_typecheck( cpp_parse_treet &cpp_parse_tree, symbol_table_baset &symbol_table, @@ -524,14 +527,18 @@ class cpp_typecheckt:public c_typecheck_baset bool user_defined_conversion_sequence( const exprt &expr, const typet &type, exprt &new_expr, unsigned &rank); - bool reference_related( - const exprt &expr, const typet &type) const; + bool reference_related(const exprt &expr, const reference_typet &type) const; bool reference_compatible( - const exprt &expr, const typet &type, unsigned &rank) const; + const exprt &expr, + const reference_typet &type, + unsigned &rank) const; bool reference_binding( - exprt expr, const typet &type, exprt &new_expr, unsigned &rank); + exprt expr, + const reference_typet &type, + exprt &new_expr, + unsigned &rank); bool implicit_conversion_sequence( const exprt &expr, const typet &type, exprt &new_expr, unsigned &rank); @@ -542,7 +549,7 @@ class cpp_typecheckt:public c_typecheck_baset bool implicit_conversion_sequence( const exprt &expr, const typet &type, exprt &new_expr); - void reference_initializer(exprt &expr, const typet &type); + void reference_initializer(exprt &expr, const reference_typet &type); void implicit_typecast(exprt &expr, const typet &type) override; @@ -556,9 +563,7 @@ class cpp_typecheckt:public c_typecheck_baset const struct_typet &from, const struct_typet &to) const; - void make_ptr_typecast( - exprt &expr, - const typet &dest_type); + void make_ptr_typecast(exprt &expr, const pointer_typet &dest_type); // the C++ typecasts diff --git a/src/cpp/cpp_typecheck_code.cpp b/src/cpp/cpp_typecheck_code.cpp index d09f36e21d4..b43e8c966b1 100644 --- a/src/cpp/cpp_typecheck_code.cpp +++ b/src/cpp/cpp_typecheck_code.cpp @@ -9,15 +9,15 @@ Author: Daniel Kroening, kroening@cs.cmu.edu /// \file /// C++ Language Type Checking -#include "cpp_typecheck.h" - #include #include +#include #include #include #include "cpp_declarator_converter.h" #include "cpp_exception_id.h" +#include "cpp_typecheck.h" #include "cpp_typecheck_fargs.h" #include "cpp_util.h" @@ -258,8 +258,7 @@ void cpp_typecheckt::typecheck_member_initializer(codet &code) PRECONDITION(this_expr.is_not_nil()); make_ptr_typecast( - this_expr, - code_type.parameters().front().type()); + this_expr, to_pointer_type(code_type.parameters().front().type())); function_call.arguments().push_back(this_expr); @@ -354,7 +353,8 @@ void cpp_typecheckt::typecheck_member_initializer(codet &code) throw 0; } - reference_initializer(code.op0(), symbol_expr.type()); + reference_initializer( + code.op0(), to_reference_type(symbol_expr.type())); // assign the pointers symbol_expr.type().remove(ID_C_reference); @@ -421,8 +421,13 @@ void cpp_typecheckt::typecheck_decl(codet &code) CHECK_RETURN(type.is_not_nil()); - if(declaration.declarators().empty() && - follow(type).get_bool(ID_C_is_anonymous)) + if( + declaration.declarators().empty() && + ((type.id() == ID_struct_tag && + follow_tag(to_struct_tag_type(type)).get_bool(ID_C_is_anonymous)) || + (type.id() == ID_union_tag && + follow_tag(to_union_tag_type(type)).get_bool(ID_C_is_anonymous)) || + type.get_bool(ID_C_is_anonymous))) { if(type.id() != ID_union_tag) { @@ -470,8 +475,7 @@ void cpp_typecheckt::typecheck_decl(codet &code) { decl_statement.copy_to_operands(symbol.value); DATA_INVARIANT( - has_auto(symbol.type) || - follow(decl_statement.op1().type()) == follow(symbol.type), + has_auto(symbol.type) || decl_statement.op1().type() == symbol.type, "declarator type should match symbol type"); } diff --git a/src/cpp/cpp_typecheck_compound_type.cpp b/src/cpp/cpp_typecheck_compound_type.cpp index 5672216392c..feeb1c6b162 100644 --- a/src/cpp/cpp_typecheck_compound_type.cpp +++ b/src/cpp/cpp_typecheck_compound_type.cpp @@ -1019,15 +1019,21 @@ void cpp_typecheckt::typecheck_compound_body(symbolt &symbol) throw 0; } - typet final_type=follow(declaration.type()); - // anonymous member? - if(declaration.declarators().empty() && - final_type.get_bool(ID_C_is_anonymous)) + if( + declaration.declarators().empty() && + ((declaration.type().id() == ID_struct_tag && + follow_tag(to_struct_tag_type(declaration.type())) + .get_bool(ID_C_is_anonymous)) || + (declaration.type().id() == ID_union_tag && + follow_tag(to_union_tag_type(declaration.type())) + .get_bool(ID_C_is_anonymous)) || + declaration.type().get_bool(ID_C_is_anonymous))) { // we only allow this on struct/union types - if(final_type.id()!=ID_union && - final_type.id()!=ID_struct) + if( + declaration.type().id() != ID_union_tag && + declaration.type().id() != ID_struct_tag) { error().source_location=declaration.type().source_location(); error() << "member declaration does not declare anything" @@ -1423,8 +1429,14 @@ void cpp_typecheckt::convert_anon_struct_union_member( const irep_idt &access, struct_typet::componentst &components) { + const struct_union_typet &final_type = + declaration.type().id() == ID_struct_tag + ? static_cast( + follow_tag(to_struct_tag_type(declaration.type()))) + : static_cast( + follow_tag(to_union_tag_type(declaration.type()))); symbolt &struct_union_symbol = - symbol_table.get_writeable_ref(follow(declaration.type()).get(ID_name)); + symbol_table.get_writeable_ref(final_type.get(ID_name)); if(declaration.storage_spec().is_static() || declaration.storage_spec().is_mutable()) @@ -1477,13 +1489,15 @@ bool cpp_typecheckt::get_component( const irep_idt &component_name, exprt &member) { - const typet &followed_type=follow(object.type()); - PRECONDITION( - followed_type.id() == ID_struct || followed_type.id() == ID_union); + object.type().id() == ID_struct_tag || object.type().id() == ID_union_tag); - struct_union_typet final_type= - to_struct_union_type(followed_type); + struct_union_typet final_type = + object.type().id() == ID_struct_tag + ? static_cast( + follow_tag(to_struct_tag_type(object.type()))) + : static_cast( + follow_tag(to_union_tag_type(object.type()))); const struct_union_typet::componentst &components= final_type.components(); @@ -1529,14 +1543,22 @@ bool cpp_typecheckt::get_component( return true; // component found } - else if(follow(component.type()).find(ID_C_unnamed_object).is_not_nil()) + else if( + (component.type().id() == ID_struct_tag && + follow_tag(to_struct_tag_type(component.type())) + .find(ID_C_unnamed_object) + .is_not_nil()) || + (component.type().id() == ID_union_tag && + follow_tag(to_union_tag_type(component.type())) + .find(ID_C_unnamed_object) + .is_not_nil()) || + component.type().find(ID_C_unnamed_object).is_not_nil()) { // could be anonymous union or struct - const typet &component_type=follow(component.type()); - - if(component_type.id()==ID_union || - component_type.id()==ID_struct) + if( + component.type().id() == ID_union_tag || + component.type().id() == ID_struct_tag) { // recursive call! if(get_component(source_location, tmp, component_name, member)) @@ -1680,18 +1702,17 @@ bool cpp_typecheckt::subtype_typecast( void cpp_typecheckt::make_ptr_typecast( exprt &expr, - const typet &dest_type) + const pointer_typet &dest_type) { typet src_type=expr.type(); PRECONDITION(src_type.id() == ID_pointer); - PRECONDITION(dest_type.id() == ID_pointer); - const struct_typet &src_struct = to_struct_type( - static_cast(follow(to_pointer_type(src_type).base_type()))); + const struct_typet &src_struct = + follow_tag(to_struct_tag_type(to_pointer_type(src_type).base_type())); - const struct_typet &dest_struct = to_struct_type( - static_cast(follow(to_pointer_type(dest_type).base_type()))); + const struct_typet &dest_struct = + follow_tag(to_struct_tag_type(dest_type.base_type())); PRECONDITION( subtype_typecast(src_struct, dest_struct) || diff --git a/src/cpp/cpp_typecheck_conversions.cpp b/src/cpp/cpp_typecheck_conversions.cpp index bdbe04933d5..41ec14ef5c2 100644 --- a/src/cpp/cpp_typecheck_conversions.cpp +++ b/src/cpp/cpp_typecheck_conversions.cpp @@ -484,8 +484,9 @@ bool cpp_typecheckt::standard_conversion_pointer( return false; } - typet sub_from = follow(to_pointer_type(expr.type()).base_type()); - typet sub_to = follow(to_pointer_type(type).base_type()); + const pointer_typet &pointer_type = to_pointer_type(type); + const typet &sub_from = to_pointer_type(expr.type()).base_type(); + const typet &sub_to = pointer_type.base_type(); // std::nullptr_t to _any_ pointer type if(sub_from.id()==ID_nullptr) @@ -502,16 +503,16 @@ bool cpp_typecheckt::standard_conversion_pointer( } // struct * to struct * - if(sub_from.id()==ID_struct && sub_to.id()==ID_struct) + if(sub_from.id() == ID_struct_tag && sub_to.id() == ID_struct_tag) { - const struct_typet &from_struct=to_struct_type(sub_from); - const struct_typet &to_struct=to_struct_type(sub_to); + const struct_typet &from_struct = follow_tag(to_struct_tag_type(sub_from)); + const struct_typet &to_struct = follow_tag(to_struct_tag_type(sub_to)); if(subtype_typecast(from_struct, to_struct)) { c_qualifierst qual_from; qual_from.read(to_pointer_type(expr.type()).base_type()); new_expr=expr; - make_ptr_typecast(new_expr, type); + make_ptr_typecast(new_expr, pointer_type); qual_from.write(to_pointer_type(new_expr.type()).base_type()); return true; } @@ -608,11 +609,11 @@ bool cpp_typecheckt::standard_conversion_pointer_to_member( return true; } - const struct_typet &from_struct = to_struct_type( - follow(static_cast(expr.type().find(ID_to_member)))); + const struct_typet &from_struct = follow_tag(to_struct_tag_type( + static_cast(expr.type().find(ID_to_member)))); - const struct_typet &to_struct = - to_struct_type(follow(static_cast(type.find(ID_to_member)))); + const struct_typet &to_struct = follow_tag( + to_struct_tag_type(static_cast(type.find(ID_to_member)))); if(subtype_typecast(to_struct, from_struct)) { @@ -722,12 +723,14 @@ bool cpp_typecheckt::standard_conversion_sequence( // two enums are the same if the tag is the same, // even if the width differs (enum bit-fields!) - if(follow(type).id()==ID_c_enum && - follow(curr_expr.type()).id()==ID_c_enum) + if(type.id() == ID_c_enum_tag && curr_expr.type().id() == ID_c_enum_tag) { - if(follow(type).find(ID_tag)== - follow(curr_expr.type()).find(ID_tag)) + if( + to_tag_type(type).get_identifier() == + to_tag_type(curr_expr.type()).get_identifier()) + { return true; + } else { // In contrast to C, we simply don't allow implicit conversions @@ -737,12 +740,13 @@ bool cpp_typecheckt::standard_conversion_sequence( } // need to consider #c_type - if(follow(curr_expr.type())!=follow(type) || - curr_expr.type().get(ID_C_c_type)!=type.get(ID_C_c_type)) + if( + curr_expr.type() != type || + curr_expr.type().get(ID_C_c_type) != type.get(ID_C_c_type)) { - if(type.id()==ID_signedbv || - type.id()==ID_unsignedbv || - follow(type).id()==ID_c_enum) + if( + type.id() == ID_signedbv || type.id() == ID_unsignedbv || + type.id() == ID_c_enum_tag) { if(!standard_conversion_integral_promotion(curr_expr, new_expr) || new_expr.type() != type) @@ -858,15 +862,14 @@ bool cpp_typecheckt::standard_conversion_sequence( /// the conversion is stored in 'new_expr'. bool cpp_typecheckt::user_defined_conversion_sequence( const exprt &expr, - const typet &type, + const typet &to, exprt &new_expr, unsigned &rank) { PRECONDITION(!is_reference(expr.type())); - PRECONDITION(!is_reference(type)); + PRECONDITION(!is_reference(to)); - const typet &from=follow(expr.type()); - const typet &to=follow(type); + const typet &from = expr.type(); new_expr.make_nil(); @@ -879,16 +882,16 @@ bool cpp_typecheckt::user_defined_conversion_sequence( else rank+=4; // higher than all the standard conversions - if(to.id()==ID_struct) + if(to.id() == ID_struct_tag) { std::string err_msg; if(cpp_is_pod(to)) { - if(from.id()==ID_struct) + if(from.id() == ID_struct_tag) { - const struct_typet &from_struct=to_struct_type(from); - const struct_typet &to_struct=to_struct_type(to); + const struct_typet &from_struct = follow_tag(to_struct_tag_type(from)); + const struct_typet &to_struct = follow_tag(to_struct_tag_type(to)); // potentially requires // expr.get_bool(ID_C_lvalue) ?? @@ -901,7 +904,7 @@ bool cpp_typecheckt::user_defined_conversion_sequence( if(expr.id()==ID_dereference) address = to_dereference_expr(expr).pointer(); - pointer_typet ptr_sub=pointer_type(type); + pointer_typet ptr_sub = pointer_type(to); c_qualifierst qual_from; qual_from.read(expr.type()); qual_from.write(ptr_sub.base_type()); @@ -911,7 +914,7 @@ bool cpp_typecheckt::user_defined_conversion_sequence( // create temporary object side_effect_exprt tmp_object_expr( - ID_temporary_object, type, expr.source_location()); + ID_temporary_object, to, expr.source_location()); tmp_object_expr.copy_to_operands(deref); tmp_object_expr.set(ID_C_lvalue, true); tmp_object_expr.set(ID_mode, ID_cpp); @@ -924,8 +927,9 @@ bool cpp_typecheckt::user_defined_conversion_sequence( else { bool found=false; + const auto &struct_type_to = follow_tag(to_struct_tag_type(to)); - for(const auto &component : to_struct_type(to).components()) + for(const auto &component : struct_type_to.components()) { if(component.get_bool(ID_from_base)) continue; @@ -989,13 +993,13 @@ bool cpp_typecheckt::user_defined_conversion_sequence( new_expr.swap(ctor_expr); - if(to.get_bool(ID_C_constant)) + if(struct_type_to.get_bool(ID_C_constant)) new_expr.type().set(ID_C_constant, true); rank += tmp_rank; } } - else if(from.id() == ID_struct && arg1_type.id() == ID_struct_tag) + else if(from.id() == ID_struct_tag && arg1_type.id() == ID_struct_tag) { // try derived-to-base conversion address_of_exprt expr_pfrom(expr, pointer_type(expr.type())); @@ -1018,7 +1022,7 @@ bool cpp_typecheckt::user_defined_conversion_sequence( expr_deref.set(ID_C_lvalue, true); expr_deref.add_source_location()=expr.source_location(); - exprt new_object(ID_new_object, type); + exprt new_object(ID_new_object, to); new_object.set(ID_C_lvalue, true); new_object.type().set(ID_C_constant, false); @@ -1039,7 +1043,7 @@ bool cpp_typecheckt::user_defined_conversion_sequence( new_expr.get(ID_statement)==ID_temporary_object, "statement ID"); - if(to.get_bool(ID_C_constant)) + if(struct_type_to.get_bool(ID_C_constant)) new_expr.type().set(ID_C_constant, true); } } @@ -1050,10 +1054,11 @@ bool cpp_typecheckt::user_defined_conversion_sequence( } // conversion operators - if(from.id()==ID_struct) + if(from.id() == ID_struct_tag) { bool found=false; - for(const auto &component : to_struct_type(from).components()) + for(const auto &component : + follow_tag(to_struct_tag_type(from)).components()) { if(component.get_bool(ID_from_base)) continue; @@ -1092,7 +1097,7 @@ bool cpp_typecheckt::user_defined_conversion_sequence( expr.source_location()); typecheck_side_effect_function_call(func_expr); - if(standard_conversion_sequence(func_expr, type, tmp_expr, tmp_rank)) + if(standard_conversion_sequence(func_expr, to, tmp_expr, tmp_rank)) { // check if it's ambiguous if(found) @@ -1114,32 +1119,44 @@ bool cpp_typecheckt::user_defined_conversion_sequence( /// Reference-related /// \par parameters: A typechecked expression 'expr', /// a reference 'type'. -/// \return True iff an the reference 'type' is reference-related to 'expr'. +/// \return True iff the reference 'type' is reference-related to 'expr'. bool cpp_typecheckt::reference_related( const exprt &expr, - const typet &type) const + const reference_typet &reference_type) const { - PRECONDITION(is_reference(type)); PRECONDITION(!is_reference(expr.type())); - typet from=follow(expr.type()); - typet to = follow(to_reference_type(type).base_type()); + const typet &from = expr.type(); + const typet &from_followed = + from.id() == ID_struct_tag + ? static_cast(follow_tag(to_struct_tag_type(from))) + : from.id() == ID_union_tag + ? static_cast(follow_tag(to_union_tag_type(from))) + : from; + const typet &to = reference_type.base_type(); + const typet &to_followed = + to.id() == ID_struct_tag + ? static_cast(follow_tag(to_struct_tag_type(to))) + : to.id() == ID_union_tag + ? static_cast(follow_tag(to_union_tag_type(to))) + : to; // need to check #c_type - if(from.get(ID_C_c_type)!=to.get(ID_C_c_type)) + if(from_followed.get(ID_C_c_type) != to_followed.get(ID_C_c_type)) return false; if(from==to) return true; - if(from.id()==ID_struct && - to.id()==ID_struct) - return subtype_typecast(to_struct_type(from), - to_struct_type(to)); + if(from.id() == ID_struct_tag && to.id() == ID_struct_tag) + { + return subtype_typecast( + to_struct_type(from_followed), to_struct_type(to_followed)); + } if( - from.id() == ID_struct && type.get_bool(ID_C_this) && - to_pointer_type(type).base_type().id() == ID_empty) + from.id() == ID_struct_tag && reference_type.get_bool(ID_C_this) && + to.id() == ID_empty) { // virtual-call case return true; @@ -1154,23 +1171,22 @@ bool cpp_typecheckt::reference_related( /// \return True iff an the reference 'type' is reference-compatible to 'expr'. bool cpp_typecheckt::reference_compatible( const exprt &expr, - const typet &type, + const reference_typet &reference_type, unsigned &rank) const { - PRECONDITION(is_reference(type)); PRECONDITION(!is_reference(expr.type())); - if(!reference_related(expr, type)) + if(!reference_related(expr, reference_type)) return false; - if(expr.type() != to_reference_type(type).base_type()) + if(expr.type() != reference_type.base_type()) rank+=3; c_qualifierst qual_from; qual_from.read(expr.type()); c_qualifierst qual_to; - qual_to.read(to_reference_type(type).base_type()); + qual_to.read(reference_type.base_type()); if(qual_from!=qual_to) rank+=1; @@ -1217,17 +1233,15 @@ bool cpp_typecheckt::reference_compatible( /// of the conversion is stored in 'new_expr'. bool cpp_typecheckt::reference_binding( exprt expr, - const typet &type, + const reference_typet &reference_type, exprt &new_expr, unsigned &rank) { - PRECONDITION(is_reference(type)); PRECONDITION(!is_reference(expr.type())); unsigned backup_rank=rank; - if(type.get_bool(ID_C_this) && - !expr.get_bool(ID_C_lvalue)) + if(reference_type.get_bool(ID_C_this) && !expr.get_bool(ID_C_lvalue)) { // `this' has to be an lvalue if(expr.get(ID_statement)==ID_temporary_object) @@ -1248,32 +1262,33 @@ bool cpp_typecheckt::reference_binding( if( expr.get_bool(ID_C_lvalue) || - to_reference_type(type).base_type().get_bool(ID_C_constant)) + reference_type.base_type().get_bool(ID_C_constant)) { - if(reference_compatible(expr, type, rank)) + if(reference_compatible(expr, reference_type, rank)) { if(!expr.get_bool(ID_C_lvalue)) { // create temporary object - side_effect_exprt tmp{ID_temporary_object, - {std::move(expr)}, - to_reference_type(type).base_type(), - expr.source_location()}; + side_effect_exprt tmp{ + ID_temporary_object, + {std::move(expr)}, + reference_type.base_type(), + expr.source_location()}; tmp.set(ID_mode, ID_cpp); expr.swap(tmp); } { - address_of_exprt tmp(expr, reference_type(expr.type())); + address_of_exprt tmp(expr, ::reference_type(expr.type())); tmp.add_source_location()=expr.source_location(); new_expr.swap(tmp); } - if(expr.type() != to_reference_type(type).base_type()) + if(expr.type() != reference_type.base_type()) { c_qualifierst qual_from; qual_from.read(expr.type()); - new_expr = typecast_exprt::conditional_cast(new_expr, type); + new_expr = typecast_exprt::conditional_cast(new_expr, reference_type); qual_from.write(to_reference_type(new_expr.type()).base_type()); } @@ -1284,10 +1299,10 @@ bool cpp_typecheckt::reference_binding( } // conversion operators - const typet &from_type = follow(expr.type()); - if(from_type.id()==ID_struct) + if(expr.type().id() == ID_struct_tag) { - for(const auto &component : to_struct_type(from_type).components()) + for(const auto &component : + follow_tag(to_struct_tag_type(expr.type())).components()) { if(component.get_bool(ID_from_base)) continue; @@ -1337,8 +1352,9 @@ bool cpp_typecheckt::reference_binding( exprt returned_value=func_expr; add_implicit_dereference(returned_value); - if(returned_value.get_bool(ID_C_lvalue) && - reference_compatible(returned_value, type, rank)) + if( + returned_value.get_bool(ID_C_lvalue) && + reference_compatible(returned_value, reference_type, rank)) { // returned values are lvalues in case of references only DATA_INVARIANT( @@ -1347,11 +1363,11 @@ bool cpp_typecheckt::reference_binding( new_expr = to_multi_ary_expr(returned_value).op0(); - if(returned_value.type() != to_reference_type(type).base_type()) + if(returned_value.type() != reference_type.base_type()) { c_qualifierst qual_from; qual_from.read(returned_value.type()); - make_ptr_typecast(new_expr, type); + make_ptr_typecast(new_expr, reference_type); qual_from.write(to_reference_type(new_expr.type()).base_type()); } rank+=4+tmp_rank; @@ -1362,17 +1378,17 @@ bool cpp_typecheckt::reference_binding( } // No temporary allowed for `this' - if(type.get_bool(ID_C_this)) + if(reference_type.get_bool(ID_C_this)) return false; if( - !to_reference_type(type).base_type().get_bool(ID_C_constant) || - to_reference_type(type).base_type().get_bool(ID_C_volatile)) + !reference_type.base_type().get_bool(ID_C_constant) || + reference_type.base_type().get_bool(ID_C_volatile)) return false; // TODO: handle the case for implicit parameters if( - !to_reference_type(type).base_type().get_bool(ID_C_constant) && + !reference_type.base_type().get_bool(ID_C_constant) && !expr.get_bool(ID_C_lvalue)) return false; @@ -1385,9 +1401,9 @@ bool cpp_typecheckt::reference_binding( } if(user_defined_conversion_sequence( - arg_expr, to_reference_type(type).base_type(), new_expr, rank)) + arg_expr, reference_type.base_type(), new_expr, rank)) { - address_of_exprt tmp(new_expr, reference_type(new_expr.type())); + address_of_exprt tmp(new_expr, ::reference_type(new_expr.type())); tmp.add_source_location()=new_expr.source_location(); new_expr.swap(tmp); return true; @@ -1395,13 +1411,13 @@ bool cpp_typecheckt::reference_binding( rank=backup_rank; if(standard_conversion_sequence( - expr, to_reference_type(type).base_type(), new_expr, rank)) + expr, reference_type.base_type(), new_expr, rank)) { { // create temporary object side_effect_exprt tmp( ID_temporary_object, - to_reference_type(type).base_type(), + reference_type.base_type(), expr.source_location()); tmp.set(ID_mode, ID_cpp); // tmp.set(ID_C_lvalue, true); @@ -1439,7 +1455,7 @@ bool cpp_typecheckt::implicit_conversion_sequence( if(is_reference(type)) { - if(!reference_binding(e, type, new_expr, rank)) + if(!reference_binding(e, to_reference_type(type), new_expr, rank)) return false; #if 0 @@ -1533,7 +1549,7 @@ void cpp_typecheckt::implicit_typecast(exprt &expr, const typet &type) error() << "invalid implicit conversion from '" << to_string(e.type()) << "' to '" << to_string(type) << "'" << eom; #if 0 - str << "\n " << follow(e.type()).pretty() << '\n'; + str << "\n " << e.type().pretty() << '\n'; str << "\n " << type.pretty() << '\n'; #endif throw 0; @@ -1584,14 +1600,13 @@ void cpp_typecheckt::implicit_typecast(exprt &expr, const typet &type) /// than, cv2; otherwise, the program is ill-formed. void cpp_typecheckt::reference_initializer( exprt &expr, - const typet &type) + const reference_typet &reference_type) { - PRECONDITION(is_reference(type)); add_implicit_dereference(expr); unsigned rank=0; exprt new_expr; - if(reference_binding(expr, type, new_expr, rank)) + if(reference_binding(expr, reference_type, new_expr, rank)) { expr.swap(new_expr); return; @@ -1897,14 +1912,15 @@ bool cpp_typecheckt::static_typecast( if(type.get_bool(ID_C_reference)) { + const reference_typet &reference_type = to_reference_type(type); unsigned rank=0; - if(reference_binding(e, type, new_expr, rank)) + if(reference_binding(e, reference_type, new_expr, rank)) return true; - typet subto = follow(to_pointer_type(type).base_type()); - typet from=follow(e.type()); + typet subto = reference_type.base_type(); + typet from = e.type(); - if(subto.id()==ID_struct && from.id()==ID_struct) + if(subto.id() == ID_struct_tag && from.id() == ID_struct_tag) { if(!expr.get_bool(ID_C_lvalue)) return false; @@ -1913,25 +1929,25 @@ bool cpp_typecheckt::static_typecast( qual_from.read(e.type()); c_qualifierst qual_to; - qual_to.read(to_pointer_type(type).base_type()); + qual_to.read(subto); if(!qual_to.is_subset_of(qual_from)) return false; - const struct_typet &from_struct = to_struct_type(from); - const struct_typet &subto_struct = to_struct_type(subto); + const struct_typet &from_struct = follow_tag(to_struct_tag_type(from)); + const struct_typet &subto_struct = follow_tag(to_struct_tag_type(subto)); if(subtype_typecast(subto_struct, from_struct)) { if(e.id()==ID_dereference) { - make_ptr_typecast(to_dereference_expr(e).pointer(), type); + make_ptr_typecast(to_dereference_expr(e).pointer(), reference_type); new_expr.swap(to_dereference_expr(e).pointer()); return true; } exprt address_of=address_of_exprt(e); - make_ptr_typecast(address_of, type); + make_ptr_typecast(address_of, reference_type); new_expr.swap(address_of); return true; } @@ -1981,10 +1997,11 @@ bool cpp_typecheckt::static_typecast( if(type.id()==ID_pointer && e.type().id()==ID_pointer) { + const pointer_typet &pointer_type = to_pointer_type(type); if(type.find(ID_to_member).is_nil() && e.type().find(ID_to_member).is_nil()) { - typet to = follow(to_pointer_type(type).base_type()); - typet from = follow(to_pointer_type(e.type()).base_type()); + typet to = pointer_type.base_type(); + typet from = to_pointer_type(e.type()).base_type(); if(from.id()==ID_empty) { @@ -1992,7 +2009,7 @@ bool cpp_typecheckt::static_typecast( return true; } - if(to.id()==ID_struct && from.id()==ID_struct) + if(to.id() == ID_struct_tag && from.id() == ID_struct_tag) { if(e.get_bool(ID_C_lvalue)) { @@ -2001,11 +2018,11 @@ bool cpp_typecheckt::static_typecast( return false; } - const struct_typet &from_struct = to_struct_type(from); - const struct_typet &to_struct = to_struct_type(to); + const struct_typet &from_struct = follow_tag(to_struct_tag_type(from)); + const struct_typet &to_struct = follow_tag(to_struct_tag_type(to)); if(subtype_typecast(to_struct, from_struct)) { - make_ptr_typecast(e, type); + make_ptr_typecast(e, pointer_type); new_expr.swap(e); return true; } @@ -2017,16 +2034,14 @@ bool cpp_typecheckt::static_typecast( type.find(ID_to_member).is_not_nil() && e.type().find(ID_to_member).is_not_nil()) { - if( - to_pointer_type(type).base_type() != - to_pointer_type(e.type()).base_type()) + if(pointer_type.base_type() != to_pointer_type(e.type()).base_type()) return false; - const struct_typet &from_struct = to_struct_type( - follow(static_cast(e.type().find(ID_to_member)))); + const struct_typet &from_struct = follow_tag(to_struct_tag_type( + static_cast(e.type().find(ID_to_member)))); - const struct_typet &to_struct = to_struct_type( - follow(static_cast(type.find(ID_to_member)))); + const struct_typet &to_struct = follow_tag(to_struct_tag_type( + static_cast(type.find(ID_to_member)))); if(subtype_typecast(from_struct, to_struct)) { @@ -2038,18 +2053,16 @@ bool cpp_typecheckt::static_typecast( type.find(ID_to_member).is_nil() && e.type().find(ID_to_member).is_not_nil()) { - if( - to_pointer_type(type).base_type() != - to_pointer_type(e.type()).base_type()) + if(pointer_type.base_type() != to_pointer_type(e.type()).base_type()) { return false; } - const struct_typet &from_struct = to_struct_type( - follow(static_cast(e.type().find(ID_to_member)))); + const struct_tag_typet &from_struct_tag = to_struct_tag_type( + static_cast(e.type().find(ID_to_member))); new_expr = e; - new_expr.type().add(ID_to_member) = from_struct; + new_expr.type().add(ID_to_member) = from_struct_tag; return true; } diff --git a/src/cpp/cpp_typecheck_declaration.cpp b/src/cpp/cpp_typecheck_declaration.cpp index 1f14b35df7e..9e769b331ab 100644 --- a/src/cpp/cpp_typecheck_declaration.cpp +++ b/src/cpp/cpp_typecheck_declaration.cpp @@ -52,7 +52,18 @@ codet cpp_typecheckt::convert_anonymous_union(cpp_declarationt &declaration) if(!cpp_is_pod(declaration.type())) { - error().source_location=follow(declaration.type()).source_location(); + const typet &followed = + declaration.type().id() == ID_struct_tag + ? static_cast( + follow_tag(to_struct_tag_type(declaration.type()))) + : declaration.type().id() == ID_union_tag + ? static_cast( + follow_tag(to_union_tag_type(declaration.type()))) + : declaration.type().id() == ID_c_enum_tag + ? static_cast( + follow_tag(to_c_enum_tag_type(declaration.type()))) + : declaration.type(); + error().source_location = followed.source_location(); error() << "anonymous union is not POD" << eom; throw 0; } @@ -60,8 +71,8 @@ codet cpp_typecheckt::convert_anonymous_union(cpp_declarationt &declaration) new_code.add_to_operands(code_frontend_declt(cpp_symbol_expr(symbol))); // do scoping - symbolt &union_symbol = - symbol_table.get_writeable_ref(follow(symbol.type).get(ID_name)); + symbolt &union_symbol = symbol_table.get_writeable_ref( + follow_tag(to_union_tag_type(symbol.type)).get(ID_name)); for(const auto &c : to_union_type(union_symbol.type).components()) { @@ -120,14 +131,19 @@ void cpp_typecheckt::convert_non_template_declaration( already_typechecked_typet::make_already_typechecked(declaration_type); // Special treatment for anonymous unions - if(declaration.declarators().empty() && - follow(declaration.type()).get_bool(ID_C_is_anonymous)) + if( + declaration.declarators().empty() && + ((declaration.type().id() == ID_struct_tag && + follow_tag(to_struct_tag_type(declaration.type())) + .get_bool(ID_C_is_anonymous)) || + (declaration.type().id() == ID_union_tag && + follow_tag(to_union_tag_type(declaration.type())) + .get_bool(ID_C_is_anonymous)) || + declaration.type().get_bool(ID_C_is_anonymous))) { - typet final_type=follow(declaration.type()); - - if(final_type.id()!=ID_union) + if(declaration.type().id() != ID_union_tag) { - error().source_location=final_type.source_location(); + error().source_location = declaration.type().source_location(); error() << "top-level declaration does not declare anything" << eom; throw 0; diff --git a/src/cpp/cpp_typecheck_destructor.cpp b/src/cpp/cpp_typecheck_destructor.cpp index 6f080c1f55c..08f7d1c81e7 100644 --- a/src/cpp/cpp_typecheck_destructor.cpp +++ b/src/cpp/cpp_typecheck_destructor.cpp @@ -134,9 +134,8 @@ codet cpp_typecheckt::dtor(const symbolt &symbol, const symbol_exprt &this_expr) bit++) { DATA_INVARIANT(bit->id() == ID_base, "base class expression expected"); - const symbolt &psymb = lookup(bit->type()); - dereference_exprt object{this_expr, psymb.type}; + dereference_exprt object{this_expr, bit->type()}; object.add_source_location() = source_location; const bool disabled_access_control = disable_access_control; diff --git a/src/cpp/cpp_typecheck_expr.cpp b/src/cpp/cpp_typecheck_expr.cpp index b8a33c7faa2..1719d3750b7 100644 --- a/src/cpp/cpp_typecheck_expr.cpp +++ b/src/cpp/cpp_typecheck_expr.cpp @@ -96,15 +96,13 @@ void cpp_typecheckt::typecheck_expr_main(exprt &expr) typecheck_type(base); typecheck_type(deriv); - base = follow(base); - deriv = follow(deriv); - - if(base.id()!=ID_struct || deriv.id()!=ID_struct) + if(base.id() != ID_struct_tag || deriv.id() != ID_struct_tag) expr=false_exprt(); else { - irep_idt base_name=base.get(ID_name); - const class_typet &class_type=to_class_type(deriv); + irep_idt base_name = follow_tag(to_struct_tag_type(base)).get(ID_name); + const class_typet &class_type = + to_class_type(follow_tag(to_struct_tag_type(deriv))); if(class_type.has_base(base_name)) expr=true_exprt(); @@ -486,11 +484,11 @@ bool cpp_typecheckt::operator_is_overloaded(exprt &expr) // See if the struct declares the cast operator as a member bool found_in_struct=false; PRECONDITION(!expr.operands().empty()); - typet t0(follow(to_unary_expr(expr).op().type())); + const typet &t0 = to_unary_expr(expr).op().type(); - if(t0.id()==ID_struct) + if(t0.id() == ID_struct_tag) { - for(const auto &c : to_struct_type(t0).components()) + for(const auto &c : follow_tag(to_struct_tag_type(t0)).components()) { if(!c.get_bool(ID_from_base) && c.get_base_name() == op_name) { @@ -565,9 +563,7 @@ bool cpp_typecheckt::operator_is_overloaded(exprt &expr) // TODO: need to resolve an incomplete struct (template) here // go into scope of first operand - if( - to_multi_ary_expr(expr).op0().type().id() == ID_struct_tag && - follow(to_multi_ary_expr(expr).op0().type()).id() == ID_struct) + if(to_multi_ary_expr(expr).op0().type().id() == ID_struct_tag) { const irep_idt &struct_identifier = to_multi_ary_expr(expr).op0().type().get(ID_identifier); @@ -719,8 +715,8 @@ void cpp_typecheckt::typecheck_expr_address_of(exprt &expr) else if(op.id() == ID_ptrmember && to_unary_expr(op).op().id() == "cpp-this") { expr.type() = pointer_type(op.type()); - expr.type().add(ID_to_member) = - to_pointer_type(to_unary_expr(op).op().type()).base_type(); + expr.type().add(ID_to_member) = to_struct_tag_type( + to_pointer_type(to_unary_expr(op).op().type()).base_type()); return; } @@ -1098,20 +1094,21 @@ void cpp_typecheckt::typecheck_expr_member( // The member operator will trigger template elaboration elaborate_class_template(op0.type()); - const typet &followed_op0_type=follow(op0.type()); - - if(followed_op0_type.id()!=ID_struct && - followed_op0_type.id()!=ID_union) + if(op0.type().id() != ID_struct_tag && op0.type().id() != ID_union_tag) { error().source_location=expr.find_source_location(); error() << "error: member operator requires struct/union type " - << "on left hand side but got '" << to_string(followed_op0_type) - << "'" << eom; + << "on left hand side but got '" << to_string(op0.type()) << "'" + << eom; throw 0; } - const struct_union_typet &type= - to_struct_union_type(followed_op0_type); + const struct_union_typet &type = + op0.type().id() == ID_struct_tag + ? static_cast( + follow_tag(to_struct_tag_type(op0.type()))) + : static_cast( + follow_tag(to_union_tag_type(op0.type()))); if(type.is_incomplete()) { @@ -1576,8 +1573,6 @@ void cpp_typecheckt::typecheck_side_effect_function_call( // look at type of function - expr.function().type() = follow(expr.function().type()); - if(expr.function().type().id()==ID_pointer) { if(expr.function().type().find(ID_to_member).is_not_nil()) @@ -1646,7 +1641,7 @@ void cpp_typecheckt::typecheck_side_effect_function_call( this_type.base_type().get_string(ID_identifier) + "::@vtable_pointer"; const struct_typet &vt_struct = - to_struct_type(follow(this_type.base_type())); + follow_tag(to_struct_tag_type(this_type.base_type())); const struct_typet::componentt &vt_compo= vt_struct.get_component(vtable_name); @@ -1689,7 +1684,7 @@ void cpp_typecheckt::typecheck_side_effect_function_call( return; } } - else if(expr.function().type().id()==ID_struct) + else if(expr.function().type().id() == ID_struct_tag) { const cpp_namet cppname("operator()", expr.source_location()); @@ -1759,8 +1754,8 @@ void cpp_typecheckt::typecheck_side_effect_function_call( // will be available { // find name of destructor - const struct_typet::componentst &components= - to_struct_type(follow(tmp_object_expr.type())).components(); + const struct_typet::componentst &components = + follow_tag(to_struct_tag_type(tmp_object_expr.type())).components(); for(const auto &c : components) { @@ -2201,18 +2196,15 @@ void cpp_typecheckt::convert_pmop(exprt &expr) typet t1((const typet &)op1.type().find(ID_to_member)); - t0=follow(t0); - t1=follow(t1); - - if(t0.id()!=ID_struct) + if(t0.id() != ID_struct_tag) { error().source_location=expr.source_location(); error() << "pointer-to-member type error" << eom; throw 0; } - const struct_typet &from_struct=to_struct_type(t0); - const struct_typet &to_struct=to_struct_type(t1); + const struct_typet &from_struct = follow_tag(to_struct_tag_type(t0)); + const struct_typet &to_struct = follow_tag(to_struct_tag_type(t1)); if(!subtype_typecast(from_struct, to_struct)) { diff --git a/src/cpp/cpp_typecheck_initializer.cpp b/src/cpp/cpp_typecheck_initializer.cpp index a59f38773d8..3eb9d8ac8c6 100644 --- a/src/cpp/cpp_typecheck_initializer.cpp +++ b/src/cpp/cpp_typecheck_initializer.cpp @@ -72,7 +72,7 @@ void cpp_typecheckt::convert_initializer(symbolt &symbol) implicit_typecast(symbol.value, symbol.type); } - reference_initializer(symbol.value, symbol.type); + reference_initializer(symbol.value, to_reference_type(symbol.type)); } else if(cpp_is_pod(symbol.type)) { @@ -199,11 +199,9 @@ void cpp_typecheckt::zero_initializer( const source_locationt &source_location, exprt::operandst &ops) { - const typet &final_type=follow(type); - - if(final_type.id()==ID_struct) + if(type.id() == ID_struct_tag) { - const auto &struct_type = to_struct_type(final_type); + const auto &struct_type = follow_tag(to_struct_tag_type(type)); if(struct_type.is_incomplete()) { @@ -230,8 +228,7 @@ void cpp_typecheckt::zero_initializer( } } else if( - final_type.id() == ID_array && - !cpp_is_pod(to_array_type(final_type).element_type())) + type.id() == ID_array && !cpp_is_pod(to_array_type(type).element_type())) { const array_typet &array_type=to_array_type(type); const exprt &size_expr=array_type.size(); @@ -251,9 +248,9 @@ void cpp_typecheckt::zero_initializer( zero_initializer(index, array_type.element_type(), source_location, ops); } } - else if(final_type.id()==ID_union) + else if(type.id() == ID_union_tag) { - const auto &union_type = to_union_type(final_type); + const auto &union_type = follow_tag(to_union_tag_type(type)); if(union_type.is_incomplete()) { @@ -298,10 +295,10 @@ void cpp_typecheckt::zero_initializer( zero_initializer(member, comp.type(), source_location, ops); } } - else if(final_type.id()==ID_c_enum) + else if(type.id() == ID_c_enum_tag) { const unsignedbv_typet enum_type( - to_bitvector_type(to_c_enum_type(final_type).underlying_type()) + to_bitvector_type(follow_tag(to_c_enum_tag_type(type)).underlying_type()) .get_width()); exprt zero = @@ -322,12 +319,11 @@ void cpp_typecheckt::zero_initializer( } else { - const auto value = ::zero_initializer(final_type, source_location, *this); + const auto value = ::zero_initializer(type, source_location, *this); if(!value.has_value()) { error().source_location = source_location; - error() << "cannot zero-initialize '" << to_string(final_type) << "'" - << eom; + error() << "cannot zero-initialize '" << to_string(type) << "'" << eom; throw 0; } diff --git a/src/cpp/cpp_typecheck_resolve.cpp b/src/cpp/cpp_typecheck_resolve.cpp index 9c46f74d81f..37d4d529dc4 100644 --- a/src/cpp/cpp_typecheck_resolve.cpp +++ b/src/cpp/cpp_typecheck_resolve.cpp @@ -137,7 +137,18 @@ void cpp_typecheck_resolvet::remove_templates( for(const auto &old_id : old_identifiers) { - if(!cpp_typecheck.follow(old_id.type()).get_bool(ID_is_template)) + const typet &followed = + old_id.type().id() == ID_struct_tag + ? static_cast( + cpp_typecheck.follow_tag(to_struct_tag_type(old_id.type()))) + : old_id.type().id() == ID_union_tag + ? static_cast( + cpp_typecheck.follow_tag(to_union_tag_type(old_id.type()))) + : old_id.type().id() == ID_c_enum_tag + ? static_cast( + cpp_typecheck.follow_tag(to_c_enum_tag_type(old_id.type()))) + : old_id.type(); + if(!followed.get_bool(ID_is_template)) identifiers.push_back(old_id); } } @@ -282,16 +293,21 @@ exprt cpp_typecheck_resolvet::convert_identifier( } // check if the member can be applied to the object - typet object_type=cpp_typecheck.follow(object.type()); - - if(object_type.id()==ID_struct || - object_type.id()==ID_union) + if( + object.type().id() == ID_struct_tag || + object.type().id() == ID_union_tag) { + const struct_union_typet &object_type = + object.type().id() == ID_struct_tag + ? static_cast( + cpp_typecheck.follow_tag(to_struct_tag_type(object.type()))) + : static_cast( + cpp_typecheck.follow_tag(to_union_tag_type(object.type()))); if(!has_component_rec( - to_struct_union_type(object_type), - identifier.identifier, - cpp_typecheck)) + object_type, identifier.identifier, cpp_typecheck)) + { object.make_nil(); // failed! + } } else object.make_nil(); @@ -314,8 +330,11 @@ exprt cpp_typecheck_resolvet::convert_identifier( else { e.id(ID_ptrmember); - e.copy_to_operands( - exprt("cpp-this", pointer_type(compound_symbol.type))); + tag_typet class_tag_type{ + compound_symbol.type.id() == ID_struct ? ID_struct_tag + : ID_union_tag, + identifier.class_identifier}; + e.copy_to_operands(exprt("cpp-this", pointer_type(class_tag_type))); e.type() = type; } } @@ -538,20 +557,20 @@ void cpp_typecheck_resolvet::disambiguate_functions( type2=tmp; } - const typet &followed1=cpp_typecheck.follow(type1); - const typet &followed2=cpp_typecheck.follow(type2); - - if(followed1.id() != ID_struct || followed2.id() != ID_struct) + if(type1.id() != ID_struct_tag || type2.id() != ID_struct_tag) continue; - const struct_typet &struct1=to_struct_type(followed1); - const struct_typet &struct2=to_struct_type(followed2); - - if(f1_better && cpp_typecheck.subtype_typecast(struct1, struct2)) + if( + f1_better && cpp_typecheck.subtype_typecast( + cpp_typecheck.follow_tag(to_struct_tag_type(type1)), + cpp_typecheck.follow_tag(to_struct_tag_type(type2)))) { f2_better=false; } - else if(f2_better && cpp_typecheck.subtype_typecast(struct2, struct1)) + else if( + f2_better && cpp_typecheck.subtype_typecast( + cpp_typecheck.follow_tag(to_struct_tag_type(type2)), + cpp_typecheck.follow_tag(to_struct_tag_type(type1)))) { f1_better=false; } @@ -584,11 +603,9 @@ void cpp_typecheck_resolvet::make_constructors( continue; } - const typet &symbol_type = cpp_typecheck.follow(identifier.type()); - // is it a POD? - if(cpp_typecheck.cpp_is_pod(symbol_type)) + if(cpp_typecheck.cpp_is_pod(identifier.type())) { // there are two pod constructors: @@ -608,7 +625,7 @@ void cpp_typecheck_resolvet::make_constructors( } // enums, in addition, can also be constructed from int - if(symbol_type.id()==ID_c_enum_tag) + if(identifier.type().id() == ID_c_enum_tag) { const code_typet t3( {code_typet::parametert(signed_int_type())}, identifier.type()); @@ -616,9 +633,10 @@ void cpp_typecheck_resolvet::make_constructors( new_identifiers.push_back(pod_constructor3); } } - else if(symbol_type.id()==ID_struct) + else if(identifier.type().id() == ID_struct_tag) { - const struct_typet &struct_type=to_struct_type(symbol_type); + const struct_typet &struct_type = + cpp_typecheck.follow_tag(to_struct_tag_type(identifier.type())); // go over components for(const auto &component : struct_type.components()) @@ -1880,7 +1898,17 @@ exprt cpp_typecheck_resolvet::guess_function_template_args( const exprt &expr, const cpp_typecheck_fargst &fargs) { - typet tmp = cpp_typecheck.follow(expr.type()); + const typet &tmp = + expr.type().id() == ID_struct_tag + ? static_cast( + cpp_typecheck.follow_tag(to_struct_tag_type(expr.type()))) + : expr.type().id() == ID_union_tag + ? static_cast( + cpp_typecheck.follow_tag(to_union_tag_type(expr.type()))) + : expr.type().id() == ID_c_enum_tag + ? static_cast( + cpp_typecheck.follow_tag(to_c_enum_tag_type(expr.type()))) + : expr.type(); if(!tmp.get_bool(ID_is_template)) return nil_exprt(); // not a template @@ -2333,11 +2361,16 @@ void cpp_typecheck_resolvet::resolve_with_arguments( // not clear what this is good for for(const auto &arg : fargs.operands) { - const typet &final_type=cpp_typecheck.follow(arg.type()); - - if(final_type.id()!=ID_struct && final_type.id()!=ID_union) + if(arg.type().id() != ID_struct_tag && arg.type().id() != ID_union_tag) continue; + const struct_union_typet &final_type = + arg.type().id() == ID_struct_tag + ? static_cast( + cpp_typecheck.follow_tag(to_struct_tag_type(arg.type()))) + : static_cast( + cpp_typecheck.follow_tag(to_union_tag_type(arg.type()))); + cpp_scopet &scope= cpp_typecheck.cpp_scopes.get_scope(final_type.get(ID_name)); const auto tmp_set = scope.lookup(base_name, cpp_scopet::SCOPE_ONLY); diff --git a/src/cpp/expr2cpp.cpp b/src/cpp/expr2cpp.cpp index 0b6265aee1d..37d1c6bc09b 100644 --- a/src/cpp/expr2cpp.cpp +++ b/src/cpp/expr2cpp.cpp @@ -51,12 +51,13 @@ std::string expr2cppt::convert_struct( const exprt &src, unsigned &precedence) { - const typet &full_type=ns.follow(src.type()); - - if(full_type.id()!=ID_struct) + if(src.type().id() != ID_struct && src.type().id() != ID_struct_tag) return convert_norep(src, precedence); - const struct_typet &struct_type=to_struct_type(full_type); + const struct_typet &struct_type = + src.type().id() == ID_struct_tag + ? ns.follow_tag(to_struct_tag_type(src.type())) + : to_struct_type(src.type()); std::string dest="{ ";