diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -194,6 +194,8 @@ move assignment operator. Fixes `Issue 56456 `_. - Fixed a crash when a variable with a bool enum type that has no definition used in comparison operators. Fixes `Issue 56560 `_. +- Fix that ``if consteval`` could evaluate to ``true`` at runtime because it was incorrectly + constant folded. Fixes `Issue 55638 `_. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -5266,10 +5266,14 @@ } } 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()) { diff --git a/clang/test/CodeGenCXX/cxx2b-consteval-if.cpp b/clang/test/CodeGenCXX/cxx2b-consteval-if.cpp --- a/clang/test/CodeGenCXX/cxx2b-consteval-if.cpp +++ b/clang/test/CodeGenCXX/cxx2b-consteval-if.cpp @@ -26,3 +26,30 @@ 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; +} + +}