Bug 21868 – DIP1000 doesn't catch pointer to struct temporary

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-04-27T09:34:21Z
Last change time
2021-07-23T13:39:00Z
Keywords
accepts-invalid, pull, safe
Assigned to
No Owner
Creator
moonlightsentinel
See also
https://issues.dlang.org/show_bug.cgi?id=22040, https://issues.dlang.org/show_bug.cgi?id=22108

Comments

Comment #0 by moonlightsentinel — 2021-04-27T09:34:21Z
Reduced example from TempCString in Phobos: ======================================================================= char* foo(string s) @safe { // Previously used via `alias this` char* p = tempCString(s).ptr; // Also works TempCStringBuffer res; p = res.ptr; return p; } TempCStringBuffer tempCString(scope string str) @safe; struct TempCStringBuffer { char* ptr() return scope @safe { return &_buff[0]; } private: char* _ptr; // <= Required char[256] _buff; } ======================================================================= Note that DMD reports the correct error when the unused `_ptr` is absent.
Comment #1 by dkorpel — 2021-06-03T18:46:15Z
Here's it reduced some more: ``` struct S { int buf; int* ptr; // <= required } int* getPtr(ref return scope S this_) { return &this_.buf; } ``` Since getPtr does not return by `ref`, the `return scope` applies to the members of `S` and not the `ref this_` itself. The compiler checks whether `&this_.buf;` is escaped by value. In `visit(AddrExp e)` of escape.d, it reduces this to checking whether `this_.x` escapes by ref, which reduces to checking whether `this_` escapes by ref. Then it looks at the parameter's storage classes, and sees `return`, so it allows it. This is wrong, the `return` does not apply to `&this_.x`, only to `this_.buf`; Without the `buf` member, S has no pointers, so the `return scope` attribute is meaningless, so it is stripped away at some earlier stage. This way the compiler can't mistake it for a `ref return`, so it raises an error. I'm still trying to grasp the incredibly difficult logic in escape.d so I'm not sure how to fix this yet.
Comment #2 by dkorpel — 2021-06-03T18:48:42Z
> This is wrong, the `return` does not apply to `&this_.x`, only to `this_.buf`; I should be careful when renaming variables :) Corrections: * reduces this to checking whether `this_.buf` escapes by ref * This is wrong, the `return` does not apply to `&this_.buf`, only to `this_.ptr`;
Comment #3 by dlang-bot — 2021-06-10T14:58:30Z
@dkorpel created dlang/dmd pull request #12665 "Fix issue 21868 - conflation of return-ref and return-scope" fixing this issue: - fix issue 21868 - conflation of return-ref and return-scope https://github.com/dlang/dmd/pull/12665
Comment #4 by dkorpel — 2021-06-10T19:22:40Z
*** Issue 18792 has been marked as a duplicate of this issue. ***
Comment #5 by bugzilla — 2021-07-06T07:32:46Z
Minimized test case: ref int test(ref scope return int* p) { return *p; }
Comment #6 by dlang-bot — 2021-07-06T08:02:19Z
@WalterBright created dlang/dmd pull request #12817 "fix Issue 21868 - DIP1000 doesn't catch pointer to struct temporary" fixing this issue: - fix Issue 21868 - DIP1000 doesn't catch pointer to struct temporary https://github.com/dlang/dmd/pull/12817
Comment #7 by bugzilla — 2021-07-07T01:44:55Z
(In reply to Walter Bright from comment #5) > Minimized test case: > > ref int test(ref scope return int* p) > { > return *p; > } This is a separate bug, so moved to: https://issues.dlang.org/show_bug.cgi?id=22108
Comment #8 by dlang-bot — 2021-07-07T10:31:25Z
@WalterBright created dlang/dmd pull request #12829 "fix Issue 21868 - DIP1000 does not catch pointer to struct temporary" fixing this issue: - fix Issue 21868 - DIP1000 does not catch pointer to struct temporary https://github.com/dlang/dmd/pull/12829
Comment #9 by dlang-bot — 2021-07-23T13:39:00Z
dlang/dmd pull request #12829 "fix Issue 21868 - DIP1000 does not catch pointer to struct temporary" was merged into master: - f05f600c66edb966fa63d54653f3c3d280cfda8e by Walter Bright: fix Issue 21868 - DIP1000 does not catch pointer to struct temporary https://github.com/dlang/dmd/pull/12829