www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Evaluation order of "+="

reply Johan Engelen <j j.nl> writes:
LDC recently changed the evaluation order of "+=" (I think 
unintentionally, some other eval order problems were fixed). Now, 
it is different from DMD.
I am going to argue that I think DMD's order is more useful in 
the context of fibers, and would like your opinion.

Consider this code:
```
int sum;

int return1_add9tosum() {
     sum += 9;
     return 1;
}

void main() {
     sum = 0;
     sum += return1_add9tosum();

     import std.stdio;
     writeln(sum);
}
```
DMD 2.071 prints "10".
LDC master prints "1". (LDC 1.0.0 prints "10")

I find the spec [1] to be unclear on this point, so which one is 
correct?

The bug was caught by code involving fibers. Instead of 
`return1_add9tosum`, a function `return1_yieldsFiber` is called, 
and multiple fibers write to `sum`. In that case, upon completing 
the "+=", an older version of `sum` is used to calculate the 
result. I think that it is best to do what DMD does, such that 
fibers can do "+=" without worrying about yields on the rhs.

[1] https://dlang.org/spec/expression.html
Jul 11 2016
next sibling parent reply Danika <d dto.com> writes:
On Monday, 11 July 2016 at 23:04:00 UTC, Johan Engelen wrote:
 LDC recently changed the evaluation order of "+=" (I think 
 unintentionally, some other eval order problems were fixed). 
 Now, it is different from DMD.
 I am going to argue that I think DMD's order is more useful in 
 the context of fibers, and would like your opinion.
I really think it is a bug, in C it prints 10. And following the flow, you changed the sum to 9 and after that added 1, so It would be 10.6
Jul 11 2016
parent reply deadalnix <deadalnix gmail.com> writes:
On Monday, 11 July 2016 at 23:31:40 UTC, Danika wrote:
 On Monday, 11 July 2016 at 23:04:00 UTC, Johan Engelen wrote:
 LDC recently changed the evaluation order of "+=" (I think 
 unintentionally, some other eval order problems were fixed). 
 Now, it is different from DMD.
 I am going to argue that I think DMD's order is more useful in 
 the context of fibers, and would like your opinion.
I really think it is a bug, in C it prints 10. And following the flow, you changed the sum to 9 and after that added 1, so It would be 10.6
In C, it is UB.
Jul 11 2016
parent reply Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Tuesday, 12 July 2016 at 00:16:58 UTC, deadalnix wrote:
 On Monday, 11 July 2016 at 23:31:40 UTC, Danika wrote:
 On Monday, 11 July 2016 at 23:04:00 UTC, Johan Engelen wrote:
 LDC recently changed the evaluation order of "+=" (I think 
 unintentionally, some other eval order problems were fixed). 
 Now, it is different from DMD.
 I am going to argue that I think DMD's order is more useful 
 in the context of fibers, and would like your opinion.
I really think it is a bug, in C it prints 10. And following the flow, you changed the sum to 9 and after that added 1, so It would be 10.6
In C, it is UB.
A function call is a sequence point in C, so it is not UB. What happens here in LDC is probably that the call is inlined and therefore losing the sequence point. That is one of the dangers of aggressive inlining. The behaviour described by op would be definitly a bug in C. For D I don't know as I don't know if the sequence point rules are as strictly defined as in C.
Jul 11 2016
next sibling parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Tuesday, 12 July 2016 at 05:46:58 UTC, Patrick Schluter wrote:
 On Tuesday, 12 July 2016 at 00:16:58 UTC, deadalnix wrote:
 On Monday, 11 July 2016 at 23:31:40 UTC, Danika wrote:
 On Monday, 11 July 2016 at 23:04:00 UTC, Johan Engelen wrote:
 LDC recently changed the evaluation order of "+=" (I think 
 unintentionally, some other eval order problems were fixed). 
 Now, it is different from DMD.
 I am going to argue that I think DMD's order is more useful 
 in the context of fibers, and would like your opinion.
I really think it is a bug, in C it prints 10. And following the flow, you changed the sum to 9 and after that added 1, so It would be 10.6
In C, it is UB.
A function call is a sequence point in C, so it is not UB.
UB happens when a variable is changed more than once between sequence points, which is not the case here.
 What happens here in LDC is probably that the call is inlined 
 and therefore losing the sequence point. That is one of the 
 dangers of aggressive inlining. The behaviour described by op 
 would be definitly a bug in C. For D I don't know as I don't 
 know if the sequence point rules are as strictly defined as in 
 C.
Jul 11 2016
prev sibling parent Johan Engelen <j j.nl> writes:
On Tuesday, 12 July 2016 at 05:46:58 UTC, Patrick Schluter wrote:
 
 What happens here in LDC is probably that the call is inlined 
 and therefore losing the sequence point. That is one of the 
 dangers of aggressive inlining.
Going off-topic but briefly: all inlining in LDC happens by LLVM. With the possibility of LLVM bugs, bugs by inlining are very rare I'd think. (in this case, it happens for debug builds (so no inlining) too.)
Jul 12 2016
prev sibling next sibling parent reply deadalnix <deadalnix gmail.com> writes:
On Monday, 11 July 2016 at 23:04:00 UTC, Johan Engelen wrote:
 LDC recently changed the evaluation order of "+=" (I think 
 unintentionally, some other eval order problems were fixed). 
 Now, it is different from DMD.
 I am going to argue that I think DMD's order is more useful in 
 the context of fibers, and would like your opinion.

 Consider this code:
 ```
 int sum;

 int return1_add9tosum() {
     sum += 9;
     return 1;
 }

 void main() {
     sum = 0;
     sum += return1_add9tosum();

     import std.stdio;
     writeln(sum);
 }
 ```
 DMD 2.071 prints "10".
 LDC master prints "1". (LDC 1.0.0 prints "10")

 I find the spec [1] to be unclear on this point, so which one 
 is correct?

 The bug was caught by code involving fibers. Instead of 
 `return1_add9tosum`, a function `return1_yieldsFiber` is 
 called, and multiple fibers write to `sum`. In that case, upon 
 completing the "+=", an older version of `sum` is used to 
 calculate the result. I think that it is best to do what DMD 
 does, such that fibers can do "+=" without worrying about 
 yields on the rhs.

 [1] https://dlang.org/spec/expression.html
There was a very lenghty discussion about this in the past. DMD is correct on that one. The semantic is such as : int plusEqual(ref int a, int b) { a = a + b; return a; }
Jul 11 2016
next sibling parent reply Johan Engelen <j j.nl> writes:
On Tuesday, 12 July 2016 at 02:27:04 UTC, deadalnix wrote:
 There was a very lenghty discussion about this in the past. DMD 
 is correct on that one. The semantic is such as :

 int plusEqual(ref int a, int b) {
   a = a + b;
   return a;
 }
Thanks. Could this be added to the spec please?
Jul 12 2016
parent reply Johan Engelen <j j.nl> writes:
On Tuesday, 12 July 2016 at 07:57:37 UTC, Johan Engelen wrote:
 On Tuesday, 12 July 2016 at 02:27:04 UTC, deadalnix wrote:
 There was a very lenghty discussion about this in the past. 
 DMD is correct on that one. The semantic is such as :

 int plusEqual(ref int a, int b) {
   a = a + b;
   return a;
 }
Thanks. Could this be added to the spec please?
https://github.com/dlang/dlang.org/pull/1429
Jul 12 2016
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/12/16 5:15 AM, Johan Engelen wrote:
 On Tuesday, 12 July 2016 at 07:57:37 UTC, Johan Engelen wrote:
 On Tuesday, 12 July 2016 at 02:27:04 UTC, deadalnix wrote:
 There was a very lenghty discussion about this in the past. DMD is
 correct on that one. The semantic is such as :

 int plusEqual(ref int a, int b) {
   a = a + b;
   return a;
 }
Thanks. Could this be added to the spec please?
https://github.com/dlang/dlang.org/pull/1429
Great, thanks. I added a comment to that, which in turn caused a bug report. What does the community think? -- Andrei
Jul 12 2016
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12.07.2016 19:20, Andrei Alexandrescu wrote:
 On 7/12/16 5:15 AM, Johan Engelen wrote:
 On Tuesday, 12 July 2016 at 07:57:37 UTC, Johan Engelen wrote:
 On Tuesday, 12 July 2016 at 02:27:04 UTC, deadalnix wrote:
 There was a very lenghty discussion about this in the past. DMD is
 correct on that one. The semantic is such as :

 int plusEqual(ref int a, int b) {
   a = a + b;
   return a;
 }
Thanks. Could this be added to the spec please?
https://github.com/dlang/dlang.org/pull/1429
Great, thanks. I added a comment to that, which in turn caused a bug report. What does the community think? -- Andrei
int main() { int sum=0; int return1_add9tosum() { sum += 9; return 1; } sum += return1_add9tosum(); return sum; } pragma(msg, main()); // 1
Jul 12 2016
parent Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 13 July 2016 at 07:20, Timon Gehr via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 12.07.2016 19:20, Andrei Alexandrescu wrote:
 On 7/12/16 5:15 AM, Johan Engelen wrote:
 On Tuesday, 12 July 2016 at 07:57:37 UTC, Johan Engelen wrote:
 On Tuesday, 12 July 2016 at 02:27:04 UTC, deadalnix wrote:
 There was a very lenghty discussion about this in the past. DMD is
 correct on that one. The semantic is such as :

 int plusEqual(ref int a, int b) {
   a = a + b;
   return a;
 }
Thanks. Could this be added to the spec please?
https://github.com/dlang/dlang.org/pull/1429
Great, thanks. I added a comment to that, which in turn caused a bug report. What does the community think? -- Andrei
int main() { int sum=0; int return1_add9tosum() { sum += 9; return 1; } sum += return1_add9tosum(); return sum; } pragma(msg, main()); // 1
I see you've found more cases where runtime and ctfe do things differently. ;-)
Jul 12 2016
prev sibling parent reply kink <noone nowhere.com> writes:
On Tuesday, 12 July 2016 at 02:27:04 UTC, deadalnix wrote:
 There was a very lenghty discussion about this in the past. DMD 
 is correct on that one.
Great, so after that very lengthy discussion, why did nobody add a frigging test?! Argh.
Jul 12 2016
parent reply deadalnix <deadalnix gmail.com> writes:
On Tuesday, 12 July 2016 at 16:17:18 UTC, kink wrote:
 On Tuesday, 12 July 2016 at 02:27:04 UTC, deadalnix wrote:
 There was a very lenghty discussion about this in the past. 
 DMD is correct on that one.
Great, so after that very lengthy discussion, why did nobody add a frigging test?! Argh.
For what it's worth, the test is in SDC's test suite.
Jul 12 2016
parent Johan Engelen <j j.nl> writes:
On Tuesday, 12 July 2016 at 18:44:44 UTC, deadalnix wrote:
 On Tuesday, 12 July 2016 at 16:17:18 UTC, kink wrote:
 On Tuesday, 12 July 2016 at 02:27:04 UTC, deadalnix wrote:
 There was a very lenghty discussion about this in the past. 
 DMD is correct on that one.
Great, so after that very lengthy discussion, why did nobody add a frigging test?! Argh.
For what it's worth, the test is in SDC's test suite.
Thanks for letting us know. I'll try to copy them.
Jul 12 2016
prev sibling parent Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 12 July 2016 at 01:04, Johan Engelen via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 LDC recently changed the evaluation order of "+=" (I think unintentionally,
 some other eval order problems were fixed). Now, it is different from DMD.
 I am going to argue that I think DMD's order is more useful in the context
 of fibers, and would like your opinion.
When I said stabilize references, I meant references, not *all* side effects. :-) Assuming that the last conversations I had with kinke are related to this.
Jul 12 2016