Order of evaluation - aka hidden undefined behaviours.

Timon Gehr timon.gehr at gmx.ch
Tue Sep 25 16:10:00 PDT 2012


On 09/26/2012 12:58 AM, Iain Buclaw wrote:
> Pop quiz!
>
> Analyse this code:
> ----
> string abc;
>
> float[] A()
> {
>      abc ~= "A";
>      return [];
> }
>
> float[] B()
> {
>      abc ~= "B";
>      return [];
> }
>
> float[] C()
> {
>      abc ~= "C";
>      return [];
> }
>
> void main()
> {
>      A()[] = B()[] + C()[];
>      assert(abc == "???");
> }
> ----
>
> Without cheating, I invite people to have a good guess what 'abc' is
> equal to, but just to narrow it down.
>
> 1)  It isn't "ABC".
> 2)  On x86/x86_64, it isn't "ACB".
> 3)  On everything else, it's the reverse of what you'd expect on
> x86/x86_64.
>
> The problem here is that the array operation A[] = B[] + C[] gets
> transformed into an extern(C) call.  And because there's no strict rules
> in place over the order of which it's parameters are evaluated, it could
> go either way (LTR, or RTL).
>
> Serious note: This test is bogus as this and similar other failing tests
> on non-x86 platforms are not at all obvious to the users who get issues.
> So what are we to do about it?
>
>
> Regards,
> Iain.

As far as my understanding of the issue goes, the correct answer is
"ABC", and compilers that do not produce "ABC" are buggy.

The solution is to transform the code to code that evaluates the
arguments to the extern(C) call in the correct order and eg. stores
them in temporaries before passing them on.





More information about the Digitalmars-d mailing list