diff --git a/src/ansi-c/anonymous_member.cpp b/src/ansi-c/anonymous_member.cpp index 4f8b88da9c4..e2ed779df93 100644 --- a/src/ansi-c/anonymous_member.cpp +++ b/src/ansi-c/anonymous_member.cpp @@ -26,11 +26,10 @@ static member_exprt make_member_expr( result.set(ID_C_lvalue, true); // todo: should to typedef chains properly - const typet &type= - ns.follow(struct_union.type()); - + const auto &tag_type = to_struct_or_union_tag_type(struct_union.type()); if( - type.get_bool(ID_C_constant) || struct_union.type().get_bool(ID_C_constant)) + ns.follow_tag(tag_type).get_bool(ID_C_constant) || + struct_union.type().get_bool(ID_C_constant)) { result.type().set(ID_C_constant, true); } @@ -43,13 +42,9 @@ exprt get_component_rec( const irep_idt &component_name, const namespacet &ns) { - const struct_union_typet &struct_union_type= - to_struct_union_type(ns.follow(struct_union.type())); - - const struct_union_typet::componentst &components= - struct_union_type.components(); + const auto &tag_type = to_struct_or_union_tag_type(struct_union.type()); - for(const auto &comp : components) + for(const auto &comp : ns.follow_tag(tag_type).components()) { const typet &type = comp.type(); @@ -76,13 +71,9 @@ bool has_component_rec( const irep_idt &component_name, const namespacet &ns) { - const struct_union_typet &struct_union_type= - to_struct_union_type(ns.follow(type)); - - const struct_union_typet::componentst &components= - struct_union_type.components(); + const auto &tag_type = to_struct_or_union_tag_type(type); - for(const auto &comp : components) + for(const auto &comp : ns.follow_tag(tag_type).components()) { if(comp.get_name()==component_name) { diff --git a/src/ansi-c/c_typecast.cpp b/src/ansi-c/c_typecast.cpp index 10547403f5a..873e857af8f 100644 --- a/src/ansi-c/c_typecast.cpp +++ b/src/ansi-c/c_typecast.cpp @@ -289,9 +289,17 @@ typet c_typecastt::follow_with_qualifiers(const typet &src_type) // collect qualifiers c_qualifierst qualifiers(src_type); - while(result_type.id() == ID_struct_tag || result_type.id() == ID_union_tag) + if( + auto struct_tag_type = type_try_dynamic_cast(result_type)) + { + const typet &followed_type = ns.follow_tag(*struct_tag_type); + result_type = followed_type; + qualifiers += c_qualifierst(followed_type); + } + else if( + auto union_tag_type = type_try_dynamic_cast(result_type)) { - const typet &followed_type = ns.follow(result_type); + const typet &followed_type = ns.follow_tag(*union_tag_type); result_type = followed_type; qualifiers += c_qualifierst(followed_type); } diff --git a/src/ansi-c/c_typecheck_base.cpp b/src/ansi-c/c_typecheck_base.cpp index 54d36ae96fa..333c0382f50 100644 --- a/src/ansi-c/c_typecheck_base.cpp +++ b/src/ansi-c/c_typecheck_base.cpp @@ -53,8 +53,6 @@ void c_typecheck_baset::typecheck_symbol(symbolt &symbol) { bool is_function=symbol.type.id()==ID_code; - const typet &final_type=follow(symbol.type); - // set a few flags symbol.is_lvalue=!symbol.is_type && !symbol.is_macro; @@ -91,15 +89,15 @@ void c_typecheck_baset::typecheck_symbol(symbolt &symbol) } // set the pretty name - if(symbol.is_type && final_type.id() == ID_struct) + if(symbol.is_type && symbol.type.id() == ID_struct) { symbol.pretty_name="struct "+id2string(symbol.base_name); } - else if(symbol.is_type && final_type.id() == ID_union) + else if(symbol.is_type && symbol.type.id() == ID_union) { symbol.pretty_name="union "+id2string(symbol.base_name); } - else if(symbol.is_type && final_type.id() == ID_c_enum) + else if(symbol.is_type && symbol.type.id() == ID_c_enum) { symbol.pretty_name="enum "+id2string(symbol.base_name); } @@ -191,8 +189,8 @@ void c_typecheck_baset::typecheck_redefinition_type( symbolt &old_symbol, symbolt &new_symbol) { - const typet &final_old=follow(old_symbol.type); - const typet &final_new=follow(new_symbol.type); + const typet &final_old = old_symbol.type; + const typet &final_new = new_symbol.type; // see if we had something incomplete before if( @@ -260,8 +258,8 @@ void c_typecheck_baset::typecheck_redefinition_type( else if( config.ansi_c.os == configt::ansi_ct::ost::OS_WIN && final_new.id() == ID_pointer && final_old.id() == ID_pointer && - follow(to_pointer_type(final_new).base_type()).id() == ID_c_enum && - follow(to_pointer_type(final_old).base_type()).id() == ID_c_enum) + to_pointer_type(final_new).base_type().id() == ID_c_enum && + to_pointer_type(final_old).base_type().id() == ID_c_enum) { // under Windows, ignore this silently; // MSC doesn't think this is a problem, but GCC complains. @@ -269,7 +267,7 @@ void c_typecheck_baset::typecheck_redefinition_type( else { // see if it changed - if(follow(new_symbol.type)!=follow(old_symbol.type)) + if(new_symbol.type != old_symbol.type) { error().source_location=new_symbol.location; error() << "type symbol '" << new_symbol.display_name() @@ -321,8 +319,8 @@ void c_typecheck_baset::typecheck_redefinition_non_type( symbolt &old_symbol, symbolt &new_symbol) { - const typet &final_old=follow(old_symbol.type); - const typet &initial_new=follow(new_symbol.type); + const typet &final_old = old_symbol.type; + const typet &initial_new = new_symbol.type; if( final_old.id() == ID_array && @@ -351,7 +349,7 @@ void c_typecheck_baset::typecheck_redefinition_non_type( if(new_symbol.type.id() != ID_code && !new_symbol.is_macro) do_initializer(new_symbol); - const typet &final_new=follow(new_symbol.type); + const typet &final_new = new_symbol.type; // K&R stuff? if(old_symbol.type.id()==ID_KnR) @@ -548,9 +546,10 @@ void c_typecheck_baset::typecheck_redefinition_non_type( // int (*f) (); } else if( - final_old.id() == ID_struct && final_new.id() == ID_struct && + final_old.id() == ID_struct_tag && final_new.id() == ID_struct_tag && is_instantiation_of_flexible_array( - to_struct_type(final_old), to_struct_type(final_new))) + follow_tag(to_struct_tag_type(final_old)), + follow_tag(to_struct_tag_type(final_new)))) { old_symbol.type = new_symbol.type; } diff --git a/src/ansi-c/c_typecheck_code.cpp b/src/ansi-c/c_typecheck_code.cpp index 184e1657671..462978601bd 100644 --- a/src/ansi-c/c_typecheck_code.cpp +++ b/src/ansi-c/c_typecheck_code.cpp @@ -387,9 +387,13 @@ bool c_typecheck_baset::is_complete_type(const typet &type) const } else if(type.id()==ID_vector) return is_complete_type(to_vector_type(type).element_type()); - else if(type.id() == ID_struct_tag || type.id() == ID_union_tag) + else if(auto struct_tag_type = type_try_dynamic_cast(type)) { - return is_complete_type(follow(type)); + return is_complete_type(follow_tag(*struct_tag_type)); + } + else if(auto union_tag_type = type_try_dynamic_cast(type)) + { + return is_complete_type(follow_tag(*union_tag_type)); } return true; diff --git a/src/ansi-c/c_typecheck_expr.cpp b/src/ansi-c/c_typecheck_expr.cpp index 3683df91c16..16c1e0dd59c 100644 --- a/src/ansi-c/c_typecheck_expr.cpp +++ b/src/ansi-c/c_typecheck_expr.cpp @@ -451,14 +451,13 @@ void c_typecheck_baset::typecheck_expr_main(exprt &expr) exprt default_match=nil_exprt(); exprt assoc_match=nil_exprt(); - const typet &op_type = follow(op.type()); + const typet &op_type = op.type(); for(const auto &irep : generic_associations) { if(irep.get(ID_type_arg) == ID_default) default_match = static_cast(irep.find(ID_value)); - else if( - op_type == follow(static_cast(irep.find(ID_type_arg)))) + else if(op_type == static_cast(irep.find(ID_type_arg))) { assoc_match = static_cast(irep.find(ID_value)); } @@ -590,11 +589,9 @@ void c_typecheck_baset::typecheck_expr_builtin_offsetof(exprt &expr) for(const auto &op : member.operands()) { - type = follow(type); - if(op.id() == ID_member) { - if(type.id()!=ID_union && type.id()!=ID_struct) + if(type.id() != ID_union_tag && type.id() != ID_struct_tag) { error().source_location = expr.source_location(); error() << "offsetof of member expects struct/union type, " @@ -607,20 +604,20 @@ void c_typecheck_baset::typecheck_expr_builtin_offsetof(exprt &expr) while(!found) { - PRECONDITION(type.id() == ID_union || type.id() == ID_struct); + PRECONDITION(type.id() == ID_union_tag || type.id() == ID_struct_tag); - const struct_union_typet &struct_union_type= - to_struct_union_type(type); + const struct_union_typet &struct_union_type = + follow_tag(to_struct_or_union_tag_type(type)); // direct member? if(struct_union_type.has_component(component_name)) { found=true; - if(type.id()==ID_struct) + if(type.id() == ID_struct_tag) { - auto o_opt = - member_offset_expr(to_struct_type(type), component_name, *this); + auto o_opt = member_offset_expr( + follow_tag(to_struct_tag_type(type)), component_name, *this); if(!o_opt.has_value()) { @@ -650,10 +647,10 @@ void c_typecheck_baset::typecheck_expr_builtin_offsetof(exprt &expr) { if(has_component_rec(c.type(), component_name, *this)) { - if(type.id()==ID_struct) + if(type.id() == ID_struct_tag) { auto o_opt = member_offset_expr( - to_struct_type(type), c.get_name(), *this); + follow_tag(to_struct_tag_type(type)), c.get_name(), *this); if(!o_opt.has_value()) { @@ -669,9 +666,10 @@ void c_typecheck_baset::typecheck_expr_builtin_offsetof(exprt &expr) o_opt.value(), size_type())); } - typet tmp = follow(c.type()); + typet tmp = c.type(); type=tmp; - CHECK_RETURN(type.id() == ID_union || type.id() == ID_struct); + CHECK_RETURN( + type.id() == ID_union_tag || type.id() == ID_struct_tag); found2=true; break; // we run into another iteration of the outer loop } @@ -1377,7 +1375,7 @@ void c_typecheck_baset::typecheck_expr_rel( if(expr.id()==ID_equal || expr.id()==ID_notequal) { - if(follow(o_type0)==follow(o_type1)) + if(o_type0 == o_type1) { if(o_type0.id() != ID_array) { @@ -1530,10 +1528,7 @@ void c_typecheck_baset::typecheck_expr_member(exprt &expr) exprt &op0 = to_unary_expr(expr).op(); typet type=op0.type(); - type = follow(type); - - if(type.id()!=ID_struct && - type.id()!=ID_union) + if(type.id() != ID_struct_tag && type.id() != ID_union_tag) { error().source_location = expr.source_location(); error() << "member operator requires structure type " @@ -1542,8 +1537,8 @@ void c_typecheck_baset::typecheck_expr_member(exprt &expr) throw 0; } - const struct_union_typet &struct_union_type= - to_struct_union_type(type); + const struct_union_typet &struct_union_type = + follow_tag(to_struct_or_union_tag_type(type)); if(struct_union_type.is_incomplete()) { @@ -1585,8 +1580,12 @@ void c_typecheck_baset::typecheck_expr_member(exprt &expr) if(op0.get_bool(ID_C_lvalue)) expr.set(ID_C_lvalue, true); - if(op0.type().get_bool(ID_C_constant) || type.get_bool(ID_C_constant)) + if( + op0.type().get_bool(ID_C_constant) || + struct_union_type.get_bool(ID_C_constant)) + { expr.type().set(ID_C_constant, true); + } // copy method identifier const irep_idt &identifier=component.get(ID_C_identifier); @@ -3649,11 +3648,10 @@ exprt c_typecheck_baset::do_special_functions( // The value doesn't matter at all, we only care about the type. // Need to sync with typeclass.h. - typet type = follow(object.type()); - // use underlying type for bit fields - if(type.id() == ID_c_bit_field) - type = to_c_bit_field_type(type).underlying_type(); + const typet &type = object.type().id() == ID_c_bit_field + ? to_c_bit_field_type(object.type()).underlying_type() + : object.type(); unsigned type_number; @@ -3665,23 +3663,17 @@ exprt c_typecheck_baset::do_special_functions( } else { - type_number = - type.id() == ID_empty - ? 0u - : (type.id() == ID_bool || type.id() == ID_c_bool) - ? 4u - : (type.id() == ID_pointer || type.id() == ID_array) - ? 5u - : type.id() == ID_floatbv - ? 8u - : (type.id() == ID_complex && - to_complex_type(type).subtype().id() == ID_floatbv) - ? 9u - : type.id() == ID_struct - ? 12u - : type.id() == ID_union - ? 13u - : 1u; // int, short, char, enum_tag + type_number = type.id() == ID_empty ? 0u + : (type.id() == ID_bool || type.id() == ID_c_bool) ? 4u + : (type.id() == ID_pointer || type.id() == ID_array) ? 5u + : type.id() == ID_floatbv ? 8u + : (type.id() == ID_complex && + to_complex_type(type).subtype().id() == ID_floatbv) + ? 9u + : type.id() == ID_struct_tag ? 12u + : type.id() == ID_union_tag + ? 13u + : 1u; // int, short, char, enum_tag } exprt tmp=from_integer(type_number, expr.type()); diff --git a/src/ansi-c/c_typecheck_initializer.cpp b/src/ansi-c/c_typecheck_initializer.cpp index 6dd7934f023..eebba08236b 100644 --- a/src/ansi-c/c_typecheck_initializer.cpp +++ b/src/ansi-c/c_typecheck_initializer.cpp @@ -58,11 +58,11 @@ exprt c_typecheck_baset::do_initializer_rec( const typet &type, bool force_constant) { - const typet &full_type=follow(type); - if( - (full_type.id() == ID_struct || full_type.id() == ID_union) && - to_struct_union_type(full_type).is_incomplete()) + (type.id() == ID_struct_tag && + follow_tag(to_struct_tag_type(type)).is_incomplete()) || + (type.id() == ID_union_tag && + follow_tag(to_union_tag_type(type)).is_incomplete())) { error().source_location = value.source_location(); error() << "type '" << to_string(type) @@ -75,25 +75,24 @@ exprt c_typecheck_baset::do_initializer_rec( if( value.id() == ID_array && value.get_bool(ID_C_string_constant) && - full_type.id() == ID_array && - (to_array_type(full_type).element_type().id() == ID_signedbv || - to_array_type(full_type).element_type().id() == ID_unsignedbv) && - to_bitvector_type(to_array_type(full_type).element_type()).get_width() == + type.id() == ID_array && + (to_array_type(type).element_type().id() == ID_signedbv || + to_array_type(type).element_type().id() == ID_unsignedbv) && + to_bitvector_type(to_array_type(type).element_type()).get_width() == to_bitvector_type(to_array_type(value.type()).element_type()).get_width()) { exprt tmp=value; // adjust char type to_array_type(tmp.type()).element_type() = - to_array_type(full_type).element_type(); + to_array_type(type).element_type(); Forall_operands(it, tmp) - it->type() = to_array_type(full_type).element_type(); + it->type() = to_array_type(type).element_type(); - if(full_type.id()==ID_array && - to_array_type(full_type).is_complete()) + if(type.id() == ID_array && to_array_type(type).is_complete()) { - const auto &array_type = to_array_type(full_type); + const auto &array_type = to_array_type(type); // check size const auto array_size = numeric_cast(array_type.size()); @@ -139,10 +138,10 @@ exprt c_typecheck_baset::do_initializer_rec( } if( - value.id() == ID_string_constant && full_type.id() == ID_array && - (to_array_type(full_type).element_type().id() == ID_signedbv || - to_array_type(full_type).element_type().id() == ID_unsignedbv) && - to_bitvector_type(to_array_type(full_type).element_type()).get_width() == + value.id() == ID_string_constant && type.id() == ID_array && + (to_array_type(type).element_type().id() == ID_signedbv || + to_array_type(type).element_type().id() == ID_unsignedbv) && + to_bitvector_type(to_array_type(type).element_type()).get_width() == char_type().get_width()) { // will go away, to be replaced by the above block @@ -150,21 +149,20 @@ exprt c_typecheck_baset::do_initializer_rec( string_constantt tmp1=to_string_constant(value); // adjust char type to_array_type(tmp1.type()).element_type() = - to_array_type(full_type).element_type(); + to_array_type(type).element_type(); exprt tmp2=tmp1.to_array_expr(); - if(full_type.id()==ID_array && - to_array_type(full_type).is_complete()) + if(type.id() == ID_array && to_array_type(type).is_complete()) { // check size const auto array_size = - numeric_cast(to_array_type(full_type).size()); + numeric_cast(to_array_type(type).size()); if(!array_size.has_value()) { error().source_location = value.source_location(); error() << "array size needs to be constant, got " - << to_string(to_array_type(full_type).size()) << eom; + << to_string(to_array_type(type).size()) << eom; throw 0; } @@ -186,14 +184,12 @@ exprt c_typecheck_baset::do_initializer_rec( // fill up tmp2.type()=type; const auto zero = zero_initializer( - to_array_type(full_type).element_type(), - value.source_location(), - *this); + to_array_type(type).element_type(), value.source_location(), *this); if(!zero.has_value()) { error().source_location = value.source_location(); error() << "cannot zero-initialize array with subtype '" - << to_string(to_array_type(full_type).element_type()) << "'" + << to_string(to_array_type(type).element_type()) << "'" << eom; throw 0; } @@ -204,20 +200,18 @@ exprt c_typecheck_baset::do_initializer_rec( return tmp2; } - if(full_type.id()==ID_array && - to_array_type(full_type).size().is_nil()) + if(type.id() == ID_array && to_array_type(type).size().is_nil()) { error().source_location = value.source_location(); - error() << "type '" << to_string(full_type) - << "' cannot be initialized with '" << to_string(value) << "'" - << eom; + error() << "type '" << to_string(type) << "' cannot be initialized with '" + << to_string(value) << "'" << eom; throw 0; } if(value.id()==ID_designated_initializer) { error().source_location = value.source_location(); - error() << "type '" << to_string(full_type) + error() << "type '" << to_string(type) << "' cannot be initialized with designated initializer" << eom; throw 0; } @@ -259,11 +253,9 @@ void c_typecheck_baset::designator_enter( { designatort::entryt entry(type); - const typet &full_type=follow(type); - - if(full_type.id()==ID_struct) + if(auto struct_tag_type = type_try_dynamic_cast(type)) { - const struct_typet &struct_type=to_struct_type(full_type); + const struct_typet &struct_type = follow_tag(*struct_tag_type); entry.size=struct_type.components().size(); entry.subtype.make_nil(); @@ -286,9 +278,9 @@ void c_typecheck_baset::designator_enter( ++entry.index; } } - else if(full_type.id()==ID_union) + else if(auto union_tag_type = type_try_dynamic_cast(type)) { - const union_typet &union_type=to_union_type(full_type); + const union_typet &union_type = follow_tag(*union_tag_type); if(union_type.components().empty()) { @@ -303,9 +295,9 @@ void c_typecheck_baset::designator_enter( entry.subtype=union_type.components().front().type(); } } - else if(full_type.id()==ID_array) + else if(type.id() == ID_array) { - const array_typet &array_type=to_array_type(full_type); + const array_typet &array_type = to_array_type(type); if(array_type.size().is_nil()) { @@ -327,9 +319,9 @@ void c_typecheck_baset::designator_enter( entry.subtype = array_type.element_type(); } } - else if(full_type.id()==ID_vector) + else if(type.id() == ID_vector) { - const vector_typet &vector_type=to_vector_type(full_type); + const vector_typet &vector_type = to_vector_type(type); const auto vector_size = numeric_cast(vector_type.size()); @@ -387,10 +379,8 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer( { size_t index=designator[i].index; const typet &type=designator[i].type; - const typet &full_type=follow(type); - if(full_type.id()==ID_array || - full_type.id()==ID_vector) + if(type.id() == ID_array || type.id() == ID_vector) { // zero_initializer may have built an array_of expression for a large // array; as we have a designated initializer we need to have an array of @@ -403,7 +393,7 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer( { error().source_location = value.source_location(); error() << "cannot zero-initialize array with element type '" - << to_string(to_type_with_subtype(full_type).subtype()) << "'" + << to_string(to_type_with_subtype(type).subtype()) << "'" << eom; throw 0; } @@ -414,11 +404,11 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer( if(index>=dest->operands().size()) { - if(full_type.id()==ID_array && - (to_array_type(full_type).size().is_zero() || - to_array_type(full_type).size().is_nil())) + if( + type.id() == ID_array && (to_array_type(type).size().is_zero() || + to_array_type(type).size().is_nil())) { - const typet &element_type = to_array_type(full_type).element_type(); + const typet &element_type = to_array_type(type).element_type(); // we are willing to grow an incomplete or zero-sized array -- // do_initializer_list will fix up the resulting type @@ -446,10 +436,11 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer( dest = &(dest->operands()[numeric_cast_v(index)]); } - else if(full_type.id()==ID_struct) + else if( + auto struct_tag_type = type_try_dynamic_cast(type)) { - const struct_typet::componentst &components= - to_struct_type(full_type).components(); + const struct_typet::componentst &components = + follow_tag(*struct_tag_type).components(); if(index>=dest->operands().size()) { @@ -471,9 +462,9 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer( dest=&(dest->operands()[index]); } - else if(full_type.id()==ID_union) + else if(auto union_tag_type = type_try_dynamic_cast(type)) { - const union_typet &union_type=to_union_type(full_type); + const union_typet &union_type = follow_tag(*union_tag_type); const union_typet::componentst &components= union_type.components(); @@ -574,13 +565,11 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer( // see what type we have to initialize const typet &type=designator.back().subtype; - const typet &full_type=follow(type); // do we initialize a scalar? - if(full_type.id()!=ID_struct && - full_type.id()!=ID_union && - full_type.id()!=ID_array && - full_type.id()!=ID_vector) + if( + type.id() != ID_struct_tag && type.id() != ID_union_tag && + type.id() != ID_array && type.id() != ID_vector) { // The initializer for a scalar shall be a single expression, // * optionally enclosed in braces. * @@ -594,16 +583,16 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer( else *dest=do_initializer_rec(value, type, force_constant); - DATA_INVARIANT(full_type == follow(dest->type()), "matching types"); + DATA_INVARIANT(type == dest->type(), "matching types"); return ++init_it; // done } // union? The component in the zero initializer might // not be the first one. - if(full_type.id()==ID_union) + if(auto union_tag_type = type_try_dynamic_cast(type)) { - const union_typet &union_type=to_union_type(full_type); + const union_typet &union_type = follow_tag(*union_tag_type); const union_typet::componentst &components= union_type.components(); @@ -640,22 +629,22 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer( // which are like arrays. We only do so if we are to // initialize an array of scalars. if( - full_type.id() == ID_array && - (to_array_type(full_type).element_type().id() == ID_signedbv || - to_array_type(full_type).element_type().id() == ID_unsignedbv)) + type.id() == ID_array && + (to_array_type(type).element_type().id() == ID_signedbv || + to_array_type(type).element_type().id() == ID_unsignedbv)) { *dest=do_initializer_rec(value, type, force_constant); return ++init_it; // done } } - else if(follow(value.type())==full_type) + else if(value.type() == type) { // a struct/union/vector can be initialized directly with // an expression of the right type. This doesn't // work with arrays, unfortunately. - if(full_type.id()==ID_struct || - full_type.id()==ID_union || - full_type.id()==ID_vector) + if( + type.id() == ID_struct_tag || type.id() == ID_union_tag || + type.id() == ID_vector) { *dest=value; return ++init_it; // done @@ -663,13 +652,13 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer( } DATA_INVARIANT( - full_type.id() == ID_struct || full_type.id() == ID_union || - full_type.id() == ID_array || full_type.id() == ID_vector, + type.id() == ID_struct_tag || type.id() == ID_union_tag || + type.id() == ID_array || type.id() == ID_vector, "full type must be composite"); // we are initializing a compound type, and enter it! - // this may change the type, full_type might not be valid any more - const typet dest_type=full_type; + // this may change the type, type might not be valid any more + const typet dest_type = type; const bool vla_permitted=designator.back().vla_permitted; designator_enter(type, designator); @@ -721,20 +710,17 @@ void c_typecheck_baset::increment_designator(designatort &designator) while(true) { designatort::entryt &entry=designator[designator.size()-1]; - const typet &full_type=follow(entry.type); entry.index++; - if(full_type.id()==ID_array && - to_array_type(full_type).size().is_nil()) + if(entry.type.id() == ID_array && to_array_type(entry.type).size().is_nil()) return; // we will keep going forever - if(full_type.id()==ID_struct && - entry.index(to_array_type(full_type).size())) + numeric_cast(to_array_type(entry.type).size())) size = *size_opt; else { @@ -817,13 +802,14 @@ designatort c_typecheck_baset::make_designator( entry.index = numeric_cast_v(index); entry.size = numeric_cast_v(size); - entry.subtype = to_array_type(full_type).element_type(); + entry.subtype = to_array_type(entry.type).element_type(); } - else if(full_type.id()==ID_struct || - full_type.id()==ID_union) + else if( + auto struct_union_tag_type = + type_try_dynamic_cast(entry.type)) { - const struct_union_typet &struct_union_type= - to_struct_union_type(full_type); + const struct_union_typet &struct_union_type = + follow_tag(*struct_union_tag_type); if(d_op.id()!=ID_member) { @@ -854,8 +840,8 @@ designatort c_typecheck_baset::make_designator( { repeat=false; std::size_t number = 0; - const struct_union_typet::componentst &components= - to_struct_union_type(follow(tmp_type)).components(); + const struct_union_typet::componentst &components = + follow_tag(to_struct_or_union_tag_type(tmp_type)).components(); for(const auto &c : components) { @@ -873,7 +859,9 @@ designatort c_typecheck_baset::make_designator( c.type().id() == ID_union_tag) && (config.ansi_c.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO || - follow(c.type()).find(ID_tag).is_nil()) && + follow_tag(to_struct_or_union_tag_type(c.type())) + .find(ID_tag) + .is_nil()) && has_component_rec(c.type(), component_name, *this)) { entry.index=number; @@ -905,7 +893,7 @@ designatort c_typecheck_baset::make_designator( { error().source_location = d_op.source_location(); error() << "designated initializers cannot initialize '" - << to_string(full_type) << "'" << eom; + << to_string(entry.type) << "'" << eom; throw 0; } @@ -925,16 +913,14 @@ exprt c_typecheck_baset::do_initializer_list( { PRECONDITION(value.id() == ID_initializer_list); - const typet &full_type=follow(type); - // 6.7.9, 14: An array of character type may be initialized by a character // string literal or UTF-8 string literal, optionally enclosed in braces. if( - full_type.id() == ID_array && value.operands().size() >= 1 && + type.id() == ID_array && value.operands().size() >= 1 && to_multi_ary_expr(value).op0().id() == ID_string_constant && - (to_array_type(full_type).element_type().id() == ID_signedbv || - to_array_type(full_type).element_type().id() == ID_unsignedbv) && - to_bitvector_type(to_array_type(full_type).element_type()).get_width() == + (to_array_type(type).element_type().id() == ID_signedbv || + to_array_type(type).element_type().id() == ID_unsignedbv) && + to_bitvector_type(to_array_type(type).element_type()).get_width() == char_type().get_width()) { if(value.operands().size() > 1) @@ -948,27 +934,26 @@ exprt c_typecheck_baset::do_initializer_list( } exprt result; - if(full_type.id()==ID_struct || - full_type.id()==ID_union || - full_type.id()==ID_vector) + if( + type.id() == ID_struct_tag || type.id() == ID_union_tag || + type.id() == ID_vector) { // start with zero everywhere const auto zero = zero_initializer(type, value.source_location(), *this); if(!zero.has_value()) { error().source_location = value.source_location(); - error() << "cannot zero-initialize '" << to_string(full_type) << "'" - << eom; + error() << "cannot zero-initialize '" << to_string(type) << "'" << eom; throw 0; } result = *zero; } - else if(full_type.id()==ID_array) + else if(type.id() == ID_array) { - if(to_array_type(full_type).size().is_nil()) + if(to_array_type(type).size().is_nil()) { // start with empty array - result = array_exprt({}, to_array_type(full_type)); + result = array_exprt({}, to_array_type(type)); result.add_source_location()=value.source_location(); } else @@ -978,8 +963,7 @@ exprt c_typecheck_baset::do_initializer_list( if(!zero.has_value()) { error().source_location = value.source_location(); - error() << "cannot zero-initialize '" << to_string(full_type) << "'" - << eom; + error() << "cannot zero-initialize '" << to_string(type) << "'" << eom; throw 0; } result = *zero; @@ -995,7 +979,7 @@ exprt c_typecheck_baset::do_initializer_list( to_unary_expr(value).op(), type, force_constant); error().source_location = value.source_location(); - error() << "cannot initialize '" << to_string(full_type) + error() << "cannot initialize '" << to_string(type) << "' with an initializer list" << eom; throw 0; } @@ -1015,9 +999,9 @@ exprt c_typecheck_baset::do_initializer_list( increment_designator(current_designator); } - if(full_type.id()==ID_struct) + if(auto struct_tag_type = type_try_dynamic_cast(type)) { - const struct_typet &full_struct_type = to_struct_type(full_type); + const struct_typet &full_struct_type = follow_tag(*struct_tag_type); const struct_typet::componentst &components = full_struct_type.components(); // make sure we didn't mess up index computation CHECK_RETURN(result.operands().size() == components.size()); @@ -1058,8 +1042,7 @@ exprt c_typecheck_baset::do_initializer_list( } } - if(full_type.id()==ID_array && - to_array_type(full_type).size().is_nil()) + if(type.id() == ID_array && to_array_type(type).size().is_nil()) { // make complete by setting array size array_typet &array_type = to_array_type(result.type()); diff --git a/src/ansi-c/c_typecheck_type.cpp b/src/ansi-c/c_typecheck_type.cpp index 59f37f1a52e..02e50709308 100644 --- a/src/ansi-c/c_typecheck_type.cpp +++ b/src/ansi-c/c_typecheck_type.cpp @@ -525,11 +525,11 @@ void c_typecheck_baset::typecheck_array_type(array_typet &type) } // We don't allow incomplete structs or unions as element type. - const typet &followed_subtype = follow(type.element_type()); - if( - (followed_subtype.id() == ID_struct || followed_subtype.id() == ID_union) && - to_struct_union_type(followed_subtype).is_incomplete()) + (type.element_type().id() == ID_struct_tag && + follow_tag(to_struct_tag_type(type.element_type())).is_incomplete()) || + (type.element_type().id() == ID_union_tag && + follow_tag(to_union_tag_type(type.element_type())).is_incomplete())) { // ISO/IEC 9899 6.7.5.2 throw errort().with_location(type.source_location()) diff --git a/src/ansi-c/expr2c.cpp b/src/ansi-c/expr2c.cpp index 6ca3038e1a9..1105a6b52e7 100644 --- a/src/ansi-c/expr2c.cpp +++ b/src/ansi-c/expr2c.cpp @@ -890,13 +890,11 @@ std::string expr2ct::convert_with( const irep_idt &component_name= src.operands()[i].get(ID_component_name); - const typet &full_type = ns.follow(old.type()); - - const struct_union_typet &struct_union_type= - to_struct_union_type(full_type); - - const struct_union_typet::componentt &comp_expr= - struct_union_type.get_component(component_name); + const struct_union_typet::componentt &comp_expr = + (old.type().id() == ID_struct_tag || old.type().id() == ID_union_tag) + ? ns.follow_tag(to_struct_or_union_tag_type(old.type())) + .get_component(component_name) + : to_struct_union_type(old.type()).get_component(component_name); CHECK_RETURN(comp_expr.is_not_nil()); irep_idt display_component_name; @@ -1551,14 +1549,19 @@ std::string expr2ct::convert_member( dest+='.'; } - const typet &full_type = ns.follow(compound.type()); - - if(full_type.id()!=ID_struct && - full_type.id()!=ID_union) + if( + compound.type().id() != ID_struct && compound.type().id() != ID_union && + compound.type().id() != ID_struct_tag && + compound.type().id() != ID_union_tag) + { return convert_norep(src, precedence); + } - const struct_union_typet &struct_union_type= - to_struct_union_type(full_type); + const struct_union_typet &struct_union_type = + (compound.type().id() == ID_struct_tag || + compound.type().id() == ID_union_tag) + ? ns.follow_tag(to_struct_or_union_tag_type(compound.type())) + : to_struct_union_type(compound.type()); irep_idt component_name=src.get_component_name(); @@ -2056,13 +2059,13 @@ std::string expr2ct::convert_struct( unsigned &precedence, bool include_padding_components) { - 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()); const struct_typet::componentst &components= struct_type.components(); diff --git a/src/ansi-c/padding.cpp b/src/ansi-c/padding.cpp index d7996e6d831..b034eb15c5a 100644 --- a/src/ansi-c/padding.cpp +++ b/src/ansi-c/padding.cpp @@ -387,7 +387,10 @@ static void add_padding_gcc(struct_typet &type, const namespacet &ns) // check minimum alignment if( a < config.ansi_c.alignment && !it_type.get_bool(ID_C_packed) && - !ns.follow(it_type).get_bool(ID_C_packed)) + (it_type.id() != ID_struct_tag || + !ns.follow_tag(to_struct_tag_type(it_type)).get_bool(ID_C_packed)) && + (it_type.id() != ID_union_tag || + !ns.follow_tag(to_union_tag_type(it_type)).get_bool(ID_C_packed))) { a=config.ansi_c.alignment; } diff --git a/src/cpp/cpp_typecheck_resolve.cpp b/src/cpp/cpp_typecheck_resolve.cpp index 37d4d529dc4..0afadc656bb 100644 --- a/src/cpp/cpp_typecheck_resolve.cpp +++ b/src/cpp/cpp_typecheck_resolve.cpp @@ -294,23 +294,13 @@ exprt cpp_typecheck_resolvet::convert_identifier( // check if the member can be applied to the object if( - object.type().id() == ID_struct_tag || - object.type().id() == ID_union_tag) + (object.type().id() != ID_struct_tag && + object.type().id() != ID_union_tag) || + !has_component_rec(object.type(), identifier.identifier, cpp_typecheck)) { - 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( - object_type, identifier.identifier, cpp_typecheck)) - { - object.make_nil(); // failed! - } - } - else + // failed object.make_nil(); + } if(object.is_not_nil()) {