diff --git a/src/declaration.d b/src/declaration.d index 94943a709cda..c5b61f85a38f 100644 --- a/src/declaration.d +++ b/src/declaration.d @@ -1535,16 +1535,18 @@ 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); @@ -1552,7 +1554,7 @@ public: _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. @@ -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()); } diff --git a/src/dinterpret.d b/src/dinterpret.d index e27b07e4195c..6f3f18570b4f 100644 --- a/src/dinterpret.d +++ b/src/dinterpret.d @@ -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. diff --git a/src/e2ir.c b/src/e2ir.c index d06cd2ee9af4..1d94e8acd88d 100644 --- a/src/e2ir.c +++ b/src/e2ir.c @@ -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) */ diff --git a/test/runnable/imports/a14992.d b/test/runnable/imports/a14992.d new file mode 100644 index 000000000000..1cdd0ef90264 --- /dev/null +++ b/test/runnable/imports/a14992.d @@ -0,0 +1,5 @@ +module imports.a14992; + +struct S1 { } + +struct S2 { int v; int[] a; } diff --git a/test/runnable/link14992.d b/test/runnable/link14992.d new file mode 100644 index 000000000000..2da97b9afa7c --- /dev/null +++ b/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(); +}