aboutsummaryrefslogtreecommitdiff
path: root/clang-tidy/performance
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2016-08-03 23:06:03 +0000
committerAlexander Kornienko <alexfh@google.com>2016-08-03 23:06:03 +0000
commitceb7e1b1682adc2b642dd0eed3e6ef09d5543557 (patch)
tree893bb77f23991aebcae630b07e7b9b20e93754e9 /clang-tidy/performance
parentfbf16ebbf5c0fc7cd316f73ec7908a59d19c539a (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')
-rw-r--r--clang-tidy/performance/CMakeLists.txt1
-rw-r--r--clang-tidy/performance/InefficientStringConcatenationCheck.cpp86
-rw-r--r--clang-tidy/performance/InefficientStringConcatenationCheck.h41
-rw-r--r--clang-tidy/performance/PerformanceTidyModule.cpp3
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>(