clang-tools 22.0.0git
InefficientStringConcatenationCheck.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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/ASTMatchers/ASTMatchFinder.h"
11
12using namespace clang::ast_matchers;
13
15
18 Options.store(Opts, "StrictMode", StrictMode);
19}
20
22 StringRef Name, ClangTidyContext *Context)
23 : ClangTidyCheck(Name, Context),
24 StrictMode(Options.get("StrictMode", false)) {}
25
27 MatchFinder *Finder) {
28 const auto BasicStringType =
29 hasType(qualType(hasUnqualifiedDesugaredType(recordType(
30 hasDeclaration(cxxRecordDecl(hasName("::std::basic_string")))))));
31
32 const auto BasicStringPlusOperator = cxxOperatorCallExpr(
33 hasOverloadedOperatorName("+"),
34 hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))));
35
36 const auto PlusOperator =
37 cxxOperatorCallExpr(
38 hasOverloadedOperatorName("+"),
39 hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))),
40 hasDescendant(BasicStringPlusOperator))
41 .bind("plusOperator");
42
43 const auto AssignOperator = cxxOperatorCallExpr(
44 hasOverloadedOperatorName("="),
45 hasArgument(0, declRefExpr(BasicStringType,
46 hasDeclaration(decl().bind("lhsStrT")))
47 .bind("lhsStr")),
48 hasArgument(1, stmt(hasDescendant(declRefExpr(
49 hasDeclaration(decl(equalsBoundNode("lhsStrT"))))))),
50 hasDescendant(BasicStringPlusOperator));
51
52 if (StrictMode) {
53 Finder->addMatcher(cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator)),
54 this);
55 } else {
56 Finder->addMatcher(
57 cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator),
58 hasAncestor(stmt(anyOf(cxxForRangeStmt(),
59 whileStmt(), forStmt())))),
60 this);
61 }
62}
63
65 const MatchFinder::MatchResult &Result) {
66 const auto *LhsStr = Result.Nodes.getNodeAs<DeclRefExpr>("lhsStr");
67 const auto *PlusOperator =
68 Result.Nodes.getNodeAs<CXXOperatorCallExpr>("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(PlusOperator->getExprLoc(), DiagMsg);
77}
78
79} // namespace clang::tidy::performance
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
llvm::StringMap< ClangTidyValue > OptionMap