Index: clang-tidy/performance/InefficientStringAdditionCheck.cpp =================================================================== --- clang-tidy/performance/InefficientStringAdditionCheck.cpp +++ clang-tidy/performance/InefficientStringAdditionCheck.cpp @@ -28,13 +28,13 @@ IsStrictMode(Options.get("isStrictMode", 0)) {} void InefficientStringAdditionCheck::registerMatchers(MatchFinder *Finder) { - auto BasicStringType = hasType(cxxRecordDecl(hasName("::std::basic_string"))); + const auto BasicStringType = hasType(cxxRecordDecl(hasName("::std::basic_string"))); - auto BasicStringPlusOperator = + const auto BasicStringPlusOperator = cxxOperatorCallExpr(hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))), hasOverloadedOperatorName("+")); - auto PlusOperatorMatcher = + const auto PlusOperatorMatcher = cxxBindTemporaryExpr( hasDescendant( cxxOperatorCallExpr(hasDescendant(BasicStringPlusOperator), @@ -43,7 +43,7 @@ .bind("plusOperator"))) .bind("whole-rhs"); - auto AssingOperator = cxxOperatorCallExpr( + const auto AssingOperator = cxxOperatorCallExpr( hasOverloadedOperatorName("="),hasDescendant(BasicStringPlusOperator), allOf(hasArgument( 0, allOf(declRefExpr(BasicStringType), @@ -53,14 +53,14 @@ 1, stmt(hasDescendant(declRefExpr(hasDeclaration(decl( equalsBoundNode("lhsStrT")))) /*.bind("rhs-self")*/))))); - auto DescendantAssignMatcher = hasDescendant(AssingOperator); + const auto DescendantAssignMatcher = hasDescendant(AssingOperator); if (IsStrictMode == 0) { - auto SurroundLoopMatcher = + const auto SurroundLoopMatcher = anyOf(hasAncestor(cxxForRangeStmt()), hasAncestor(whileStmt()), hasAncestor(forStmt())); - auto WholeMatcher = + const auto WholeMatcher = exprWithCleanups(SurroundLoopMatcher, DescendantAssignMatcher); Finder->addMatcher(WholeMatcher, this); @@ -69,9 +69,8 @@ unless(WholeMatcher)), this); } else { - auto WholeMatcher = exprWithCleanups(DescendantAssignMatcher); + const auto WholeMatcher = exprWithCleanups(DescendantAssignMatcher); Finder->addMatcher(WholeMatcher, this); - Finder->addMatcher(exprWithCleanups(hasDescendant(PlusOperatorMatcher), unless(WholeMatcher)), this); Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -184,6 +184,12 @@ Warns about range-based loop with a loop variable of const ref type where the type of the variable does not match the one returned by the iterator. +- New `performance-inefficient-string-addition + `_ check + + This check is to warn about the performance overhead arising from concatenating + strings, using the operator+, instead of operator+=. + - New `performance-unnecessary-value-param `_ check Index: docs/clang-tidy/checks/performance-inefficient-string-addition.rst =================================================================== --- docs/clang-tidy/checks/performance-inefficient-string-addition.rst +++ docs/clang-tidy/checks/performance-inefficient-string-addition.rst @@ -1,24 +1,22 @@ .. title:: clang-tidy - performance-inefficient-string-addition performance-inefficient-string-addition -===================================== +======================================= The problem ------------------- +----------- This check is to warn about the performance overhead arising from concatenating strings, using the operator+, for instance: .. code:: c++ - - std::string a = "Foo", b = "Bar"; + std::string a("Foo"), b("Bar"); a = a + b; -Instead of this structure you should use **operator+=** or std::string's (std::basic_string) class member function **append**. For instance: +Instead of this structure you should use `operator+=` or std::string's (std::basic_string) class member function `append`. For instance: .. code:: c++ - - std::string a = "Foo", b = "Baz"; + std::string a("Foo"), b("Baz"); for(int i = 0; i < 20000; ++i) { a = a + "Bar" + b; @@ -28,7 +26,7 @@ .. code:: c++ - std::string a = "Foo", b = "Baz"; + std::string a("Foo"), b("Baz"); for(int i = 0; i < 20000; ++i) { a.append("Bar").append(b); @@ -39,10 +37,10 @@ .. code:: c++ void f(const std::string&){} - std::string a = "Foo", b = "Baz"; + std::string a("Foo"), b("Baz"); void g() { - f(a+"Bar"+b); + f(a + "Bar" + b); } In a slightly more efficient way like: @@ -50,8 +48,8 @@ .. code:: c++ void f(const std::string&){} - std::string a = "Foo", b = "Baz"; + std::string a("Foo"), b("Baz"); void g() { f(std::string(a).append("Bar").append(b)); - } \ No newline at end of file + } Index: test/clang-tidy/performance-inefficient-string-addition.cpp =================================================================== --- test/clang-tidy/performance-inefficient-string-addition.cpp +++ test/clang-tidy/performance-inefficient-string-addition.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s performance-inefficient-string-addition %t -- -- -std=c++11 +// RUN: %check_clang_tidy %s performance-inefficient-string-addition %t namespace std { template @@ -24,11 +24,11 @@ f(mystr1 + mystr2 + mystr1); // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: Inefficient string concatenation mystr1 = mystr1 + mystr2; - // CHECK-MESSAGES: :[[@LINE-1]]:2: warning: Ineff + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: Ineff mystr1 = mystr2 + mystr2 + mystr2; - // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: Ineff + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: Ineff mystr1 = mystr2 + mystr1; - // CHECK-MESSAGES: :[[@LINE-1]]:2: warning: Ineff + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: Ineff mywstr1 = mywstr2 + mywstr1; // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: Ineff mywstr1 = mywstr2 + mywstr2 + mywstr2; @@ -41,4 +41,4 @@ mystr1 = g(mystr1); } return 0; -} \ No newline at end of file +}