Skip to content

Commit

Permalink
fix Issue 19473 - DMD Segfault on circular struct reference
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Dec 13, 2018
1 parent 33bc192 commit d2b6fc9
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/dmd/aggregate.d
Expand Up @@ -39,6 +39,7 @@ enum Sizeok : int
{
none, // size of aggregate is not yet able to compute
fwd, // size of aggregate is ready to compute
inProcess, // in the midst of computing the size
done, // size of aggregate is set correctly
}

Expand All @@ -60,7 +61,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
uint structsize; // size of struct
uint alignsize; // size of struct for alignment purposes
VarDeclarations fields; // VarDeclaration fields
Sizeok sizeok; // set when structsize contains valid data
Sizeok sizeok = Sizeok.none; // set when structsize contains valid data
Dsymbol deferred; // any deferred semantic2() or semantic3() symbol
bool isdeprecated; // true if deprecated

Expand Down
1 change: 1 addition & 0 deletions src/dmd/aggregate.h
Expand Up @@ -39,6 +39,7 @@ enum Sizeok
{
SIZEOKnone, // size of aggregate is not yet able to compute
SIZEOKfwd, // size of aggregate is ready to compute
SIZEOKinProcess, // in the midst of computing the size
SIZEOKdone, // size of aggregate is set correctly
};

Expand Down
9 changes: 9 additions & 0 deletions src/dmd/dstruct.d
Expand Up @@ -355,6 +355,12 @@ extern (C++) class StructDeclaration : AggregateDeclaration
//printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
assert(sizeok != Sizeok.done);

if (sizeok == Sizeok.inProcess)
{
return;
}
sizeok = Sizeok.inProcess;

//printf("+StructDeclaration::finalizeSize() %s, fields.dim = %d, sizeok = %d\n", toChars(), fields.dim, sizeok);

fields.setDim(0); // workaround
Expand All @@ -368,7 +374,10 @@ extern (C++) class StructDeclaration : AggregateDeclaration
s.setFieldOffset(this, &offset, isunion);
}
if (type.ty == Terror)
{
errors = true;
return;
}

// 0 sized struct's are set to 1 byte
if (structsize == 0)
Expand Down
31 changes: 31 additions & 0 deletions test/fail_compilation/test19473.d
@@ -0,0 +1,31 @@
/* TEST_OUTPUT:
---
fail_compilation/test19473.d(14): Error: union `test19473.P` no size because of forward reference
---
*/

// https://issues.dlang.org/show_bug.cgi?id=19473

struct A {
P p;

struct UTpl() {
union {
P p;
}
}

alias U = UTpl!();
}

alias B = A.U;

struct C {
union D {
B b;
}
}

union P {
C.D p;
}

0 comments on commit d2b6fc9

Please sign in to comment.