brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.0 KiB · e32ddbf Raw
77 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 "ShrinkToFitCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "clang/Lex/Lexer.h"13#include "llvm/ADT/StringRef.h"14 15using namespace clang::ast_matchers;16 17namespace clang::tidy::modernize {18 19void ShrinkToFitCheck::registerMatchers(MatchFinder *Finder) {20  // Swap as a function need not to be considered, because rvalue can not21  // be bound to a non-const reference.22  const auto ShrinkableExpr = mapAnyOf(memberExpr, declRefExpr);23  const auto Shrinkable =24      ShrinkableExpr.with(hasDeclaration(valueDecl().bind("ContainerDecl")));25  const auto BoundShrinkable = ShrinkableExpr.with(26      hasDeclaration(valueDecl(equalsBoundNode("ContainerDecl"))));27 28  Finder->addMatcher(29      cxxMemberCallExpr(30          callee(cxxMethodDecl(hasName("swap"))),31          hasArgument(32              0, anyOf(Shrinkable, unaryOperator(hasUnaryOperand(Shrinkable)))),33          on(cxxConstructExpr(hasArgument(34              0,35              expr(anyOf(BoundShrinkable,36                         unaryOperator(hasUnaryOperand(BoundShrinkable))),37                   hasType(hasCanonicalType(hasDeclaration(namedDecl(hasAnyName(38                       "std::basic_string", "std::deque", "std::vector"))))))39                  .bind("ContainerToShrink")))))40          .bind("CopyAndSwapTrick"),41      this);42}43 44void ShrinkToFitCheck::check(const MatchFinder::MatchResult &Result) {45  const auto *MemberCall =46      Result.Nodes.getNodeAs<CXXMemberCallExpr>("CopyAndSwapTrick");47  const auto *Container = Result.Nodes.getNodeAs<Expr>("ContainerToShrink");48  FixItHint Hint;49 50  if (!MemberCall->getBeginLoc().isMacroID()) {51    const LangOptions &Opts = getLangOpts();52    std::string ReplacementText;53    if (const auto *UnaryOp = llvm::dyn_cast<UnaryOperator>(Container)) {54      ReplacementText = std::string(55          Lexer::getSourceText(CharSourceRange::getTokenRange(56                                   UnaryOp->getSubExpr()->getSourceRange()),57                               *Result.SourceManager, Opts));58      ReplacementText += "->shrink_to_fit()";59    } else {60      ReplacementText = std::string(Lexer::getSourceText(61          CharSourceRange::getTokenRange(Container->getSourceRange()),62          *Result.SourceManager, Opts));63      ReplacementText += ".shrink_to_fit()";64    }65 66    Hint = FixItHint::CreateReplacement(MemberCall->getSourceRange(),67                                        ReplacementText);68  }69 70  diag(MemberCall->getBeginLoc(), "the shrink_to_fit method should be used "71                                  "to reduce the capacity of a shrinkable "72                                  "container")73      << Hint;74}75 76} // namespace clang::tidy::modernize77