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