Author: Victor Chernyakin
Date: 2026-01-08T14:31:22-07:00
New Revision: 6506f92844cfc56f84d1edc42034369eb3369111

URL: 
https://github.com/llvm/llvm-project/commit/6506f92844cfc56f84d1edc42034369eb3369111
DIFF: 
https://github.com/llvm/llvm-project/commit/6506f92844cfc56f84d1edc42034369eb3369111.diff

LOG: [clang-tidy] Prefer the faster LLVM ADT sets and maps over `std::` ones 
(#174357)

The LLVM docs give a good description of [why `std::` containers are
slower than LLVM
alternatives](https://llvm.org/docs/ProgrammersManual.html#set). To see
what difference switching to the LLVM ones made, I [reused the
approach](https://github.com/llvm/llvm-project/pull/174237#issuecomment-3707395449)
of measuring how long it takes to run all checks over all standard
library headers (MSVC STL in my case). Using hyperfine (which basically
runs a program multiple times and computes how long it took):
```sh
hyperfine --shell=none './build/release/bin/clang-tidy --checks=* 
all_headers.cpp -header-filter=.* -system-headers -- -std=c++23'
```
...the results were:

Before:
```
Benchmark 1: ./build/release/bin/clang-tidy --checks=* all_headers.cpp 
-header-filter=.* -system-headers -- -std=c++23
  Time (mean ± σ):     53.253 s ±  0.089 s    [User: 46.480 s, System: 6.748 s]
  Range (min … max):   53.118 s … 53.440 s    10 runs
```
After:
```txt
Benchmark 1: ./build/release/bin/clang-tidy --checks=* all_headers.cpp 
-header-filter=.* -system-headers -- -std=c++23
  Time (mean ± σ):     51.798 s ±  0.126 s    [User: 45.194 s, System: 6.575 s]
  Range (min … max):   51.620 s … 51.995 s    10 runs
```

...which is a nice little speedup for just switching some containers. I
didn't investigate which checks in particular were the source of the
speedup though.

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/altera/IdDependentBackwardBranchCheck.h
    clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
    clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h
    clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
    clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp
    clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.h
    clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp
    clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
    clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.h
    clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.h
    clang-tools-extra/clang-tidy/utils/HeaderGuard.cpp

Removed: 
    


################################################################################
diff  --git 
a/clang-tools-extra/clang-tidy/altera/IdDependentBackwardBranchCheck.h 
b/clang-tools-extra/clang-tidy/altera/IdDependentBackwardBranchCheck.h
index 297e7751e4f49..01a4ccdf1e717 100644
--- a/clang-tools-extra/clang-tidy/altera/IdDependentBackwardBranchCheck.h
+++ b/clang-tools-extra/clang-tidy/altera/IdDependentBackwardBranchCheck.h
@@ -39,9 +39,9 @@ class IdDependentBackwardBranchCheck : public ClangTidyCheck {
     std::string Message;
   };
   // Stores the locations where ID-dependent variables are created.
-  std::map<const VarDecl *, IdDependencyRecord> IdDepVarsMap;
+  llvm::DenseMap<const VarDecl *, IdDependencyRecord> IdDepVarsMap;
   // Stores the locations where ID-dependent fields are created.
-  std::map<const FieldDecl *, IdDependencyRecord> IdDepFieldsMap;
+  llvm::DenseMap<const FieldDecl *, IdDependencyRecord> IdDepFieldsMap;
   /// Returns an IdDependencyRecord if the Expression contains an ID-dependent
   /// variable, returns a nullptr otherwise.
   const IdDependencyRecord *hasIdDepVar(const Expr *Expression);

diff  --git a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
index 892dc02b02298..11e2d2e6a72f4 100644
--- a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
@@ -30,8 +30,7 @@ static constexpr bool DefaultIgnoreMacros = false;
 // either a function body or a lambda body.
 class MacroExpansionsWithFileAndLine : public PPCallbacks {
 public:
-  explicit MacroExpansionsWithFileAndLine(
-      LambdaFunctionNameCheck::SourceRangeSet *SME)
+  explicit MacroExpansionsWithFileAndLine(llvm::DenseSet<SourceRange> *SME)
       : SuppressMacroExpansions(SME) {}
 
   void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
@@ -52,7 +51,7 @@ class MacroExpansionsWithFileAndLine : public PPCallbacks {
   }
 
 private:
-  LambdaFunctionNameCheck::SourceRangeSet *SuppressMacroExpansions;
+  llvm::DenseSet<SourceRange> *SuppressMacroExpansions;
 };
 
 AST_MATCHER(CXXMethodDecl, isInLambda) { return Node.getParent()->isLambda(); }
@@ -97,8 +96,7 @@ void LambdaFunctionNameCheck::check(const 
MatchFinder::MatchResult &Result) {
 
     auto ER =
         Result.SourceManager->getImmediateExpansionRange(E->getLocation());
-    if (SuppressMacroExpansions.find(ER.getAsRange()) !=
-        SuppressMacroExpansions.end()) {
+    if (SuppressMacroExpansions.contains(ER.getAsRange())) {
       // This is a macro expansion for which we should not warn.
       return;
     }

diff  --git a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h 
b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h
index d5655037847d3..5893fe3df1b01 100644
--- a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h
@@ -21,15 +21,6 @@ namespace clang::tidy::bugprone {
 /// 
https://clang.llvm.org/extra/clang-tidy/checks/bugprone/lambda-function-name.html
 class LambdaFunctionNameCheck : public ClangTidyCheck {
 public:
-  struct SourceRangeLessThan {
-    bool operator()(const SourceRange &L, const SourceRange &R) const {
-      if (L.getBegin() == R.getBegin())
-        return L.getEnd() < R.getEnd();
-      return L.getBegin() < R.getBegin();
-    }
-  };
-  using SourceRangeSet = std::set<SourceRange, SourceRangeLessThan>;
-
   LambdaFunctionNameCheck(StringRef Name, ClangTidyContext *Context);
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
     return LangOpts.CPlusPlus11;
@@ -42,7 +33,7 @@ class LambdaFunctionNameCheck : public ClangTidyCheck {
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
 
 private:
-  SourceRangeSet SuppressMacroExpansions;
+  llvm::DenseSet<SourceRange> SuppressMacroExpansions;
   bool IgnoreMacros;
 };
 

diff  --git a/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp 
b/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
index 41521067be86b..3bf96fbb94c8d 100644
--- a/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
+++ b/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
@@ -14,8 +14,8 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
 #include "llvm/Support/FormatVariadic.h"
-#include <map>
 #include <string>
+#include <utility>
 
 using namespace clang::ast_matchers;
 
@@ -70,12 +70,13 @@ static FixItHint getCallFixItHint(const ObjCMessageExpr 
*Expr,
   StringRef Receiver =
       getReceiverString(Expr->getReceiverRange(), SM, LangOpts);
   // Some classes should use standard factory methods instead of alloc/init.
-  std::map<StringRef, StringRef> ClassToFactoryMethodMap = {{"NSDate", "date"},
-                                                            {"NSNull", 
"null"}};
-  auto FoundClassFactory = ClassToFactoryMethodMap.find(Receiver);
-  if (FoundClassFactory != ClassToFactoryMethodMap.end()) {
-    StringRef ClassName = FoundClassFactory->first;
-    StringRef FactorySelector = FoundClassFactory->second;
+  static constexpr std::pair<StringRef, StringRef> ClassToFactoryMethodMap[] = 
{
+      {"NSDate", "date"}, {"NSNull", "null"}};
+  const auto *FoundClassFactory =
+      llvm::find_if(ClassToFactoryMethodMap,
+                    [&](const auto &Entry) { return Entry.first == Receiver; 
});
+  if (FoundClassFactory != std::end(ClassToFactoryMethodMap)) {
+    const auto &[ClassName, FactorySelector] = *FoundClassFactory;
     const std::string NewCall =
         std::string(llvm::formatv("[{0} {1}]", ClassName, FactorySelector));
     return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall);

diff  --git a/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp
index 416aca188e01c..592a4313dc197 100644
--- a/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/IncludeOrderCheck.cpp
@@ -42,7 +42,7 @@ class IncludeOrderPPCallbacks : public PPCallbacks {
   };
 
   using FileIncludes = std::vector<IncludeDirective>;
-  std::map<clang::FileID, FileIncludes> IncludeDirectives;
+  llvm::DenseMap<FileID, FileIncludes> IncludeDirectives;
   bool LookForMainModule = true;
 
   ClangTidyCheck &Check;

diff  --git a/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.h 
b/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.h
index 9c7aff082f8cd..36af07c9fbd17 100644
--- a/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.h
+++ b/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.h
@@ -10,14 +10,12 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_NEWDELETEOVERLOADSCHECK_H
 
 #include "../ClangTidyCheck.h"
-#include "llvm/ADT/SmallVector.h"
-#include <map>
 
 namespace clang::tidy::misc {
 
 class NewDeleteOverloadsCheck : public ClangTidyCheck {
-  std::map<const clang::CXXRecordDecl *,
-           llvm::SmallVector<const clang::FunctionDecl *, 4>>
+  llvm::DenseMap<const CXXRecordDecl *,
+                 llvm::SmallVector<const FunctionDecl *, 4>>
       Overloads;
 
 public:

diff  --git a/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp
index 47363a24abc14..6cebb35a9dad7 100644
--- a/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp
@@ -15,8 +15,6 @@
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
-#include <unordered_map>
-#include <unordered_set>
 
 using namespace clang::ast_matchers;
 
@@ -84,12 +82,12 @@ class UnusedParametersCheck::IndexerVisitor
 public:
   IndexerVisitor(ASTContext &Ctx) { TraverseAST(Ctx); }
 
-  const std::unordered_set<const CallExpr *> &
+  const llvm::SmallPtrSetImpl<const CallExpr *> &
   getFnCalls(const FunctionDecl *Fn) {
     return Index[Fn->getCanonicalDecl()].Calls;
   }
 
-  const std::unordered_set<const DeclRefExpr *> &
+  const llvm::SmallPtrSetImpl<const DeclRefExpr *> &
   getOtherRefs(const FunctionDecl *Fn) {
     return Index[Fn->getCanonicalDecl()].OtherRefs;
   }
@@ -119,11 +117,11 @@ class UnusedParametersCheck::IndexerVisitor
 
 private:
   struct IndexEntry {
-    std::unordered_set<const CallExpr *> Calls;
-    std::unordered_set<const DeclRefExpr *> OtherRefs;
+    llvm::SmallPtrSet<const CallExpr *, 2> Calls;
+    llvm::SmallPtrSet<const DeclRefExpr *, 2> OtherRefs;
   };
 
-  std::unordered_map<const FunctionDecl *, IndexEntry> Index;
+  llvm::DenseMap<const FunctionDecl *, IndexEntry> Index;
 };
 
 UnusedParametersCheck::~UnusedParametersCheck() = default;

diff  --git a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
index bc450ad4a1f2b..137fdb577fca2 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
@@ -21,9 +21,9 @@ namespace clang::tidy::modernize {
 static constexpr char SpecialFunction[] = "SpecialFunction";
 
 /// Finds all the named non-static fields of \p Record.
-static std::set<const FieldDecl *>
+static llvm::SmallPtrSet<const FieldDecl *, 0>
 getAllNamedFields(const CXXRecordDecl *Record) {
-  std::set<const FieldDecl *> Result;
+  llvm::SmallPtrSet<const FieldDecl *, 0> Result;
   for (const auto *Field : Record->fields()) {
     // Static data members are not in this range.
     if (Field->isUnnamedBitField())
@@ -35,8 +35,9 @@ getAllNamedFields(const CXXRecordDecl *Record) {
 
 /// Returns the names of the direct bases of \p Record, both virtual and
 /// non-virtual.
-static std::set<const Type *> getAllDirectBases(const CXXRecordDecl *Record) {
-  std::set<const Type *> Result;
+static llvm::SmallPtrSet<const Type *, 0>
+getAllDirectBases(const CXXRecordDecl *Record) {
+  llvm::SmallPtrSet<const Type *, 0> Result;
   for (auto Base : Record->bases()) {
     // CXXBaseSpecifier.
     const auto *BaseType = Base.getTypeSourceInfo()->getType().getTypePtr();

diff  --git 
a/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.h 
b/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.h
index 183f1fa8b8a8e..c99e4650a44a8 100644
--- a/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.h
@@ -57,7 +57,7 @@ class BracesAroundStatementsCheck : public ClangTidyCheck {
     return TK_IgnoreUnlessSpelledInSource;
   }
 
-  std::set<const Stmt *> ForceBracesStmts;
+  llvm::SmallPtrSet<const Stmt *, 0> ForceBracesStmts;
   const unsigned ShortStatementLines;
 };
 

diff  --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.h 
b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.h
index 7dcb16e4253b8..7931b6898bbf5 100644
--- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.h
@@ -39,7 +39,7 @@ class NonConstParameterCheck : public ClangTidyCheck {
   };
 
   /// Track all nonconst integer/float parameters.
-  std::map<const ParmVarDecl *, ParmInfo> Parameters;
+  llvm::DenseMap<const ParmVarDecl *, ParmInfo> Parameters;
 
   /// Add function parameter.
   void addParm(const ParmVarDecl *Parm);

diff  --git a/clang-tools-extra/clang-tidy/utils/HeaderGuard.cpp 
b/clang-tools-extra/clang-tidy/utils/HeaderGuard.cpp
index 59cae88708377..88012c3a4b48e 100644
--- a/clang-tools-extra/clang-tidy/utils/HeaderGuard.cpp
+++ b/clang-tools-extra/clang-tidy/utils/HeaderGuard.cpp
@@ -261,9 +261,10 @@ class HeaderGuardPPCallbacks : public PPCallbacks {
 
   std::vector<std::pair<Token, const MacroInfo *>> Macros;
   llvm::StringMap<const FileEntry *> Files;
-  std::map<const IdentifierInfo *, std::pair<SourceLocation, SourceLocation>>
+  llvm::DenseMap<const IdentifierInfo *,
+                 std::pair<SourceLocation, SourceLocation>>
       Ifndefs;
-  std::map<SourceLocation, SourceLocation> EndIfs;
+  llvm::DenseMap<SourceLocation, SourceLocation> EndIfs;
 
   Preprocessor *PP;
   HeaderGuardCheck *Check;


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

Reply via email to