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.
isConstantEvaluated() doesn't imply that the expression is necessarily reachable, so always giving an error here doesn't seem right. Instead, we should (already) have the relevant range checks in the constant evaluator for such builtins that are usable in constant expressions, and should never need to check here (if the code is reached during a constant evaluation, then the evaluation will be non-constant and hence ill-formed).
I think we should just return early from this function if isConstantEvaluated() like you do in checkFortifiedBuiltinMemoryFunction.