clang-tools  12.0.0git
InefficientStringConcatenationCheck.cpp
Go to the documentation of this file.
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 
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 
13 using namespace clang::ast_matchers;
14 
15 namespace clang {
16 namespace tidy {
17 namespace performance {
18 
19 void InefficientStringConcatenationCheck::storeOptions(
21  Options.store(Opts, "StrictMode", StrictMode);
22 }
23 
24 InefficientStringConcatenationCheck::InefficientStringConcatenationCheck(
25  StringRef Name, ClangTidyContext *Context)
26  : ClangTidyCheck(Name, Context),
27  StrictMode(Options.getLocalOrGlobal("StrictMode", false)) {}
28 
30  MatchFinder *Finder) {
31  const auto BasicStringType =
32  hasType(qualType(hasUnqualifiedDesugaredType(recordType(
33  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string")))))));
34 
35  const auto BasicStringPlusOperator = cxxOperatorCallExpr(
36  hasOverloadedOperatorName("+"),
37  hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))));
38 
39  const auto PlusOperator =
40  cxxOperatorCallExpr(
41  hasOverloadedOperatorName("+"),
42  hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))),
43  hasDescendant(BasicStringPlusOperator))
44  .bind("plusOperator");
45 
46  const auto AssignOperator = cxxOperatorCallExpr(
47  hasOverloadedOperatorName("="),
48  hasArgument(0, declRefExpr(BasicStringType,
49  hasDeclaration(decl().bind("lhsStrT")))
50  .bind("lhsStr")),
51  hasArgument(1, stmt(hasDescendant(declRefExpr(
52  hasDeclaration(decl(equalsBoundNode("lhsStrT"))))))),
53  hasDescendant(BasicStringPlusOperator));
54 
55  if (StrictMode) {
56  Finder->addMatcher(cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator)),
57  this);
58  } else {
59  Finder->addMatcher(
60  cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator),
61  hasAncestor(stmt(anyOf(cxxForRangeStmt(),
62  whileStmt(), forStmt())))),
63  this);
64  }
65 }
66 
68  const MatchFinder::MatchResult &Result) {
69  const auto *LhsStr = Result.Nodes.getNodeAs<DeclRefExpr>("lhsStr");
70  const auto *PlusOperator =
71  Result.Nodes.getNodeAs<CXXOperatorCallExpr>("plusOperator");
72  const auto DiagMsg =
73  "string concatenation results in allocation of unnecessary temporary "
74  "strings; consider using 'operator+=' or 'string::append()' instead";
75 
76  if (LhsStr)
77  diag(LhsStr->getExprLoc(), DiagMsg);
78  else if (PlusOperator)
79  diag(PlusOperator->getExprLoc(), DiagMsg);
80 }
81 
82 } // namespace performance
83 } // namespace tidy
84 } // namespace clang
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
Base class for all clang-tidy checks.
static constexpr llvm::StringLiteral Name
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
std::map< std::string, ClangTidyValue > OptionMap
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check&#39;s name.