0

I ran into strange behavior in VC++2010, and I think it's a compiler bug, unless I'm missing something obvious:

class A
{
public:
    A& B(int& value)
    {
        value = 10;
        return *this;
    }
    A& C(int value)
    {
        printf("%d\r\n", value);
        return *this;
    }
    A& D(int value1, int value2)
    {
        printf("%d, %d\r\n", value1, value2);
        return *this;
    }
}

int main()
{
    A a;
    int x = 0; // get uninitialized variable warning if I don't assign x
    a.B(x).C(x).D(x, x - 1);
}

I would expect:

10
10, 9

But it actually prints:

10
10, -1

It's obviously assuming x can't be modified by any of the prior function calls and replaces "x - 1" with "-1".

Is this somehow invoking undefined behavior, and thus acting unexpectedly, or is it a compiler bug?

Bryce Wagner
  • 1,151
  • 7
  • 18
  • 2
    Yes. The evaluation order of function arguments is unspecified. The longer the expression, the more chances of reordering. – StoryTeller - Unslander Monica Dec 01 '17 at 21:05
  • So it can evaluate all the variables for all the functions in any order before it calls any of them? – Bryce Wagner Dec 01 '17 at 21:07
  • @StoryTeller the order of function arguments across the entire expression or within one function call? – Richard Hodges Dec 01 '17 at 21:07
  • @RichardHodges - *"within one function call"* depends on the standard revision you are quoting. Across the entire expression is the same as it always was IIRC. – StoryTeller - Unslander Monica Dec 01 '17 at 21:08
  • 1
    @BryceWagner - Not *all* of them. Since the result of some functions are needed to call others. But that `x - 1` can be evaluated at any point the compiler so chooses. – StoryTeller - Unslander Monica Dec 01 '17 at 21:10
  • 1
    @StoryTeller Really? When did that change. Because C++17 still has unspecified ordering of arguments inside a function call (it did change from UB if that is what you are referring too). – Rakete1111 Dec 01 '17 at 21:12
  • 1
    @StoryTeller you're right. they fixed it in c++17 to allow future continuations to work. – Richard Hodges Dec 01 '17 at 21:13
  • @Rakete1111 - The change they made is best [described by this answer](https://stackoverflow.com/a/46472497/817643). Not highly relevant here, but regardless. – StoryTeller - Unslander Monica Dec 01 '17 at 21:17
  • I suppose this behavior makes some sort of sense if you think of it in nested form, so it's actually calling D(C(B(a, x), x), x, x - 1). – Bryce Wagner Dec 01 '17 at 21:22
  • in g++ 6.3 and VC2017 the result is `0\n 0, -1`, which is perfectly logic, given the parsing starts from the extreme right going left. in assembly it pushes the address of `this` pointer and `x` which at the first time is `0`, the evaluation of `D` is passed to the function call `C` then to `B`, at the time of calling `D(x, x-1)` `x` is perfectly known and doesn't depend on any other variable. So I think it is a bug in VC10 – organicoman Dec 01 '17 at 22:16

0 Answers0