Bug 21586 – Struct dtor is called twice if struct is created inside ternary operator

Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-01-26T22:27:45Z
Last change time
2021-02-13T12:29:59Z
Keywords
pull
Assigned to
No Owner
Creator
Temtaime

Comments

Comment #0 by temtaime — 2021-01-26T22:27:45Z
import std.stdio; struct S { this(int arg) { a = arg; writeln(`this`); } ~this() { writeln(`~this `, a); } int a; } void main() { auto s = true ? S(1) : S(0); } Outputs: this ~this 1 ~this 1 Should: this ~this 1
Comment #1 by moonlightsentinel — 2021-01-26T23:38:09Z
Modified: extern (C) int printf(scope const char*, ...); struct S { this(int arg) { a = arg; printf("this(%d), this = %p\n", a, &this); } ~this() { printf("~this(%d), this = %p\n", a, &this); } int a; } void main() { auto s = true ? S(1) : S(0); printf("main\n"); } ---- this(1), this = 0x7fff3b745b88 ~this(1), this = 0x7fff3b745b88 main ~this(1), this = 0x7fff3b745b98 --- So there's only one dtor call for the temporary created inside of the ternary operator and another call for the variable s at the end of main.
Comment #2 by razvan.nitu1305 — 2021-01-27T09:33:11Z
(In reply to Temtaime from comment #0) As moonlightsentinel highlighted, the variable is destroyed only once. The code in main is roughly translated to this: void main() { S tmp; auto s = (true ? tmp = S(1) : tmp = S(0); tmp); tmp.__dtor; s.__dtor; } This is the intended behavior. Closing as invalid.
Comment #3 by japplegame — 2021-01-27T10:27:54Z
But if you add a copy constructor to the structure, no temporary copy is created. It's weird, but acceptable.
Comment #4 by boris2.9 — 2021-01-27T11:45:50Z
The temporary variable also disappears when there's a postblit. AST generated when a postblit or copy constructor is present: S s = (true) ? s = 0 , s.this(1) : (s = 0 , s.this(0)); In the original case: S s = (true) ? (S(0)).this(1) : (S(0)).this(0); Looks like a frontend bad decision, there's no reason to not generate the equivalent code to a simple assignment. For example: S s = S(1); generates: S s = s = 0 , s.this(1);
Comment #5 by dlang-bot — 2021-01-28T11:56:07Z
@BorisCarvajal created dlang/dmd pull request #12163 "Fix Issue 21586 - Struct dtor is called twice if struct is created in…" fixing this issue: - Fix Issue 21586 - Struct dtor is called twice if struct is created inside ternary operator https://github.com/dlang/dmd/pull/12163
Comment #6 by dlang-bot — 2021-01-31T09:12:51Z
dlang/dmd pull request #12163 "Fix Issue 21586 - Struct dtor is called twice if struct is created in…" was merged into stable: - 9ca0687a06db987e12581ca216445976b559fae4 by Boris Carvajal: Fix Issue 21586 - Struct dtor is called twice if struct is created inside ternary operator https://github.com/dlang/dmd/pull/12163
Comment #7 by dlang-bot — 2021-02-13T12:29:59Z
dlang/dmd pull request #12195 "Merge stable" was merged into master: - a3b4319bd1aa9a92db46bf61bcc2feb2ab668b7f by Boris Carvajal: Fix Issue 21586 - Struct dtor is called twice if struct is created inside ternary operator (#12163) https://github.com/dlang/dmd/pull/12195