clang-tools 3.8.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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 {
20 bool isShrinkableContainer(llvm::StringRef ClassName) {
21 static const char *const Shrinkables[] = {
22 "std::basic_string",
23 "std::deque",
24 "std::vector"
25 };
26 return std::binary_search(std::begin(Shrinkables), std::end(Shrinkables),
27 ClassName);
28 }
29
30 AST_MATCHER(NamedDecl, stlShrinkableContainer) {
31 return isShrinkableContainer(Node.getQualifiedNameAsString());
32 }
33 } // namespace
34
35 namespace tidy {
36 namespace modernize {
37
38 void ShrinkToFitCheck::registerMatchers(MatchFinder *Finder) {
39 // Swap as a function need not to be considered, because rvalue can not
40 // be bound to a non-const reference.
41 const auto ShrinkableAsMember =
42 memberExpr(member(valueDecl().bind("ContainerDecl")));
43 const auto ShrinkableAsDecl =
44 declRefExpr(hasDeclaration(valueDecl().bind("ContainerDecl")));
45 const auto CopyCtorCall = cxxConstructExpr(
46 hasArgument(0, anyOf(ShrinkableAsMember, ShrinkableAsDecl,
47 unaryOperator(has(ShrinkableAsMember)),
48 unaryOperator(has(ShrinkableAsDecl)))));
49 const auto SwapParam = expr(anyOf(
50 memberExpr(member(equalsBoundNode("ContainerDecl"))),
51 declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))),
52 unaryOperator(has(memberExpr(member(equalsBoundNode("ContainerDecl"))))),
53 unaryOperator(
54 has(declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl")))))));
55
56 Finder->addMatcher(
57 cxxMemberCallExpr(on(hasType(namedDecl(stlShrinkableContainer()))),
58 callee(cxxMethodDecl(hasName("swap"))),
59 has(memberExpr(hasDescendant(CopyCtorCall))),
60 hasArgument(0, SwapParam.bind("ContainerToShrink")),
61 unless(isInTemplateInstantiation()))
62 .bind("CopyAndSwapTrick"),
63 this);
64 }
65
66 void ShrinkToFitCheck::check(const MatchFinder::MatchResult &Result) {
67 const LangOptions &Opts = Result.Context->getLangOpts();
68
69 if (!Opts.CPlusPlus11)
70 return;
71
72 const auto *MemberCall =
73 Result.Nodes.getNodeAs<CXXMemberCallExpr>("CopyAndSwapTrick");
74 const auto *Container = Result.Nodes.getNodeAs<Expr>("ContainerToShrink");
75 FixItHint Hint;
76
77 if (!MemberCall->getLocStart().isMacroID()) {
78 std::string ReplacementText;
79 if (const auto *UnaryOp = llvm::dyn_cast<UnaryOperator>(Container)) {
80 ReplacementText =
81 Lexer::getSourceText(CharSourceRange::getTokenRange(
82 UnaryOp->getSubExpr()->getSourceRange()),
83 *Result.SourceManager, Opts);
84 ReplacementText += "->shrink_to_fit()";
85 } else {
86 ReplacementText = Lexer::getSourceText(
87 CharSourceRange::getTokenRange(Container->getSourceRange()),
88 *Result.SourceManager, Opts);
89 ReplacementText += ".shrink_to_fit()";
90 }
91
92 Hint = FixItHint::CreateReplacement(MemberCall->getSourceRange(),
93 ReplacementText);
94 }
95
96 diag(MemberCall->getLocStart(), "the shrink_to_fit method should be used "
97 "to reduce the capacity of a shrinkable "
98 "container")
99 << Hint;
100 }
101
102 } // namespace modernize
103 } // namespace tidy
104 } // namespace clang
Finder
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:188
clang::tidy::AST_MATCHER
AST_MATCHER(Stmt, isInsideOfRangeBeginEndStmt)
Definition: ProBoundsArrayToPointerDecayCheck.cpp:25
ShrinkToFitCheck.h
Result
const NamedDecl * Result
Definition: USRFinder.cpp:121