1//===--- InefficientStringConcatenationCheck.cpp - clang-tidy--------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "InefficientStringConcatenationCheck.h"
10#include "clang/ASTMatchers/ASTMatchFinder.h"
11
12using namespace clang::ast_matchers;
13
14namespace clang::tidy::performance {
15
16void InefficientStringConcatenationCheck::storeOptions(
17 ClangTidyOptions::OptionMap &Opts) {
18 Options.store(Options&: Opts, LocalName: "StrictMode", Value: StrictMode);
19}
20
21InefficientStringConcatenationCheck::InefficientStringConcatenationCheck(
22 StringRef Name, ClangTidyContext *Context)
23 : ClangTidyCheck(Name, Context),
24 StrictMode(Options.getLocalOrGlobal(LocalName: "StrictMode", Default: false)) {}
25
26void InefficientStringConcatenationCheck::registerMatchers(
27 MatchFinder *Finder) {
28 const auto BasicStringType =
29 hasType(InnerMatcher: qualType(hasUnqualifiedDesugaredType(InnerMatcher: recordType(
30 hasDeclaration(InnerMatcher: cxxRecordDecl(hasName(Name: "::std::basic_string")))))));
31
32 const auto BasicStringPlusOperator = cxxOperatorCallExpr(
33 hasOverloadedOperatorName(Name: "+"),
34 hasAnyArgument(InnerMatcher: ignoringImpCasts(InnerMatcher: declRefExpr(BasicStringType))));
35
36 const auto PlusOperator =
37 cxxOperatorCallExpr(
38 hasOverloadedOperatorName(Name: "+"),
39 hasAnyArgument(InnerMatcher: ignoringImpCasts(InnerMatcher: declRefExpr(BasicStringType))),
40 hasDescendant(BasicStringPlusOperator))
41 .bind(ID: "plusOperator");
42
43 const auto AssignOperator = cxxOperatorCallExpr(
44 hasOverloadedOperatorName(Name: "="),
45 hasArgument(N: 0, InnerMatcher: declRefExpr(BasicStringType,
46 hasDeclaration(InnerMatcher: decl().bind(ID: "lhsStrT")))
47 .bind(ID: "lhsStr")),
48 hasArgument(N: 1, InnerMatcher: stmt(hasDescendant(declRefExpr(
49 hasDeclaration(InnerMatcher: decl(equalsBoundNode(ID: "lhsStrT"))))))),
50 hasDescendant(BasicStringPlusOperator));
51
52 if (StrictMode) {
53 Finder->addMatcher(NodeMatch: cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator)),
54 Action: this);
55 } else {
56 Finder->addMatcher(
57 NodeMatch: cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator),
58 hasAncestor(stmt(anyOf(cxxForRangeStmt(),
59 whileStmt(), forStmt())))),
60 Action: this);
61 }
62}
63
64void InefficientStringConcatenationCheck::check(
65 const MatchFinder::MatchResult &Result) {
66 const auto *LhsStr = Result.Nodes.getNodeAs<DeclRefExpr>(ID: "lhsStr");
67 const auto *PlusOperator =
68 Result.Nodes.getNodeAs<CXXOperatorCallExpr>(ID: "plusOperator");
69 const char *DiagMsg =
70 "string concatenation results in allocation of unnecessary temporary "
71 "strings; consider using 'operator+=' or 'string::append()' instead";
72
73 if (LhsStr)
74 diag(LhsStr->getExprLoc(), DiagMsg);
75 else if (PlusOperator)
76 diag(Loc: PlusOperator->getExprLoc(), Description: DiagMsg);
77}
78
79} // namespace clang::tidy::performance
80

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.cpp