Struct assignment, possible DMD bug?

Ali Çehreli acehreli at yahoo.com
Sat Sep 29 20:32:45 PDT 2012


On 09/29/2012 08:13 PM, ixid wrote:
 > On Sunday, 30 September 2012 at 00:24:34 UTC, Ali Çehreli wrote:
 >> 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
 >
 > This would still seem to be a very poor behaviour worth fixing.

I agree. Would you please create a bug report:

   http://d.puremagic.com/issues/

 > What is
 > the compiler generating instead of the constructor example you gave?

I haven't read the generated assembly output but I am pretty sure that 
the compiler is generating the three expressions of the user-defined 
constructor "out in the open":

   s.a = 4;
   s.b = s.a;   // oops
   s.c = 6;

Ali



More information about the Digitalmars-d-learn mailing list