[clang-tools-extra] [clang-tidy] Fix modernize-use-nullptr false positive on ordering comparisons (PR #225585)

Peiqi Li via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 4 20:07:41 PDT 2026


https://github.com/voyager-jhk updated https://github.com/llvm/llvm-project/pull/225585

>From a7704e7c5361f782ea9042bdb2d14f7f3289ae3f Mon Sep 17 00:00:00 2001
From: voyager-jhk <voyager.lpq at gmail.com>
Date: Wed, 23 Sep 2026 12:20:45 +0800
Subject: [PATCH 1/2] [clang-tidy] Fix modernize-use-nullptr false positive on
 ordering comparisons

libstdc++ 16 renamed __cmp_cat::__unspec to __cmp_cat::__literal_zero.
Add the new name to the default IgnoredTypes.

Fixes #206245
---
 .../clang-tidy/modernize/UseNullptrCheck.cpp  |  8 +++++--
 clang-tools-extra/docs/ReleaseNotes.md        |  5 +++++
 .../checks/modernize/use-nullptr.rst          |  2 +-
 .../checkers/modernize/use-nullptr-cxx20.cpp  | 21 +++++++++++++++++++
 4 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index 01bb98cfbcfd4e8..42a16c873980838 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -38,6 +38,10 @@ AST_MATCHER(DecltypeType, decltypeTypeNullptrLiteral) {
 
 static constexpr char CastSequence[] = "sequence";
 
+static constexpr char DefaultIgnoredTypes[] = "std::_CmpUnspecifiedParam;"
+                                              "^std::__cmp_cat::__unspec;"
+                                              "^std::__cmp_cat::__literal_zero";
+
 /// Create a matcher that finds implicit casts as well as the head of a
 /// sequence of zero or more nested explicit casts that have an implicit cast
 /// to null within.
@@ -505,8 +509,8 @@ class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
 UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       NullMacrosStr(Options.get("NullMacros", "NULL")),
-      IgnoredTypes(utils::options::parseStringList(Options.get(
-          "IgnoredTypes", "_CmpUnspecifiedParam;^std::__cmp_cat::__unspec"))),
+      IgnoredTypes(utils::options::parseStringList(
+          Options.get("IgnoredTypes", DefaultIgnoredTypes))),
       UseNullptrT(Options.get("UseNullptrT", true)),
       IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
                                                utils::IncludeSorter::IS_LLVM),
diff --git a/clang-tools-extra/docs/ReleaseNotes.md b/clang-tools-extra/docs/ReleaseNotes.md
index d0906f9ee6be813..d72f5cb9a0d1855 100644
--- a/clang-tools-extra/docs/ReleaseNotes.md
+++ b/clang-tools-extra/docs/ReleaseNotes.md
@@ -240,6 +240,11 @@ infrastructure are described first, followed by tool-specific sections.
   <clang-tidy/checks/modernize/use-nullptr>` to turn `decltype(nullptr)` into
   `std::nullptr_t` from `<cstdef>`.
 
+- Improved {doc}`modernize-use-nullptr
+  <clang-tidy/checks/modernize/use-nullptr>` check to avoid replacing `0`
+  with `nullptr` in comparisons with ordering types such as
+  `std::strong_ordering`.
+
 - Improved {doc}`performance-inefficient-algorithm
   <clang-tidy/checks/performance/inefficient-algorithm>` check to no longer
   produce a fix with the container or the searched-for value missing, such as
diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
index ce43e1e4eb5dc52..ab33ec5f0957cf0 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
@@ -53,7 +53,7 @@ Options
 
   Semicolon-separated list of regular expressions to match pointer types for
   which implicit casts will be ignored. Default value:
-  `std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec`.
+  `std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec;^std::__cmp_cat::__literal_zero`.
 
 .. option:: NullMacros
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
index 2cd2f1e07b0b125..3000ad0160eb656 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-nullptr %t -- -- -DGCC
+// RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-nullptr %t -- -- -DGCC_LITERAL_ZERO
 // RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-nullptr %t -- -- -DCLANG
 
 namespace std {
@@ -24,6 +25,17 @@ namespace __cmp_cat {
 #define UNSPECIFIED_TYPE __cmp_cat::__unspec
 #endif
 
+// libstdc++ 16 renamed __cmp_cat::__unspec to __cmp_cat::__literal_zero.
+#ifdef GCC_LITERAL_ZERO
+namespace __cmp_cat {
+  struct __literal_zero {
+    consteval __literal_zero(__literal_zero*) noexcept { }
+  };
+}
+
+#define UNSPECIFIED_TYPE __cmp_cat::__literal_zero
+#endif
+
 struct strong_ordering {
   signed char value;
 
@@ -82,6 +94,15 @@ void testValidZero() {
   // CHECK-FIXES: if (result < 0) {}
 }
 
+void testOrderingConstantsComparedWithZero() {
+  void(std::strong_ordering::equal == 0);
+  // CHECK-FIXES: void(std::strong_ordering::equal == 0);
+  void(std::strong_ordering::less == 0);
+  // CHECK-FIXES: void(std::strong_ordering::less == 0);
+  void(std::strong_ordering::greater == 0);
+  // CHECK-FIXES: void(std::strong_ordering::greater == 0);
+}
+
 template<class T1, class T2>
 struct P {
   T1 x1;

>From 2751f52ff65a636df0ac66dd7392ceaa682f644a Mon Sep 17 00:00:00 2001
From: voyager-jhk <voyager.lpq at gmail.com>
Date: Mon, 5 Oct 2026 10:53:39 +0800
Subject: [PATCH 2/2] Trigger CI




More information about the cfe-commits mailing list