www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - postincrement behaviour (differences between dmd and gdc)

reply Iain Buclaw <ibuclaw ubuntu.com> writes:
This was partially discussed before some time ago -
http://www.digitalmars.com/d/archives/digitalmars/D/postincrement_behaviour_differences_between_dmd_and_gdc_47334.html


The following statement has different behaviours in dmd and gdc.

int x;
x = x++;


Where the backend for DMD interprets it as:

  tmp = x;
  x++;
  x = tmp;

And the backend for GDC interprets it as:

  x = x;
  x++;


Skipping all undefined behaviour/which one is correct talk, an alternative
suggestion would be to treat such nonsensical code as an error - like "Cannot
modify the value of a variable twice in the same expression." - as this kind
of thing I would expect to be almost always a bug.


Regards
Apr 20 2011
next sibling parent spir <denis.spir gmail.com> writes:
On 04/20/2011 11:33 AM, Iain Buclaw wrote:
 This was partially discussed before some time ago -
 http://www.digitalmars.com/d/archives/digitalmars/D/postincrement_behaviour_differences_between_dmd_and_gdc_47334.html


 The following statement has different behaviours in dmd and gdc.

 int x;
 x = x++;


 Where the backend for DMD interprets it as:

    tmp = x;
    x++;
    x = tmp;

 And the backend for GDC interprets it as:

    x = x;
    x++;


 Skipping all undefined behaviour/which one is correct talk, an alternative
 suggestion would be to treat such nonsensical code as an error - like "Cannot
 modify the value of a variable twice in the same expression." - as this kind
 of thing I would expect to be almost always a bug.
Very probable. Also, the dmd interpretation makes even less sense for me. At least, gdc performs what the probable intent is. But an error is certainly far better. denis -- _________________ vita es estrany spir.wikidot.com
Apr 20 2011
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
 This was partially discussed before some time ago -
 http://www.digitalmars.com/d/archives/digitalmars/D/postincrement_behaviour
 _differences_between_dmd_and_gdc_47334.html
 
 
 The following statement has different behaviours in dmd and gdc.
 
 int x;
 x = x++;
 
 
 Where the backend for DMD interprets it as:
 
   tmp = x;
   x++;
   x = tmp;
 
 And the backend for GDC interprets it as:
 
   x = x;
   x++;
 
 
 Skipping all undefined behaviour/which one is correct talk, an alternative
 suggestion would be to treat such nonsensical code as an error - like
 "Cannot modify the value of a variable twice in the same expression." - as
 this kind of thing I would expect to be almost always a bug.
Actually, I would have expected postincrement and preincrement to be identical in this case. It was my understanding that the entire expression to the right of the assignment operator was evaluated before the assignment was made, but I guess I could see how that could be open to interpretation with regards to the postincrement operator. Regardless, I think that making this sort of case an error would make good sense. - Jonathan M Davis
Apr 20 2011
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 20.04.2011 13:53, Jonathan M Davis wrote:
 This was partially discussed before some time ago -
 http://www.digitalmars.com/d/archives/digitalmars/D/postincrement_behaviour
 _differences_between_dmd_and_gdc_47334.html


 The following statement has different behaviours in dmd and gdc.

 int x;
 x = x++;


 Where the backend for DMD interprets it as:

    tmp = x;
    x++;
    x = tmp;

 And the backend for GDC interprets it as:

    x = x;
    x++;


 Skipping all undefined behaviour/which one is correct talk, an alternative
 suggestion would be to treat such nonsensical code as an error - like
 "Cannot modify the value of a variable twice in the same expression." - as
 this kind of thing I would expect to be almost always a bug.
Actually, I would have expected postincrement and preincrement to be identical in this case. It was my understanding that the entire expression to the right of the assignment operator was evaluated before the assignment was made, but I guess I could see how that could be open to interpretation with regards to the postincrement operator.
No, I think post-increment is done after the whole expression is evaluated, see the common C idiom: *p++ = *q++; it's always interpreted as: *p = *q; p++,q++; // or q++,p++;
 Regardless, I think that making this sort of case an error would make good
 sense.
Agreed, using variable as an L-value and post-incrementing it in the same expression is plain mistake.
 - Jonathan M Davis
-- Dmitry Olshansky
Apr 20 2011
parent reply Mafi <mafi example.org> writes:
Am 20.04.2011 12:01, schrieb Dmitry Olshansky:
 On 20.04.2011 13:53, Jonathan M Davis wrote:
 This was partially discussed before some time ago -
 http://www.digitalmars.com/d/archives/digitalmars/D/postincrement_behaviour

 _differences_between_dmd_and_gdc_47334.html


 The following statement has different behaviours in dmd and gdc.

 int x;
 x = x++;


 Where the backend for DMD interprets it as:

 tmp = x;
 x++;
 x = tmp;

 And the backend for GDC interprets it as:

 x = x;
 x++;


 Skipping all undefined behaviour/which one is correct talk, an
 alternative
 suggestion would be to treat such nonsensical code as an error - like
 "Cannot modify the value of a variable twice in the same expression."
 - as
 this kind of thing I would expect to be almost always a bug.
Actually, I would have expected postincrement and preincrement to be identical in this case. It was my understanding that the entire expression to the right of the assignment operator was evaluated before the assignment was made, but I guess I could see how that could be open to interpretation with regards to the postincrement operator.
No, I think post-increment is done after the whole expression is evaluated, see the common C idiom: *p++ = *q++; it's always interpreted as: *p = *q; p++,q++; // or q++,p++;
IMHO it should be interpreted as typeof(p) tmp_p; typeof(q) tmp_q; *((tmp_p = p), ++p, tmp_p) = *((tmp_q = q), q++, tmp_q); In this case the overall semantics are identical but your expandation looks like gdc's and mine like dmd's. Therefore I think dmd's is more correct although less useful. Generally I think it should just be an error to assign twice in the same expression. Mafi
Apr 20 2011
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 20.04.2011 14:16, Mafi wrote:
 Am 20.04.2011 12:01, schrieb Dmitry Olshansky:
 On 20.04.2011 13:53, Jonathan M Davis wrote:
 This was partially discussed before some time ago -
 http://www.digitalmars.com/d/archives/digitalmars/D/postincrement_behaviour 


 _differences_between_dmd_and_gdc_47334.html


 The following statement has different behaviours in dmd and gdc.

 int x;
 x = x++;


 Where the backend for DMD interprets it as:

 tmp = x;
 x++;
 x = tmp;

 And the backend for GDC interprets it as:

 x = x;
 x++;


 Skipping all undefined behaviour/which one is correct talk, an
 alternative
 suggestion would be to treat such nonsensical code as an error - like
 "Cannot modify the value of a variable twice in the same expression."
 - as
 this kind of thing I would expect to be almost always a bug.
Actually, I would have expected postincrement and preincrement to be identical in this case. It was my understanding that the entire expression to the right of the assignment operator was evaluated before the assignment was made, but I guess I could see how that could be open to interpretation with regards to the postincrement operator.
No, I think post-increment is done after the whole expression is evaluated, see the common C idiom: *p++ = *q++; it's always interpreted as: *p = *q; p++,q++; // or q++,p++;
IMHO it should be interpreted as typeof(p) tmp_p; typeof(q) tmp_q; *((tmp_p = p), ++p, tmp_p) = *((tmp_q = q), q++, tmp_q);
Yes, I got the idea about this interpretation right after posting (BTW it should '++q' vs 'q++') ... In the end should be expanded to autoincrementing address mode, in case of x86 the equivalent would be "string" ops.
 In this case the overall semantics are identical but your expandation 
 looks like gdc's and mine like dmd's. Therefore I think dmd's is more 
 correct although less useful.

 Generally I think it should just be an error to assign twice in the 
 same expression.
Why not ? I kind of liked this one: a = b = 0;
 Mafi
-- Dmitry Olshansky
Apr 20 2011
parent Mafi <mafi example.org> writes:
Am 20.04.2011 13:36, schrieb Dmitry Olshansky:
 In this case the overall semantics are identical but your expandation
 looks like gdc's and mine like dmd's. Therefore I think dmd's is more
 correct although less useful.

 Generally I think it should just be an error to assign twice in the
 same expression.
Why not ? I kind of liked this one: a = b = 0;
I also like it and I meant assign the same variable twice in one statement. Mafi
Apr 20 2011
prev sibling next sibling parent Kagamin <spam here.lot> writes:
Iain Buclaw Wrote:

 And the backend for GDC interprets it as:
 
   x = x;
   x++;
As I understand, you pass the expression to the backend as is, the backend interprets it in the C way, and you get surprising result on discrepancy between C and D semantics?
Apr 20 2011
prev sibling next sibling parent Kagamin <spam here.lot> writes:
Iain Buclaw Wrote:

 suggestion would be to treat such nonsensical code as an error - like "Cannot
 modify the value of a variable twice in the same expression." - as this kind
 of thing I would expect to be almost always a bug.
What about this? x=(*y)++;
Apr 20 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Iain Buclaw:

 Skipping all undefined behaviour/which one is correct talk, an alternative
 suggestion would be to treat such nonsensical code as an error - like "Cannot
 modify the value of a variable twice in the same expression." - as this kind
 of thing I would expect to be almost always a bug.
Thank you for raising this topic again. In my opinion in a modern language, even a system language, this kind of undefined (and different across different compilers) is _not_ acceptable. Another source of some undefined behaviours are function calls. Two possible solutions for D: - Turn such situations that lead to undefined behaviour into syntax errors; - Do define and standardize such behaviours, even if this may cause tiny performance losses on some CPUs. Bye, bearophile
Apr 20 2011
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 20.04.2011 12:58, schrieb bearophile:
 Iain Buclaw:

 Skipping all undefined behaviour/which one is correct talk, an alternative
 suggestion would be to treat such nonsensical code as an error - like "Cannot
 modify the value of a variable twice in the same expression." - as this kind
 of thing I would expect to be almost always a bug.
Thank you for raising this topic again. In my opinion in a modern language, even a system language, this kind of undefined (and different across different compilers) is _not_ acceptable. Another source of some undefined behaviours are function calls.
I think the DMD way is conformant with the D2 specification, see http://digitalmars.com/d/2.0/operatoroverloading.html "e++ [is rewritten as] (auto t=e, ++e, t)", so x=x++; shouldn't change the value of x. (Yeah, this is for overloading, but the operator should behave the same for simple types). Of course x = x++; still makes no sense and should probably cause a warning or an error.
 Two possible solutions for D:
 - Turn such situations that lead to undefined behaviour into syntax errors;
 - Do define and standardize such behaviours, even if this may cause tiny
performance losses on some CPUs.

 Bye,
 bearophile
Cheers, - Daniel
Apr 20 2011
parent reply KennyTM~ <kennytm gmail.com> writes:
On Apr 20, 11 19:28, Daniel Gibson wrote:
 I think the DMD way is conformant with the D2 specification, see
 http://digitalmars.com/d/2.0/operatoroverloading.html
 "e++ [is rewritten as] (auto t=e, ++e, t)", so x=x++; shouldn't change
 the value of x. (Yeah, this is for overloading, but the operator should
 behave the same for simple types).

 Of course x = x++; still makes no sense and should probably cause a
 warning or an error.
The D2 specification simply said "x = x++" is illegal. I don't think operatoroverloading.html applies to built-in types. http://www.digitalmars.com/d/2.0/expression.html "It is an error to depend on order of evaluation when it is not specified. For example, the following are illegal: i = i++; c = a + (a = b); func(++i, ++i); 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." and yes DMD should raise a compiler error.
Apr 20 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 04/20/2011 07:12 AM, KennyTM~ wrote:
 On Apr 20, 11 19:28, Daniel Gibson wrote:
 I think the DMD way is conformant with the D2 specification, see
 http://digitalmars.com/d/2.0/operatoroverloading.html
 "e++ [is rewritten as] (auto t=e, ++e, t)", so x=x++; shouldn't change
 the value of x. (Yeah, this is for overloading, but the operator should
 behave the same for simple types).

 Of course x = x++; still makes no sense and should probably cause a
 warning or an error.
The D2 specification simply said "x = x++" is illegal. I don't think operatoroverloading.html applies to built-in types. http://www.digitalmars.com/d/2.0/expression.html "It is an error to depend on order of evaluation when it is not specified. For example, the following are illegal: i = i++; c = a + (a = b); func(++i, ++i); 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." and yes DMD should raise a compiler error.
That's not possible in the presence of aliasing, so it would be an error of limited usefulness and one that gives a false sense of security. The right way is to define the semantics of x = x++ the same as the semantics of x = postIncrement(x) where T postincrement(T)(ref T a) { auto r = a; ++a; return r; } In that case x = x++ would simply reassign x to itself. Andrei
Apr 20 2011
parent maarten van damme <maartenvd1994 gmail.com> writes:
This is something I also came across in java.
When you do that in java it follows the dmd behaviour.

Simply my 2 cents :p
Apr 21 2011