diff --git a/src/ansi-c/c_typecast.cpp b/src/ansi-c/c_typecast.cpp index f29d882c7ef..eb31923d73a 100644 --- a/src/ansi-c/c_typecast.cpp +++ b/src/ansi-c/c_typecast.cpp @@ -156,7 +156,6 @@ bool check_c_implicit_typecast( src_type_id==ID_signedbv || src_type_id==ID_c_enum || src_type_id==ID_c_enum_tag || - src_type_id==ID_incomplete_c_enum || src_type_id==ID_c_bool) { if(dest_type.id()==ID_unsignedbv || @@ -171,7 +170,6 @@ bool check_c_implicit_typecast( dest_type.id()==ID_pointer || dest_type.id()==ID_c_enum || dest_type.id()==ID_c_enum_tag || - dest_type.id()==ID_incomplete_c_enum || dest_type.id()==ID_complex) return false; } @@ -345,9 +343,7 @@ c_typecastt::c_typet c_typecastt::get_c_type( { return PTR; } - else if(type.id()==ID_c_enum || - type.id()==ID_c_enum_tag || - type.id()==ID_incomplete_c_enum) + else if(type.id() == ID_c_enum || type.id() == ID_c_enum_tag) { return INT; } diff --git a/src/ansi-c/c_typecheck_base.cpp b/src/ansi-c/c_typecheck_base.cpp index 249cd9a4fde..03170ca8fbe 100644 --- a/src/ansi-c/c_typecheck_base.cpp +++ b/src/ansi-c/c_typecheck_base.cpp @@ -85,21 +85,15 @@ void c_typecheck_baset::typecheck_symbol(symbolt &symbol) } // set the pretty name - if(symbol.is_type && - (final_type.id()==ID_struct || - final_type.id()==ID_incomplete_struct)) + if(symbol.is_type && final_type.id() == ID_struct) { symbol.pretty_name="struct "+id2string(symbol.base_name); } - else if(symbol.is_type && - (final_type.id()==ID_union || - final_type.id()==ID_incomplete_union)) + else if(symbol.is_type && final_type.id() == ID_union) { symbol.pretty_name="union "+id2string(symbol.base_name); } - else if(symbol.is_type && - (final_type.id()==ID_c_enum || - final_type.id()==ID_incomplete_c_enum)) + else if(symbol.is_type && final_type.id() == ID_c_enum) { symbol.pretty_name="enum "+id2string(symbol.base_name); } @@ -176,12 +170,21 @@ void c_typecheck_baset::typecheck_redefinition_type( const typet &final_new=follow(new_symbol.type); // see if we had something incomplete before - if(final_old.id()==ID_incomplete_struct || - final_old.id()==ID_incomplete_union || - final_old.id()==ID_incomplete_c_enum) + if( + (final_old.id() == ID_struct && + to_struct_type(final_old).is_incomplete()) || + (final_old.id() == ID_union && to_union_type(final_old).is_incomplete()) || + (final_old.id() == ID_c_enum && to_c_enum_type(final_old).is_incomplete())) { - // new one complete? - if("incomplete_"+final_new.id_string()==final_old.id_string()) + // is the new one complete? + if( + final_new.id() == final_old.id() && + ((final_new.id() == ID_struct && + !to_struct_type(final_new).is_incomplete()) || + (final_new.id() == ID_union && + !to_union_type(final_new).is_incomplete()) || + (final_new.id() == ID_c_enum && + !to_c_enum_type(final_new).is_incomplete()))) { // overwrite location old_symbol.location=new_symbol.location; @@ -190,7 +193,7 @@ void c_typecheck_baset::typecheck_redefinition_type( old_symbol.type.swap(new_symbol.type); } else if(new_symbol.type.id()==old_symbol.type.id()) - return; + return; // ignore else { error().source_location=new_symbol.location; @@ -203,11 +206,15 @@ void c_typecheck_baset::typecheck_redefinition_type( else { // see if new one is just a tag - if(final_new.id()==ID_incomplete_struct || - final_new.id()==ID_incomplete_union || - final_new.id()==ID_incomplete_c_enum) + if( + (final_new.id() == ID_struct && + to_struct_type(final_new).is_incomplete()) || + (final_new.id() == ID_union && + to_union_type(final_new).is_incomplete()) || + (final_new.id() == ID_c_enum && + to_c_enum_type(final_new).is_incomplete())) { - if("incomplete_"+final_old.id_string()==final_new.id_string()) + if(final_old.id() == final_new.id()) { // just ignore silently } @@ -418,13 +425,6 @@ void c_typecheck_baset::typecheck_redefinition_non_type( PRECONDITION(old_symbol.type.id() != ID_symbol_type); old_symbol.type=new_symbol.type; } - else if((final_old.id()==ID_incomplete_c_enum || - final_old.id()==ID_c_enum) && - (final_new.id()==ID_incomplete_c_enum || - final_new.id()==ID_c_enum)) - { - // this is ok for now - } else if(final_old.id()==ID_pointer && follow(final_old).subtype().id()==ID_code && to_code_type(follow(final_old).subtype()).has_ellipsis() && @@ -477,12 +477,10 @@ void c_typecheck_baset::typecheck_redefinition_non_type( } else { - if(new_symbol.is_macro && - (final_new.id()==ID_incomplete_c_enum || - final_new.id()==ID_c_enum) && - old_symbol.value.is_constant() && - new_symbol.value.is_constant() && - old_symbol.value.get(ID_value)==new_symbol.value.get(ID_value)) + if( + new_symbol.is_macro && final_new.id() == ID_c_enum && + old_symbol.value.is_constant() && new_symbol.value.is_constant() && + old_symbol.value.get(ID_value) == new_symbol.value.get(ID_value)) { // ignore } diff --git a/src/ansi-c/c_typecheck_code.cpp b/src/ansi-c/c_typecheck_code.cpp index f41af100e12..e885807f3ce 100644 --- a/src/ansi-c/c_typecheck_code.cpp +++ b/src/ansi-c/c_typecheck_code.cpp @@ -341,10 +341,7 @@ void c_typecheck_baset::typecheck_decl(codet &code) bool c_typecheck_baset::is_complete_type(const typet &type) const { - if(type.id()==ID_incomplete_struct || - type.id()==ID_incomplete_union) - return false; - else if(type.id()==ID_array) + if(type.id() == ID_array) { if(to_array_type(type).size().is_nil()) return false; @@ -352,7 +349,12 @@ bool c_typecheck_baset::is_complete_type(const typet &type) const } else if(type.id()==ID_struct || type.id()==ID_union) { - for(const auto &c : to_struct_union_type(type).components()) + const auto &struct_union_type = to_struct_union_type(type); + + if(struct_union_type.is_incomplete()) + return false; + + for(const auto &c : struct_union_type.components()) if(!is_complete_type(c.type())) return false; } diff --git a/src/ansi-c/c_typecheck_expr.cpp b/src/ansi-c/c_typecheck_expr.cpp index e11a21f5e39..35d0c72449d 100644 --- a/src/ansi-c/c_typecheck_expr.cpp +++ b/src/ansi-c/c_typecheck_expr.cpp @@ -1361,8 +1361,7 @@ void c_typecheck_baset::typecheck_expr_rel( if(follow(o_type0)==follow(o_type1)) { const typet &final_type=follow(o_type0); - if(final_type.id()!=ID_array && - final_type.id()!=ID_incomplete_struct) + if(final_type.id() != ID_array) { adjust_float_rel(expr); return; // no promotion necessary @@ -1524,22 +1523,6 @@ void c_typecheck_baset::typecheck_expr_member(exprt &expr) type = follow(type); - if(type.id()==ID_incomplete_struct) - { - error().source_location = expr.source_location(); - error() << "member operator got incomplete struct type " - "on left hand side" << eom; - throw 0; - } - - if(type.id()==ID_incomplete_union) - { - error().source_location = expr.source_location(); - error() << "member operator got incomplete union type " - "on left hand side" << eom; - throw 0; - } - if(type.id()!=ID_struct && type.id()!=ID_union) { @@ -1553,6 +1536,14 @@ void c_typecheck_baset::typecheck_expr_member(exprt &expr) const struct_union_typet &struct_union_type= to_struct_union_type(type); + if(struct_union_type.is_incomplete()) + { + error().source_location = expr.source_location(); + error() << "member operator got incomplete " << type.id() + << " type on left hand side" << eom; + throw 0; + } + const irep_idt &component_name= expr.get(ID_component_name); @@ -1897,8 +1888,7 @@ void c_typecheck_baset::typecheck_expr_side_effect(side_effect_exprt &expr) if(final_type0.id()==ID_c_enum_tag) { - if(follow_tag(to_c_enum_tag_type(final_type0)).id()== - ID_incomplete_c_enum) + if(follow_tag(to_c_enum_tag_type(final_type0)).is_incomplete()) { error().source_location = expr.source_location(); error() << "operator `" << statement @@ -3166,7 +3156,17 @@ void c_typecheck_baset::typecheck_arithmetic_pointer(const exprt &expr) typet subtype=type.subtype(); - if(subtype.id()==ID_incomplete_struct) + if( + subtype.id() == ID_struct_tag && + follow_tag(to_struct_tag_type(subtype)).is_incomplete()) + { + error().source_location = expr.source_location(); + error() << "pointer arithmetic with unknown object size" << eom; + throw 0; + } + else if( + subtype.id() == ID_union_tag && + follow_tag(to_union_tag_type(subtype)).is_incomplete()) { error().source_location = expr.source_location(); error() << "pointer arithmetic with unknown object size" << eom; @@ -3370,8 +3370,7 @@ void c_typecheck_baset::typecheck_side_effect_assignment( if(underlying_type.id()==ID_c_enum_tag) { - const typet &c_enum_type= - follow_tag(to_c_enum_tag_type(underlying_type)); + const auto &c_enum_type = to_c_enum_tag_type(underlying_type); underlying_type=c_enum_type.subtype(); } diff --git a/src/ansi-c/c_typecheck_initializer.cpp b/src/ansi-c/c_typecheck_initializer.cpp index 94d9e7e2f2f..3219954dc42 100644 --- a/src/ansi-c/c_typecheck_initializer.cpp +++ b/src/ansi-c/c_typecheck_initializer.cpp @@ -58,10 +58,12 @@ exprt c_typecheck_baset::do_initializer_rec( { const typet &full_type=follow(type); - if(full_type.id()==ID_incomplete_struct) + if( + (full_type.id() == ID_struct || full_type.id() == ID_union) && + to_struct_union_type(full_type).is_incomplete()) { error().source_location = value.source_location(); - error() << "type `" << to_string(full_type) + error() << "type `" << to_string(type) << "' is still incomplete -- cannot initialize" << eom; throw 0; } diff --git a/src/ansi-c/c_typecheck_type.cpp b/src/ansi-c/c_typecheck_type.cpp index 4ef6a5f2f8b..79702a80b49 100644 --- a/src/ansi-c/c_typecheck_type.cpp +++ b/src/ansi-c/c_typecheck_type.cpp @@ -523,9 +523,11 @@ void c_typecheck_baset::typecheck_array_type(array_typet &type) } // we don't allow incomplete structs or unions as subtype + const typet &followed_subtype = follow(type.subtype()); + if( - follow(type.subtype()).id() == ID_incomplete_struct || - follow(type.subtype()).id() == ID_incomplete_union) + (followed_subtype.id() == ID_struct || followed_subtype.id() == ID_union) && + to_struct_union_type(followed_subtype).is_incomplete()) { // ISO/IEC 9899 6.7.5.2 error().source_location = type.source_location(); @@ -806,12 +808,8 @@ void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type) typet new_type=compound_symbol.type; - if(compound_symbol.type.id()==ID_struct) - compound_symbol.type.id(ID_incomplete_struct); - else if(compound_symbol.type.id()==ID_union) - compound_symbol.type.id(ID_incomplete_union); - else - UNREACHABLE; + // mark as incomplete + to_struct_union_type(compound_symbol.type).make_incomplete(); symbolt *new_symbol; move_symbol(compound_symbol, new_symbol); @@ -826,8 +824,9 @@ void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type) else { // yes, it exists already - if(s_it->second.type.id()==ID_incomplete_struct || - s_it->second.type.id()==ID_incomplete_union) + if( + s_it->second.type.id() == type.id() && + to_struct_union_type(s_it->second.type).is_incomplete()) { // Maybe we got a body now. if(have_body) @@ -852,9 +851,9 @@ void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type) typet tag_type; - if(type.id() == ID_union || type.id() == ID_incomplete_union) + if(type.id() == ID_union) tag_type = union_tag_typet(identifier); - else if(type.id() == ID_struct || type.id() == ID_incomplete_struct) + else if(type.id() == ID_struct) tag_type = struct_tag_typet(identifier); else UNREACHABLE; @@ -1278,13 +1277,20 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type) // Yes. const symbolt &symbol=s_it->second; - if(symbol.type.id()==ID_incomplete_c_enum) + if(symbol.type.id() != ID_c_enum) + { + error().source_location = source_location; + error() << "use of tag that does not match previous declaration" << eom; + throw 0; + } + + if(to_c_enum_type(symbol.type).is_incomplete()) { // Ok, overwrite the type in the symbol table. // This gives us the members and the subtype. symbol_table.get_writeable_ref(symbol.name).type=enum_tag_symbol.type; } - else if(symbol.type.id()==ID_c_enum) + else { // We might already have the same anonymous enum, and this is // simply ok. Note that the C standard treats these as @@ -1296,12 +1302,6 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type) throw 0; } } - else - { - error().source_location=source_location; - error() << "use of tag that does not match previous declaration" << eom; - throw 0; - } } else { @@ -1341,8 +1341,7 @@ void c_typecheck_baset::typecheck_c_enum_tag_type(c_enum_tag_typet &type) // Yes. const symbolt &symbol=s_it->second; - if(symbol.type.id()!=ID_c_enum && - symbol.type.id()!=ID_incomplete_c_enum) + if(symbol.type.id() != ID_c_enum) { error().source_location=source_location; error() << "use of tag that does not match previous declaration" << eom; @@ -1352,9 +1351,9 @@ void c_typecheck_baset::typecheck_c_enum_tag_type(c_enum_tag_typet &type) else { // no, add it as an incomplete c_enum - typet new_type(ID_incomplete_c_enum); - new_type.subtype()=signed_int_type(); // default + c_enum_typet new_type(signed_int_type()); // default subtype new_type.add(ID_tag)=tag; + new_type.make_incomplete(); symbolt enum_tag_symbol; @@ -1424,10 +1423,10 @@ void c_typecheck_baset::typecheck_c_bit_field_type(c_bit_field_typet &type) // These point to an enum, which has a sub-subtype, // which may be smaller or larger than int, and we thus have // to check. - const typet &c_enum_type= - follow_tag(to_c_enum_tag_type(subtype)); + const auto &c_enum_type = + to_c_enum_type(follow_tag(to_c_enum_tag_type(subtype))); - if(c_enum_type.id()==ID_incomplete_c_enum) + if(c_enum_type.is_incomplete()) { error().source_location=type.source_location(); error() << "bit field has incomplete enum type" << eom; diff --git a/src/ansi-c/expr2c.cpp b/src/ansi-c/expr2c.cpp index 6023a83f7aa..9768e61844d 100644 --- a/src/ansi-c/expr2c.cpp +++ b/src/ansi-c/expr2c.cpp @@ -332,17 +332,6 @@ std::string expr2ct::convert_rec( { return convert_struct_type(src, q, d); } - else if(src.id()==ID_incomplete_struct) - { - std::string dest=q+"struct"; - - const std::string &tag=src.get_string(ID_tag); - if(tag!="") - dest+=" "+tag; - dest+=d; - - return dest; - } else if(src.id()==ID_union) { const union_typet &union_type=to_union_type(src); @@ -352,28 +341,21 @@ std::string expr2ct::convert_rec( const irep_idt &tag=union_type.get_tag(); if(tag!="") dest+=" "+id2string(tag); - dest+=" {"; - for(const auto &c : union_type.components()) + if(!union_type.is_incomplete()) { - dest+=' '; - dest += convert_rec(c.type(), c_qualifierst(), id2string(c.get_name())); - dest+=';'; - } - - dest+=" }"; + dest += " {"; - dest+=d; + for(const auto &c : union_type.components()) + { + dest += ' '; + dest += convert_rec(c.type(), c_qualifierst(), id2string(c.get_name())); + dest += ';'; + } - return dest; - } - else if(src.id()==ID_incomplete_union) - { - std::string dest=q+"union"; + dest += " }"; + } - const std::string &tag=src.get_string(ID_tag); - if(tag!="") - dest+=" "+tag; dest+=d; return dest; @@ -397,40 +379,31 @@ std::string expr2ct::convert_rec( } result+=' '; - result+='{'; - // add members - const c_enum_typet::memberst &members=to_c_enum_type(src).members(); - - for(c_enum_typet::memberst::const_iterator - it=members.begin(); - it!=members.end(); - it++) + if(!to_c_enum_type(src).is_incomplete()) { - if(it!=members.begin()) - result+=','; - result+=' '; - result+=id2string(it->get_base_name()); - result+='='; - result+=id2string(it->get_value()); - } + result += '{'; - result+=" }"; + // add members + const c_enum_typet::memberst &members = to_c_enum_type(src).members(); - result+=d; - return result; - } - else if(src.id()==ID_incomplete_c_enum) - { - const irept &tag=src.find(ID_tag); + for(c_enum_typet::memberst::const_iterator it = members.begin(); + it != members.end(); + it++) + { + if(it != members.begin()) + result += ','; + result += ' '; + result += id2string(it->get_base_name()); + result += '='; + result += id2string(it->get_value()); + } - if(tag.is_not_nil()) - { - std::string result=q+"enum"; - result+=" "+tag.get_string(ID_C_base_name); - result+=d; - return result; + result += " }"; } + + result += d; + return result; } else if(src.id()==ID_c_enum_tag) { @@ -708,7 +681,7 @@ std::string expr2ct::convert_struct_type( if(tag!="") dest+=" "+id2string(tag); - if(inc_struct_body) + if(inc_struct_body && !struct_type.is_incomplete()) { dest+=" {"; diff --git a/src/ansi-c/padding.cpp b/src/ansi-c/padding.cpp index 08d8fd1c4f5..032cf12bf8d 100644 --- a/src/ansi-c/padding.cpp +++ b/src/ansi-c/padding.cpp @@ -120,9 +120,9 @@ underlying_width(const c_bit_field_typet &type, const namespacet &ns) // These point to an enum, which has a sub-subtype, // which may be smaller or larger than int, and we thus have // to check. - const typet &c_enum_type = ns.follow_tag(to_c_enum_tag_type(subtype)); + const auto &c_enum_type = ns.follow_tag(to_c_enum_tag_type(subtype)); - if(c_enum_type.id() == ID_c_enum) + if(!c_enum_type.is_incomplete()) return to_bitvector_type(c_enum_type.subtype()).get_width(); else return {}; diff --git a/src/ansi-c/type2name.cpp b/src/ansi-c/type2name.cpp index da231e328bd..06fb45d21b2 100644 --- a/src/ansi-c/type2name.cpp +++ b/src/ansi-c/type2name.cpp @@ -200,49 +200,60 @@ static std::string type2name( else if(type.id()==ID_struct || type.id()==ID_union) { - if(type.id()==ID_struct) - result+="ST"; - if(type.id()==ID_union) - result+="UN"; - result+='['; - bool first = true; - for(const auto &c : to_struct_union_type(type).components()) - { - if(!first) - result+='|'; - else - first = false; + const auto &struct_union_type = to_struct_union_type(type); - result += type2name(c.type(), ns, symbol_number); - const irep_idt &component_name = c.get_name(); - CHECK_RETURN(!component_name.empty()); - result+="'"+id2string(component_name)+"'"; + if(struct_union_type.is_incomplete()) + { + if(type.id() == ID_struct) + result += "ST?"; + else if(type.id() == ID_union) + result += "UN?"; + } + else + { + if(type.id() == ID_struct) + result += "ST"; + if(type.id() == ID_union) + result += "UN"; + result += '['; + bool first = true; + for(const auto &c : struct_union_type.components()) + { + if(!first) + result += '|'; + else + first = false; + + result += type2name(c.type(), ns, symbol_number); + const irep_idt &component_name = c.get_name(); + CHECK_RETURN(!component_name.empty()); + result += "'" + id2string(component_name) + "'"; + } + result += ']'; } - result+=']'; } - else if(type.id()==ID_incomplete_struct) - result +="ST?"; - else if(type.id()==ID_incomplete_union) - result +="UN?"; else if(type.id()==ID_c_enum) { - result +="EN"; const c_enum_typet &t=to_c_enum_type(type); - const c_enum_typet::memberst &members=t.members(); - result+='['; - for(c_enum_typet::memberst::const_iterator - it=members.begin(); - it!=members.end(); - ++it) + + if(t.is_incomplete()) + result += "EN?"; + else { - if(it!=members.begin()) - result+='|'; - result+=id2string(it->get_value()); - result+="'"+id2string(it->get_identifier())+"'"; + result += "EN"; + const c_enum_typet::memberst &members = t.members(); + result += '['; + for(c_enum_typet::memberst::const_iterator it = members.begin(); + it != members.end(); + ++it) + { + if(it != members.begin()) + result += '|'; + result += id2string(it->get_value()); + result += "'" + id2string(it->get_identifier()) + "'"; + } } } - else if(type.id()==ID_incomplete_c_enum) - result +="EN?"; else if(type.id()==ID_c_bit_field) result+="BF"+pointer_offset_bits_as_string(type, ns); else if(type.id()==ID_vector) diff --git a/src/cpp/cpp_instantiate_template.cpp b/src/cpp/cpp_instantiate_template.cpp index 2fdbe6331ee..c2cff0e5c1b 100644 --- a/src/cpp/cpp_instantiate_template.cpp +++ b/src/cpp/cpp_instantiate_template.cpp @@ -145,13 +145,14 @@ const symbolt &cpp_typecheckt::class_template_symbol( if(s_it!=symbol_table.symbols.end()) return s_it->second; - // Create as incomplete_struct, but mark as + // Create as incomplete struct, but mark as // "template_class_instance", to be elaborated later. symbolt new_symbol; new_symbol.name=identifier; new_symbol.pretty_name=template_symbol.pretty_name; new_symbol.location=template_symbol.location; - new_symbol.type=typet(ID_incomplete_struct); + new_symbol.type = struct_typet(); + to_struct_type(new_symbol.type).make_incomplete(); new_symbol.type.set(ID_tag, template_symbol.type.find(ID_tag)); if(template_symbol.type.get_bool(ID_C_class)) new_symbol.type.set(ID_C_class, true); @@ -194,8 +195,7 @@ void cpp_typecheckt::elaborate_class_template( // Make a copy, as instantiate will destroy the symbol type! const typet t_type=symbol.type; - if(t_type.id()==ID_incomplete_struct && - t_type.get_bool(ID_template_class_instance)) + if(t_type.id() == ID_struct && t_type.get_bool(ID_template_class_instance)) { instantiate_template( type.source_location(), diff --git a/src/cpp/cpp_typecheck_bases.cpp b/src/cpp/cpp_typecheck_bases.cpp index 68156d96c1c..5ffde029cea 100644 --- a/src/cpp/cpp_typecheck_bases.cpp +++ b/src/cpp/cpp_typecheck_bases.cpp @@ -56,17 +56,18 @@ void cpp_typecheckt::typecheck_compound_bases(struct_typet &type) const symbolt &base_symbol = lookup(to_struct_tag_type(base_symbol_expr.type())); - if(base_symbol.type.id()==ID_incomplete_struct) + if(base_symbol.type.id() != ID_struct) { error().source_location=name.source_location(); - error() << "base type is incomplete" << eom; + error() << "expected struct or class as base, but got `" + << to_string(base_symbol.type) << "'" << eom; throw 0; } - else if(base_symbol.type.id()!=ID_struct) + + if(to_struct_type(base_symbol.type).is_incomplete()) { error().source_location=name.source_location(); - error() << "expected struct or class as base, but got `" - << to_string(base_symbol.type) << "'" << eom; + error() << "base type is incomplete" << eom; throw 0; } diff --git a/src/cpp/cpp_typecheck_compound_type.cpp b/src/cpp/cpp_typecheck_compound_type.cpp index 3ac75634abc..d548c7004fb 100644 --- a/src/cpp/cpp_typecheck_compound_type.cpp +++ b/src/cpp/cpp_typecheck_compound_type.cpp @@ -189,7 +189,9 @@ void cpp_typecheckt::typecheck_compound_type( if(has_body) { - if(symbol.type.id()=="incomplete_"+type.id_string()) + if( + symbol.type.id() == type.id() && + to_struct_union_type(symbol.type).is_incomplete()) { // a previously incomplete struct/union becomes complete symbolt &writeable_symbol = *symbol_table.get_writeable(symbol_name); @@ -258,8 +260,10 @@ void cpp_typecheckt::typecheck_compound_type( typecheck_compound_body(*new_symbol); else { - typet new_type("incomplete_"+new_symbol->type.id_string()); + struct_union_typet new_type(new_symbol->type.id()); new_type.set(ID_tag, new_symbol->base_name); + new_type.make_incomplete(); + new_type.add_source_location() = type.source_location(); new_symbol->type.swap(new_type); } } diff --git a/src/cpp/cpp_typecheck_conversions.cpp b/src/cpp/cpp_typecheck_conversions.cpp index 7549344b19c..929ac9d7f6d 100644 --- a/src/cpp/cpp_typecheck_conversions.cpp +++ b/src/cpp/cpp_typecheck_conversions.cpp @@ -49,9 +49,15 @@ bool cpp_typecheckt::standard_conversion_lvalue_to_rvalue( { assert(expr.get_bool(ID_C_lvalue)); - if(expr.type().id()==ID_code || - expr.type().id()==ID_incomplete_struct || - expr.type().id()==ID_incomplete_union) + if(expr.type().id() == ID_code) + return false; + + if( + expr.type().id() == ID_struct && + to_struct_type(expr.type()).is_incomplete()) + return false; + + if(expr.type().id() == ID_union && to_union_type(expr.type()).is_incomplete()) return false; new_expr=expr; diff --git a/src/cpp/cpp_typecheck_expr.cpp b/src/cpp/cpp_typecheck_expr.cpp index cfbe51b92de..125063d52e3 100644 --- a/src/cpp/cpp_typecheck_expr.cpp +++ b/src/cpp/cpp_typecheck_expr.cpp @@ -427,7 +427,6 @@ bool cpp_typecheckt::overloadable(const exprt &expr) t=t.subtype(); if(t.id()==ID_struct || - t.id() == ID_incomplete_struct || t.id()==ID_union || t.id()==ID_c_enum || t.id() == ID_c_enum_tag) return true; @@ -1110,15 +1109,6 @@ void cpp_typecheckt::typecheck_expr_member( const typet &followed_op0_type=follow(op0.type()); - if(followed_op0_type.id()==ID_incomplete_struct || - followed_op0_type.id()==ID_incomplete_union) - { - error().source_location=expr.find_source_location(); - error() << "error: member operator got incomplete type " - << "on left hand side" << eom; - throw 0; - } - if(followed_op0_type.id()!=ID_struct && followed_op0_type.id()!=ID_union) { @@ -1132,6 +1122,14 @@ void cpp_typecheckt::typecheck_expr_member( const struct_union_typet &type= to_struct_union_type(followed_op0_type); + if(type.is_incomplete()) + { + error().source_location = expr.find_source_location(); + error() << "error: member operator got incomplete type " + << "on left hand side" << eom; + throw 0; + } + irep_idt struct_identifier=type.get(ID_name); if(expr.find(ID_component_cpp_name).is_not_nil()) diff --git a/src/cpp/cpp_typecheck_initializer.cpp b/src/cpp/cpp_typecheck_initializer.cpp index ccc84862c10..4c7163b46b2 100644 --- a/src/cpp/cpp_typecheck_initializer.cpp +++ b/src/cpp/cpp_typecheck_initializer.cpp @@ -199,7 +199,16 @@ void cpp_typecheckt::zero_initializer( if(final_type.id()==ID_struct) { - for(const auto &component : to_struct_type(final_type).components()) + const auto &struct_type = to_struct_type(final_type); + + if(struct_type.is_incomplete()) + { + error().source_location = source_location; + error() << "cannot zero-initialize incomplete struct" << eom; + throw 0; + } + + for(const auto &component : struct_type.components()) { if(component.type().id()==ID_code) continue; @@ -238,12 +247,21 @@ void cpp_typecheckt::zero_initializer( } else if(final_type.id()==ID_union) { + const auto &union_type = to_union_type(final_type); + + if(union_type.is_incomplete()) + { + error().source_location = source_location; + error() << "cannot zero-initialize incomplete union" << eom; + throw 0; + } + // Select the largest component for zero-initialization mp_integer max_comp_size=0; union_typet::componentt comp; - for(const auto &component : to_union_type(final_type).components()) + for(const auto &component : union_type.components()) { assert(component.type().is_not_nil()); @@ -294,13 +312,6 @@ void cpp_typecheckt::zero_initializer( typecheck_code(assign); ops.push_back(assign); } - else if(final_type.id()==ID_incomplete_struct || - final_type.id()==ID_incomplete_union) - { - error().source_location=source_location; - error() << "cannot zero-initialize incomplete compound" << eom; - throw 0; - } else { const auto value = ::zero_initializer(final_type, source_location, *this); diff --git a/src/cpp/cpp_typecheck_resolve.cpp b/src/cpp/cpp_typecheck_resolve.cpp index 66a5d3de1bf..405d4c3cf38 100644 --- a/src/cpp/cpp_typecheck_resolve.cpp +++ b/src/cpp/cpp_typecheck_resolve.cpp @@ -1184,8 +1184,7 @@ symbol_typet cpp_typecheck_resolvet::disambiguate_template_classes( match.specialization_args, match.full_args); - if(instance.type.id()!=ID_struct && - instance.type.id()!=ID_incomplete_struct) + if(instance.type.id()!=ID_struct) { cpp_typecheck.error().source_location=source_location; cpp_typecheck.str << "template `" @@ -2298,9 +2297,7 @@ void cpp_typecheck_resolvet::filter_for_named_scopes( if(symbol.type.id() == ID_symbol_type) type=to_symbol_type(symbol.type); else if(symbol.type.id()==ID_struct || - symbol.type.id()==ID_incomplete_struct || symbol.type.id()==ID_union || - symbol.type.id()==ID_incomplete_union || symbol.type.id()==ID_c_enum) { // this is a scope, too! diff --git a/src/cpp/expr2cpp.cpp b/src/cpp/expr2cpp.cpp index 0def14c786f..26f34dfe02b 100644 --- a/src/cpp/expr2cpp.cpp +++ b/src/cpp/expr2cpp.cpp @@ -161,8 +161,7 @@ std::string expr2cppt::convert_rec( const symbolt &symbol=ns.lookup(identifier); - if(symbol.type.id()==ID_struct || - symbol.type.id()==ID_incomplete_struct) + if(symbol.type.id() == ID_struct) { std::string dest=q; @@ -196,8 +195,7 @@ std::string expr2cppt::convert_rec( else return expr2ct::convert_rec(src, qualifiers, declarator); } - else if(src.id()==ID_struct || - src.id()==ID_incomplete_struct) + else if(src.id() == ID_struct) { std::string dest=q; diff --git a/src/goto-instrument/dump_c.cpp b/src/goto-instrument/dump_c.cpp index 5e8b3d56d96..03a1cd900e0 100644 --- a/src/goto-instrument/dump_c.cpp +++ b/src/goto-instrument/dump_c.cpp @@ -171,9 +171,7 @@ void dump_ct::operator()(std::ostream &os) if(symbol.is_type && symbol.location.get_function().empty() && (type_id==ID_struct || - type_id==ID_incomplete_struct || type_id==ID_union || - type_id==ID_incomplete_union || type_id==ID_c_enum)) { if(!system_symbols.is_symbol_internal_symbol(symbol, system_headers)) @@ -235,11 +233,9 @@ void dump_ct::operator()(std::ostream &os) { const symbolt &symbol=ns.lookup(*it); - if(symbol.is_type && - (symbol.type.id()==ID_struct || - symbol.type.id()==ID_incomplete_struct || - symbol.type.id()==ID_union || - symbol.type.id()==ID_incomplete_union)) + if( + symbol.is_type && + (symbol.type.id() == ID_struct || symbol.type.id() == ID_union)) convert_compound_declaration( symbol, compound_body_stream); diff --git a/src/goto-programs/goto_convert_side_effect.cpp b/src/goto-programs/goto_convert_side_effect.cpp index 63537c3d721..6c8e4950aba 100644 --- a/src/goto-programs/goto_convert_side_effect.cpp +++ b/src/goto-programs/goto_convert_side_effect.cpp @@ -110,7 +110,7 @@ void goto_convertt::remove_assignment( // We convert c_enums to their underlying type, do the // operation, and then convert back const auto &enum_type = ns.follow_tag(to_c_enum_tag_type(op0_type)); - auto underlying_type = to_c_enum_type(enum_type).subtype(); + auto underlying_type = enum_type.subtype(); auto op0 = typecast_exprt(expr.op0(), underlying_type); auto op1 = typecast_exprt(expr.op1(), underlying_type); binary_exprt tmp(op0, new_id, op1, underlying_type); diff --git a/src/linking/linking.cpp b/src/linking/linking.cpp index 3518bae3ea7..625650c3f4d 100644 --- a/src/linking/linking.cpp +++ b/src/linking/linking.cpp @@ -82,24 +82,32 @@ std::string linkingt::type_to_string_verbose( const std::string &tag=followed.get_string(ID_tag); if(tag!="") result+=" "+tag; - result+=" {\n"; - for(const auto &c : to_struct_union_type(followed).components()) + if(to_struct_union_type(followed).is_incomplete()) { - const typet &subtype = c.type(); - result+=" "; - result += type_to_string(symbol.name, subtype); - result+=' '; + result += " (incomplete)"; + } + else + { + result += " {\n"; - if(!c.get_base_name().empty()) - result += id2string(c.get_base_name()); - else - result += id2string(c.get_name()); + for(const auto &c : to_struct_union_type(followed).components()) + { + const typet &subtype = c.type(); + result += " "; + result += type_to_string(symbol.name, subtype); + result += ' '; - result+=";\n"; - } + if(!c.get_base_name().empty()) + result += id2string(c.get_base_name()); + else + result += id2string(c.get_name()); + + result += ";\n"; + } - result+='}'; + result += '}'; + } return result; } @@ -107,11 +115,6 @@ std::string linkingt::type_to_string_verbose( { return type_to_string_verbose(symbol, followed.subtype()) + " *"; } - else if(followed.id()==ID_incomplete_struct || - followed.id()==ID_incomplete_union) - { - return type_to_string(symbol.name, type) + " (incomplete)"; - } return type_to_string(symbol.name, type); } @@ -837,15 +840,32 @@ bool linkingt::adjust_object_type_rec( // ignore return false; } - else if((t1.id()==ID_incomplete_struct && t2.id()==ID_struct) || - (t1.id()==ID_incomplete_union && t2.id()==ID_union)) + else if( + t1.id() == ID_struct && to_struct_type(t1).is_incomplete() && + t2.id() == ID_struct && !to_struct_type(t2).is_incomplete()) { info.set_to_new=true; // store new type return false; } - else if((t1.id()==ID_struct && t2.id()==ID_incomplete_struct) || - (t1.id()==ID_union && t2.id()==ID_incomplete_union)) + else if( + t1.id() == ID_union && to_union_type(t1).is_incomplete() && + t2.id() == ID_union && !to_union_type(t2).is_incomplete()) + { + info.set_to_new = true; // store new type + + return false; + } + else if( + t1.id() == ID_struct && !to_struct_type(t1).is_incomplete() && + t2.id() == ID_struct && to_struct_type(t2).is_incomplete()) + { + // ignore + return false; + } + else if( + t1.id() == ID_union && !to_union_type(t1).is_incomplete() && + t2.id() == ID_union && to_union_type(t2).is_incomplete()) { // ignore return false; @@ -1109,31 +1129,43 @@ void linkingt::duplicate_type_symbol( if(old_symbol.type==new_symbol.type) return; - if(old_symbol.type.id()==ID_incomplete_struct && - new_symbol.type.id()==ID_struct) + if( + old_symbol.type.id() == ID_struct && + to_struct_type(old_symbol.type).is_incomplete() && + new_symbol.type.id() == ID_struct && + !to_struct_type(new_symbol.type).is_incomplete()) { old_symbol.type=new_symbol.type; old_symbol.location=new_symbol.location; return; } - if(old_symbol.type.id()==ID_struct && - new_symbol.type.id()==ID_incomplete_struct) + if( + old_symbol.type.id() == ID_struct && + !to_struct_type(old_symbol.type).is_incomplete() && + new_symbol.type.id() == ID_struct && + to_struct_type(new_symbol.type).is_incomplete()) { // ok, keep old return; } - if(old_symbol.type.id()==ID_incomplete_union && - new_symbol.type.id()==ID_union) + if( + old_symbol.type.id() == ID_union && + to_union_type(old_symbol.type).is_incomplete() && + new_symbol.type.id() == ID_union && + !to_union_type(new_symbol.type).is_incomplete()) { old_symbol.type=new_symbol.type; old_symbol.location=new_symbol.location; return; } - if(old_symbol.type.id()==ID_union && - new_symbol.type.id()==ID_incomplete_union) + if( + old_symbol.type.id() == ID_union && + !to_union_type(old_symbol.type).is_incomplete() && + new_symbol.type.id() == ID_union && + to_union_type(new_symbol.type).is_incomplete()) { // ok, keep old return; @@ -1183,20 +1215,32 @@ bool linkingt::needs_renaming_type( if(old_symbol.type==new_symbol.type) return false; - if(old_symbol.type.id()==ID_incomplete_struct && - new_symbol.type.id()==ID_struct) + if( + old_symbol.type.id() == ID_struct && + to_struct_type(old_symbol.type).is_incomplete() && + new_symbol.type.id() == ID_struct && + !to_struct_type(new_symbol.type).is_incomplete()) return false; // not different - if(old_symbol.type.id()==ID_struct && - new_symbol.type.id()==ID_incomplete_struct) + if( + old_symbol.type.id() == ID_struct && + !to_struct_type(old_symbol.type).is_incomplete() && + new_symbol.type.id() == ID_struct && + to_struct_type(new_symbol.type).is_incomplete()) return false; // not different - if(old_symbol.type.id()==ID_incomplete_union && - new_symbol.type.id()==ID_union) + if( + old_symbol.type.id() == ID_union && + to_union_type(old_symbol.type).is_incomplete() && + new_symbol.type.id() == ID_union && + !to_union_type(new_symbol.type).is_incomplete()) return false; // not different - if(old_symbol.type.id()==ID_union && - new_symbol.type.id()==ID_incomplete_union) + if( + old_symbol.type.id() == ID_union && + !to_union_type(old_symbol.type).is_incomplete() && + new_symbol.type.id() == ID_union && + to_union_type(new_symbol.type).is_incomplete()) return false; // not different if(old_symbol.type.id()==ID_array && diff --git a/src/linking/static_lifetime_init.cpp b/src/linking/static_lifetime_init.cpp index b9bb0828e64..a595f7202d8 100644 --- a/src/linking/static_lifetime_init.cpp +++ b/src/linking/static_lifetime_init.cpp @@ -104,8 +104,9 @@ void static_lifetime_init( writable_symbol.type.set(ID_size, from_integer(1, size_type())); } - if(type.id()==ID_incomplete_struct || - type.id()==ID_incomplete_union) + if( + (type.id() == ID_struct || type.id() == ID_union) && + to_struct_union_type(type).is_incomplete()) continue; // do not initialize if(symbol.value.id()==ID_nondet) diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 21c6f5947eb..db85f8f7a9f 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -410,11 +410,9 @@ void value_sett::get_value_set_rec( const typet &type=ns.follow(expr.op0().type()); - DATA_INVARIANT(type.id()==ID_struct || - type.id()==ID_union || - type.id()==ID_incomplete_struct || - type.id()==ID_incomplete_union, - "operand 0 of member expression must be struct or union"); + DATA_INVARIANT( + type.id() == ID_struct || type.id() == ID_union, + "operand 0 of member expression must be struct or union"); const std::string &component_name= expr.get_string(ID_component_name); @@ -1358,11 +1356,9 @@ void value_sett::assign_rec( const typet &type=ns.follow(lhs.op0().type()); - DATA_INVARIANT(type.id()==ID_struct || - type.id()==ID_union || - type.id()==ID_incomplete_struct || - type.id()==ID_incomplete_union, - "operand 0 of member expression must be struct or union"); + DATA_INVARIANT( + type.id() == ID_struct || type.id() == ID_union, + "operand 0 of member expression must be struct or union"); assign_rec( lhs.op0(), values_rhs, "."+component_name+suffix, ns, add_to_sets); diff --git a/src/pointer-analysis/value_set_fi.cpp b/src/pointer-analysis/value_set_fi.cpp index 57a707c13a6..3920652c619 100644 --- a/src/pointer-analysis/value_set_fi.cpp +++ b/src/pointer-analysis/value_set_fi.cpp @@ -426,11 +426,9 @@ void value_set_fit::get_value_set_rec( { const typet &type=ns.follow(expr.op0().type()); - DATA_INVARIANT(type.id()==ID_struct || - type.id()==ID_union || - type.id()==ID_incomplete_struct || - type.id()==ID_incomplete_union, - "operand 0 of member expression must be struct or union"); + DATA_INVARIANT( + type.id() == ID_struct || type.id() == ID_union, + "operand 0 of member expression must be struct or union"); const std::string &component_name= expr.get_string(ID_component_name); @@ -1219,11 +1217,9 @@ void value_set_fit::assign_rec( const typet &type=ns.follow(lhs.op0().type()); - DATA_INVARIANT(type.id()==ID_struct || - type.id()==ID_union || - type.id()==ID_incomplete_struct || - type.id()==ID_incomplete_union, - "operand 0 of member expression must be struct or union"); + DATA_INVARIANT( + type.id() == ID_struct || type.id() == ID_union, + "operand 0 of member expression must be struct or union"); assign_rec(lhs.op0(), values_rhs, "."+component_name+suffix, ns, recursion_set); diff --git a/src/pointer-analysis/value_set_fivr.cpp b/src/pointer-analysis/value_set_fivr.cpp index a0a5eed0092..8751f835920 100644 --- a/src/pointer-analysis/value_set_fivr.cpp +++ b/src/pointer-analysis/value_set_fivr.cpp @@ -538,11 +538,9 @@ void value_set_fivrt::get_value_set_rec( { const typet &type=ns.follow(expr.op0().type()); - DATA_INVARIANT(type.id()==ID_struct || - type.id()==ID_union || - type.id()==ID_incomplete_struct || - type.id()==ID_incomplete_union, - "operand 0 of member expression must be struct or union"); + DATA_INVARIANT( + type.id() == ID_struct || type.id() == ID_union, + "operand 0 of member expression must be struct or union"); const std::string &component_name= expr.get_string(ID_component_name); @@ -1351,11 +1349,9 @@ void value_set_fivrt::assign_rec( const typet &type=ns.follow(lhs.op0().type()); - DATA_INVARIANT(type.id()==ID_struct || - type.id()==ID_union || - type.id()==ID_incomplete_struct || - type.id()==ID_incomplete_union, - "operand 0 of member expression must be struct or union"); + DATA_INVARIANT( + type.id() == ID_struct || type.id() == ID_union, + "operand 0 of member expression must be struct or union"); assign_rec(lhs.op0(), values_rhs, "."+component_name+suffix, ns, recursion_set, add_to_sets); diff --git a/src/pointer-analysis/value_set_fivrns.cpp b/src/pointer-analysis/value_set_fivrns.cpp index 2669b20d333..38762767e68 100644 --- a/src/pointer-analysis/value_set_fivrns.cpp +++ b/src/pointer-analysis/value_set_fivrns.cpp @@ -331,11 +331,9 @@ void value_set_fivrnst::get_value_set_rec( { const typet &type=ns.follow(expr.op0().type()); - DATA_INVARIANT(type.id()==ID_struct || - type.id()==ID_union || - type.id()==ID_incomplete_struct || - type.id()==ID_incomplete_union, - "operand 0 of member expression must be struct or union"); + DATA_INVARIANT( + type.id() == ID_struct || type.id() == ID_union, + "operand 0 of member expression must be struct or union"); const std::string &component_name= expr.get_string(ID_component_name); @@ -1011,11 +1009,9 @@ void value_set_fivrnst::assign_rec( const typet &type=ns.follow(lhs.op0().type()); - DATA_INVARIANT(type.id()==ID_struct || - type.id()==ID_union || - type.id()==ID_incomplete_struct || - type.id()==ID_incomplete_union, - "operand 0 of member expression must be struct or union"); + DATA_INVARIANT( + type.id() == ID_struct || type.id() == ID_union, + "operand 0 of member expression must be struct or union"); assign_rec(lhs.op0(), values_rhs, "."+component_name+suffix, ns, add_to_sets); diff --git a/src/solvers/flattening/boolbv_constant.cpp b/src/solvers/flattening/boolbv_constant.cpp index 50e5a26ddc6..b69b974699c 100644 --- a/src/solvers/flattening/boolbv_constant.cpp +++ b/src/solvers/flattening/boolbv_constant.cpp @@ -68,16 +68,12 @@ bvt boolbvt::convert_constant(const constant_exprt &expr) return bv; } - else if(expr_type.id()==ID_unsignedbv || - expr_type.id()==ID_signedbv || - expr_type.id()==ID_bv || - expr_type.id()==ID_fixedbv || - expr_type.id()==ID_floatbv || - expr_type.id()==ID_c_enum || - expr_type.id()==ID_c_enum_tag || - expr_type.id()==ID_c_bool || - expr_type.id()==ID_c_bit_field || - expr_type.id()==ID_incomplete_c_enum) + else if( + expr_type.id() == ID_unsignedbv || expr_type.id() == ID_signedbv || + expr_type.id() == ID_bv || expr_type.id() == ID_fixedbv || + expr_type.id() == ID_floatbv || expr_type.id() == ID_c_enum || + expr_type.id() == ID_c_enum_tag || expr_type.id() == ID_c_bool || + expr_type.id() == ID_c_bit_field) { const auto &value = expr.get_value(); diff --git a/src/solvers/flattening/boolbv_type.cpp b/src/solvers/flattening/boolbv_type.cpp index fc65dde98f8..bbe23c5a180 100644 --- a/src/solvers/flattening/boolbv_type.cpp +++ b/src/solvers/flattening/boolbv_type.cpp @@ -17,9 +17,7 @@ bvtypet get_bvtype(const typet &type) return bvtypet::IS_UNSIGNED; else if(type.id()==ID_c_bool) return bvtypet::IS_C_BOOL; - else if(type.id()==ID_c_enum || - type.id()==ID_c_enum_tag || - type.id()==ID_incomplete_c_enum) + else if(type.id() == ID_c_enum || type.id() == ID_c_enum_tag) return bvtypet::IS_C_ENUM; else if(type.id()==ID_floatbv) return bvtypet::IS_FLOAT; diff --git a/src/solvers/flattening/boolbv_width.cpp b/src/solvers/flattening/boolbv_width.cpp index ff91a2ed986..6f7dea334a6 100644 --- a/src/solvers/flattening/boolbv_width.cpp +++ b/src/solvers/flattening/boolbv_width.cpp @@ -178,10 +178,6 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const entry.total_width = to_bitvector_type(type.subtype()).get_width(); CHECK_RETURN(entry.total_width > 0); } - else if(type_id==ID_incomplete_c_enum) - { - // no width - } else if(type_id==ID_pointer) entry.total_width = type_checked_cast(type).get_width(); else if(type_id == ID_symbol_type) diff --git a/src/solvers/smt2/smt2_conv.cpp b/src/solvers/smt2/smt2_conv.cpp index c47986a21b1..5966fb87fd3 100644 --- a/src/solvers/smt2/smt2_conv.cpp +++ b/src/solvers/smt2/smt2_conv.cpp @@ -2711,7 +2711,6 @@ void smt2_convt::convert_constant(const constant_exprt &expr) expr_type.id()==ID_c_enum || expr_type.id()==ID_c_enum_tag || expr_type.id()==ID_c_bool || - expr_type.id()==ID_incomplete_c_enum || expr_type.id()==ID_c_bit_field) { const std::size_t width = boolbv_width(expr_type); diff --git a/src/util/base_type.cpp b/src/util/base_type.cpp index 03059cc6f57..d98af3c5f9d 100644 --- a/src/util/base_type.cpp +++ b/src/util/base_type.cpp @@ -224,14 +224,6 @@ bool base_type_eqt::base_type_eq_rec( return true; } - else if(type1.id()==ID_incomplete_struct) - { - return true; - } - else if(type1.id()==ID_incomplete_union) - { - return true; - } else if(type1.id()==ID_code) { const code_typet::parameterst ¶meters1= diff --git a/src/util/expr_initializer.cpp b/src/util/expr_initializer.cpp index 364d8db1b26..50211115a22 100644 --- a/src/util/expr_initializer.cpp +++ b/src/util/expr_initializer.cpp @@ -52,7 +52,6 @@ exprt expr_initializert::expr_initializer_rec( type_id==ID_signedbv || type_id==ID_pointer || type_id==ID_c_enum || - type_id==ID_incomplete_c_enum || type_id==ID_c_bit_field || type_id==ID_bool || type_id==ID_c_bool || diff --git a/src/util/irep_ids.def b/src/util/irep_ids.def index 9eea3d33f2e..90c90f9e47b 100644 --- a/src/util/irep_ids.def +++ b/src/util/irep_ids.def @@ -123,10 +123,8 @@ IREP_ID_ONE(asm) IREP_ID_ONE(gcc_asm_input) IREP_ID_ONE(gcc_asm_output) IREP_ID_ONE(gcc_asm_clobbered_register) -IREP_ID_ONE(incomplete_struct) -IREP_ID_ONE(incomplete_union) +IREP_ID_ONE(incomplete) IREP_ID_ONE(incomplete_class) -IREP_ID_ONE(incomplete_c_enum) IREP_ID_TWO(C_incomplete, #incomplete) IREP_ID_ONE(identifier) IREP_ID_ONE(name) diff --git a/src/util/json_expr.cpp b/src/util/json_expr.cpp index c97884f38a3..83f25189ed2 100644 --- a/src/util/json_expr.cpp +++ b/src/util/json_expr.cpp @@ -158,10 +158,7 @@ json_objectt json( else if(type.id()==ID_c_enum_tag) { // we return the base type - return json( - to_c_enum_type(ns.follow_tag(to_c_enum_tag_type(type))).subtype(), - ns, - mode); + return json(ns.follow_tag(to_c_enum_tag_type(type)).subtype(), ns, mode); } else if(type.id()==ID_fixedbv) { diff --git a/src/util/namespace.cpp b/src/util/namespace.cpp index 43d92234842..c0bcc910731 100644 --- a/src/util/namespace.cpp +++ b/src/util/namespace.cpp @@ -87,37 +87,36 @@ const typet &namespace_baset::follow(const typet &src) const /// Follow type tag of union type. /// \param src: The union tag type to dispatch on. /// \return The type of the union tag in the symbol table. -const typet &namespace_baset::follow_tag(const union_tag_typet &src) const +const union_typet &namespace_baset::follow_tag(const union_tag_typet &src) const { const symbolt &symbol=lookup(src.get_identifier()); CHECK_RETURN(symbol.is_type); - CHECK_RETURN( - symbol.type.id() == ID_union || symbol.type.id() == ID_incomplete_union); - return symbol.type; + CHECK_RETURN(symbol.type.id() == ID_union); + return to_union_type(symbol.type); } /// Follow type tag of struct type. /// \param src: The struct tag type to dispatch on. /// \return The type of the struct tag in the symbol table. -const typet &namespace_baset::follow_tag(const struct_tag_typet &src) const +const struct_typet & +namespace_baset::follow_tag(const struct_tag_typet &src) const { const symbolt &symbol=lookup(src.get_identifier()); CHECK_RETURN(symbol.is_type); - CHECK_RETURN( - symbol.type.id() == ID_struct || symbol.type.id() == ID_incomplete_struct); - return symbol.type; + CHECK_RETURN(symbol.type.id() == ID_struct); + return to_struct_type(symbol.type); } /// Follow type tag of enum type. /// \param src: The enum tag type to dispatch on. /// \return The type of the enum tag in the symbol table. -const typet &namespace_baset::follow_tag(const c_enum_tag_typet &src) const +const c_enum_typet & +namespace_baset::follow_tag(const c_enum_tag_typet &src) const { const symbolt &symbol=lookup(src.get_identifier()); CHECK_RETURN(symbol.is_type); - CHECK_RETURN( - symbol.type.id() == ID_c_enum || symbol.type.id() == ID_incomplete_c_enum); - return symbol.type; + CHECK_RETURN(symbol.type.id() == ID_c_enum); + return to_c_enum_type(symbol.type); } /// Follow macros to their values in a given expression. diff --git a/src/util/namespace.h b/src/util/namespace.h index c7555a8d394..87dc00d528b 100644 --- a/src/util/namespace.h +++ b/src/util/namespace.h @@ -65,9 +65,9 @@ class namespace_baset // These produce union_typet, struct_typet, c_enum_typet or // the incomplete version. - const typet &follow_tag(const union_tag_typet &) const; - const typet &follow_tag(const struct_tag_typet &) const; - const typet &follow_tag(const c_enum_tag_typet &) const; + const union_typet &follow_tag(const union_tag_typet &) const; + const struct_typet &follow_tag(const struct_tag_typet &) const; + const c_enum_typet &follow_tag(const c_enum_tag_typet &) const; /// Returns the minimal integer n such that there is no symbol (in any of the /// symbol tables) whose name is of the form "An" where A is \p prefix. diff --git a/src/util/simplify_expr.cpp b/src/util/simplify_expr.cpp index d642a9484fd..74a3cab7c93 100644 --- a/src/util/simplify_expr.cpp +++ b/src/util/simplify_expr.cpp @@ -494,8 +494,8 @@ bool simplify_exprt::simplify_typecast(exprt &expr) } else if(expr_type_id==ID_c_enum_tag) { - const typet &c_enum_type=ns.follow_tag(to_c_enum_tag_type(expr_type)); - if(c_enum_type.id()==ID_c_enum) // possibly incomplete + const auto &c_enum_type = ns.follow_tag(to_c_enum_tag_type(expr_type)); + if(!c_enum_type.is_incomplete()) // possibly incomplete { unsigned int_value = operand.is_true() ? 1u : 0u; exprt tmp=from_integer(int_value, c_enum_type); @@ -564,8 +564,8 @@ bool simplify_exprt::simplify_typecast(exprt &expr) if(expr_type_id==ID_c_enum_tag) { - const typet &c_enum_type=ns.follow_tag(to_c_enum_tag_type(expr_type)); - if(c_enum_type.id()==ID_c_enum) // possibly incomplete + const auto &c_enum_type = ns.follow_tag(to_c_enum_tag_type(expr_type)); + if(!c_enum_type.is_incomplete()) // possibly incomplete { exprt tmp=from_integer(int_value, c_enum_type); tmp.type()=expr_type; // we maintain the tag type @@ -678,7 +678,7 @@ bool simplify_exprt::simplify_typecast(exprt &expr) else if(op_type_id==ID_c_enum_tag) // enum to int { const typet &base_type = - to_c_enum_type(ns.follow_tag(to_c_enum_tag_type(op_type))).subtype(); + ns.follow_tag(to_c_enum_tag_type(op_type)).subtype(); if(base_type.id()==ID_signedbv || base_type.id()==ID_unsignedbv) { // enum constants use the representation of their base type @@ -1574,7 +1574,7 @@ optionalt simplify_exprt::expr2bits( } else if(type.id() == ID_c_enum_tag) { - const typet &c_enum_type = ns.follow_tag(to_c_enum_tag_type(type)); + const auto &c_enum_type = ns.follow_tag(to_c_enum_tag_type(type)); return expr2bits(constant_exprt(value, c_enum_type), little_endian); } else if(type.id() == ID_c_enum) diff --git a/src/util/simplify_expr_floatbv.cpp b/src/util/simplify_expr_floatbv.cpp index 13990e46db3..fbdfa283595 100644 --- a/src/util/simplify_expr_floatbv.cpp +++ b/src/util/simplify_expr_floatbv.cpp @@ -243,8 +243,8 @@ bool simplify_exprt::simplify_floatbv_typecast(exprt &expr) { // go through underlying type const auto &enum_type = ns.follow_tag(to_c_enum_tag_type(src_type)); - exprt simplified_typecast = simplify_expr( - typecast_exprt(casted_expr, to_c_enum_type(enum_type).subtype()), ns); + exprt simplified_typecast = + simplify_expr(typecast_exprt(casted_expr, enum_type.subtype()), ns); if(simplified_typecast.is_constant()) { floatbv_typecast_exprt new_floatbv_typecast_expr = diff --git a/src/util/std_types.h b/src/util/std_types.h index 9ffbdd05714..a89e1fb9481 100644 --- a/src/util/std_types.h +++ b/src/util/std_types.h @@ -238,6 +238,18 @@ class struct_union_typet:public typet { return is_class() ? ID_private : ID_public; } + + /// A struct/union may be incomplete + bool is_incomplete() const + { + return get_bool(ID_incomplete); + } + + /// A struct/union may be incomplete + void make_incomplete() + { + set(ID_incomplete, true); + } }; /// Check whether a reference to a typet is a \ref struct_union_typet. @@ -675,6 +687,18 @@ class c_enum_typet:public type_with_subtypet { return (const memberst &)(find(ID_body).get_sub()); } + + /// enum types may be incomplete + bool is_incomplete() const + { + return get_bool(ID_incomplete); + } + + /// enum types may be incomplete + void make_incomplete() + { + set(ID_incomplete, true); + } }; /// Check whether a reference to a typet is a \ref c_enum_typet. diff --git a/src/util/xml_expr.cpp b/src/util/xml_expr.cpp index d007099613b..b290c8ddcbf 100644 --- a/src/util/xml_expr.cpp +++ b/src/util/xml_expr.cpp @@ -85,8 +85,7 @@ xmlt xml( else if(type.id()==ID_c_enum_tag) { // we return the base type - return xml( - to_c_enum_type(ns.follow_tag(to_c_enum_tag_type(type))).subtype(), ns); + return xml(ns.follow_tag(to_c_enum_tag_type(type)).subtype(), ns); } else if(type.id()==ID_fixedbv) {