Bug 5071 – passing value by ref to a function with an inner dynamic closure results in a wrong code

Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2010-10-18T09:44:00Z
Last change time
2010-10-20T01:16:13Z
Keywords
patch, wrong-code
Assigned to
nobody
Creator
2korden

Comments

Comment #0 by 2korden — 2010-10-18T09:44:59Z
Here is a test case: import std.stdio; void passObject(ref char c, bool dummy) { } void passClosure(void delegate() dg) { } void test(ref char c, bool dummy = false) { writeln("inside c=", c, " (", cast(int)c, ") &c=", &c); void closure() { passObject(c, dummy); } passClosure(&closure); } void main() { //* Test one (c is on heap) char* c = new char; *c = 'a'; writeln("outside c=", *c, " (", cast(int)*c, ") &c=", c); test(*c, true); /*/ Test two (c is on stack) char c = 'a'; writeln("outside c=", c, " (", cast(int)c, ") &c=", &c); test(c); //*/ } Test one output: outside c=a (97) &c=12B2E40 inside c= (0) &c=12B0140 Test two output: outside c=a (97) &c=12FE54 object.Error: Access Violation Note that passing by pointer instead works fine: outside c=a (97) &c=582E40 inside c=a (97) &c=582E40
Comment #1 by bugzilla — 2010-10-18T11:05:58Z
Priority bumped up because newbies run into it.
Comment #2 by clugdbug — 2010-10-19T08:42:34Z
REDUCED TEST CASE: void doNothing() {} void bug5071(short d, ref short c) { assert(c==0x76); void closure() { auto c2 = c; auto d2 = d; doNothing(); } auto useless = &closure; } void main() { short c = 0x76; bug5071(7, c); } PATCH: toir.c, FuncDeclaration::buildClosure(), line 648. When it copies the parameters into the closure, it correctly recognizes that ref params are just pointers. But, it needs to do the same thing when working out what offsets they are at. #if DMDV2 if (v->storage_class & STClazy) { /* Lazy variables are really delegates, * so give same answers that TypeDelegate would */ memsize = PTRSIZE * 2; memalignsize = memsize; xalign = global.structalign; } + else if (v->isRef() || v->isOut()) + { // reference parameters are just pointers + memsize = PTRSIZE; + memalignsize = memsize; + xalign = global.structalign; + } else #endif { memsize = v->type->size(); memalignsize = v->type->alignsize(); xalign = v->type->memalign(global.structalign); }
Comment #3 by bugzilla — 2010-10-20T01:16:13Z