Skip to content

Commit 5419894

Browse files
author
Daniel Kroening
authored
Merge pull request #3643 from diffblue/incomplete_compound_types
replace incomplete compound types
2 parents 4714c4e + 4e031ff commit 5419894

39 files changed

+392
-375
lines changed

src/ansi-c/c_typecast.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ bool check_c_implicit_typecast(
156156
src_type_id==ID_signedbv ||
157157
src_type_id==ID_c_enum ||
158158
src_type_id==ID_c_enum_tag ||
159-
src_type_id==ID_incomplete_c_enum ||
160159
src_type_id==ID_c_bool)
161160
{
162161
if(dest_type.id()==ID_unsignedbv ||
@@ -171,7 +170,6 @@ bool check_c_implicit_typecast(
171170
dest_type.id()==ID_pointer ||
172171
dest_type.id()==ID_c_enum ||
173172
dest_type.id()==ID_c_enum_tag ||
174-
dest_type.id()==ID_incomplete_c_enum ||
175173
dest_type.id()==ID_complex)
176174
return false;
177175
}
@@ -345,9 +343,7 @@ c_typecastt::c_typet c_typecastt::get_c_type(
345343
{
346344
return PTR;
347345
}
348-
else if(type.id()==ID_c_enum ||
349-
type.id()==ID_c_enum_tag ||
350-
type.id()==ID_incomplete_c_enum)
346+
else if(type.id() == ID_c_enum || type.id() == ID_c_enum_tag)
351347
{
352348
return INT;
353349
}

src/ansi-c/c_typecheck_base.cpp

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -85,21 +85,15 @@ void c_typecheck_baset::typecheck_symbol(symbolt &symbol)
8585
}
8686

8787
// set the pretty name
88-
if(symbol.is_type &&
89-
(final_type.id()==ID_struct ||
90-
final_type.id()==ID_incomplete_struct))
88+
if(symbol.is_type && final_type.id() == ID_struct)
9189
{
9290
symbol.pretty_name="struct "+id2string(symbol.base_name);
9391
}
94-
else if(symbol.is_type &&
95-
(final_type.id()==ID_union ||
96-
final_type.id()==ID_incomplete_union))
92+
else if(symbol.is_type && final_type.id() == ID_union)
9793
{
9894
symbol.pretty_name="union "+id2string(symbol.base_name);
9995
}
100-
else if(symbol.is_type &&
101-
(final_type.id()==ID_c_enum ||
102-
final_type.id()==ID_incomplete_c_enum))
96+
else if(symbol.is_type && final_type.id() == ID_c_enum)
10397
{
10498
symbol.pretty_name="enum "+id2string(symbol.base_name);
10599
}
@@ -176,12 +170,21 @@ void c_typecheck_baset::typecheck_redefinition_type(
176170
const typet &final_new=follow(new_symbol.type);
177171

178172
// see if we had something incomplete before
179-
if(final_old.id()==ID_incomplete_struct ||
180-
final_old.id()==ID_incomplete_union ||
181-
final_old.id()==ID_incomplete_c_enum)
173+
if(
174+
(final_old.id() == ID_struct &&
175+
to_struct_type(final_old).is_incomplete()) ||
176+
(final_old.id() == ID_union && to_union_type(final_old).is_incomplete()) ||
177+
(final_old.id() == ID_c_enum && to_c_enum_type(final_old).is_incomplete()))
182178
{
183-
// new one complete?
184-
if("incomplete_"+final_new.id_string()==final_old.id_string())
179+
// is the new one complete?
180+
if(
181+
final_new.id() == final_old.id() &&
182+
((final_new.id() == ID_struct &&
183+
!to_struct_type(final_new).is_incomplete()) ||
184+
(final_new.id() == ID_union &&
185+
!to_union_type(final_new).is_incomplete()) ||
186+
(final_new.id() == ID_c_enum &&
187+
!to_c_enum_type(final_new).is_incomplete())))
185188
{
186189
// overwrite location
187190
old_symbol.location=new_symbol.location;
@@ -190,7 +193,7 @@ void c_typecheck_baset::typecheck_redefinition_type(
190193
old_symbol.type.swap(new_symbol.type);
191194
}
192195
else if(new_symbol.type.id()==old_symbol.type.id())
193-
return;
196+
return; // ignore
194197
else
195198
{
196199
error().source_location=new_symbol.location;
@@ -203,11 +206,15 @@ void c_typecheck_baset::typecheck_redefinition_type(
203206
else
204207
{
205208
// see if new one is just a tag
206-
if(final_new.id()==ID_incomplete_struct ||
207-
final_new.id()==ID_incomplete_union ||
208-
final_new.id()==ID_incomplete_c_enum)
209+
if(
210+
(final_new.id() == ID_struct &&
211+
to_struct_type(final_new).is_incomplete()) ||
212+
(final_new.id() == ID_union &&
213+
to_union_type(final_new).is_incomplete()) ||
214+
(final_new.id() == ID_c_enum &&
215+
to_c_enum_type(final_new).is_incomplete()))
209216
{
210-
if("incomplete_"+final_old.id_string()==final_new.id_string())
217+
if(final_old.id() == final_new.id())
211218
{
212219
// just ignore silently
213220
}
@@ -418,13 +425,6 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
418425
PRECONDITION(old_symbol.type.id() != ID_symbol_type);
419426
old_symbol.type=new_symbol.type;
420427
}
421-
else if((final_old.id()==ID_incomplete_c_enum ||
422-
final_old.id()==ID_c_enum) &&
423-
(final_new.id()==ID_incomplete_c_enum ||
424-
final_new.id()==ID_c_enum))
425-
{
426-
// this is ok for now
427-
}
428428
else if(final_old.id()==ID_pointer &&
429429
follow(final_old).subtype().id()==ID_code &&
430430
to_code_type(follow(final_old).subtype()).has_ellipsis() &&
@@ -477,12 +477,10 @@ void c_typecheck_baset::typecheck_redefinition_non_type(
477477
}
478478
else
479479
{
480-
if(new_symbol.is_macro &&
481-
(final_new.id()==ID_incomplete_c_enum ||
482-
final_new.id()==ID_c_enum) &&
483-
old_symbol.value.is_constant() &&
484-
new_symbol.value.is_constant() &&
485-
old_symbol.value.get(ID_value)==new_symbol.value.get(ID_value))
480+
if(
481+
new_symbol.is_macro && final_new.id() == ID_c_enum &&
482+
old_symbol.value.is_constant() && new_symbol.value.is_constant() &&
483+
old_symbol.value.get(ID_value) == new_symbol.value.get(ID_value))
486484
{
487485
// ignore
488486
}

src/ansi-c/c_typecheck_code.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -341,18 +341,20 @@ void c_typecheck_baset::typecheck_decl(codet &code)
341341

342342
bool c_typecheck_baset::is_complete_type(const typet &type) const
343343
{
344-
if(type.id()==ID_incomplete_struct ||
345-
type.id()==ID_incomplete_union)
346-
return false;
347-
else if(type.id()==ID_array)
344+
if(type.id() == ID_array)
348345
{
349346
if(to_array_type(type).size().is_nil())
350347
return false;
351348
return is_complete_type(type.subtype());
352349
}
353350
else if(type.id()==ID_struct || type.id()==ID_union)
354351
{
355-
for(const auto &c : to_struct_union_type(type).components())
352+
const auto &struct_union_type = to_struct_union_type(type);
353+
354+
if(struct_union_type.is_incomplete())
355+
return false;
356+
357+
for(const auto &c : struct_union_type.components())
356358
if(!is_complete_type(c.type()))
357359
return false;
358360
}

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,8 +1361,7 @@ void c_typecheck_baset::typecheck_expr_rel(
13611361
if(follow(o_type0)==follow(o_type1))
13621362
{
13631363
const typet &final_type=follow(o_type0);
1364-
if(final_type.id()!=ID_array &&
1365-
final_type.id()!=ID_incomplete_struct)
1364+
if(final_type.id() != ID_array)
13661365
{
13671366
adjust_float_rel(expr);
13681367
return; // no promotion necessary
@@ -1524,22 +1523,6 @@ void c_typecheck_baset::typecheck_expr_member(exprt &expr)
15241523

15251524
type = follow(type);
15261525

1527-
if(type.id()==ID_incomplete_struct)
1528-
{
1529-
error().source_location = expr.source_location();
1530-
error() << "member operator got incomplete struct type "
1531-
"on left hand side" << eom;
1532-
throw 0;
1533-
}
1534-
1535-
if(type.id()==ID_incomplete_union)
1536-
{
1537-
error().source_location = expr.source_location();
1538-
error() << "member operator got incomplete union type "
1539-
"on left hand side" << eom;
1540-
throw 0;
1541-
}
1542-
15431526
if(type.id()!=ID_struct &&
15441527
type.id()!=ID_union)
15451528
{
@@ -1553,6 +1536,14 @@ void c_typecheck_baset::typecheck_expr_member(exprt &expr)
15531536
const struct_union_typet &struct_union_type=
15541537
to_struct_union_type(type);
15551538

1539+
if(struct_union_type.is_incomplete())
1540+
{
1541+
error().source_location = expr.source_location();
1542+
error() << "member operator got incomplete " << type.id()
1543+
<< " type on left hand side" << eom;
1544+
throw 0;
1545+
}
1546+
15561547
const irep_idt &component_name=
15571548
expr.get(ID_component_name);
15581549

@@ -1897,8 +1888,7 @@ void c_typecheck_baset::typecheck_expr_side_effect(side_effect_exprt &expr)
18971888

18981889
if(final_type0.id()==ID_c_enum_tag)
18991890
{
1900-
if(follow_tag(to_c_enum_tag_type(final_type0)).id()==
1901-
ID_incomplete_c_enum)
1891+
if(follow_tag(to_c_enum_tag_type(final_type0)).is_incomplete())
19021892
{
19031893
error().source_location = expr.source_location();
19041894
error() << "operator `" << statement
@@ -3166,7 +3156,17 @@ void c_typecheck_baset::typecheck_arithmetic_pointer(const exprt &expr)
31663156

31673157
typet subtype=type.subtype();
31683158

3169-
if(subtype.id()==ID_incomplete_struct)
3159+
if(
3160+
subtype.id() == ID_struct_tag &&
3161+
follow_tag(to_struct_tag_type(subtype)).is_incomplete())
3162+
{
3163+
error().source_location = expr.source_location();
3164+
error() << "pointer arithmetic with unknown object size" << eom;
3165+
throw 0;
3166+
}
3167+
else if(
3168+
subtype.id() == ID_union_tag &&
3169+
follow_tag(to_union_tag_type(subtype)).is_incomplete())
31703170
{
31713171
error().source_location = expr.source_location();
31723172
error() << "pointer arithmetic with unknown object size" << eom;
@@ -3370,8 +3370,7 @@ void c_typecheck_baset::typecheck_side_effect_assignment(
33703370

33713371
if(underlying_type.id()==ID_c_enum_tag)
33723372
{
3373-
const typet &c_enum_type=
3374-
follow_tag(to_c_enum_tag_type(underlying_type));
3373+
const auto &c_enum_type = to_c_enum_tag_type(underlying_type);
33753374
underlying_type=c_enum_type.subtype();
33763375
}
33773376

src/ansi-c/c_typecheck_initializer.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,12 @@ exprt c_typecheck_baset::do_initializer_rec(
5858
{
5959
const typet &full_type=follow(type);
6060

61-
if(full_type.id()==ID_incomplete_struct)
61+
if(
62+
(full_type.id() == ID_struct || full_type.id() == ID_union) &&
63+
to_struct_union_type(full_type).is_incomplete())
6264
{
6365
error().source_location = value.source_location();
64-
error() << "type `" << to_string(full_type)
66+
error() << "type `" << to_string(type)
6567
<< "' is still incomplete -- cannot initialize" << eom;
6668
throw 0;
6769
}

src/ansi-c/c_typecheck_type.cpp

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -523,9 +523,11 @@ void c_typecheck_baset::typecheck_array_type(array_typet &type)
523523
}
524524

525525
// we don't allow incomplete structs or unions as subtype
526+
const typet &followed_subtype = follow(type.subtype());
527+
526528
if(
527-
follow(type.subtype()).id() == ID_incomplete_struct ||
528-
follow(type.subtype()).id() == ID_incomplete_union)
529+
(followed_subtype.id() == ID_struct || followed_subtype.id() == ID_union) &&
530+
to_struct_union_type(followed_subtype).is_incomplete())
529531
{
530532
// ISO/IEC 9899 6.7.5.2
531533
error().source_location = type.source_location();
@@ -806,12 +808,8 @@ void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type)
806808

807809
typet new_type=compound_symbol.type;
808810

809-
if(compound_symbol.type.id()==ID_struct)
810-
compound_symbol.type.id(ID_incomplete_struct);
811-
else if(compound_symbol.type.id()==ID_union)
812-
compound_symbol.type.id(ID_incomplete_union);
813-
else
814-
UNREACHABLE;
811+
// mark as incomplete
812+
to_struct_union_type(compound_symbol.type).make_incomplete();
815813

816814
symbolt *new_symbol;
817815
move_symbol(compound_symbol, new_symbol);
@@ -826,8 +824,9 @@ void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type)
826824
else
827825
{
828826
// yes, it exists already
829-
if(s_it->second.type.id()==ID_incomplete_struct ||
830-
s_it->second.type.id()==ID_incomplete_union)
827+
if(
828+
s_it->second.type.id() == type.id() &&
829+
to_struct_union_type(s_it->second.type).is_incomplete())
831830
{
832831
// Maybe we got a body now.
833832
if(have_body)
@@ -852,9 +851,9 @@ void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type)
852851

853852
typet tag_type;
854853

855-
if(type.id() == ID_union || type.id() == ID_incomplete_union)
854+
if(type.id() == ID_union)
856855
tag_type = union_tag_typet(identifier);
857-
else if(type.id() == ID_struct || type.id() == ID_incomplete_struct)
856+
else if(type.id() == ID_struct)
858857
tag_type = struct_tag_typet(identifier);
859858
else
860859
UNREACHABLE;
@@ -1278,13 +1277,20 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
12781277
// Yes.
12791278
const symbolt &symbol=s_it->second;
12801279

1281-
if(symbol.type.id()==ID_incomplete_c_enum)
1280+
if(symbol.type.id() != ID_c_enum)
1281+
{
1282+
error().source_location = source_location;
1283+
error() << "use of tag that does not match previous declaration" << eom;
1284+
throw 0;
1285+
}
1286+
1287+
if(to_c_enum_type(symbol.type).is_incomplete())
12821288
{
12831289
// Ok, overwrite the type in the symbol table.
12841290
// This gives us the members and the subtype.
12851291
symbol_table.get_writeable_ref(symbol.name).type=enum_tag_symbol.type;
12861292
}
1287-
else if(symbol.type.id()==ID_c_enum)
1293+
else
12881294
{
12891295
// We might already have the same anonymous enum, and this is
12901296
// simply ok. Note that the C standard treats these as
@@ -1296,12 +1302,6 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
12961302
throw 0;
12971303
}
12981304
}
1299-
else
1300-
{
1301-
error().source_location=source_location;
1302-
error() << "use of tag that does not match previous declaration" << eom;
1303-
throw 0;
1304-
}
13051305
}
13061306
else
13071307
{
@@ -1341,8 +1341,7 @@ void c_typecheck_baset::typecheck_c_enum_tag_type(c_enum_tag_typet &type)
13411341
// Yes.
13421342
const symbolt &symbol=s_it->second;
13431343

1344-
if(symbol.type.id()!=ID_c_enum &&
1345-
symbol.type.id()!=ID_incomplete_c_enum)
1344+
if(symbol.type.id() != ID_c_enum)
13461345
{
13471346
error().source_location=source_location;
13481347
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)
13521351
else
13531352
{
13541353
// no, add it as an incomplete c_enum
1355-
typet new_type(ID_incomplete_c_enum);
1356-
new_type.subtype()=signed_int_type(); // default
1354+
c_enum_typet new_type(signed_int_type()); // default subtype
13571355
new_type.add(ID_tag)=tag;
1356+
new_type.make_incomplete();
13581357

13591358
symbolt enum_tag_symbol;
13601359

@@ -1424,10 +1423,10 @@ void c_typecheck_baset::typecheck_c_bit_field_type(c_bit_field_typet &type)
14241423
// These point to an enum, which has a sub-subtype,
14251424
// which may be smaller or larger than int, and we thus have
14261425
// to check.
1427-
const typet &c_enum_type=
1428-
follow_tag(to_c_enum_tag_type(subtype));
1426+
const auto &c_enum_type =
1427+
to_c_enum_type(follow_tag(to_c_enum_tag_type(subtype)));
14291428

1430-
if(c_enum_type.id()==ID_incomplete_c_enum)
1429+
if(c_enum_type.is_incomplete())
14311430
{
14321431
error().source_location=type.source_location();
14331432
error() << "bit field has incomplete enum type" << eom;

0 commit comments

Comments
 (0)