diff options
author | Alexander Kornienko <alexfh@google.com> | 2016-08-03 23:06:03 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2016-08-03 23:06:03 +0000 |
commit | ceb7e1b1682adc2b642dd0eed3e6ef09d5543557 (patch) | |
tree | 893bb77f23991aebcae630b07e7b9b20e93754e9 /clang-tidy/performance | |
parent | fbf16ebbf5c0fc7cd316f73ec7908a59d19c539a (diff) |
[clang-tidy] Inefficient string operation
Patch by Bittner Barni!
Differential revision: https://reviews.llvm.org/D20196
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@277677 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'clang-tidy/performance')
4 files changed, 131 insertions, 0 deletions
diff --git a/clang-tidy/performance/CMakeLists.txt b/clang-tidy/performance/CMakeLists.txt index 32d8a240..71becce5 100644 --- a/clang-tidy/performance/CMakeLists.txt +++ b/clang-tidy/performance/CMakeLists.txt @@ -4,6 +4,7 @@ add_clang_library(clangTidyPerformanceModule FasterStringFindCheck.cpp ForRangeCopyCheck.cpp ImplicitCastInLoopCheck.cpp + InefficientStringConcatenationCheck.cpp PerformanceTidyModule.cpp UnnecessaryCopyInitialization.cpp UnnecessaryValueParamCheck.cpp diff --git a/clang-tidy/performance/InefficientStringConcatenationCheck.cpp b/clang-tidy/performance/InefficientStringConcatenationCheck.cpp new file mode 100644 index 00000000..9e03fbc1 --- /dev/null +++ b/clang-tidy/performance/InefficientStringConcatenationCheck.cpp @@ -0,0 +1,86 @@ +//===--- InefficientStringConcatenationCheck.cpp - clang-tidy--------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "InefficientStringConcatenationCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace performance { + +void InefficientStringConcatenationCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "StrictMode", StrictMode); +} + +InefficientStringConcatenationCheck::InefficientStringConcatenationCheck( + StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), StrictMode(Options.get("StrictMode", 0)) {} + +void InefficientStringConcatenationCheck::registerMatchers( + MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + + const auto BasicStringType = + hasType(cxxRecordDecl(hasName("::std::basic_string"))); + + const auto BasicStringPlusOperator = cxxOperatorCallExpr( + hasOverloadedOperatorName("+"), + hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType)))); + + const auto PlusOperator = + cxxOperatorCallExpr( + hasOverloadedOperatorName("+"), + hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))), + hasDescendant(BasicStringPlusOperator)) + .bind("plusOperator"); + + const auto AssignOperator = cxxOperatorCallExpr( + hasOverloadedOperatorName("="), + hasArgument(0, declRefExpr(BasicStringType, + hasDeclaration(decl().bind("lhsStrT"))) + .bind("lhsStr")), + hasArgument(1, stmt(hasDescendant(declRefExpr( + hasDeclaration(decl(equalsBoundNode("lhsStrT"))))))), + hasDescendant(BasicStringPlusOperator)); + + if (StrictMode) { + Finder->addMatcher(cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator)), + this); + } else { + Finder->addMatcher( + cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator), + hasAncestor(stmt(anyOf(cxxForRangeStmt(), + whileStmt(), forStmt())))), + this); + } +} + +void InefficientStringConcatenationCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *LhsStr = Result.Nodes.getNodeAs<DeclRefExpr>("lhsStr"); + const auto *PlusOperator = + Result.Nodes.getNodeAs<CXXOperatorCallExpr>("plusOperator"); + const auto DiagMsg = + "string concatenation results in allocation of unnecessary temporary " + "strings; consider using 'operator+=' or 'string::append()' instead"; + + if (LhsStr) + diag(LhsStr->getExprLoc(), DiagMsg); + else if (PlusOperator) + diag(PlusOperator->getExprLoc(), DiagMsg); +} + +} // namespace performance +} // namespace tidy +} // namespace clang diff --git a/clang-tidy/performance/InefficientStringConcatenationCheck.h b/clang-tidy/performance/InefficientStringConcatenationCheck.h new file mode 100644 index 00000000..12a154c2 --- /dev/null +++ b/clang-tidy/performance/InefficientStringConcatenationCheck.h @@ -0,0 +1,41 @@ +//===--- InefficientStringConcatenationCheck.h - clang-tidy-----------*- C++ +//-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENTSTRINGCONCATENATION_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENTSTRINGCONCATENATION_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace performance { + +/// This check is to warn about the performance overhead arising from +/// concatenating strings, using the operator+, instead of operator+=. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/performance-inefficient-string-concatenation.html +class InefficientStringConcatenationCheck : public ClangTidyCheck { +public: + InefficientStringConcatenationCheck(StringRef Name, + ClangTidyContext *Context); + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + +private: + const bool StrictMode; +}; + +} // namespace performance +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_INEFFICIENTSTRINGCONCATENATION_H diff --git a/clang-tidy/performance/PerformanceTidyModule.cpp b/clang-tidy/performance/PerformanceTidyModule.cpp index 984a9fb2..a722ffb1 100644 --- a/clang-tidy/performance/PerformanceTidyModule.cpp +++ b/clang-tidy/performance/PerformanceTidyModule.cpp @@ -10,6 +10,7 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "InefficientStringConcatenationCheck.h" #include "FasterStringFindCheck.h" #include "ForRangeCopyCheck.h" @@ -30,6 +31,8 @@ public: "performance-for-range-copy"); CheckFactories.registerCheck<ImplicitCastInLoopCheck>( "performance-implicit-cast-in-loop"); + CheckFactories.registerCheck<InefficientStringConcatenationCheck>( + "performance-inefficient-string-concatenation"); CheckFactories.registerCheck<UnnecessaryCopyInitialization>( "performance-unnecessary-copy-initialization"); CheckFactories.registerCheck<UnnecessaryValueParamCheck>( |