仍然不确定 C++ 中的有符号整数溢出

Still unsure about signed integer overflow in C++

在下面的代码中,我测试了哪种形式的溢出会导致 UB 并因此导致 constexpr 上下文中的硬错误:

#include <cstdint>
#include <limits>

using T = int8_t;
int main() {    
    constexpr bool b = []{
        T x = std::numeric_limits<T>::max();
        ++x; // GCC: UB, Clang: no UB
//        x += 1;
//        x = x + 1;
        return (x > std::numeric_limits<T>::max());
    }();

    return b;    
}

预增量给出了 gcc 的错误(如我所料),但不是 clang。

更奇怪的是,标准说 ++xx += 1 相同,但使用它在 gcc(和以前的 clang)上不再出现错误。

并且进一步x += 1应该和x = x + 1一样,所以rhs被提升为int并且结果被隐式转换。所以,这应该是较新的 UB。

所以,问题是,这三个语句中哪一个真的应该是 UB(我认为只有 ++x),哪个编译器是正确的?

[expr.pre.incr]/1

The expression ++x is equivalent to x+=1.

[expr.ass]/6

The behavior of an expression of the form E1 op= E2 is equivalent to E1 = E1 op E2 except that E1 is evaluated only once.

但是x = x + 1不是UB(整数提升和收缩整数转换),所以原来是well-formed。所以,GCC是错误的。