0

MSVC 19.33 disagrees with GCC >= 4.8.1 and Clang >= 3.4.1 on the outcome of the following code:

int x{0};
x = x++; // 1 with MSVC, 0 with GCC and Clang

I know the code is silly. It is auto-generated and it's not the point. I wonder how the post-increment is defined by the standard such that MSVC differs in its implementation.

I would expect an implementation like this:

int operator++( int& i )
{
    int old{ i };
    ++i;
    return old;
}

With this implementation the increment happens first and then the old value is returned by the function. But MSVC does something else. What would be a possible implementation to reproduce this behaviour?

honey_badger
  • 472
  • 3
  • 10
  • 2
    Why does `x` need an assignment here at all? I am not so sure this isn't considered _UB_. – πάντα ῥεῖ Oct 20 '22 at 15:31
  • 2
    I believe this is UB or implementation defined – CoffeeTableEspresso Oct 20 '22 at 15:31
  • 13
    What version of the C++ standard are you using? This was [undefined behavior](https://en.cppreference.com/w/cpp/language/eval_order) prior to C++17 – Nathan Pierson Oct 20 '22 at 15:31
  • That looks like an MSVC bug, then. Note that it's not [the post-increment itself](https://godbolt.org/z/TW7YWxhzz) doing anything weird, but specifically the interaction of post-incrementing `x` and assigning to `x`. – Nathan Pierson Oct 20 '22 at 15:58
  • 2
    Cannot reproduce, latest version of MSVC with /std:c++17 switch does yield 0 in this case. https://gcc.godbolt.org/z/zbbaPf5Kf – Revolver_Ocelot Oct 20 '22 at 16:02
  • 5
    The line x = x++; is itself arcane and confusing. It maybe of interest language-lawyer what it does but in real product it should not pass code review. – Öö Tiib Oct 20 '22 at 16:04
  • 1
    Going back to 19.14 of MSVC still produces 0, with c++17, which is, I believe, Visual Studio 2017 version 15.7 (that's the further godbolt goes back) – ChrisMM Oct 20 '22 at 16:08
  • @ChrisMM actually, 1914 is the only version which __does__ produce 1 for me: https://gcc.godbolt.org/z/G84YYPGjG – Revolver_Ocelot Oct 20 '22 at 16:11
  • 1
    New MSVC can produce 1 in this case (as any other number, since it is UB) if used with any standard version before C++17. https://gcc.godbolt.org/z/89jx1ETe7 – Revolver_Ocelot Oct 20 '22 at 16:16
  • Ok, I was certain msvc 19.33 was using c++17 for some reason, but I was wrong. UB it is then. Thank you everyone! – honey_badger Oct 20 '22 at 16:19
  • 3
    @honey_badger never rely on compilers using some standard version by default. Always explicitely select one you need. – Revolver_Ocelot Oct 20 '22 at 16:20
  • @Revolver_Ocelot, you're right. I swear it said `xor eax, eax` the first time, but it's `mov eax, 1` now. Might have just taken longer than usual to compile. – ChrisMM Oct 20 '22 at 16:45
  • The msvc compiler in Visual Studio 2019 defaults to c++14. I am not sure what the default is on Visual Studio 2021 as I don't use that yet because of a dependency on a paid addon that I would have to repurchase – drescherjm Oct 20 '22 at 16:51
  • @drescherjm, for reference VS 2022 still defaults to C++14. – ChrisMM Oct 20 '22 at 18:59
  • 1
    `x = x++` is absolutely UB (two modifications to x in the same expression without any sequencing relationship). – Toby Speight Oct 21 '22 at 07:06
  • If that code is auto-generated as you say, then you need to fix the code generator! – Toby Speight Oct 21 '22 at 07:07
  • 1
    @TobySpeight believe me, I am trying to rid of it altogether as much as I can – honey_badger Oct 21 '22 at 09:56

0 Answers0