Skip to content

Commit 151efbc

Browse files
author
Daniel Kroening
authored
Merge pull request #131 from tautschnig/struct-init-error
Array initialization with a non-array is expected to fail
2 parents d023498 + 9740142 commit 151efbc

File tree

7 files changed

+105
-27
lines changed

7 files changed

+105
-27
lines changed

regression/ansi-c/Struct_Initialization1/main.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
#define STATIC_ASSERT(condition) \
22
int some_array##__LINE__[(condition) ? 1 : -1]
33

4+
struct A {
5+
int x;
6+
int y;
7+
};
8+
49
struct _classinfo {
510
char a;
11+
struct A s;
612
int *interfaces[];
713
};
814

9-
struct _classinfo nullclass1 = { 42, 0, 0 };
10-
struct _classinfo nullclass2 = { 42, { 0, 0 } };
15+
struct _classinfo nullclass1 = { 42, 1, 2, 3, 4 };
16+
struct _classinfo nullclass2 = { 42, { 1, 2 }, { 3, 4 } };
1117

1218
STATIC_ASSERT(sizeof(nullclass1)==sizeof(struct _classinfo));
1319
STATIC_ASSERT(sizeof(nullclass2)==sizeof(struct _classinfo));

regression/ansi-c/Struct_Initialization1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#define STATIC_ASSERT(condition) \
2+
int some_array##__LINE__[(condition) ? 1 : -1]
3+
4+
struct A {
5+
int x;
6+
int y;
7+
int arr[];
8+
};
9+
10+
struct _classinfo {
11+
char a;
12+
struct A s;
13+
int *interfaces[];
14+
};
15+
16+
struct _classinfo nullclass1 = { 42, 1, 2, 0, 3, 4 };
17+
struct _classinfo nullclass2 = { 42, { 1, 2, 0 }, { 3, 4 } };
18+
19+
STATIC_ASSERT(sizeof(nullclass1)==sizeof(struct _classinfo));
20+
STATIC_ASSERT(sizeof(nullclass2)==sizeof(struct _classinfo));
21+
22+
int main()
23+
{
24+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=(64|1)$
5+
^SIGNAL=0$
6+
^CONVERSION ERROR$
7+
--
8+
^warning: ignoring
9+
--
10+
variable-length arrays in the middle of a struct are not permitted

src/ansi-c/c_typecheck_base.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,11 @@ class c_typecheck_baset:
8989
const typet &type,
9090
bool force_constant);
9191

92-
virtual void do_designated_initializer(
92+
virtual exprt::operandst::const_iterator do_designated_initializer(
9393
exprt &result,
9494
designatort &designator,
95-
const exprt &value,
95+
const exprt &initializer_list,
96+
exprt::operandst::const_iterator init_it,
9697
bool force_constant);
9798

9899
designatort make_designator(const typet &type, const exprt &src);

src/ansi-c/c_typecheck_initializer.cpp

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,7 @@ void c_typecheck_baset::designator_enter(
256256
const typet &type,
257257
designatort &designator)
258258
{
259-
designatort::entryt entry;
260-
entry.type=type;
261-
entry.index=0;
259+
designatort::entryt entry(type);
262260

263261
const typet &full_type=follow(type);
264262

@@ -268,6 +266,8 @@ void c_typecheck_baset::designator_enter(
268266

269267
entry.size=struct_type.components().size();
270268
entry.subtype.make_nil();
269+
// only a top-level struct may end with a variable-length array
270+
entry.vla_permitted=designator.empty();
271271

272272
for(struct_typet::componentst::const_iterator
273273
it=struct_type.components().begin();
@@ -351,12 +351,16 @@ void c_typecheck_baset::designator_enter(
351351

352352
/// \param pre:initialized result, designator
353353
/// \return sets result
354-
void c_typecheck_baset::do_designated_initializer(
354+
exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
355355
exprt &result,
356356
designatort &designator,
357-
const exprt &value,
357+
const exprt &initializer_list,
358+
exprt::operandst::const_iterator init_it,
358359
bool force_constant)
359360
{
361+
// copy the value, we may need to adjust it
362+
exprt value=*init_it;
363+
360364
assert(!designator.empty());
361365

362366
if(value.id()==ID_designated_initializer)
@@ -370,8 +374,10 @@ void c_typecheck_baset::do_designated_initializer(
370374

371375
assert(!designator.empty());
372376

373-
return do_designated_initializer(
374-
result, designator, value.op0(), force_constant);
377+
// discard the return value
378+
do_designated_initializer(
379+
result, designator, value, value.operands().begin(), force_constant);
380+
return ++init_it;
375381
}
376382

377383
exprt *dest=&result;
@@ -503,7 +509,7 @@ void c_typecheck_baset::do_designated_initializer(
503509

504510
assert(full_type==follow(dest->type()));
505511

506-
return; // done
512+
return ++init_it; // done
507513
}
508514

509515
// union? The component in the zero initializer might
@@ -537,7 +543,7 @@ void c_typecheck_baset::do_designated_initializer(
537543
if(value.id()==ID_initializer_list)
538544
{
539545
*dest=do_initializer_rec(value, type, force_constant);
540-
return; // done
546+
return ++init_it; // done
541547
}
542548
else if(value.id()==ID_string_constant)
543549
{
@@ -549,7 +555,7 @@ void c_typecheck_baset::do_designated_initializer(
549555
follow(full_type.subtype()).id()==ID_unsignedbv))
550556
{
551557
*dest=do_initializer_rec(value, type, force_constant);
552-
return; // done
558+
return ++init_it; // done
553559
}
554560
}
555561
else if(follow(value.type())==full_type)
@@ -562,7 +568,7 @@ void c_typecheck_baset::do_designated_initializer(
562568
full_type.id()==ID_vector)
563569
{
564570
*dest=value;
565-
return; // done
571+
return ++init_it; // done
566572
}
567573
}
568574

@@ -574,21 +580,49 @@ void c_typecheck_baset::do_designated_initializer(
574580
// we are initializing a compound type, and enter it!
575581
// this may change the type, full_type might not be valid any more
576582
const typet dest_type=full_type;
583+
const bool vla_permitted=designator.back().vla_permitted;
577584
designator_enter(type, designator);
578585

586+
// GCC permits (though issuing a warning with -Wall) composite
587+
// types built from flat initializer lists
579588
if(dest->operands().empty())
580589
{
581-
err_location(value);
582-
error() << "cannot initialize type `"
583-
<< to_string(dest_type) << "' using value `"
584-
<< to_string(value) << "'" << eom;
585-
throw 0;
590+
warning().source_location=value.find_source_location();
591+
warning() << "initialisation of " << full_type.id()
592+
<< " requires initializer list, found "
593+
<< value.id() << " instead" << eom;
594+
595+
// in case of a variable-length array consume all remaining
596+
// initializer elements
597+
if(vla_permitted &&
598+
dest_type.id()==ID_array &&
599+
(to_array_type(dest_type).size().is_zero() ||
600+
to_array_type(dest_type).size().is_nil()))
601+
{
602+
value.id(ID_initializer_list);
603+
value.operands().clear();
604+
for( ; init_it!=initializer_list.operands().end(); ++init_it)
605+
value.copy_to_operands(*init_it);
606+
*dest=do_initializer_rec(value, dest_type, force_constant);
607+
608+
return init_it;
609+
}
610+
else
611+
{
612+
err_location(value);
613+
error() << "cannot initialize type `"
614+
<< to_string(dest_type) << "' using value `"
615+
<< to_string(value) << "'" << eom;
616+
throw 0;
617+
}
586618
}
587619

588620
dest=&(dest->op0());
589621

590622
// we run into another loop iteration
591623
}
624+
625+
return ++init_it;
592626
}
593627

594628
void c_typecheck_baset::increment_designator(designatort &designator)
@@ -651,8 +685,7 @@ designatort c_typecheck_baset::make_designator(
651685
forall_operands(it, src)
652686
{
653687
const exprt &d_op=*it;
654-
designatort::entryt entry;
655-
entry.type=type;
688+
designatort::entryt entry(type);
656689
const typet &full_type=follow(entry.type);
657690

658691
if(full_type.id()==ID_array)
@@ -856,10 +889,12 @@ exprt c_typecheck_baset::do_initializer_list(
856889

857890
designator_enter(type, current_designator);
858891

859-
forall_operands(it, value)
892+
const exprt::operandst &operands=value.operands();
893+
for(exprt::operandst::const_iterator it=operands.begin();
894+
it!=operands.end(); ) // no ++it
860895
{
861-
do_designated_initializer(
862-
result, current_designator, *it, force_constant);
896+
it=do_designated_initializer(
897+
result, current_designator, value, it, force_constant);
863898

864899
// increase designator -- might go up
865900
increment_designator(current_designator);

src/ansi-c/designator.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ class designatort
2424
{
2525
size_t index;
2626
size_t size;
27+
bool vla_permitted;
2728
typet type, subtype;
2829

29-
entryt():index(0), size(0)
30+
explicit entryt(const typet &type):
31+
index(0), size(0), vla_permitted(false), type(type)
3032
{
3133
}
3234
};

0 commit comments

Comments
 (0)