D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 7516 - Postblit not called for structs returned from a ternary operator
Summary: Postblit not called for structs returned from a ternary operator
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 major
Assignee: No Owner
URL:
Keywords: pull, wrong-code
: 7130 (view as issue list)
Depends on:
Blocks:
 
Reported: 2012-02-16 03:28 UTC by Sönke Ludwig
Modified: 2017-08-02 08:07 UTC (History)
3 users (show)

See Also:


Attachments
Reproduction case (919 bytes, application/octet-stream)
2012-02-16 03:28 UTC, Sönke Ludwig
Details

Note You need to log in before you can comment on or make changes to this issue.
Description Sönke Ludwig 2012-02-16 03:28:54 UTC
Created attachment 1075 [details]
Reproduction case

Attached is a small example with a pseudo RefCount struct.
Running with the ternary operator enabled "dmd -version=BUG -run" yields:

---
1st pass
POS1: 613D80 -100
CREATE 18FDFC 1
DESTROY 18FDE0 -100 IN
DESTROY 18FDE0 -100 OUT
POS2: 613D80 1
DESTROY 18FE0C 1 IN          <- destroys the object although the static
variable
DESTROY 18FE0C -100 OUT         in func() should still hold a reference

2nd pass
POS1: 613D80 0               <- the static variable now references a destroyed
POS2: 613D80 0                  object
DESTROY 18FE0C 0 IN
DESTROY 18FE0C -1 OUT
---

The line "return cnt.cnt ? cnt : cnt;" fails to call the struct's postblit and
causes the returned object to get destroyed.

running with "dmd -run" yields the expected output:

---
1st pass
POS1: 533D80 -100
CREATE 18FDFC 1
DESTROY 18FDE0 -100 IN
DESTROY 18FDE0 -100 OUT
POS2: 533D80 1
COPY 18FE0C 2                 <- correctly copied on return
DESTROY 18FE0C 2 IN
DESTROY 18FE0C 1 OUT

2nd pass
POS1: 533D80 1
POS2: 533D80 1
COPY 18FE0C 2
DESTROY 18FE0C 2 IN
DESTROY 18FE0C 1 OUT          <- the static reference is still there
---

"return cnt;" will correctly call the postblit constructor.

Occurs for DMD 2.058 (2.57 fails for both cases)
Comment 1 SomeDude 2012-04-20 00:43:05 UTC
See also issue 7506
Comment 2 SomeDude 2012-04-20 01:01:16 UTC
See also issue 7530
Comment 3 Kenji Hara 2012-05-10 22:56:59 UTC
Test cases:

void main()
{
    static struct S
    {
        int val;

        this(int n) { val = n; }
        this(this) { val *= 3; }
    }

    // cond ? lvalue : lvalue
    S foo(bool f)
    {
        auto s1 = S(1), s2 = S(2);
        return f ? s1 : s2;
    }
    auto s1 = foo(true);
    assert(s1.val == 3);
    auto s2 = foo(false);
    assert(s2.val == 6);

    // cond ? rvalue : rvalue
    S bar(bool f)
    {
        return f ? S(1) : S(2);
    }
    auto s3 = bar(true);
    assert(s3.val == 1);
    auto s4 = bar(false);
    assert(s4.val == 2);

    // cond ? lvalue : rvalue
    S baz(bool f)
    {
        auto s1 = S(1);
        return f ? s1 : S(2);
    }
    auto s5 = baz(true);
    assert(s5.val == 3);
    auto s6 = baz(false);
    assert(s6.val == 2);
}
Comment 4 Kenji Hara 2012-05-10 23:05:16 UTC
*** Issue 7130 has been marked as a duplicate of this issue. ***
Comment 5 briancschott 2014-05-05 00:28:50 UTC
Still fails with dmd 2.065
Comment 7 github-bugzilla 2016-02-05 06:59:00 UTC
Commits pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/094b358ba1c5ecd6708ccd82660f44462cd06314
fix Issue 7516 - Postblit not called for structs returned from a ternary operator

https://github.com/D-Programming-Language/dmd/commit/1ea699106e924387269681d4b54f2802a25e24d3
Merge pull request #4805 from 9rnsr/fix7516

Issue 7516 - Postblit not called for structs returned from a ternary operator
Comment 8 github-bugzilla 2017-08-02 08:07:13 UTC
Commit pushed to dmd-cxx at https://github.com/dlang/dmd

https://github.com/dlang/dmd/commit/3f497efad06f609476b4852482f8ecb24a4d33fd
Issue 7516 - Postblit not called for structs returned from a ternary operator