Skip to content

Commit

Permalink
Fix zero-sized fields in struct initializers
Browse files Browse the repository at this point in the history
For things like:
struct S { union { int a; int[0] b; int c;} }
we need to recognize that a and c are part of the same union. We need to
check the size as well as the offset.
  • Loading branch information
Don Clugston committed Apr 15, 2011
1 parent 31528d9 commit 4e78123
Showing 1 changed file with 18 additions and 3 deletions.
21 changes: 18 additions & 3 deletions src/struct.c
Expand Up @@ -245,15 +245,24 @@ int AggregateDeclaration::isNested()
*/
int AggregateDeclaration::firstFieldInUnion(int indx)
{
if (isUnionDeclaration())
return 0;
VarDeclaration * vd = (VarDeclaration *)fields.data[indx];
int firstNonZero = indx; // first index in the union with non-zero size
for (; ;)
{
if (indx == 0)
return indx;
return firstNonZero;
VarDeclaration * v = (VarDeclaration *)fields.data[indx - 1];
if (v->offset != vd->offset)
return indx;
return firstNonZero;
--indx;
/* If it is a zero-length field, it's ambiguous: we don't know if it is
* in the union unless we find an earlier non-zero sized field with the
* same offset.
*/
if (v->size(loc) != 0)
firstNonZero = indx;
}
}

Expand All @@ -264,11 +273,17 @@ int AggregateDeclaration::firstFieldInUnion(int indx)
int AggregateDeclaration::numFieldsInUnion(int firstIndex)
{
VarDeclaration * vd = (VarDeclaration *)fields.data[firstIndex];
/* If it is a zero-length field, AND we can't find an earlier non-zero
* sized field with the same offset, we assume it's not part of a union.
*/
if (vd->size(loc) == 0 && !isUnionDeclaration() &&
firstFieldInUnion(firstIndex) == firstIndex)
return 1;
int count = 1;
for (int i = firstIndex+1; i < fields.dim; ++i)
{
VarDeclaration * v = (VarDeclaration *)fields.data[i];
// They are in a union if they have the same offset
// If offsets are different, they are not in the same union
if (v->offset != vd->offset)
break;
++count;
Expand Down

0 comments on commit 4e78123

Please sign in to comment.