Bug 14364 – Spec is incorrect for opAssign operators.

Status
REOPENED
Severity
normal
Priority
P3
Component
dlang.org
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-03-28T16:59:38Z
Last change time
2024-12-15T15:22:53Z
Keywords
wrong-code
Assigned to
No Owner
Creator
Shammah Chancellor
Moved to GitHub: dlang.org#4040 →

Comments

Comment #0 by shammah.chancellor — 2015-03-28T16:59:38Z
``` > rdmd test0167.d [email protected](9): Assertion failure ``` ```test0167.d //T compiles:yes //T has-passed:yes //T retval:53 // Tests TernaryOperator int main() { int ret = 5; ret += ((ret++ == 5) ? (ret += 3) : (ret -= 11)) + ret; assert(ret == 23); ret += ((ret-- == 22) ? (ret += 5) : (ret -= 7)) + ret; assert(ret == 53); return ret; } ```
Comment #1 by ag0aep6g — 2015-03-28T18:25:38Z
(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
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dlang.org/issues/4040 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB