Bug 3270 – pure functions returning struct

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2009-08-28T13:54:00Z
Last change time
2015-06-09T01:28:07Z
Keywords
patch, wrong-code
Assigned to
nobody
Creator
qwerty

Comments

Comment #0 by qwerty — 2009-08-28T13:54:20Z
If a pure function tries to return a struct, the return value becomes garbage. Example: struct Foo { int x, y real z; } pure Foo makeFoo(const int x, const int y) { return Foo(x, y, 3.0); } int main() { auto f = makeFoo(1, 2); writeln(f.x, f.y, f.z); } Possible cause: The compiler might be optimizing makeFoo to pure void makeFoo(ref Foo f, const int x, const int y) { f = Foo(x, y, 3.0); } in order to prevent returning the entire struct on the stack. Since makeFoo is pure, this optimization breaks the program.
Comment #1 by clugdbug — 2009-10-28T03:01:58Z
If my patch to bug 3269 is in place, the functions will need to be "pure nothrow" in order to reproduce the bug. The bug clearly lies in the handling of OPucallns. It's failing to deal with the 'hidden parameter'. In e2ir.c, line 290, if you change it to ALWAYS use OPucall instead of OPucallns, the problem disappears. But that's pretty drastic. The bug lies in the back-end somewhere.
Comment #2 by clugdbug — 2009-12-30T13:11:55Z
Shouldn't be doing no-side-effect calls if there's a hidden parameter. This happens if the value is being returned on the stack. PATCH (e2ir.c line 287): else if (ep) - e = el_bin((tf->ispure && tf->isnothrow) ? OPcallns : OPcall,tyret,ec,ep); + e = el_bin((tf->ispure && tf->isnothrow && (retmethod != RETstack)) ? OPcallns : OPcall,tyret,ec,ep); else - e = el_una((tf->ispure && tf->isnothrow) ? OPucallns : OPucall,tyret,ec); + e = el_una((tf->ispure && tf->isnothrow && (retmethod != RETstack)) ? OPucallns : OPucall,tyret,ec); ------- TEST CASE: struct Foo { int x, y; real z; } pure nothrow Foo makeFoo(const int x, const int y) { return Foo(x, y, 3.0); } void main() { auto f = makeFoo(1, 2); assert(f.x==1); assert(f.y==2); assert(f.z==3); }
Comment #3 by bugzilla — 2009-12-30T17:38:24Z
Changeset 323
Comment #4 by bugzilla — 2009-12-31T11:18:57Z
Fixed dmd 2.038