Struct assignment, possible DMD bug?

Ali Çehreli acehreli at yahoo.com
Sat Sep 29 17:25:01 PDT 2012


On 09/29/2012 04:02 PM, Timon Gehr wrote:
 > On 09/30/2012 12:51 AM, Ali Çehreli wrote:
 >> On 09/29/2012 11:16 AM, Timon Gehr wrote:
 >> > On 09/29/2012 06:26 PM, Maxim Fomin wrote:
 >>
 >> >>> S s = S(1,2,3);
 >> >>> s = S(4, s.a, 6);
 >> >>>
 >> >>> assert(a == [4,1,6]);
 >> >>> assert(s == S(4,4,6));
 >> >>> }
 >> >>>
 >> >>> Setting the struct writes s.a before evaluating it while the reverse
 >> >>> is true of the array assignment. Using DMD 2.0.60. GDC does what I'd
 >> >>> expect and gives both as 4,1,6.
 >> >>
 >> >> I think this is notorious "i = ++i + ++i".
 >> >
 >> > There is only one mutating sub-expression.
 >>
 >> But that mutation is happening to an object that is also being read
 >> inside the same expression.
 >>
 >> This is one of the definitions of undefined behavior, not a compiler 
bug.
 >>
 >> >> Statement s = S(4, s.a, 6) writes to s object and simultaneously 
reads
 >> >> it.
 >> >> http://dlang.org/expression.html states that assign expression is
 >> >> evaluated in implementation defined-manner and it is an error to
 >> depend
 >> >> on things like this.
 >> >
 >> > No evaluation order of the assignment expression can possibly lead to
 >> > this result. This seems to be a DMD bug.
 >>
 >> The compiler seems to be applying an optimization, which it is entitled
 >> to as long as the language definition is not violated.
 >>
 >
 > Technically there is no language definition to violate.
 >
 >> If we are using the same object both to read and write in the same
 >> expression, then we should expect the consequences.
 >>
 >
 > No. Why?

I am confused. Of course single mutation and many reads should be fine.

 >
 >> Disclaimer: I assume that D's rules are the same as C and C++ here.
 >>
 >
 > C and C++ do not have struct literals and if I am not mistaken,
 > constructor invocation is a sequence point.

Yes. And in this case it is the compiler-generated constructor. The OP's 
problem goes away if there is a user-provided constructor:

     struct S {
         int a, b, c;

         this(int a, int b, int c)
         {
             this.a = a;
             this.b = b;
             this.c = c;
         }
     }

Now it is as expected:

     assert(s == S(4,1,6));

 > Besides, this does not make any sense, what is the relevant part of the
 > standard?
 >
 > int c = 0;
 > c = c+1; // c is both read and written to in the same expression

Silly me! :p

Ali



More information about the Digitalmars-d-learn mailing list