https://github.com/unterumarmung updated 
https://github.com/llvm/llvm-project/pull/189743

>From 22c6d0ed956ce150a21eb11cc7931021fec03940 Mon Sep 17 00:00:00 2001
From: Daniil Dudkin <[email protected]>
Date: Tue, 31 Mar 2026 22:56:57 +0300
Subject: [PATCH 1/3] [clang-tidy] Add modernize-use-if-consteval check

---
 .../clang-tidy/modernize/CMakeLists.txt       |   1 +
 .../modernize/ModernizeTidyModule.cpp         |   3 +
 .../modernize/UseIfConstevalCheck.cpp         | 136 +++++++++
 .../modernize/UseIfConstevalCheck.h           |  36 +++
 clang-tools-extra/docs/ReleaseNotes.rst       |   5 +
 .../docs/clang-tidy/checks/list.rst           |   1 +
 .../checks/modernize/use-if-consteval.rst     |  47 ++++
 .../checkers/modernize/use-if-consteval.cpp   | 263 ++++++++++++++++++
 8 files changed, 492 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.cpp
 create mode 100644 clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-if-consteval.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-if-consteval.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index 2c5c44db587fe..9e15c9ae13123 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -39,6 +39,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   UseEmplaceCheck.cpp
   UseEqualsDefaultCheck.cpp
   UseEqualsDeleteCheck.cpp
+  UseIfConstevalCheck.cpp
   UseIntegerSignComparisonCheck.cpp
   UseNodiscardCheck.cpp
   UseNoexceptCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index cc13da7535bcb..6c786c9b9f596 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -39,6 +39,7 @@
 #include "UseEmplaceCheck.h"
 #include "UseEqualsDefaultCheck.h"
 #include "UseEqualsDeleteCheck.h"
+#include "UseIfConstevalCheck.h"
 #include "UseIntegerSignComparisonCheck.h"
 #include "UseNodiscardCheck.h"
 #include "UseNoexceptCheck.h"
@@ -90,6 +91,8 @@ class ModernizeModule : public ClangTidyModule {
     CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
     CheckFactories.registerCheck<UseDesignatedInitializersCheck>(
         "modernize-use-designated-initializers");
+    CheckFactories.registerCheck<UseIfConstevalCheck>(
+        "modernize-use-if-consteval");
     CheckFactories.registerCheck<UseIntegerSignComparisonCheck>(
         "modernize-use-integer-sign-comparison");
     CheckFactories.registerCheck<UseRangesCheck>("modernize-use-ranges");
diff --git a/clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.cpp
new file mode 100644
index 0000000000000..b31a4b97a01ff
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.cpp
@@ -0,0 +1,136 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "UseIfConstevalCheck.h"
+
+#include "../utils/BracesAroundStatement.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+
+struct BraceFix {
+  bool NeedsBraces = false;
+  utils::BraceInsertionHints Hints;
+};
+
+} // namespace
+
+static const Stmt *ignoreAttributedStmt(const Stmt *S) {
+  while (const auto *AS = dyn_cast_or_null<AttributedStmt>(S))
+    S = AS->getSubStmt();
+  return S;
+}
+
+static std::optional<CharSourceRange>
+getHeaderRange(const IfStmt *If, const SourceManager &SM,
+               const LangOptions &LangOpts) {
+  if (If->getIfLoc().isMacroID() || If->getRParenLoc().isMacroID())
+    return std::nullopt;
+
+  const CharSourceRange HeaderRange = Lexer::makeFileCharRange(
+      CharSourceRange::getTokenRange(If->getIfLoc(), If->getRParenLoc()), SM,
+      LangOpts);
+  if (HeaderRange.isInvalid())
+    return std::nullopt;
+  return HeaderRange;
+}
+
+static std::optional<BraceFix>
+getBraceFix(const Stmt *S, const LangOptions &LangOpts, const SourceManager 
&SM,
+            SourceLocation StartLoc,
+            SourceLocation EndLocHint = SourceLocation()) {
+  S = ignoreAttributedStmt(S);
+  if (!S || isa<CompoundStmt>(S))
+    return BraceFix();
+
+  const auto Hints =
+      utils::getBraceInsertionsHints(S, LangOpts, SM, StartLoc, EndLocHint);
+  if (!Hints || !Hints.offersFixIts())
+    return std::nullopt;
+
+  return BraceFix{true, Hints};
+}
+void UseIfConstevalCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsConstantEvaluatedCall =
+      callExpr(callee(functionDecl(hasName("is_constant_evaluated"),
+                                   isInStdNamespace())))
+          .bind("call");
+  const auto IsNegatedConstantEvaluatedExpr =
+      unaryOperator(hasOperatorName("!"), 
hasUnaryOperand(ignoringParenImpCasts(
+                                              IsConstantEvaluatedCall)))
+          .bind("negation");
+  const auto IsConstantEvaluatedExpr =
+      expr(anyOf(ignoringParenImpCasts(IsConstantEvaluatedCall),
+                 ignoringParenImpCasts(IsNegatedConstantEvaluatedExpr)));
+
+  Finder->addMatcher(
+      ifStmt(unless(anyOf(isConstexpr(), isConsteval())),
+             anyOf(hasCondition(IsConstantEvaluatedExpr),
+                   hasConditionVariableStatement(declStmt(hasSingleDecl(
+                       varDecl(hasInitializer(IsConstantEvaluatedExpr)))))))
+          .bind("if"),
+      this);
+}
+
+void UseIfConstevalCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+  assert(If && Call && "expected to match an if statement and its call");
+
+  const bool IsNegated = Result.Nodes.getNodeAs<UnaryOperator>("negation");
+  const char *Replacement = IsNegated ? "if !consteval" : "if consteval";
+  const SourceLocation DiagLoc =
+      Result.SourceManager->getExpansionLoc(Call->getExprLoc());
+
+  auto Diag =
+      diag(
+          DiagLoc,
+          "use '%0' instead of checking 'std::is_constant_evaluated()' in this 
"
+          "'if' statement")
+      << Replacement;
+
+  if (If->hasInitStorage() || If->hasVarStorage())
+    return;
+
+  std::optional<CharSourceRange> HeaderRange =
+      getHeaderRange(If, *Result.SourceManager, getLangOpts());
+  if (!HeaderRange)
+    return;
+
+  std::optional<BraceFix> ThenBraceFix =
+      getBraceFix(If->getThen(), getLangOpts(), *Result.SourceManager,
+                  If->getRParenLoc(), If->getElseLoc());
+  if (!ThenBraceFix)
+    return;
+
+  std::optional<BraceFix> ElseBraceFix = BraceFix();
+  const Stmt *Else = ignoreAttributedStmt(If->getElse());
+  if (Else && !isa<IfStmt>(Else)) {
+    ElseBraceFix = getBraceFix(If->getElse(), getLangOpts(),
+                               *Result.SourceManager, If->getElseLoc());
+  }
+
+  std::string HeaderReplacement(Replacement);
+  if (ThenBraceFix->NeedsBraces)
+    HeaderReplacement += " {";
+  Diag << FixItHint::CreateReplacement(*HeaderRange, HeaderReplacement);
+
+  if (ThenBraceFix->NeedsBraces)
+    Diag << ThenBraceFix->Hints.closingBraceFixIt();
+
+  if (ElseBraceFix && ElseBraceFix->NeedsBraces)
+    Diag << ElseBraceFix->Hints.openingBraceFixIt()
+         << ElseBraceFix->Hints.closingBraceFixIt();
+}
+
+} // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.h 
b/clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.h
new file mode 100644
index 0000000000000..a87c9e6c5c8df
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.h
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEIFCONSTEVALCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEIFCONSTEVALCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::modernize {
+
+/// Use if consteval instead of std::is_constant_evaluated in if statements.
+///
+/// For the user-facing documentation see:
+/// 
https://clang.llvm.org/extra/clang-tidy/checks/modernize/use-if-consteval.html
+class UseIfConstevalCheck : public ClangTidyCheck {
+public:
+  UseIfConstevalCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+    return LangOpts.CPlusPlus23;
+  }
+  std::optional<TraversalKind> getCheckTraversalKind() const override {
+    return TK_IgnoreUnlessSpelledInSource;
+  }
+};
+
+} // namespace clang::tidy::modernize
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEIFCONSTEVALCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 69dc5b9633398..64a3cf077b8bd 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -133,6 +133,11 @@ New checks
   ``llvm::to_vector(llvm::make_filter_range(...))`` that can be replaced with
   ``llvm::map_to_vector`` and ``llvm::filter_to_vector``.
 
+- New :doc:`modernize-use-if-consteval
+  <clang-tidy/checks/modernize/use-if-consteval>` check.
+
+  Use ``if consteval`` instead of ``std::is_constant_evaluated`` in if 
statements.
+
 - New :doc:`modernize-use-std-bit
   <clang-tidy/checks/modernize/use-std-bit>` check.
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst 
b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 2b5be931271ec..8536ee08746ea 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -318,6 +318,7 @@ Clang-Tidy Checks
    :doc:`modernize-use-emplace <modernize/use-emplace>`, "Yes"
    :doc:`modernize-use-equals-default <modernize/use-equals-default>`, "Yes"
    :doc:`modernize-use-equals-delete <modernize/use-equals-delete>`, "Yes"
+   :doc:`modernize-use-if-consteval <modernize/use-if-consteval>`, "Yes"
    :doc:`modernize-use-integer-sign-comparison 
<modernize/use-integer-sign-comparison>`, "Yes"
    :doc:`modernize-use-nodiscard <modernize/use-nodiscard>`, "Yes"
    :doc:`modernize-use-noexcept <modernize/use-noexcept>`, "Yes"
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-if-consteval.rst 
b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-if-consteval.rst
new file mode 100644
index 0000000000000..6875b54025bc7
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-if-consteval.rst
@@ -0,0 +1,47 @@
+.. title:: clang-tidy - modernize-use-if-consteval
+
+modernize-use-if-consteval
+==========================
+
+Replaces direct ``std::is_constant_evaluated()`` checks in ``if`` statements
+with C++23's ``if consteval`` syntax.
+
+In C++20, code often spells constant-evaluation branches as:
+
+.. code-block:: c++
+
+  if (std::is_constant_evaluated()) {
+    return slow_but_constexpr_path();
+  } else {
+    return fast_runtime_path();
+  }
+
+In C++23, the language has a dedicated spelling for the same idea:
+
+.. code-block:: c++
+
+  if consteval {
+    return slow_but_constexpr_path();
+  } else {
+    return fast_runtime_path();
+  }
+
+The check also recognizes the direct negated form and rewrites it to
+``if !consteval``.
+
+The check only diagnoses direct uses in ``if`` statements whose condition is a
+call to ``std::is_constant_evaluated()`` or a direct negation of that call.
+Lookup through ``using`` declarations, ``using namespace`` directives, and
+namespace aliases is handled.
+
+When the rewrite is source-safe, fix-its are provided. This includes inserting
+braces around unbraced ``then`` and ``else`` branches because ``if consteval``
+always requires compound statements.
+
+The check still diagnoses, but does not provide fix-its for:
+
+- ``if`` statements with an init-statement
+- ``if`` statements with a condition variable
+- cases where the necessary edits would cross unsafe macro or source ranges
+
+``if constexpr`` and existing ``if consteval`` statements are ignored.
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-if-consteval.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-if-consteval.cpp
new file mode 100644
index 0000000000000..95047d119b4f8
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-if-consteval.cpp
@@ -0,0 +1,263 @@
+// RUN: %check_clang_tidy -std=c++23-or-later %s modernize-use-if-consteval %t
+
+namespace std {
+constexpr bool is_constant_evaluated() noexcept {
+  return __builtin_is_constant_evaluated();
+}
+}
+
+namespace mine {
+constexpr bool is_constant_evaluated() noexcept {
+  return __builtin_is_constant_evaluated();
+}
+}
+
+namespace alias = std;
+
+#define ICE_CALL() std::is_constant_evaluated()
+#define IF_ICE_HEADER if (std::is_constant_evaluated())
+#define RETURN_ONE() return 1;
+#define RETURN_THREE() return 3;
+
+bool runtime_predicate();
+
+int direct() {
+  if (std::is_constant_evaluated())
+    return 1;
+  else
+    return 2;
+  // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+  // CHECK-FIXES-NEXT:   return 1;
+  // CHECK-FIXES-NEXT: } else {
+  // CHECK-FIXES-NEXT:   return 2;
+  // CHECK-FIXES-NEXT: }
+}
+
+int direct_global() {
+  if (::std::is_constant_evaluated()) {
+    return 1;
+  }
+  return 2;
+  // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+}
+
+int using_decl() {
+  using std::is_constant_evaluated;
+  if (is_constant_evaluated()) {
+    return 1;
+  }
+  return 2;
+  // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+}
+
+int using_namespace() {
+  using namespace std;
+  if (is_constant_evaluated()) {
+    return 1;
+  }
+  return 2;
+  // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+}
+
+int namespace_alias() {
+  if (alias::is_constant_evaluated()) {
+    return 1;
+  }
+  return 2;
+  // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+}
+
+int negated() {
+  if (!std::is_constant_evaluated())
+    return 1;
+  return 2;
+  // CHECK-MESSAGES: :[[@LINE-3]]:8: warning: use 'if !consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if !consteval {
+  // CHECK-FIXES-NEXT:   return 1;
+  // CHECK-FIXES-NEXT: }
+  // CHECK-FIXES-NEXT:   return 2;
+}
+
+int negated_alternative_token() {
+  if (not std::is_constant_evaluated())
+    return 1;
+  return 2;
+  // CHECK-MESSAGES: :[[@LINE-3]]:11: warning: use 'if !consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if !consteval {
+  // CHECK-FIXES-NEXT:   return 1;
+  // CHECK-FIXES-NEXT: }
+  // CHECK-FIXES-NEXT:   return 2;
+}
+
+int extra_parens() {
+  if ((((std::is_constant_evaluated())))) {
+    return 1;
+  }
+  return 2;
+  // CHECK-MESSAGES: :[[@LINE-4]]:10: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+}
+
+template <typename T>
+int templated() {
+  if (std::is_constant_evaluated()) {
+    return sizeof(T);
+  }
+  return 0;
+  // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+}
+
+template int templated<int>();
+template int templated<long>();
+
+auto Lambda = [] {
+  if (std::is_constant_evaluated())
+    return 1;
+  return 2;
+  // CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+  // CHECK-FIXES-NEXT:   return 1;
+  // CHECK-FIXES-NEXT: }
+  // CHECK-FIXES-NEXT:   return 2;
+};
+
+int else_if_chain(int Value) {
+  if (Value == 0)
+    return 0;
+  else if (std::is_constant_evaluated())
+    return 1;
+  else
+    return 2;
+  // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: else if consteval {
+  // CHECK-FIXES-NEXT:   return 1;
+  // CHECK-FIXES-NEXT: } else {
+  // CHECK-FIXES-NEXT:   return 2;
+  // CHECK-FIXES-NEXT: }
+}
+
+int macro_header_safe() {
+  if (ICE_CALL()) {
+    return 1;
+  } else {
+    return 2;
+  }
+  // CHECK-MESSAGES: :[[@LINE-5]]:7: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+}
+
+int with_init() {
+  if (int X = 0; std::is_constant_evaluated()) {
+    return X + 1;
+  }
+  return 0;
+  // CHECK-MESSAGES: :[[@LINE-4]]:18: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if (int X = 0; std::is_constant_evaluated()) {
+}
+
+int with_condition_variable() {
+  if (bool B = std::is_constant_evaluated())
+    return B ? 1 : 2;
+  else
+    return 3;
+  // CHECK-MESSAGES: :[[@LINE-4]]:16: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if (bool B = std::is_constant_evaluated())
+  // CHECK-FIXES-NEXT:   return B ? 1 : 2;
+  // CHECK-FIXES-NEXT: else
+  // CHECK-FIXES-NEXT:   return 3;
+}
+
+int macro_header_unsafe() {
+  IF_ICE_HEADER {
+    return 1;
+  }
+  return 0;
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: IF_ICE_HEADER {
+}
+
+int macro_body_unsafe() {
+  if (std::is_constant_evaluated())
+    RETURN_ONE()
+  return 2;
+  // CHECK-MESSAGES: :[[@LINE-3]]:7: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if (std::is_constant_evaluated())
+  // CHECK-FIXES-NEXT:   RETURN_ONE()
+  // CHECK-FIXES-NEXT:   return 2;
+}
+
+int macro_else_unsafe() {
+  if (std::is_constant_evaluated())
+    return 1;
+  else
+    RETURN_THREE()
+  return 4;
+  // CHECK-MESSAGES: :[[@LINE-5]]:7: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+  // CHECK-FIXES-NEXT:   return 1;
+  // CHECK-FIXES-NEXT: } else
+  // CHECK-FIXES-NEXT:   RETURN_THREE()
+  // CHECK-FIXES-NEXT:   return 4;
+}
+
+int not_std() {
+  if (mine::is_constant_evaluated()) {
+    return 1;
+  }
+  return 0;
+  // CHECK-MESSAGES-NOT: :[[@LINE-4]]:7: warning: use 'if consteval' instead 
of checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+}
+
+int composite_conditions() {
+  if (std::is_constant_evaluated() && runtime_predicate()) {
+    return 1;
+  }
+  if (!!std::is_constant_evaluated()) {
+    return 2;
+  }
+  return 0;
+  // CHECK-MESSAGES-NOT: :[[@LINE-7]]:7: warning: use 'if consteval' instead 
of checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-MESSAGES-NOT: :[[@LINE-5]]:9: warning: use 'if consteval' instead 
of checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+}
+
+int if_constexpr() {
+  if constexpr (std::is_constant_evaluated()) {
+    return 1;
+  }
+  return 2;
+  // CHECK-MESSAGES-NOT: :[[@LINE-4]]:17: warning: use 'if consteval' instead 
of checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+}
+
+int already_if_consteval() {
+  if consteval {
+    // CHECK-MESSAGES-NOT: :[[@LINE-1]] warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+    return 1;
+  } else {
+    return 2;
+  }
+}
+
+int already_if_not_consteval() {
+  if !consteval {
+    // CHECK-MESSAGES-NOT: :[[@LINE-1]] warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+    return 1;
+  } else {
+    return 2;
+  }
+}
+
+template <typename T>
+concept HasICE = requires {
+  std::is_constant_evaluated();
+  // CHECK-MESSAGES-NOT: :[[@LINE-1]] warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+};
+
+using ICEPtr = decltype(std::is_constant_evaluated()) *;
+ICEPtr Ptr = nullptr;
+// CHECK-MESSAGES-NOT: :[[@LINE-2]] warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]

>From 6619f28b09645001f5a6c582a8259b60b6f12364 Mon Sep 17 00:00:00 2001
From: Daniil Dudkin <[email protected]>
Date: Thu, 2 Apr 2026 20:04:36 +0300
Subject: [PATCH 2/3] Fix review comment

---
 .../modernize/UseIfConstevalCheck.cpp         | 41 +++++++++++++------
 .../checkers/modernize/use-if-consteval.cpp   | 19 +++++++++
 2 files changed, 47 insertions(+), 13 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.cpp
index b31a4b97a01ff..859bda8294b79 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseIfConstevalCheck.cpp
@@ -10,6 +10,7 @@
 
 #include "../utils/BracesAroundStatement.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/CharInfo.h"
 #include "clang/Lex/Lexer.h"
 
 using namespace clang::ast_matchers;
@@ -34,12 +35,12 @@ static const Stmt *ignoreAttributedStmt(const Stmt *S) {
 static std::optional<CharSourceRange>
 getHeaderRange(const IfStmt *If, const SourceManager &SM,
                const LangOptions &LangOpts) {
-  if (If->getIfLoc().isMacroID() || If->getRParenLoc().isMacroID())
+  if (If->getLParenLoc().isMacroID() || If->getRParenLoc().isMacroID())
     return std::nullopt;
 
   const CharSourceRange HeaderRange = Lexer::makeFileCharRange(
-      CharSourceRange::getTokenRange(If->getIfLoc(), If->getRParenLoc()), SM,
-      LangOpts);
+      CharSourceRange::getTokenRange(If->getLParenLoc(), If->getRParenLoc()),
+      SM, LangOpts);
   if (HeaderRange.isInvalid())
     return std::nullopt;
   return HeaderRange;
@@ -60,6 +61,14 @@ getBraceFix(const Stmt *S, const LangOptions &LangOpts, 
const SourceManager &SM,
 
   return BraceFix{true, Hints};
 }
+
+static bool needsLeadingSpaceBeforeConsteval(SourceLocation LParenLoc,
+                                             const SourceManager &SM) {
+  bool Invalid = false;
+  const char *LParen = SM.getCharacterData(LParenLoc, &Invalid);
+  return Invalid || !isWhitespace(LParen[-1]);
+}
+
 void UseIfConstevalCheck::registerMatchers(MatchFinder *Finder) {
   const auto IsConstantEvaluatedCall =
       callExpr(callee(functionDecl(hasName("is_constant_evaluated"),
@@ -88,16 +97,15 @@ void UseIfConstevalCheck::check(const 
MatchFinder::MatchResult &Result) {
   assert(If && Call && "expected to match an if statement and its call");
 
   const bool IsNegated = Result.Nodes.getNodeAs<UnaryOperator>("negation");
-  const char *Replacement = IsNegated ? "if !consteval" : "if consteval";
+  const llvm::StringRef ConstevalClause =
+      IsNegated ? "!consteval" : "consteval";
   const SourceLocation DiagLoc =
       Result.SourceManager->getExpansionLoc(Call->getExprLoc());
 
-  auto Diag =
-      diag(
-          DiagLoc,
-          "use '%0' instead of checking 'std::is_constant_evaluated()' in this 
"
-          "'if' statement")
-      << Replacement;
+  auto Diag = diag(DiagLoc, "use 'if %0' instead of checking "
+                            "'std::is_constant_evaluated()' in this "
+                            "'if' statement")
+              << ConstevalClause;
 
   if (If->hasInitStorage() || If->hasVarStorage())
     return;
@@ -120,9 +128,16 @@ void UseIfConstevalCheck::check(const 
MatchFinder::MatchResult &Result) {
                                *Result.SourceManager, If->getElseLoc());
   }
 
-  std::string HeaderReplacement(Replacement);
-  if (ThenBraceFix->NeedsBraces)
-    HeaderReplacement += " {";
+  const bool NeedsLeadingSpace = needsLeadingSpaceBeforeConsteval(
+      If->getLParenLoc(), *Result.SourceManager);
+  const std::string HeaderReplacement = [&] {
+    std::string Replacement = ConstevalClause.str();
+    if (NeedsLeadingSpace)
+      Replacement.insert(0, 1, ' ');
+    if (ThenBraceFix->NeedsBraces)
+      Replacement += " {";
+    return Replacement;
+  }();
   Diag << FixItHint::CreateReplacement(*HeaderRange, HeaderReplacement);
 
   if (ThenBraceFix->NeedsBraces)
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-if-consteval.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-if-consteval.cpp
index 95047d119b4f8..d3e9084776477 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-if-consteval.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-if-consteval.cpp
@@ -16,6 +16,7 @@ namespace alias = std;
 
 #define ICE_CALL() std::is_constant_evaluated()
 #define IF_ICE_HEADER if (std::is_constant_evaluated())
+#define IF_ONLY if
 #define RETURN_ONE() return 1;
 #define RETURN_THREE() return 3;
 
@@ -43,6 +44,15 @@ int direct_global() {
   // CHECK-FIXES: if consteval {
 }
 
+int compact_spacing() {
+  if(std::is_constant_evaluated()) {
+    return 1;
+  }
+  return 2;
+  // CHECK-MESSAGES: :[[@LINE-4]]:6: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: if consteval {
+}
+
 int using_decl() {
   using std::is_constant_evaluated;
   if (is_constant_evaluated()) {
@@ -182,6 +192,15 @@ int macro_header_unsafe() {
   // CHECK-FIXES: IF_ICE_HEADER {
 }
 
+int macro_if_token_unsafe() {
+  IF_ONLY (std::is_constant_evaluated()) {
+    return 1;
+  }
+  return 0;
+  // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: use 'if consteval' instead of 
checking 'std::is_constant_evaluated()' in this 'if' statement 
[modernize-use-if-consteval]
+  // CHECK-FIXES: IF_ONLY consteval {
+}
+
 int macro_body_unsafe() {
   if (std::is_constant_evaluated())
     RETURN_ONE()

>From 19470e1a5787fbc2745e7f2b325776aa3ae49bae Mon Sep 17 00:00:00 2001
From: Daniil Dudkin <[email protected]>
Date: Thu, 2 Apr 2026 20:06:47 +0300
Subject: [PATCH 3/3] Fix review comment

---
 clang-tools-extra/docs/ReleaseNotes.rst | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 64a3cf077b8bd..0aa0cf93a5141 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -136,7 +136,8 @@ New checks
 - New :doc:`modernize-use-if-consteval
   <clang-tidy/checks/modernize/use-if-consteval>` check.
 
-  Use ``if consteval`` instead of ``std::is_constant_evaluated`` in if 
statements.
+  Replaces direct ``std::is_constant_evaluated()`` checks in ``if`` statements
+  with C++23's ``if consteval`` syntax.
 
 - New :doc:`modernize-use-std-bit
   <clang-tidy/checks/modernize/use-std-bit>` check.

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to