Bug 3901 – PATCH: Nested struct assignment for CTFE

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
Other
OS
Windows
Creation time
2010-03-08T11:29:00Z
Last change time
2014-04-18T09:12:07Z
Keywords
patch, rejects-valid
Assigned to
nobody
Creator
clugdbug

Attachments

IDFilenameSummaryContent-TypeSize
586interpret.cPatch against DMD2.041 svn 409.text/plain81174

Comments

Comment #0 by clugdbug — 2010-03-08T11:29:16Z
This is a MAJOR refactoring of assignment in CTFE. The assign function was a big mess. A lot of work, and there's not really much to show for it from a user's perspective. But it's a solid platform to allow the final CTFE bugs to be fixed. To install this patch, you need to add a single function to mtype.c, and completely replace interpret.c with the attachment.(There are so many changes, that a patch doesn't make sense). Fortunately the test suite file interpret.d is getting quite extensive. And these new tests do some pretty evil things... == New features: * Arbitrary nested struct assignment now works in CTFE. a.b.c.d = e; a[i].b.c.d = e; * ref return values now work in CTFE (D2 only). BUGS FIXED: 3842 ICE(expression.c) using pointer in CTFE 3899 CTFE: poor error message for use of uninitialized variable 3900 CTFE: Wrong return value for array.var assignment ======================================================== ============ PATCH for mtype.c: ======================= ======================================================== --- mtype.c (revision 409) +++ mtype.c (working copy) @@ -3451,6 +3451,21 @@ return next->isZeroInit(loc); } +Expression *TypeSArray::defaultInitLiteral(Loc loc) +{ +#if LOGDEFAULTINIT + printf("TypeSArray::defaultInitLiteral() '%s'\n", toChars()); +#endif + size_t d = dim->toInteger(); + Expression *elementinit = next->defaultInitLiteral(loc); + Expressions *elements = new Expressions(); + elements->setDim(d); + for (size_t i = 0; i < d; i++) + elements->data[i] = elementinit; + ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); + ae->type = this; + return ae; +} Expression *TypeSArray::toExpression() { Index: mtype.h =================================================================== --- mtype.h (revision 409) +++ mtype.h (working copy) @@ -406,6 +406,7 @@ MATCH constConv(Type *to); MATCH implicitConvTo(Type *to); Expression *defaultInit(Loc loc); + Expression *defaultInitLiteral(Loc loc); dt_t **toDt(dt_t **pdt); dt_t **toDtElem(dt_t **pdt, Expression *e); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); ======================================================== ========= Test cases for test suite. =================== ======================================================== struct ArrayRet{ int x; } int arrayRetTest(int z) { ArrayRet[6] w; int q = (w[3].x = z); return q; } static assert(arrayRetTest(51)==51); // Bugzilla 3842 -- must not segfault int ice3842(int z) { ArrayRet w; return arrayRetTest((*(&w)).x); } static assert(true || is(typeof(compiles!(ice3842(51))))); int arrayret2(){ int [5] a; int [3] b; b[] = a[1..$-1] = 5; return b[1]; } static assert(arrayret2()==5); struct DotVarTest { ArrayRet z; } struct DotVarTest2 { ArrayRet z; DotVarTest p; } int dotvar1() { DotVarTest w; w.z.x = 3; return w.z.x; } int dotvar2() { DotVarTest2[4] m; m[2].z.x = 3; m[1].p.z.x = 5; return m[2].z.x + 7; } static assert(dotvar1()==3); static assert(dotvar2()==10); struct RetRefStruct{ int x; char c; } // Return value reference tests, for D2 only. ref RetRefStruct reffunc1(ref RetRefStruct a) { int y = a.x; return a; } ref RetRefStruct reffunc2(ref RetRefStruct a) { RetRefStruct z = a; return reffunc1(a); } ref int reffunc7(ref RetRefStruct aa) { return reffunc1(aa).x; } ref int reffunc3(ref int a) { return a; } struct RefTestStruct { RetRefStruct r; ref RefTestStruct reffunc4(ref RetRefStruct[3] a) { return this; } ref int reffunc6() { return this.r.x; } } ref RetRefStruct reffunc5(ref RetRefStruct[3] a) { int t = 1; for (int i=0; i<10; ++i) { if (i==7) ++t;} return a[reffunc3(t)]; } int retRefTest1() { RetRefStruct b = RetRefStruct(0,'a'); reffunc1(b).x =3; return b.x-1; } int retRefTest2() { RetRefStruct b = RetRefStruct(0,'a'); reffunc2(b).x =3; RetRefStruct[3] z; RefTestStruct w; w.reffunc4(z).reffunc4(z).r.x = 4; assert(w.r.x == 4); w.reffunc6() = 218; assert(w.r.x == 218); z[2].x = 3; int q=4; int u = reffunc5(z).x + reffunc3(q); assert(u==7); reffunc5(z).x += 7; assert(z[2].x == 10); RetRefStruct m = RetRefStruct(7, 'c'); m.x = 6; reffunc7(m)+=3; assert(m.x==9); return b.x-1; } int retRefTest3() { RetRefStruct b = RetRefStruct(0,'a'); auto deleg = function (RetRefStruct a){ return a;}; typeof(deleg)[3] z; z[] = deleg; auto y = deleg(b).x + 27; b.x = 5; assert(y == 27); y = z[1](b).x + 22; return y - 1; } int retRefTest4() { RetRefStruct b = RetRefStruct(0,'a'); reffunc3(b.x) = 218; assert(b.x == 218); return b.x; } static assert(retRefTest1()==2); static assert(retRefTest2()==2); static assert(retRefTest3()==26); static assert(retRefTest4()==218);
Comment #1 by clugdbug — 2010-03-08T11:32:25Z
Created attachment 586 Patch against DMD2.041 svn 409. Drop-in replacement for interpret.c for DMD2.041. Also works without modification for D1. Also needs the change to mtype.c.
Comment #2 by bearophile_hugs — 2010-03-08T13:21:44Z
Thank you for all such big work. > New features: ... > * ref return values now work in CTFE (D2 only). So is this fixing bug 2411 too?
Comment #3 by clugdbug — 2010-03-09T01:57:49Z
(In reply to comment #2) > Thank you for all such big work. > > > > New features: > ... > > * ref return values now work in CTFE (D2 only). > > So is this fixing bug 2411 too? Unfortunately not. This fixes the 'ref' part of the problem, but bug 1330 still prevents it from working. Bug 1330 is actually the fundamental CTFE problem: once it is fixed, almost everything will work. This patch cleans everything up so that there's a chance of fixing 1330.
Comment #4 by bugzilla — 2010-03-09T12:19:28Z
changeset 413
Comment #5 by clugdbug — 2010-04-09T19:14:41Z
Fixed DMD1.058 and DMD2.042.