(In reply to Shammah Chancellor from comment #0)
> int ret = 5;
> ret += ((ret++ == 5) ? (ret += 3) : (ret -= 11)) + ret;
> assert(ret == 23);
To arrive at 23 I guess sdc see these values:
5 + 6 + 3 + 9 = 23
ret += ((ret++ == 5) ? (ret += 3) : (ret -= 11)) + ret;
That is, sdc takes the value of the lhs before evaluating the rhs.
dmd arrives at 27 = 9 + 6 + 3 + 9, meaning it evaluates the rhs before taking the value of the lhs.
The spec has something to say about that[1]:
> The following binary expressions are evaluated in an implementation-defined order:
>
> AssignExpression, function arguments
>
> It is an error to depend on order of evaluation when it is not specified. For example, the following are illegal:
>
> i = i++;
So, both sdc and dmd are right and the test case is "illegal". Closing as invalid.
[1] http://dlang.org/expression.html
Comment #2 by shammah.chancellor — 2015-03-28T18:30:08Z
So should this not compile? Isn't this at least a DLang Spec problem?
Comment #3 by ag0aep6g — 2015-03-28T18:40:45Z
(In reply to Shammah Chancellor from comment #2)
> So should this not compile?
Reading that spec page further:
> If the compiler can determine that the result of an expression is illegally dependent on the order of evaluation, it can issue an error (but is not required to). The ability to detect these kinds of errors is a quality of implementation issue.
So, compilers are encouraged to reject such code, but they can also accept it and evaluate the sides of the assignment in either order.
> Isn't this at least a DLang Spec problem?
Feel free to file an enhancement request to specify one true order of evaluation for AssignExpression.
Comment #4 by ketmar — 2015-03-29T00:12:42Z
actually, compiler must warn about sequence point error. but DMD is for smarts, so it does it's best to carefully hide such errors from programmer.
Comment #5 by deadalnix — 2015-03-29T17:03:33Z
Reopening. The spec is wrong. It has been discussed many time that should have LTR semantic.
Comment #6 by k.hara.pg — 2015-03-30T15:28:47Z
(In reply to deadalnix from comment #5)
> Reopening. The spec is wrong. It has been discussed many time that should
> have LTR semantic.
Can you list the links to the discussions?
Comment #7 by deadalnix — 2015-03-30T18:25:12Z
(In reply to Kenji Hara from comment #6)
> (In reply to deadalnix from comment #5)
> > Reopening. The spec is wrong. It has been discussed many time that should
> > have LTR semantic.
>
> Can you list the links to the discussions?
So I reached to Andrei to know the exact details. It turns out this is a point where Andrei and Walter are not in agreement.
Andrei advocate for LTR all the way down (as SDC do) and Walter does seems to be inclined to specify it precisely for calls.
Anyway, as per spec, a += k is rewritten as
a = cast(typeof(a)) (a + k);
See http://dlang.org/expression.html, Assignment Operator Expressions for reference.
So I think that, even by Walter's standards, as this is not a call, this should be well defined.
Comment #8 by deadalnix — 2015-03-30T18:31:00Z
(In reply to Kenji Hara from comment #6)
> (In reply to deadalnix from comment #5)
> > Reopening. The spec is wrong. It has been discussed many time that should
> > have LTR semantic.
>
> Can you list the links to the discussions?
So I reached to Andrei to know the exact details. It turns out this is a point where Andrei and Walter are not in agreement.
Andrei advocate for LTR all the way down (as SDC do) and Walter does seems to be inclined to specify it precisely for calls.
Anyway, as per spec, a += k is rewritten as
a = cast(typeof(a)) (a + k);
See http://dlang.org/expression.html, Assignment Operator Expressions for reference.
So I think that, even by Walter's standards, as this is not a call, this should be well defined.
I opened a thread on the newgroup: http://forum.dlang.org/thread/[email protected]#post-dqkqvnkgxkxncyvyitid:40forum.dlang.org
Comment #9 by deadalnix — 2015-04-06T04:26:33Z
Update :
It turns out DMD has the intended behavior. However, the spec need to be fixed.
a += b do not decay as a = cast(typeof(a)) (a + b) but as :
((ref i, auto ref j) => i = cast(typeof(i)) (i + j))(a, b);
Comment #10 by robert.schadek — 2024-12-15T15:22:53Z