[clang] Fix incorrect constant folding of `if consteval`

Fixes https://github.com/llvm/llvm-project/issues/55638.

`if consteval` was evaluated incorrectly when in a
non-constant context that could be constant-folded.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D130437
This commit is contained in:
Corentin Jabot 2022-07-24 08:55:49 +02:00
parent 0ba128f7c8
commit c68baa73eb
3 changed files with 36 additions and 3 deletions

View File

@ -194,6 +194,8 @@ Bug Fixes
move assignment operator. Fixes `Issue 56456 <https://github.com/llvm/llvm-project/issues/56456>`_.
- Fixed a crash when a variable with a bool enum type that has no definition
used in comparison operators. Fixes `Issue 56560 <https://github.com/llvm/llvm-project/issues/56560>`_.
- Fix that ``if consteval`` could evaluate to ``true`` at runtime because it was incorrectly
constant folded. Fixes `Issue 55638 <https://github.com/llvm/llvm-project/issues/55638>`_.
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -5266,10 +5266,14 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
}
}
bool Cond;
if (IS->isConsteval())
if (IS->isConsteval()) {
Cond = IS->isNonNegatedConsteval();
else if (!EvaluateCond(Info, IS->getConditionVariable(), IS->getCond(),
Cond))
// If we are not in a constant context, if consteval should not evaluate
// to true.
if (!Info.InConstantContext)
Cond = !Cond;
} else if (!EvaluateCond(Info, IS->getConditionVariable(), IS->getCond(),
Cond))
return ESR_Failed;
if (const Stmt *SubStmt = Cond ? IS->getThen() : IS->getElse()) {

View File

@ -26,3 +26,30 @@ constexpr void f() {
void g() {
f();
}
namespace GH55638 {
constexpr bool is_constant_evaluated() noexcept {
if consteval { return true; } else { return false; }
}
constexpr int compiletime(int) {
return 2;
}
constexpr int runtime(int) {
return 1;
}
constexpr int test(int x) {
if(is_constant_evaluated())
return compiletime(x); // CHECK-NOT: call {{.*}}compiletime
return runtime(x); // CHECK: call {{.*}}runtime
}
int f(int x) {
x = test(x);
return x;
}
}