80 lines · cpp
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-exception6//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(Opts, "StrictMode", StrictMode);19}20 21InefficientStringConcatenationCheck::InefficientStringConcatenationCheck(22 StringRef Name, ClangTidyContext *Context)23 : ClangTidyCheck(Name, Context),24 StrictMode(Options.get("StrictMode", false)) {}25 26void InefficientStringConcatenationCheck::registerMatchers(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 64void InefficientStringConcatenationCheck::check(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::performance80