Skip to content

Commit 22faee4

Browse files
committed
disallow flexible array members in unions
This change yields an error if a flexible array member is used in a union. C11 allows them in structs, but not unions.
1 parent 584c24f commit 22faee4

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// C11 6.7.2.1 §18 allows flexible array members in structures,
2+
// but not unions.
3+
4+
union
5+
{
6+
char flexible_array_member[];
7+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE gcc-only
2+
union_flexible_array_member.c
3+
4+
^EXIT=1$
5+
^SIGNAL=0$
6+
^CONVERSION ERROR$
7+
--

src/ansi-c/c_typecheck_type.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,33 +1007,52 @@ void c_typecheck_baset::typecheck_compound_body(
10071007
}
10081008
}
10091009

1010-
// We allow an incomplete (C99) array as _last_ member!
1011-
// Zero-length is allowed everywhere.
1012-
1013-
if(type.id()==ID_struct ||
1014-
type.id()==ID_union)
1010+
// We allow an incomplete array as _last_ member of a struct,
1011+
// C11 6.7.2.1 §18. These are called "flexible array members".
1012+
// Zero-length (a gcc extension) is allowed everywhere.
1013+
if(type.id() == ID_struct)
10151014
{
10161015
for(struct_union_typet::componentst::iterator
10171016
it=components.begin();
10181017
it!=components.end();
10191018
it++)
10201019
{
1021-
typet &c_type=it->type();
1020+
typet &component_type = it->type();
10221021

1023-
if(c_type.id()==ID_array &&
1024-
to_array_type(c_type).is_incomplete())
1022+
if(
1023+
component_type.id() == ID_array &&
1024+
to_array_type(component_type).is_incomplete())
10251025
{
10261026
// needs to be last member
1027-
if(type.id()==ID_struct && it!=--components.end())
1027+
if(it != --components.end())
10281028
{
10291029
error().source_location=it->source_location();
10301030
error() << "flexible struct member must be last member" << eom;
10311031
throw 0;
10321032
}
10331033

10341034
// make it zero-length
1035-
to_array_type(c_type).size() = from_integer(0, c_index_type());
1036-
c_type.set(ID_C_flexible_array_member, true);
1035+
to_array_type(component_type).size() = from_integer(0, c_index_type());
1036+
component_type.set(ID_C_flexible_array_member, true);
1037+
}
1038+
}
1039+
}
1040+
1041+
// Flexible array members are not allowed in unions in ISO C.
1042+
// We allow this as an extension on Windows.
1043+
if(type.id() == ID_union && config.ansi_c.os != configt::ansi_ct::ost::OS_WIN)
1044+
{
1045+
for(const auto &component : components)
1046+
{
1047+
auto &component_type = component.type();
1048+
1049+
if(
1050+
component_type.id() == ID_array &&
1051+
to_array_type(component_type).is_incomplete())
1052+
{
1053+
throw invalid_source_file_exceptiont(
1054+
"flexible array members are not allowed in a union",
1055+
component.source_location());
10371056
}
10381057
}
10391058
}

0 commit comments

Comments
 (0)