Bug 17174 – can take address of member of struct parameter in @safe code
Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2017-02-10T17:48:09Z
Last change time
2018-03-04T04:14:31Z
Keywords
accepts-invalid, safe
Assigned to
No Owner
Creator
Alex
Comments
Comment #0 by sascha.orlov — 2017-02-10T17:48:09Z
As discussed here:
https://forum.dlang.org/post/[email protected]
tested with 2.073.0 on a mac.
// Code starts here
void main()
{
initStruct iSb;
iSb.var = 3;
A b = A(iSb);
assert(*b.myVar == 3); // this works
iSb.var = 4;
assert(*b.myVar == 4); // as expected
b = A(initStruct(5)); // how does
assert(*b.myVar == 5); // this work?
}
struct A
{
@disable this();
size_t* myVar;
this()(auto ref initStruct iS) @nogc
{
import core.stdc.stdio;
__traits(isRef, iS) ? printf("ref case\n") : printf("value case");
myVar = &iS.var;
/* // This treatment is not needed?
if(__traits(isRef, iS))
{
myVar = &iS.var;
}
else
{
myVar = new size_t(iS.var);
}
*/
}
}
struct initStruct
{
size_t var;
}
// Code ends here
In case of initializing an A-instance with an rvalue, it should be a compile-time error to get a pointer to the parameter.
Comment #1 by ag0aep6g — 2017-02-10T19:46:55Z
Taking the address of a value parameter is allowed in @system code. Your constructor is not marked as @safe, so it's @system and you're allowed to do that.
However, if you add @safe, the code still compiles. That's a bug. It doesn't seem to be related to `auto ref`, though. Rather, the compiler gets confused by the struct. I'm changing the summary of this issue to be about this.
----
/* Shouldn't compile: */
void f(initStruct iS) @safe
{
auto p = &iS.var; /* Should trigger the same error as below. */
}
struct initStruct
{
size_t var;
}
/* Doesn't compile, as it should be: */
void g(size_t var) @safe
{
auto p = &var; /* "Error: cannot take address of parameter" */
}
----
Comment #2 by sascha.orlov — 2017-02-11T00:39:28Z
@ag0aep6g
Ok... my complaint was about your first two lines. Didn't take this into account.
But even then, it seems strange to me to be able to take a pointer to a value parameter, in any case...
With other words:
The treatment I was wondering about (allocating memory) is needed, and I should have known this, because the constructor is not marked as @safe.
Comment #3 by bugzilla — 2018-03-04T04:14:31Z
With -dip1000, both functions pass, because taking the address is allowed, you just cannot escape the address.