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
