Bug 19384 – [Codegen] Address of stack temporary is returned

Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2018-11-09T20:59:07Z
Last change time
2020-09-07T02:41:19Z
Keywords
backend, pull, wrong-code
Assigned to
No Owner
Creator
MrSmith33

Comments

Comment #0 by mrsmith33 — 2018-11-09T20:59:07Z
opIndex function returns address of stack local temporary instead of this Reduced code: --- void main() { Vec preds = Vec(0xDEAD); void* ptr1 = &preds; void* ptr2 = &preds[0]; assert(ptr1 == ptr2); } struct Vec { uint item; ref uint opIndex(size_t index) { return item; // commenting next line removes bug foreach(ref val; range()) return val; assert(false); } } struct range { int opApply(scope int delegate(ref uint) dg) { return 0; } } --- Assembly without comment: --- ref uint opIndex(size_t index) push rbp mov rbp,rsp sub rsp,30h mov qword ptr [this],rcx mov qword ptr [index],rdx { return item; mov rax,qword ptr [this] mov qword ptr [__result],rax mov qword ptr [rbp-28h],rax // result is stored on stack lea rax,[rbp-28h] // address of stack is returned instead of value from stack // commenting next line fixes bug foreach(ref val; range()) return val; assert(false); } mov rsp,rbp pop rbp ret --- Assembly with comment: --- ref uint opIndex(size_t index) push rbp mov rbp,rsp mov qword ptr [this],rcx mov qword ptr [index],rdx { return item; mov rax,qword ptr [this] // commenting next line fixes bug //foreach(ref val; range()) return val; assert(false); } pop rbp ret --- Tested on windows and on linux (https://run.dlang.io/is/7dqb1T)
Comment #1 by bugzilla — 2020-09-06T09:33:35Z
This problem happens on 32 bit code, too. Slightly reduced test case: void main() { Vec preds = Vec(0xDEAD); void* ptr2 = &preds.august(); assert(&preds == ptr2); } struct Vec { uint item; ref uint august() { return item; // commenting next line removes bug foreach(ref val; range()) return val; assert(false); } } struct range { int opApply(scope int delegate(ref uint) dg) { return 0; } }
Comment #2 by bugzilla — 2020-09-06T09:55:00Z
Replace the `ref uint` return with a `uint*` pointer and it works. So, the problem must be in the logic that treats a pointer return, but not a ref return.
Comment #3 by dlang-bot — 2020-09-07T01:48:18Z
@WalterBright created dlang/dmd pull request #11701 "fix Issue 19384 - [Codegen] Address of stack temporary is returned" fixing this issue: - fix Issue 19384 - [Codegen] Address of stack temporary is returned https://github.com/dlang/dmd/pull/11701
Comment #4 by dlang-bot — 2020-09-07T02:41:19Z
dlang/dmd pull request #11701 "fix Issue 19384 - [Codegen] Address of stack temporary is returned" was merged into master: - d8d294f38676f98bedef7d069746532e6f6c2c64 by Walter Bright: fix Issue 19384 - [Codegen] Address of stack temporary is returned https://github.com/dlang/dmd/pull/11701