Description
Consider the following example:
#include <type_traits>
struct X { unsigned u; };
void f(X x);
void g(int a) {
f({0xFFFFFFFFLL + std::is_constant_evaluated()});
}
The standard says the conversion is narrowing if "the source is a constant expression whose value after integral promotions will fit into the target type". gcc correctly rejects because of this: it treats the expression as a constant expression, then it fails to narrow. clang incorrectly accepts because isCXX11ConstantExpr() doesn't treat the evaluation as a constant context.
We have to be a little careful here... consider the following variant:
#include <type_traits>
struct X { unsigned u; };
void f(X x);
void g(int a) {
f({0x100000000LL - std::is_constant_evaluated()});
}
clang incorrectly rejects. gcc miscompiles: it checks the narrowing in a constant context, but then doesn't evaluate the actual expression in a constant context, so the integer overflows to 0.
(I don't expect anyone to intentionally do this... wrote some synthetic testcases while looking at isCXX11ConstantExpr() for other reasons.)