brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.0 KiB · 92e3220 Raw
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