Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions regression/ansi-c/union/union_flexible_array_member.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// C11 6.7.2.1 §18 allows flexible array members in structures,
// but not unions.

union
{
char flexible_array_member[];
};
7 changes: 7 additions & 0 deletions regression/ansi-c/union/union_flexible_array_member.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CORE gcc-only
union_flexible_array_member.c

^EXIT=(1|64)$
^SIGNAL=0$
^CONVERSION ERROR$
--
13 changes: 13 additions & 0 deletions regression/ansi-c/union/union_flexible_array_member_msvc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Flexible array members in unions are allowed as an extension on Windows.

union U
{
int n;
char flexible_array_member[];
};

int main()
{
union U u;
u.n = 42;
}
6 changes: 6 additions & 0 deletions regression/ansi-c/union/union_flexible_array_member_msvc.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CORE
union_flexible_array_member_msvc.c
--i386-win32
^EXIT=0$
^SIGNAL=0$
--
19 changes: 19 additions & 0 deletions regression/ansi-c/union/union_flexible_array_member_msvc_address.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// This test exercises the Microsoft extension that allows flexible array
// members in unions by actually taking the address of the member and
// indexing into it, not just assigning to a sibling. This ensures the
// zero-length encoding produced by the type-checker survives downstream
// processing.

union U
{
int n;
char flexible_array_member[];
};

int main()
{
union U u;
u.n = 42;
char *p = &u.flexible_array_member[0];
(void)p;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CORE
union_flexible_array_member_msvc_address.c
--i386-win32
^EXIT=0$
^SIGNAL=0$
--
^CONVERSION ERROR$
9 changes: 9 additions & 0 deletions regression/ansi-c/union/union_flexible_array_member_named.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// C11 6.7.2.1 §18 allows flexible array members in structures, but not in
// unions. This file exercises the named-union form (the other, anonymous
// form is covered by union_flexible_array_member.c).

union U
{
int n;
char flexible_array_member[];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CORE gcc-only
union_flexible_array_member_named.c

^EXIT=(1|64)$
^SIGNAL=0$
^CONVERSION ERROR$
--
18 changes: 18 additions & 0 deletions regression/ansi-c/union/union_zero_length_array.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// A zero-length array [0] is a gcc extension that has historically been
// accepted anywhere in a struct or union, independently of the more recent
// C11 rule on flexible array members ([]). This test guards that
// distinction: zero-length arrays in unions must remain accepted on all
// targets (both ISO and Windows), even after the tightening of flexible
// array members in unions.

union U
{
int n;
char zero_length[0];
};

int main()
{
union U u;
u.n = 42;
}
7 changes: 7 additions & 0 deletions regression/ansi-c/union/union_zero_length_array.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CORE
union_zero_length_array.c

^EXIT=0$
^SIGNAL=0$
--
^CONVERSION ERROR$
46 changes: 29 additions & 17 deletions src/ansi-c/c_typecheck_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1070,33 +1070,45 @@ void c_typecheck_baset::typecheck_compound_body(
}
}

// We allow an incomplete (C99) array as _last_ member!
// Zero-length is allowed everywhere.

if(type.id()==ID_struct ||
type.id()==ID_union)
{
for(struct_union_typet::componentst::iterator
it=components.begin();
it!=components.end();
// We allow an incomplete array as _last_ member of a struct,
// C11 6.7.2.1 §18. These are called "flexible array members".
// Zero-length (a gcc extension) is allowed everywhere.
// Flexible array members are not allowed in unions in ISO C, but we allow
// them as an extension on Windows.
if(type.id() == ID_struct || type.id() == ID_union)
{
for(struct_union_typet::componentst::iterator it = components.begin();
it != components.end();
it++)
{
typet &c_type=it->type();
typet &component_type = it->type();

if(
component_type.id() != ID_array ||
!to_array_type(component_type).is_incomplete())
{
continue;
}

if(c_type.id()==ID_array &&
to_array_type(c_type).is_incomplete())
if(type.id() == ID_struct)
{
// needs to be last member
if(type.id()==ID_struct && it!=--components.end())
if(it != --components.end())
{
throw errort().with_location(it->source_location())
<< "flexible struct member must be last member";
}

// make it zero-length
to_array_type(c_type).size() = from_integer(0, c_index_type());
c_type.set(ID_C_flexible_array_member, true);
}
else if(config.ansi_c.os != configt::ansi_ct::ost::OS_WIN)
{
throw errort().with_location(it->source_location())
<< "flexible array members in a union are a Microsoft "
"extension, and not permitted in ISO C";
}

// make it zero-length
to_array_type(component_type).size() = from_integer(0, c_index_type());
component_type.set(ID_C_flexible_array_member, true);
}
}

Expand Down
Loading