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