Author: Victor Chernyakin
Date: 2026-02-01T16:26:41-08:00
New Revision: 9e5deb963abec2808152b55d826333cba8ad5ab0

URL: 
https://github.com/llvm/llvm-project/commit/9e5deb963abec2808152b55d826333cba8ad5ab0
DIFF: 
https://github.com/llvm/llvm-project/commit/9e5deb963abec2808152b55d826333cba8ad5ab0.diff

LOG: [clang-tidy] Speed up `modernize-use-nullptr` (#178829)

As noted in [this
comment](https://github.com/llvm/llvm-project/pull/178149#discussion_r2732896149),
it appears that registering one `anyOf(a, b, ...)` matcher is generally
slower than registering `a, b, ...` all individually. Applying that
knowledge to this check gives us an easy 3x speedup:
```txt
                    ---User Time---   --System Time--   --User+System--   
---Wall Time---  --- Name ---
Status quo:         0.3281 (  6.1%)   0.0469 (  5.2%)   0.3750 (  6.0%)   
0.3491 (  5.5%)  modernize-use-nullptr
With this change:   0.0938 (  1.8%)   0.0156 (  1.8%)   0.1094 (  1.8%)   
0.1260 (  2.1%)  modernize-use-nullptr
```
I'm not exactly sure *why* this works, but it seems pretty consistent.
I've seen a similar result trying this with `bugprone-infinite-loop`.

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index cc371a1ab55a7..85224b573edeb 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -45,8 +45,7 @@ static constexpr char CastSequence[] = "sequence";
 /// would check for the "NULL" macro instead, but that'd be harder to express.
 /// In practice, "NULL" is often defined as "__null", and this is a useful
 /// condition.
-static StatementMatcher
-makeCastSequenceMatcher(llvm::ArrayRef<StringRef> NameList) {
+void UseNullptrCheck::registerMatchers(MatchFinder *Finder) {
   auto ImplicitCastToNull = implicitCastExpr(
       anyOf(hasCastKind(CK_NullToPointer), 
hasCastKind(CK_NullToMemberPointer)),
       anyOf(hasSourceExpression(gnuNullExpr()),
@@ -54,32 +53,34 @@ makeCastSequenceMatcher(llvm::ArrayRef<StringRef> NameList) 
{
                 qualType(substTemplateTypeParmType())))),
       unless(hasSourceExpression(hasType(sugaredNullptrType()))),
       unless(hasImplicitDestinationType(
-          qualType(matchers::matchesAnyListedTypeName(NameList)))));
+          qualType(matchers::matchesAnyListedTypeName(IgnoredTypes)))));
 
   auto IsOrHasDescendant = [](const auto &InnerMatcher) {
     return anyOf(InnerMatcher, hasDescendant(InnerMatcher));
   };
 
-  return traverse(
-      TK_AsIs,
-      anyOf(castExpr(anyOf(ImplicitCastToNull,
-                           
explicitCastExpr(hasDescendant(ImplicitCastToNull))),
-                     unless(hasAncestor(explicitCastExpr())),
-                     unless(hasAncestor(cxxRewrittenBinaryOperator())))
-                .bind(CastSequence),
-            cxxRewrittenBinaryOperator(
-                // Match rewritten operators, but verify (in the check method)
-                // that if an implicit cast is found, it is not from another
-                // nested rewritten operator.
-                expr().bind("matchBinopOperands"),
-                hasEitherOperand(IsOrHasDescendant(
-                    implicitCastExpr(
-                        ImplicitCastToNull,
-                        hasAncestor(cxxRewrittenBinaryOperator().bind(
-                            "checkBinopOperands")))
-                        .bind(CastSequence))),
-                // Skip defaulted comparison operators.
-                unless(hasAncestor(functionDecl(isDefaulted()))))));
+  Finder->addMatcher(
+      castExpr(anyOf(ImplicitCastToNull,
+                     explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+               unless(hasAncestor(explicitCastExpr())),
+               unless(hasAncestor(cxxRewrittenBinaryOperator())))
+          .bind(CastSequence),
+      this);
+
+  Finder->addMatcher(
+      cxxRewrittenBinaryOperator(
+          // Match rewritten operators, but verify (in the check method)
+          // that if an implicit cast is found, it is not from another
+          // nested rewritten operator.
+          expr().bind("matchBinopOperands"),
+          hasEitherOperand(IsOrHasDescendant(
+              implicitCastExpr(ImplicitCastToNull,
+                               hasAncestor(cxxRewrittenBinaryOperator().bind(
+                                   "checkBinopOperands")))
+                  .bind(CastSequence))),
+          // Skip defaulted comparison operators.
+          unless(hasAncestor(functionDecl(isDefaulted())))),
+      this);
 }
 
 static bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
@@ -505,10 +506,6 @@ void 
UseNullptrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
                 utils::options::serializeStringList(IgnoredTypes));
 }
 
-void UseNullptrCheck::registerMatchers(MatchFinder *Finder) {
-  Finder->addMatcher(makeCastSequenceMatcher(IgnoredTypes), this);
-}
-
 void UseNullptrCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *NullCast = Result.Nodes.getNodeAs<CastExpr>(CastSequence);
   assert(NullCast && "Bad Callback. No node provided");


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

Reply via email to