Skip to content

Commit

Permalink
fix Issue 14992 - static array local variables always require .init
Browse files Browse the repository at this point in the history
Add one more special case for static array of struct initialization with zero, similar to the special case for struct initialization.
  • Loading branch information
9rnsr committed Sep 13, 2015
1 parent 2736fb4 commit 0036506
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 20 deletions.
18 changes: 10 additions & 8 deletions src/declaration.d
Original file line number Diff line number Diff line change
Expand Up @@ -1535,24 +1535,26 @@ public:
{
// Provide a default initializer
//printf("Providing default initializer for '%s'\n", toChars());
if (type.needsNested())

Type tv = type;
while (tv.ty == Tsarray) // Don't skip Tenum
tv = tv.nextOf();
if (tv.needsNested())
{
Type tv = type;
while (tv.toBasetype().ty == Tsarray)
tv = tv.toBasetype().nextOf();
assert(tv.toBasetype().ty == Tstruct);
/* Nested struct requires valid enclosing frame pointer.
* In StructLiteralExp::toElem(), it's calculated.
*/
checkFrameAccess(loc, sc, (cast(TypeStruct)tv.toBasetype()).sym);
assert(tbn.ty == Tstruct);
checkFrameAccess(loc, sc, (cast(TypeStruct)tbn).sym);

Expression e = tv.defaultInitLiteral(loc);
Expression e1 = new VarExp(loc, this);
e = new BlitExp(loc, e1, e);
e = e.semantic(sc);
_init = new ExpInitializer(loc, e);
goto Ldtor;
}
else if (type.ty == Tstruct && (cast(TypeStruct)type).sym.zeroInit == 1)
if (tv.ty == Tstruct && (cast(TypeStruct)tv).sym.zeroInit == 1)
{
/* If a struct is all zeros, as a special case
* set it's initializer to the integer 0.
Expand All @@ -1568,7 +1570,7 @@ public:
_init = new ExpInitializer(loc, e);
goto Ldtor;
}
else if (type.baseElemOf().ty == Tvoid)
if (type.baseElemOf().ty == Tvoid)
{
error("%s does not have a default initializer", type.toChars());
}
Expand Down
26 changes: 14 additions & 12 deletions src/dinterpret.d
Original file line number Diff line number Diff line change
Expand Up @@ -3495,21 +3495,23 @@ public:
Expression newval = interpret(e.e2, istate);
if (exceptionOrCant(newval))
return;
if (e.type.toBasetype().ty == Tstruct && newval.op == TOKint64)
if (e.op == TOKblit && newval.op == TOKint64)
{
/* Look for special case of struct being initialized with 0.
*/
assert(e.op == TOKconstruct || e.op == TOKblit);
newval = e.type.defaultInitLiteral(e.loc);
if (newval.op != TOKstructliteral)
Type tbn = e.type.baseElemOf();
if (tbn.ty == Tstruct)
{
e.error("nested structs with constructors are not yet supported in CTFE (Bug 6419)");
result = CTFEExp.cantexp;
return;
/* Look for special case of struct being initialized with 0.
*/
newval = e.type.defaultInitLiteral(e.loc);
if (newval.op == TOKerror)
{
result = CTFEExp.cantexp;
return;
}
newval = interpret(newval, istate); // copy and set ownedByCtfe flag
if (exceptionOrCant(newval))
return;
}
newval = interpret(newval, istate); // copy and set ownedByCtfe flag
if (exceptionOrCant(newval))
return;
}
// ----------------------------------------------------
// Deal with read-modify-write assignments.
Expand Down
23 changes: 23 additions & 0 deletions src/e2ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -2838,6 +2838,29 @@ elem *toElem(Expression *e, IRState *irs)
}
else if (t1b->ty == Tsarray)
{
if (ae->op == TOKblit && ae->e2->op == TOKint64)
{
/* Implement:
* (sarray = 0)
* with:
* memset(&sarray, 0, struct.sizeof)
*/
elem *ey = NULL;
targ_size_t sz = ae->e1->type->size();
StructDeclaration *sd = ((TypeStruct *)t1b->baseElemOf())->sym;

elem *el = e1;
elem *enbytes = el_long(TYsize_t, sz);
elem *evalue = el_long(TYsize_t, 0);

if (!(sd->isNested() && ae->op == TOKconstruct))
el = el_una(OPaddr, TYnptr, el);
e = el_param(enbytes, evalue);
e = el_bin(OPmemset,TYnptr,el,e);
e = el_combine(ey, e);
goto Lret;
}

/* Implement:
* (sarray = sarray)
*/
Expand Down
5 changes: 5 additions & 0 deletions test/runnable/imports/a14992.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module imports.a14992;

struct S1 { }

struct S2 { int v; int[] a; }
22 changes: 22 additions & 0 deletions test/runnable/link14992.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import imports.a14992; // do not link

int test()
{
S1 v1; // OK
S1* p1; // OK
S1[] da1; // OK
S1[2] a1; // OK <- NG

S2 v2; // OK
S2* p2; // OK
S2[] da2; // OK
S2[2] a2; // OK <- NG

return 1;
}
static assert(test());

void main()
{
test();
}

0 comments on commit 0036506

Please sign in to comment.