10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 12 #include "clang/Basic/LLVM.h" 13 #include "clang/Basic/LangOptions.h" 14 #include "clang/Basic/SourceLocation.h" 15 #include "clang/Lex/Lexer.h" 16 #include "llvm/ADT/ArrayRef.h" 17 #include "llvm/ADT/SmallSet.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/STLExtras.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Support/Regex.h" 23 #include "llvm/Support/raw_ostream.h" 40 BindArgumentKind
Kind = BK_Other;
46 static SmallVector<BindArgument, 4>
48 SmallVector<BindArgument, 4> BindArguments;
49 llvm::Regex MatchPlaceholder(
"^_([0-9]+)$");
52 for (
size_t I = 1, ArgCount = C->getNumArgs(); I < ArgCount; ++I) {
53 const Expr *E = C->getArg(I);
55 if (
const auto *M = dyn_cast<MaterializeTemporaryExpr>(E)) {
56 const auto *TE = M->GetTemporaryExpr();
57 B.Kind = isa<CallExpr>(TE) ? BK_CallExpr : BK_Temporary;
60 B.Tokens = Lexer::getSourceText(
62 *Result.SourceManager, Result.Context->getLangOpts());
64 SmallVector<StringRef, 2> Matches;
65 if (B.Kind == BK_Other && MatchPlaceholder.match(B.Tokens, &Matches)) {
66 B.Kind = BK_Placeholder;
67 B.PlaceHolderIndex = std::stoi(Matches[1]);
69 BindArguments.push_back(B);
75 llvm::raw_ostream &Stream) {
76 auto MaxPlaceholderIt =
77 std::max_element(Args.begin(), Args.end(),
78 [](
const BindArgument &B1,
const BindArgument &B2) {
79 return B1.PlaceHolderIndex < B2.PlaceHolderIndex;
83 if (MaxPlaceholderIt == Args.end() || MaxPlaceholderIt->PlaceHolderIndex == 0)
86 size_t PlaceholderCount = MaxPlaceholderIt->PlaceHolderIndex;
88 StringRef Delimiter =
"";
89 for (
size_t I = 1; I <= PlaceholderCount; ++I) {
90 Stream << Delimiter <<
"auto && arg" << I;
97 llvm::raw_ostream &Stream) {
98 StringRef Delimiter =
"";
99 for (
const auto &B : Args) {
100 if (B.PlaceHolderIndex)
101 Stream << Delimiter <<
"arg" << B.PlaceHolderIndex;
103 Stream << Delimiter << B.Tokens;
109 llvm::SmallSet<size_t, 4> PlaceHolderIndices;
110 for (
const BindArgument &B : Args) {
111 if (B.PlaceHolderIndex) {
112 if (!PlaceHolderIndices.insert(B.PlaceHolderIndex).second)
119 void AvoidBindCheck::registerMatchers(MatchFinder *Finder) {
120 if (!getLangOpts().CPlusPlus14)
125 callee(namedDecl(hasName(
"::std::bind"))),
126 hasArgument(0, declRefExpr(to(functionDecl().bind(
"f"))).bind(
"ref")))
131 void AvoidBindCheck::check(
const MatchFinder::MatchResult &
Result) {
132 const auto *MatchedDecl = Result.Nodes.getNodeAs<CallExpr>(
"bind");
133 auto Diag = diag(MatchedDecl->getBeginLoc(),
"prefer a lambda to std::bind");
141 if (llvm::any_of(Args,
142 [](
const BindArgument &B) {
return B.Kind == BK_CallExpr; }))
151 const auto *F = Result.Nodes.getNodeAs<FunctionDecl>(
"f");
157 if (F->getNumParams() != Args.size())
161 llvm::raw_string_ostream Stream(Buffer);
163 bool HasCapturedArgument = llvm::any_of(
164 Args, [](
const BindArgument &B) {
return B.Kind == BK_Other; });
165 const auto *Ref = Result.Nodes.getNodeAs<DeclRefExpr>(
"ref");
166 Stream <<
"[" << (HasCapturedArgument ?
"=" :
"") <<
"]";
168 Stream <<
" { return ";
169 Ref->printPretty(Stream,
nullptr, Result.Context->getPrintingPolicy());
174 Diag << FixItHint::CreateReplacement(MatchedDecl->getSourceRange(),
static bool isPlaceHolderIndexRepeated(const ArrayRef< BindArgument > Args)
static void addFunctionCallArgs(const ArrayRef< BindArgument > Args, llvm::raw_ostream &Stream)
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
static void addPlaceholderArgs(const ArrayRef< BindArgument > Args, llvm::raw_ostream &Stream)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static SmallVector< BindArgument, 4 > buildBindArguments(const MatchFinder::MatchResult &Result, const CallExpr *C)
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result