-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Description
void f(int k) {
// No UB. But warns about UB.
const int m = __builtin_is_constant_evaluated() ? 0 : *(int*)0;
}
void g(int k) {
// Has UB. But does not warn about UB.
const int m = __builtin_is_constant_evaluated() ? k : *(int*)0;
}Presumably we get f wrong because the CFG builder evaluates __builtin_is_constant_evaluated() to false when building a CFG for the conditional expression. But I'm unsure why we get g wrong too.
Perhaps the CFG builder could track whether it's within a manifestly constant evaluated context, and pass that information into the constant evaluator. However, with the likely upcoming changes adding reflection to C++, there'll be other ways in which constant evaluation becomes context-dependent, so this might not be a particularly good solution in the longer term.
Another possible option would be to make the CFG builder entirely skip constant expressions, and instead just use the already-known constant values from them. The C++ language rules already require UB checking within constant expressions, so most additional CFG-based checks are likely to be redundant (though not all of them).