Skip to content

Commit 7da25a1

Browse files
author
Daniel Kroening
committed
replace incomplete compound types
1 parent b76eb4e commit 7da25a1

32 files changed

+370
-349
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
}
@@ -341,9 +339,7 @@ c_typecastt::c_typet c_typecastt::get_c_type(
341339
{
342340
return PTR;
343341
}
344-
else if(type.id()==ID_c_enum ||
345-
type.id()==ID_c_enum_tag ||
346-
type.id()==ID_incomplete_c_enum)
342+
else if(type.id() == ID_c_enum || type.id() == ID_c_enum_tag)
347343
{
348344
return INT;
349345
}

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 & 21 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,8 @@ 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(to_c_enum_type(follow_tag(to_c_enum_tag_type(final_type0)))
1892+
.is_incomplete())
19021893
{
19031894
error().source_location = expr.source_location();
19041895
error() << "operator `" << statement
@@ -3166,7 +3157,17 @@ void c_typecheck_baset::typecheck_arithmetic_pointer(const exprt &expr)
31663157

31673158
typet subtype=type.subtype();
31683159

3169-
if(subtype.id()==ID_incomplete_struct)
3160+
if(
3161+
subtype.id() == ID_struct_tag &&
3162+
to_struct_type(follow_tag(to_struct_tag_type(subtype))).is_incomplete())
3163+
{
3164+
error().source_location = expr.source_location();
3165+
error() << "pointer arithmetic with unknown object size" << eom;
3166+
throw 0;
3167+
}
3168+
else if(
3169+
subtype.id() == ID_union_tag &&
3170+
to_union_type(follow_tag(to_union_tag_type(subtype))).is_incomplete())
31703171
{
31713172
error().source_location = expr.source_location();
31723173
error() << "pointer arithmetic with unknown object size" << eom;

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
@@ -522,9 +522,11 @@ void c_typecheck_baset::typecheck_array_type(array_typet &type)
522522
}
523523

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

806808
typet new_type=compound_symbol.type;
807809

808-
if(compound_symbol.type.id()==ID_struct)
809-
compound_symbol.type.id(ID_incomplete_struct);
810-
else if(compound_symbol.type.id()==ID_union)
811-
compound_symbol.type.id(ID_incomplete_union);
812-
else
813-
UNREACHABLE;
810+
// mark as incomplete
811+
compound_symbol.type.set(ID_incomplete, true);
814812

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

852851
typet tag_type;
853852

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

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

1343-
if(symbol.type.id()!=ID_c_enum &&
1344-
symbol.type.id()!=ID_incomplete_c_enum)
1343+
if(symbol.type.id() != ID_c_enum)
13451344
{
13461345
error().source_location=source_location;
13471346
error() << "use of tag that does not match previous declaration" << eom;
@@ -1351,9 +1350,9 @@ void c_typecheck_baset::typecheck_c_enum_tag_type(c_enum_tag_typet &type)
13511350
else
13521351
{
13531352
// no, add it as an incomplete c_enum
1354-
typet new_type(ID_incomplete_c_enum);
1355-
new_type.subtype()=signed_int_type(); // default
1353+
c_enum_typet new_type(signed_int_type()); // default subtype
13561354
new_type.add(ID_tag)=tag;
1355+
new_type.make_incomplete();
13571356

13581357
symbolt enum_tag_symbol;
13591358

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

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

0 commit comments

Comments
 (0)