Consider the following snippet of code:
int main(){
constexpr int x = -1;
if(x >= 0){
constexpr int y = 1<<x;
}
}
GCC 7 (and probably other versions of GCC) refuses to compile this and says:
error: right operand of shift expression '(1 << -1)' is negative [-fpermissive]
I can guess where this may have come from: the constexpr
declaration on y
makes GCC evaluate y
at compile time, where it might be negative. Removing the constexpr
fixes the error.
However, is this undefined behavior by the standard? The condition is always false, so the value of y
will never be used.
In my actual code, x
is a template parameter, which may or may not be negative.
GCC complains because your definition of y
is explicitly an ill-formed constexpr
declaration. The initialzier violates [expr.const]/2, which specifies:
An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:
- an operation that would have undefined behavior as specified in Clauses [intro] through [cpp] of this International Standard [ Note: including, for example, signed integer overflow (Clause [expr]), certain pointer arithmetic ([expr.add]), division by zero, or certain shift operations — end note ] ;
So you can't use 1<<x
to initialize y
. It doesn't matter that the branch will never be executed and can be eliminated. GCC is still obligated to verify it's semantically correct.