Since the addition of __builtin_is_constant_evaluated the result of an expression can change based on whether it is evaluated in constant context. a lot of semantic checking performs evaluations with out specifying context. which can lead to wrong diagnostics.
for example:
constexpr int i0 = (long long)__builtin_is_constant_evaluated() * (1ll << 33); //#1 constexpr int i1 = (long long)!__builtin_is_constant_evaluated() * (1ll << 33); //#2
before the patch, #2 was diagnosed incorrectly and #1 wasn't diagnosed.
after the patch #1 is diagnosed as it should and #2 isn't.
Changes:
- add a flag to some Expr::Evaluate* operation to evaluate in constant context.
- in SemaChecking.cpp calls to Expr::Evaluate* are now done in constant context when they should.
- in SemaChecking.cpp diagnostics for UB are not checked for in constant context because an error will be emitted by the constant evaluator.
- in SemaChecking.cpp diagnostics for construct that cannot appear in constant context are not checked for in constant context.
- in SemaChecking.cpp diagnostics on constant expression are always emitted because constant expression are always evaluated.
- semantic checking for initialization of constexpr variables is now done in constant context.
- adapt test that were depending on warning changes.
- add test.
For __attribute__((nonnull)), I think the right thing to do is to change the constant expression evaluator to consider passing a null pointer argument for a nonnull-attributed parameter to be non-constant. (It's undefined behavior, so we should not permit it in constant evaluations.) For _Nonnull, I think the situation is less clear -- that case is explicitly not undefined behavior, so it's not clear that treating it as non-constant is the right choice. But as with the other cases here, isConstantEvaluated() does not imply the code is necessarily reachable, so bypassing DiagRuntimeBehavior's check for reachability doesn't seem like the appropriate behavior.