11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 using namespace clang::ast_matchers;
18 namespace performance {
20 void InefficientStringConcatenationCheck::storeOptions(
22 Options.store(Opts,
"StrictMode", StrictMode);
25 InefficientStringConcatenationCheck::InefficientStringConcatenationCheck(
27 :
ClangTidyCheck(Name, Context), StrictMode(Options.get(
"StrictMode", 0)) {}
34 const auto BasicStringType =
35 hasType(cxxRecordDecl(hasName(
"::std::basic_string")));
37 const auto BasicStringPlusOperator = cxxOperatorCallExpr(
38 hasOverloadedOperatorName(
"+"),
39 hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))));
41 const auto PlusOperator =
43 hasOverloadedOperatorName(
"+"),
44 hasAnyArgument(ignoringImpCasts(declRefExpr(BasicStringType))),
45 hasDescendant(BasicStringPlusOperator))
46 .bind(
"plusOperator");
48 const auto AssignOperator = cxxOperatorCallExpr(
49 hasOverloadedOperatorName(
"="),
50 hasArgument(0, declRefExpr(BasicStringType,
51 hasDeclaration(decl().bind(
"lhsStrT")))
53 hasArgument(1, stmt(hasDescendant(declRefExpr(
54 hasDeclaration(decl(equalsBoundNode(
"lhsStrT"))))))),
55 hasDescendant(BasicStringPlusOperator));
58 Finder->addMatcher(cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator)),
62 cxxOperatorCallExpr(anyOf(AssignOperator, PlusOperator),
63 hasAncestor(stmt(anyOf(cxxForRangeStmt(),
64 whileStmt(), forStmt())))),
70 const MatchFinder::MatchResult &
Result) {
71 const auto *LhsStr = Result.Nodes.getNodeAs<DeclRefExpr>(
"lhsStr");
72 const auto *PlusOperator =
73 Result.Nodes.getNodeAs<CXXOperatorCallExpr>(
"plusOperator");
75 "string concatenation results in allocation of unnecessary temporary "
76 "strings; consider using 'operator+=' or 'string::append()' instead";
79 diag(LhsStr->getExprLoc(), DiagMsg);
80 else if (PlusOperator)
81 diag(PlusOperator->getExprLoc(), DiagMsg);
LangOptions getLangOpts() const
Returns the language options from the context.
std::unique_ptr< ast_matchers::MatchFinder > Finder
Base class for all clang-tidy checks.
std::map< std::string, std::string > OptionMap
ClangTidyContext & Context
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.