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 Jan 31, 2016
1 parent 84f6aaf commit e2be398
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 21 deletions.
17 changes: 8 additions & 9 deletions src/declaration.d
Expand Up @@ -1519,26 +1519,25 @@ public:
// Provide a default initializer

//printf("Providing default initializer for '%s'\n", toChars());
if (type.needsNested())
{
Type tv = type;
while (tv.toBasetype().ty == Tsarray)
tv = tv.toBasetype().nextOf();
assert(tv.toBasetype().ty == Tstruct);

Type tv = type;
while (tv.ty == Tsarray) // Don't skip Tenum
tv = tv.nextOf();
if (tv.needsNested())
{
/* 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);
e = new BlitExp(loc, new VarExp(loc, this), e);
e = e.semantic(sc);
_init = new ExpInitializer(loc, e);
goto Ldtor;
}
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 Down
26 changes: 14 additions & 12 deletions src/dinterpret.d
Expand Up @@ -3563,21 +3563,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;
}

// ----------------------------------------------------
Expand Down
23 changes: 23 additions & 0 deletions src/e2ir.c
Expand Up @@ -2854,6 +2854,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
@@ -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
@@ -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 e2be398

Please sign in to comment.