Skip to content

Commit

Permalink
Merge pull request #5014 from 9rnsr/fix14992
Browse files Browse the repository at this point in the history
Issue 14992 - static array local variables always require .init
  • Loading branch information
ibuclaw committed Feb 7, 2016
2 parents b583111 + 32d8654 commit 8388211
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 43 deletions.
40 changes: 10 additions & 30 deletions src/declaration.d
Expand Up @@ -1501,26 +1501,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 All @@ -1538,9 +1537,9 @@ public:
{
error("%s does not have a default initializer", type.toChars());
}
else
else if (auto e = type.defaultInit(loc))
{
_init = getExpInitializer();
_init = new ExpInitializer(loc, e);
}

// Default initializer is always a blit
Expand Down Expand Up @@ -2106,25 +2105,6 @@ public:
return e;
}

/****************************
* Get ExpInitializer for a variable, if there is one.
*/
final ExpInitializer getExpInitializer()
{
ExpInitializer ei;
if (_init)
ei = _init.isExpInitializer();
else
{
Expression e = type.defaultInit(loc);
if (e)
ei = new ExpInitializer(loc, e);
else
ei = null;
}
return ei;
}

/*******************************************
* If variable has a constant expression initializer, get it.
* Otherwise, return null.
Expand Down
1 change: 0 additions & 1 deletion src/declaration.h
Expand Up @@ -284,7 +284,6 @@ class VarDeclaration : public Declaration
bool canTakeAddressOf();
bool needsAutoDtor();
Expression *callScopeDtor(Scope *sc);
ExpInitializer *getExpInitializer();
Expression *getConstInitializer(bool needFullType = true);
void checkCtorConstInit();
bool checkNestedReference(Scope *sc, Loc loc);
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 @@ -2864,6 +2864,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 8388211

Please sign in to comment.