Skip to content

Commit

Permalink
fix Issue 14862 - Constructor of overlapped struct does not initializ…
Browse files Browse the repository at this point in the history
…e correctly global variables
  • Loading branch information
9rnsr committed Sep 6, 2015
1 parent 95146a5 commit 1fda8ab
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 58 deletions.
51 changes: 0 additions & 51 deletions src/aggregate.d
Expand Up @@ -355,57 +355,6 @@ public:
return type;
}

/****************************************
* If field[indx] is not part of a union, return indx.
* Otherwise, return the lowest field index of the union.
*/
final int firstFieldInUnion(int indx)
{
if (isUnionDeclaration())
return 0;
VarDeclaration vd = fields[indx];
int firstNonZero = indx; // first index in the union with non-zero size
for (;;)
{
if (indx == 0)
return firstNonZero;
VarDeclaration v = fields[indx - 1];
if (v.offset != vd.offset)
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;
}
}

/****************************************
* Count the number of fields starting at firstIndex which are part of the
* same union as field[firstIndex]. If not a union, return 1.
*/
final int numFieldsInUnion(int firstIndex)
{
VarDeclaration vd = fields[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 (size_t i = firstIndex + 1; i < fields.dim; ++i)
{
VarDeclaration v = fields[i];
// If offsets are different, they are not in the same union
if (v.offset != vd.offset)
break;
++count;
}
return count;
}

// is aggregate deprecated?
final bool isDeprecated()
{
Expand Down
2 changes: 0 additions & 2 deletions src/aggregate.h
Expand Up @@ -122,8 +122,6 @@ class AggregateDeclaration : public ScopeDsymbol
unsigned memsize, unsigned memalignsize, structalign_t memalign,
unsigned *paggsize, unsigned *paggalignsize, bool isunion);
Type *getType();
int firstFieldInUnion(int indx); // first field in union that includes indx
int numFieldsInUnion(int firstIndex); // #fields in union starting at index
bool isDeprecated(); // is aggregate deprecated?
bool isNested();
void makeNested();
Expand Down
9 changes: 4 additions & 5 deletions src/dinterpret.d
Expand Up @@ -3682,14 +3682,13 @@ public:
}
assert(0 <= fieldi && fieldi < sle.elements.dim);
// If it's a union, set all other members of this union to void
if (ex.op == TOKstructliteral)
if (ex.op == TOKstructliteral && v.overlapped)
{
assert(sle.sd);
int unionStart = sle.sd.firstFieldInUnion(fieldi);
int unionSize = sle.sd.numFieldsInUnion(fieldi);
for (int i = unionStart; i < unionStart + unionSize; ++i)
for (size_t i = 0; i < sle.sd.fields.dim; i++)
{
if (i == fieldi)
VarDeclaration v2 = sle.sd.fields[i];
if (!v.isOverlappedWith(v2))
continue;
Expression* exp = &(*sle.elements)[i];
if ((*exp).op != TOKvoid)
Expand Down
29 changes: 29 additions & 0 deletions test/runnable/interpret.d
Expand Up @@ -3323,6 +3323,34 @@ void test113()
}
}

/************************************************/
// 14862

struct S14862
{
union
{
struct { uint hi, lo; }
ulong data;
}

this(ulong data)
{
this.data = data;
}
}

void test14862()
{
S14862 s14862 = S14862(123UL);
enum S14862 e14862 = S14862(123UL);
static S14862 g14862 = S14862(123UL);

assert(s14862.data == 123UL); // OK
assert(e14862.data == 123UL); // OK
assert(g14862.data == 123UL); // OK <- fail
}

/************************************************/

int main()
Expand Down Expand Up @@ -3443,6 +3471,7 @@ int main()
test8818();
test9023();
test9954();
test14862();

printf("Success\n");
return 0;
Expand Down

0 comments on commit 1fda8ab

Please sign in to comment.