DMD 1.001 release is broken
Walter Bright
newshound at digitalmars.com
Thu Jan 25 23:16:43 PST 2007
Frits van Bommel wrote:
> Here's one that fails (tested on DMD v1.00, v1.002):
>
> -----
> import std.stdio;
>
> struct Data
> {
> int x, y;
>
> /// To make size > 8 so NRVO is used.
> /// Program runs correctly with this line commented out:
> byte filler;
> }
>
> Data frob(inout Data d)
> {
> Data ret;
> ret.y = d.x - d.y;
> ret.x = d.x + d.y;
> return ret;
> }
>
> void main() {
> Data d; d.x = 1; d.y = 2;
> d = frob(d);
> writefln(d.x);
> writefln(d.y);
> assert(d.x == 3 && d.y == -1);
> }
> -----
>
> The problem here is return value/parameter aliasing. It initializes the
> return value before even looking at the parameter...
I believe this fails with C++, too. But I don't think there's any
solution to it but completely disable NRVO. There's no reasonable way
for the compiler to detect that the d's are aliased. But NRVO is too
valuable an optimization. So instead I'll argue that this is akin to:
i = i++;
i.e. it's an order-of-evaluation issue that should be avoided.
NRVO aliasing can be avoided by using a temporary:
Data ret2 = ret;
return ret2;
instead of:
return ret;
Passing d by value instead of by ref will do the same thing. I assume
that the reason inout is used here is to pass by reference to gain
efficiency. Disabling NRVO will lose more than every bit of efficiency
gained by passing by reference - so you might as well not pass it by
reference, but by value. (NRVO eliminates two copies of the struct, not
one. Replacing inout with in adds one copy. So NRVO is still one copy
ahead <g>.)
More information about the Digitalmars-d-announce
mailing list