0

In the following code I tested which form of overflow results in UB and causes therefore an hard error in a constexpr context:

#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;    
}

The preincrement gives an error (as I expected) for gcc but not for clang.

More strange is that the standard says that ++x is the same as x += 1, but using this gives no more an error on gcc (and clang as before).

And further x += 1 should be the same as x = x + 1, so the rhs is promoted to int and the result is implicitly converted. So, this should newer be UB.

So, the question is, which of the three statement really should be UB (I think only ++x) and which compiler is correct?

12
  • 6
    It's always UB. UB doesn't mean an error will occur, it just means literally what it says; the behavior of your program is undefined. That doesn't mean it's not allowed to work how you expect; it just means the compiler is under no obligation to produce an executable that does. Commented May 29, 2022 at 16:35
  • 3
    this isn't C. There's no C/C++ language. C and C++ are completely different languages Commented May 29, 2022 at 16:42
  • 1
    @wimalopaan Since c++20 x = x + 1 is well defined. x + 1 promoted to int first so no overflow happens and the assignment back to int8_t is now defined to work modulo 2^n. Whether that applies to x += 1 and ++x too I leave to the language lawyers. int8_t has been defined as two's-complement so the result of overflow should never be in question. It's silly C++ still calls it UB, stupid integer promotion breaking it all. Commented May 29, 2022 at 16:53
  • 1
    "I tested which form of overflow results in UB" You can't. Commented May 29, 2022 at 16:53
  • 1
    @GoswinvonBrederlow And pre-C++20 narrowing signed casts were implementation-defined (aka worked in practice), not UB. Commented May 29, 2022 at 16:54

1 Answer 1

2

[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.

But x = x + 1 is not UB (integer promotion and narrowing integer conversion), so the original is well-formed. Therefore, GCC is wrong.

Sign up to request clarification or add additional context in comments.

3 Comments

Well ok, then I will file a bug to gcc and see what the gcc people say.
Simultaneous thoughts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.