clang-tools 6.0.0

ShrinkToFitCheck.cpp
Go to the documentation of this file.
1 //===--- ShrinkToFitCheck.cpp - clang-tidy---------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "ShrinkToFitCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
14 #include "llvm/ADT/StringRef.h"
15
16 using namespace clang::ast_matchers;
17
18 namespace clang {
19 namespace tidy {
20 namespace modernize {
21
22 void ShrinkToFitCheck::registerMatchers(MatchFinder *Finder) {
23 if (!getLangOpts().CPlusPlus11)
24 return;
25
26 // Swap as a function need not to be considered, because rvalue can not
27 // be bound to a non-const reference.
28 const auto ShrinkableAsMember =
29 memberExpr(member(valueDecl().bind("ContainerDecl")));
30 const auto ShrinkableAsDecl =
31 declRefExpr(hasDeclaration(valueDecl().bind("ContainerDecl")));
32 const auto CopyCtorCall = cxxConstructExpr(hasArgument(
33 0, anyOf(ShrinkableAsMember, ShrinkableAsDecl,
34 unaryOperator(has(ignoringParenImpCasts(ShrinkableAsMember))),
35 unaryOperator(has(ignoringParenImpCasts(ShrinkableAsDecl))))));
36 const auto SwapParam =
37 expr(anyOf(memberExpr(member(equalsBoundNode("ContainerDecl"))),
38 declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))),
39 unaryOperator(has(ignoringParenImpCasts(
40 memberExpr(member(equalsBoundNode("ContainerDecl")))))),
41 unaryOperator(has(ignoringParenImpCasts(declRefExpr(
42 hasDeclaration(equalsBoundNode("ContainerDecl"))))))));
43
44 Finder->addMatcher(
45 cxxMemberCallExpr(
46 on(hasType(namedDecl(
47 hasAnyName("std::basic_string", "std::deque", "std::vector")))),
48 callee(cxxMethodDecl(hasName("swap"))),
49 has(ignoringParenImpCasts(memberExpr(hasDescendant(CopyCtorCall)))),
50 hasArgument(0, SwapParam.bind("ContainerToShrink")),
51 unless(isInTemplateInstantiation()))
52 .bind("CopyAndSwapTrick"),
53 this);
54 }
55
56 void ShrinkToFitCheck::check(const MatchFinder::MatchResult &Result) {
57 const auto *MemberCall =
58 Result.Nodes.getNodeAs<CXXMemberCallExpr>("CopyAndSwapTrick");
59 const auto *Container = Result.Nodes.getNodeAs<Expr>("ContainerToShrink");
60 FixItHint Hint;
61
62 if (!MemberCall->getLocStart().isMacroID()) {
63 const LangOptions &Opts = getLangOpts();
64 std::string ReplacementText;
65 if (const auto *UnaryOp = llvm::dyn_cast<UnaryOperator>(Container)) {
66 ReplacementText =
67 Lexer::getSourceText(CharSourceRange::getTokenRange(
68 UnaryOp->getSubExpr()->getSourceRange()),
69 *Result.SourceManager, Opts);
70 ReplacementText += "->shrink_to_fit()";
71 } else {
72 ReplacementText = Lexer::getSourceText(
73 CharSourceRange::getTokenRange(Container->getSourceRange()),
74 *Result.SourceManager, Opts);
75 ReplacementText += ".shrink_to_fit()";
76 }
77
78 Hint = FixItHint::CreateReplacement(MemberCall->getSourceRange(),
79 ReplacementText);
80 }
81
82 diag(MemberCall->getLocStart(), "the shrink_to_fit method should be used "
83 "to reduce the capacity of a shrinkable "
84 "container")
85 << Hint;
86 }
87
88 } // namespace modernize
89 } // namespace tidy
90 } // namespace clang
clang::ast_matchers
Definition: ClangTidyDiagnosticConsumer.h:27
clang
Definition: AndroidTidyModule.cpp:28
ShrinkToFitCheck.h