Home | History | Annotate | Download | only in base_bind_rewriters
      1 // Copyright 2016 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <assert.h>
      6 #include <stdlib.h>
      7 #include <algorithm>
      8 #include <memory>
      9 #include <string>
     10 
     11 #include "clang/AST/ASTContext.h"
     12 #include "clang/AST/ParentMap.h"
     13 #include "clang/ASTMatchers/ASTMatchFinder.h"
     14 #include "clang/ASTMatchers/ASTMatchers.h"
     15 #include "clang/ASTMatchers/ASTMatchersMacros.h"
     16 #include "clang/Analysis/CFG.h"
     17 #include "clang/Basic/SourceManager.h"
     18 #include "clang/Frontend/FrontendActions.h"
     19 #include "clang/Lex/Lexer.h"
     20 #include "clang/Tooling/CommonOptionsParser.h"
     21 #include "clang/Tooling/Refactoring.h"
     22 #include "clang/Tooling/Tooling.h"
     23 #include "llvm/Support/CommandLine.h"
     24 #include "llvm/Support/TargetSelect.h"
     25 
     26 using Replacements = std::vector<clang::tooling::Replacement>;
     27 using clang::ASTContext;
     28 using clang::CFG;
     29 using clang::CFGBlock;
     30 using clang::CFGLifetimeEnds;
     31 using clang::CFGStmt;
     32 using clang::CallExpr;
     33 using clang::Decl;
     34 using clang::DeclRefExpr;
     35 using clang::FunctionDecl;
     36 using clang::LambdaExpr;
     37 using clang::Stmt;
     38 using clang::UnaryOperator;
     39 using clang::ast_type_traits::DynTypedNode;
     40 using clang::tooling::CommonOptionsParser;
     41 using namespace clang::ast_matchers;
     42 
     43 namespace {
     44 
     45 class Rewriter {
     46  public:
     47   virtual ~Rewriter() {}
     48 };
     49 
     50 // Removes unneeded base::Passed() on a parameter of base::BindOnce().
     51 // Example:
     52 //   // Before
     53 //   base::BindOnce(&Foo, base::Passed(&bar));
     54 //   base::BindOnce(&Foo, base::Passed(std::move(baz)));
     55 //   base::BindOnce(&Foo, base::Passed(qux));
     56 //
     57 //   // After
     58 //   base::BindOnce(&Foo, std::move(bar));
     59 //   base::BindOnce(&Foo, std::move(baz));
     60 //   base::BindOnce(&Foo, std::move(*qux));
     61 class PassedToMoveRewriter : public MatchFinder::MatchCallback,
     62                              public Rewriter {
     63  public:
     64   explicit PassedToMoveRewriter(Replacements* replacements)
     65       : replacements_(replacements) {}
     66 
     67   StatementMatcher GetMatcher() {
     68     auto is_passed = namedDecl(hasName("::base::Passed"));
     69     auto is_bind_once_call = callee(namedDecl(hasName("::base::BindOnce")));
     70 
     71     // Matches base::Passed() call on a base::BindOnce() argument.
     72     return callExpr(is_bind_once_call,
     73                     hasAnyArgument(ignoringImplicit(
     74                         callExpr(callee(is_passed)).bind("target"))));
     75   }
     76 
     77   void run(const MatchFinder::MatchResult& result) override {
     78     auto* target = result.Nodes.getNodeAs<CallExpr>("target");
     79     auto* callee = target->getCallee()->IgnoreImpCasts();
     80 
     81     auto* callee_decl = clang::dyn_cast<DeclRefExpr>(callee)->getDecl();
     82     auto* passed_decl = clang::dyn_cast<FunctionDecl>(callee_decl);
     83     auto* param_type = passed_decl->getParamDecl(0)->getType().getTypePtr();
     84 
     85     if (param_type->isRValueReferenceType()) {
     86       // base::Passed(xxx) -> xxx.
     87       // The parameter type is already an rvalue reference.
     88       // Example:
     89       //   std::unique_ptr<int> foo();
     90       //   std::unique_ptr<int> bar;
     91       //   base::Passed(foo());
     92       //   base::Passed(std::move(bar));
     93       // In these cases, we can just remove base::Passed.
     94       auto left = clang::CharSourceRange::getTokenRange(
     95           result.SourceManager->getSpellingLoc(target->getLocStart()),
     96           result.SourceManager->getSpellingLoc(target->getArg(0)->getExprLoc())
     97               .getLocWithOffset(-1));
     98       auto r_paren = clang::CharSourceRange::getTokenRange(
     99           result.SourceManager->getSpellingLoc(target->getRParenLoc()),
    100           result.SourceManager->getSpellingLoc(target->getRParenLoc()));
    101       replacements_->emplace_back(*result.SourceManager, left, " ");
    102       replacements_->emplace_back(*result.SourceManager, r_paren, " ");
    103       return;
    104     }
    105 
    106     if (!param_type->isPointerType())
    107       return;
    108 
    109     auto* passed_arg = target->getArg(0)->IgnoreImpCasts();
    110     if (auto* unary = clang::dyn_cast<clang::UnaryOperator>(passed_arg)) {
    111       if (unary->getOpcode() == clang::UO_AddrOf) {
    112         // base::Passed(&xxx) -> std::move(xxx).
    113         auto left = clang::CharSourceRange::getTokenRange(
    114             result.SourceManager->getSpellingLoc(target->getLocStart()),
    115             result.SourceManager->getSpellingLoc(
    116                 target->getArg(0)->getExprLoc()));
    117         replacements_->emplace_back(*result.SourceManager, left, "std::move(");
    118         return;
    119       }
    120     }
    121 
    122     // base::Passed(xxx) -> std::move(*xxx)
    123     auto left = clang::CharSourceRange::getTokenRange(
    124         result.SourceManager->getSpellingLoc(target->getLocStart()),
    125         result.SourceManager->getSpellingLoc(target->getArg(0)->getExprLoc())
    126             .getLocWithOffset(-1));
    127     replacements_->emplace_back(*result.SourceManager, left, "std::move(*");
    128   }
    129 
    130  private:
    131   Replacements* replacements_;
    132 };
    133 
    134 // Replace base::Bind() to base::BindOnce() where resulting base::Callback is
    135 // implicitly converted into base::OnceCallback.
    136 // Example:
    137 //   // Before
    138 //   base::PostTask(FROM_HERE, base::Bind(&Foo));
    139 //   base::OnceCallback<void()> cb = base::Bind(&Foo);
    140 //
    141 //   // After
    142 //   base::PostTask(FROM_HERE, base::BindOnce(&Foo));
    143 //   base::OnceCallback<void()> cb = base::BindOnce(&Foo);
    144 class BindOnceRewriter : public MatchFinder::MatchCallback, public Rewriter {
    145  public:
    146   explicit BindOnceRewriter(Replacements* replacements)
    147       : replacements_(replacements) {}
    148 
    149   StatementMatcher GetMatcher() {
    150     auto is_once_callback = hasType(hasCanonicalType(hasDeclaration(
    151         classTemplateSpecializationDecl(hasName("::base::OnceCallback")))));
    152     auto is_repeating_callback =
    153         hasType(hasCanonicalType(hasDeclaration(classTemplateSpecializationDecl(
    154             hasName("::base::RepeatingCallback")))));
    155 
    156     auto bind_call =
    157         callExpr(callee(namedDecl(hasName("::base::Bind")))).bind("target");
    158     auto parameter_construction =
    159         cxxConstructExpr(is_repeating_callback, argumentCountIs(1),
    160                          hasArgument(0, ignoringImplicit(bind_call)));
    161     auto constructor_conversion = cxxConstructExpr(
    162         is_once_callback, argumentCountIs(1),
    163         hasArgument(0, ignoringImplicit(parameter_construction)));
    164     return implicitCastExpr(is_once_callback,
    165                             hasSourceExpression(constructor_conversion));
    166   }
    167 
    168   void run(const MatchFinder::MatchResult& result) override {
    169     auto* target = result.Nodes.getNodeAs<clang::CallExpr>("target");
    170     auto* callee = target->getCallee();
    171     auto range = clang::CharSourceRange::getTokenRange(
    172         result.SourceManager->getSpellingLoc(callee->getLocEnd()),
    173         result.SourceManager->getSpellingLoc(callee->getLocEnd()));
    174     replacements_->emplace_back(*result.SourceManager, range, "BindOnce");
    175   }
    176 
    177  private:
    178   Replacements* replacements_;
    179 };
    180 
    181 // Converts pass-by-const-ref base::Callback's to pass-by-value.
    182 // Example:
    183 //   // Before
    184 //   using BarCallback = base::Callback<void(void*)>;
    185 //   void Foo(const base::Callback<void(int)>& cb);
    186 //   void Bar(const BarCallback& cb);
    187 //
    188 //   // After
    189 //   using BarCallback = base::Callback<void(void*)>;
    190 //   void Foo(base::Callback<void(int)> cb);
    191 //   void Bar(BarCallback cb);
    192 class PassByValueRewriter : public MatchFinder::MatchCallback, public Rewriter {
    193  public:
    194   explicit PassByValueRewriter(Replacements* replacements)
    195       : replacements_(replacements) {}
    196 
    197   DeclarationMatcher GetMatcher() {
    198     auto is_repeating_callback =
    199         namedDecl(hasName("::base::RepeatingCallback"));
    200     return parmVarDecl(
    201                hasType(hasCanonicalType(references(is_repeating_callback))))
    202         .bind("target");
    203   }
    204 
    205   void run(const MatchFinder::MatchResult& result) override {
    206     auto* target = result.Nodes.getNodeAs<clang::ParmVarDecl>("target");
    207     auto qual_type = target->getType();
    208     auto* ref_type =
    209         clang::dyn_cast<clang::LValueReferenceType>(qual_type.getTypePtr());
    210     if (!ref_type || !ref_type->getPointeeType().isLocalConstQualified())
    211       return;
    212 
    213     // Remove the leading `const` and the following `&`.
    214     auto type_loc = target->getTypeSourceInfo()->getTypeLoc();
    215     auto const_keyword = clang::CharSourceRange::getTokenRange(
    216         result.SourceManager->getSpellingLoc(target->getLocStart()),
    217         result.SourceManager->getSpellingLoc(target->getLocStart()));
    218     auto lvalue_ref = clang::CharSourceRange::getTokenRange(
    219         result.SourceManager->getSpellingLoc(type_loc.getLocEnd()),
    220         result.SourceManager->getSpellingLoc(type_loc.getLocEnd()));
    221     replacements_->emplace_back(*result.SourceManager, const_keyword, " ");
    222     replacements_->emplace_back(*result.SourceManager, lvalue_ref, " ");
    223   }
    224 
    225  private:
    226   Replacements* replacements_;
    227 };
    228 
    229 // Adds std::move() to base::RepeatingCallback<> where it looks relevant.
    230 // Example:
    231 //   // Before
    232 //   void Foo(base::Callback<void(int)> cb1) {
    233 //     base::Closure cb2 = base::Bind(cb1, 42);
    234 //     PostTask(FROM_HERE, cb2);
    235 //   }
    236 //
    237 //   // After
    238 //   void Foo(base::Callback<void(int)> cb1) {
    239 //     base::Closure cb2 = base::Bind(std::move(cb1), 42);
    240 //     PostTask(FROM_HERE, std::move(cb2));
    241 //   }
    242 class AddStdMoveRewriter : public MatchFinder::MatchCallback, public Rewriter {
    243  public:
    244   explicit AddStdMoveRewriter(Replacements* replacements)
    245       : replacements_(replacements) {}
    246 
    247   StatementMatcher GetMatcher() {
    248     return declRefExpr(
    249                hasType(hasCanonicalType(hasDeclaration(
    250                    namedDecl(hasName("::base::RepeatingCallback"))))),
    251                anyOf(hasAncestor(cxxConstructorDecl().bind("enclosing_ctor")),
    252                      hasAncestor(functionDecl().bind("enclosing_func")),
    253                      hasAncestor(lambdaExpr().bind("enclosing_lambda"))))
    254         .bind("target");
    255   }
    256 
    257   // Build Control Flow Graph (CFG) for |stmt| and populate class members with
    258   // the content of the graph. Returns true if the analysis finished
    259   // successfully.
    260   bool ExtractCFGContentToMembers(Stmt* stmt, ASTContext* context) {
    261     // Try to make a cache entry. The failure implies it's already in the cache.
    262     auto inserted = cfg_cache_.emplace(stmt, nullptr);
    263     if (!inserted.second)
    264       return !!inserted.first->second;
    265 
    266     std::unique_ptr<CFG>& cfg = inserted.first->second;
    267     CFG::BuildOptions opts;
    268     opts.AddInitializers = true;
    269     opts.AddLifetime = true;
    270     opts.AddStaticInitBranches = true;
    271     cfg = CFG::buildCFG(nullptr, stmt, context, opts);
    272 
    273     // CFG construction may fail. Report it to the caller.
    274     if (!cfg)
    275       return false;
    276     if (!parent_map_)
    277       parent_map_ = llvm::make_unique<clang::ParentMap>(stmt);
    278     else
    279       parent_map_->addStmt(stmt);
    280 
    281     // Populate |top_stmts_|, that contains Stmts that is evaluated in its own
    282     // CFGElement.
    283     for (auto* block : *cfg) {
    284       for (auto& elem : *block) {
    285         if (auto stmt = elem.getAs<CFGStmt>())
    286           top_stmts_.insert(stmt->getStmt());
    287       }
    288     }
    289 
    290     // Populate |enclosing_block_|, that maps a Stmt to a CFGBlock that contains
    291     // the Stmt.
    292     std::function<void(const CFGBlock*, const Stmt*)> recursive_set_enclosing =
    293         [&](const CFGBlock* block, const Stmt* stmt) {
    294           enclosing_block_[stmt] = block;
    295           for (auto* c : stmt->children()) {
    296             if (!c)
    297               continue;
    298             if (top_stmts_.find(c) != top_stmts_.end())
    299               continue;
    300             recursive_set_enclosing(block, c);
    301           }
    302         };
    303     for (auto* block : *cfg) {
    304       for (auto& elem : *block) {
    305         if (auto stmt = elem.getAs<CFGStmt>())
    306           recursive_set_enclosing(block, stmt->getStmt());
    307       }
    308     }
    309 
    310     return true;
    311   }
    312 
    313   const Stmt* EnclosingCxxStatement(const Stmt* stmt) {
    314     while (true) {
    315       const Stmt* parent = parent_map_->getParentIgnoreParenCasts(stmt);
    316       assert(parent);
    317       switch (parent->getStmtClass()) {
    318         case Stmt::CompoundStmtClass:
    319         case Stmt::ForStmtClass:
    320         case Stmt::CXXForRangeStmtClass:
    321         case Stmt::WhileStmtClass:
    322         case Stmt::DoStmtClass:
    323         case Stmt::IfStmtClass:
    324 
    325           // Other candidates:
    326           //   Stmt::CXXTryStmtClass
    327           //   Stmt::CXXCatchStmtClass
    328           //   Stmt::CapturedStmtClass
    329           //   Stmt::SwitchStmtClass
    330           //   Stmt::SwitchCaseClass
    331           return stmt;
    332         default:
    333           stmt = parent;
    334           break;
    335       }
    336     }
    337   }
    338 
    339   bool WasPointerTaken(const Stmt* stmt, const Decl* decl) {
    340     std::function<bool(const Stmt*)> visit_stmt = [&](const Stmt* stmt) {
    341       if (auto* op = clang::dyn_cast<UnaryOperator>(stmt)) {
    342         if (op->getOpcode() == clang::UO_AddrOf) {
    343           auto* ref = clang::dyn_cast<DeclRefExpr>(op->getSubExpr());
    344           // |ref| may be null if the sub-expr has a dependent type.
    345           if (ref && ref->getDecl() == decl)
    346             return true;
    347         }
    348       }
    349 
    350       for (auto* c : stmt->children()) {
    351         if (!c)
    352           continue;
    353         if (visit_stmt(c))
    354           return true;
    355       }
    356       return false;
    357     };
    358     return visit_stmt(stmt);
    359   }
    360 
    361   bool HasCapturingLambda(const Stmt* stmt, const Decl* decl) {
    362     std::function<bool(const Stmt*)> visit_stmt = [&](const Stmt* stmt) {
    363       if (auto* l = clang::dyn_cast<LambdaExpr>(stmt)) {
    364         for (auto c : l->captures()) {
    365           if (c.getCapturedVar() == decl)
    366             return true;
    367         }
    368       }
    369 
    370       for (auto* c : stmt->children()) {
    371         if (!c)
    372           continue;
    373 
    374         if (visit_stmt(c))
    375           return true;
    376       }
    377 
    378       return false;
    379     };
    380     return visit_stmt(stmt);
    381   }
    382 
    383   // Returns true if there are multiple occurrences to |decl| in one of C++
    384   // statements in |stmt|.
    385   bool HasUnorderedOccurrences(const Decl* decl, const Stmt* stmt) {
    386     int count = 0;
    387     std::function<void(const Stmt*)> visit_stmt = [&](const Stmt* s) {
    388       if (auto* ref = clang::dyn_cast<DeclRefExpr>(s)) {
    389         if (ref->getDecl() == decl)
    390           ++count;
    391       }
    392       for (auto* c : s->children()) {
    393         if (!c)
    394           continue;
    395         visit_stmt(c);
    396       }
    397     };
    398 
    399     visit_stmt(EnclosingCxxStatement(stmt));
    400     return count > 1;
    401   }
    402 
    403   void run(const MatchFinder::MatchResult& result) override {
    404     auto* target = result.Nodes.getNodeAs<clang::DeclRefExpr>("target");
    405     auto* decl = clang::dyn_cast<clang::VarDecl>(target->getDecl());
    406 
    407     // Other than local variables and parameters are out-of-scope.
    408     if (!decl || !decl->isLocalVarDeclOrParm())
    409       return;
    410 
    411     auto qual_type = decl->getType();
    412     // Qualified variables are out-of-scope. They are likely not movable.
    413     if (qual_type.getCanonicalType().hasQualifiers())
    414       return;
    415 
    416     auto* type = qual_type.getTypePtr();
    417     // References and pointers are out-of-scope.
    418     if (type->isReferenceType() || type->isPointerType())
    419       return;
    420 
    421     Stmt* body = nullptr;
    422     if (auto* ctor = result.Nodes.getNodeAs<LambdaExpr>("enclosing_ctor"))
    423       return;  // Skip constructor case for now. TBD.
    424     else if (auto* func =
    425                  result.Nodes.getNodeAs<FunctionDecl>("enclosing_func"))
    426       body = func->getBody();
    427     else if (auto* lambda =
    428                  result.Nodes.getNodeAs<LambdaExpr>("enclosing_lambda"))
    429       body = lambda->getBody();
    430     else
    431       return;
    432 
    433     // Disable the replacement if there is a lambda that captures |decl|.
    434     if (HasCapturingLambda(body, decl))
    435       return;
    436 
    437     // Disable the replacement if the pointer to |decl| is taken in the scope.
    438     if (WasPointerTaken(body, decl))
    439       return;
    440 
    441     if (!ExtractCFGContentToMembers(body, result.Context))
    442       return;
    443 
    444     auto* parent = parent_map_->getParentIgnoreParenCasts(target);
    445     if (auto* p = clang::dyn_cast<CallExpr>(parent)) {
    446       auto* callee = p->getCalleeDecl();
    447       // |callee| may be null if the CallExpr has an unresolved look up.
    448       if (!callee)
    449         return;
    450       auto* callee_decl = clang::dyn_cast<clang::NamedDecl>(callee);
    451       auto name = callee_decl->getQualifiedNameAsString();
    452 
    453       // Disable the replacement if it's already in std::move() or
    454       // std::forward().
    455       if (name == "std::__1::move" || name == "std::__1::forward")
    456         return;
    457     } else if (parent->getStmtClass() == Stmt::ReturnStmtClass) {
    458       // Disable the replacement if it's in a return statement.
    459       return;
    460     }
    461 
    462     // If the same C++ statement contains multiple reference to the variable,
    463     // don't insert std::move() to be conservative.
    464     if (HasUnorderedOccurrences(decl, target))
    465       return;
    466 
    467     bool saw_reuse = false;
    468     ForEachFollowingStmts(target, [&](const Stmt* stmt) {
    469       if (auto* ref = clang::dyn_cast<DeclRefExpr>(stmt)) {
    470         if (ref->getDecl() == decl) {
    471           saw_reuse = true;
    472           return false;
    473         }
    474       }
    475 
    476       // TODO: Detect Reset() and operator=() to stop the traversal.
    477       return true;
    478     });
    479     if (saw_reuse)
    480       return;
    481 
    482     replacements_->emplace_back(
    483         *result.SourceManager,
    484         result.SourceManager->getSpellingLoc(target->getLocStart()), 0,
    485         "std::move(");
    486     replacements_->emplace_back(
    487         *result.SourceManager,
    488         clang::Lexer::getLocForEndOfToken(target->getLocEnd(), 0,
    489                                           *result.SourceManager,
    490                                           result.Context->getLangOpts()),
    491         0, ")");
    492   }
    493 
    494   // Invokes |handler| for each Stmt that follows |target| until it reaches the
    495   // end of the lifetime of the variable that |target| references.
    496   // If |handler| returns false, stops following the current control flow.
    497   void ForEachFollowingStmts(const DeclRefExpr* target,
    498                              std::function<bool(const Stmt*)> handler) {
    499     auto* decl = target->getDecl();
    500     auto* block = enclosing_block_[target];
    501 
    502     std::set<const clang::CFGBlock*> visited;
    503     std::vector<const clang::CFGBlock*> stack = {block};
    504 
    505     bool saw_target = false;
    506     std::function<bool(const Stmt*)> visit_stmt = [&](const Stmt* s) {
    507       for (auto* t : s->children()) {
    508         if (!t)
    509           continue;
    510 
    511         // |t| is evaluated elsewhere if a sub-Stmt is in |top_stmt_|.
    512         if (top_stmts_.find(t) != top_stmts_.end())
    513           continue;
    514 
    515         if (!visit_stmt(t))
    516           return false;
    517       }
    518 
    519       if (!saw_target) {
    520         if (s == target)
    521           saw_target = true;
    522         return true;
    523       }
    524 
    525       return handler(s);
    526     };
    527 
    528     bool visited_initial_block_twice = false;
    529     while (!stack.empty()) {
    530       auto* b = stack.back();
    531       stack.pop_back();
    532       if (!visited.insert(b).second) {
    533         if (b != block || visited_initial_block_twice)
    534           continue;
    535         visited_initial_block_twice = true;
    536       }
    537 
    538       bool cont = true;
    539       for (auto e : *b) {
    540         if (auto s = e.getAs<CFGStmt>()) {
    541           if (!visit_stmt(s->getStmt())) {
    542             cont = false;
    543             break;
    544           }
    545         } else if (auto l = e.getAs<CFGLifetimeEnds>()) {
    546           if (l->getVarDecl() == decl) {
    547             cont = false;
    548             break;
    549           }
    550         }
    551       }
    552 
    553       if (cont) {
    554         for (auto s : b->succs()) {
    555           if (!s)
    556             continue;  // Unreachable block.
    557           stack.push_back(s);
    558         }
    559       }
    560     }
    561   }
    562 
    563  private:
    564   // Function body to CFG.
    565   std::map<const Stmt*, std::unique_ptr<CFG>> cfg_cache_;
    566 
    567   // Statement to the enclosing CFGBlock.
    568   std::map<const Stmt*, const CFGBlock*> enclosing_block_;
    569 
    570   // Stmt to its parent Stmt.
    571   std::unique_ptr<clang::ParentMap> parent_map_;
    572 
    573   // A set of Stmt that a CFGElement has it directly.
    574   std::set<const Stmt*> top_stmts_;
    575 
    576   Replacements* replacements_;
    577 };
    578 
    579 // Remove base::AdaptCallbackForRepeating() where resulting
    580 // base::RepeatingCallback is implicitly converted into base::OnceCallback.
    581 // Example:
    582 //   // Before
    583 //   base::PostTask(
    584 //       FROM_HERE,
    585 //       base::AdaptCallbackForRepeating(base::BindOnce(&Foo)));
    586 //   base::OnceCallback<void()> cb = base::AdaptCallbackForRepeating(
    587 //       base::OnceBind(&Foo));
    588 //
    589 //   // After
    590 //   base::PostTask(FROM_HERE, base::BindOnce(&Foo));
    591 //   base::OnceCallback<void()> cb = base::BindOnce(&Foo);
    592 class AdaptCallbackForRepeatingRewriter : public MatchFinder::MatchCallback,
    593                                           public Rewriter {
    594  public:
    595   explicit AdaptCallbackForRepeatingRewriter(Replacements* replacements)
    596       : replacements_(replacements) {}
    597 
    598   StatementMatcher GetMatcher() {
    599     auto is_once_callback = hasType(hasCanonicalType(hasDeclaration(
    600         classTemplateSpecializationDecl(hasName("::base::OnceCallback")))));
    601     auto is_repeating_callback =
    602         hasType(hasCanonicalType(hasDeclaration(classTemplateSpecializationDecl(
    603             hasName("::base::RepeatingCallback")))));
    604 
    605     auto adapt_callback_call =
    606         callExpr(
    607             callee(namedDecl(hasName("::base::AdaptCallbackForRepeating"))))
    608             .bind("target");
    609     auto parameter_construction =
    610         cxxConstructExpr(is_repeating_callback, argumentCountIs(1),
    611                          hasArgument(0, ignoringImplicit(adapt_callback_call)));
    612     auto constructor_conversion = cxxConstructExpr(
    613         is_once_callback, argumentCountIs(1),
    614         hasArgument(0, ignoringImplicit(parameter_construction)));
    615     return implicitCastExpr(is_once_callback,
    616                             hasSourceExpression(constructor_conversion));
    617   }
    618 
    619   void run(const MatchFinder::MatchResult& result) override {
    620     auto* target = result.Nodes.getNodeAs<clang::CallExpr>("target");
    621 
    622     auto left = clang::CharSourceRange::getTokenRange(
    623         result.SourceManager->getSpellingLoc(target->getLocStart()),
    624         result.SourceManager->getSpellingLoc(target->getArg(0)->getExprLoc())
    625             .getLocWithOffset(-1));
    626 
    627     // We use " " as replacement to work around https://crbug.com/861886.
    628     replacements_->emplace_back(*result.SourceManager, left, " ");
    629     auto r_paren = clang::CharSourceRange::getTokenRange(
    630         result.SourceManager->getSpellingLoc(target->getRParenLoc()),
    631         result.SourceManager->getSpellingLoc(target->getRParenLoc()));
    632     replacements_->emplace_back(*result.SourceManager, r_paren, " ");
    633   }
    634 
    635  private:
    636   Replacements* replacements_;
    637 };
    638 
    639 llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
    640 llvm::cl::OptionCategory rewriter_category("Rewriter Options");
    641 
    642 llvm::cl::opt<std::string> rewriter_option(
    643     "rewriter",
    644     llvm::cl::desc(R"(One of the name of rewriter to apply.
    645 Available rewriters are:
    646     remove_unneeded_passed
    647     bind_to_bind_once
    648     pass_by_value
    649     add_std_move
    650     remove_unneeded_adapt_callback
    651 The default is remove_unneeded_passed.
    652 )"),
    653     llvm::cl::init("remove_unneeded_passed"),
    654     llvm::cl::cat(rewriter_category));
    655 
    656 }  // namespace.
    657 
    658 int main(int argc, const char* argv[]) {
    659   llvm::InitializeNativeTarget();
    660   llvm::InitializeNativeTargetAsmParser();
    661   CommonOptionsParser options(argc, argv, rewriter_category);
    662   clang::tooling::ClangTool tool(options.getCompilations(),
    663                                  options.getSourcePathList());
    664 
    665   MatchFinder match_finder;
    666   std::vector<clang::tooling::Replacement> replacements;
    667 
    668   std::unique_ptr<Rewriter> rewriter;
    669   if (rewriter_option == "remove_unneeded_passed") {
    670     auto passed_to_move =
    671         llvm::make_unique<PassedToMoveRewriter>(&replacements);
    672     match_finder.addMatcher(passed_to_move->GetMatcher(), passed_to_move.get());
    673     rewriter = std::move(passed_to_move);
    674   } else if (rewriter_option == "bind_to_bind_once") {
    675     auto bind_once = llvm::make_unique<BindOnceRewriter>(&replacements);
    676     match_finder.addMatcher(bind_once->GetMatcher(), bind_once.get());
    677     rewriter = std::move(bind_once);
    678   } else if (rewriter_option == "pass_by_value") {
    679     auto pass_by_value = llvm::make_unique<PassByValueRewriter>(&replacements);
    680     match_finder.addMatcher(pass_by_value->GetMatcher(), pass_by_value.get());
    681     rewriter = std::move(pass_by_value);
    682   } else if (rewriter_option == "add_std_move") {
    683     auto add_std_move = llvm::make_unique<AddStdMoveRewriter>(&replacements);
    684     match_finder.addMatcher(add_std_move->GetMatcher(), add_std_move.get());
    685     rewriter = std::move(add_std_move);
    686   } else if (rewriter_option == "remove_unneeded_adapt_callback") {
    687     auto remove_unneeded_adapt_callback =
    688         llvm::make_unique<AdaptCallbackForRepeatingRewriter>(&replacements);
    689     match_finder.addMatcher(remove_unneeded_adapt_callback->GetMatcher(),
    690                             remove_unneeded_adapt_callback.get());
    691     rewriter = std::move(remove_unneeded_adapt_callback);
    692   } else {
    693     abort();
    694   }
    695 
    696   std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
    697       clang::tooling::newFrontendActionFactory(&match_finder);
    698   int result = tool.run(factory.get());
    699   if (result != 0)
    700     return result;
    701 
    702   // Serialization format is documented in tools/clang/scripts/run_tool.py
    703   llvm::outs() << "==== BEGIN EDITS ====\n";
    704   for (const auto& r : replacements) {
    705     std::string replacement_text = r.getReplacementText().str();
    706     std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0');
    707     llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset()
    708                  << ":::" << r.getLength() << ":::" << replacement_text << "\n";
    709   }
    710   llvm::outs() << "==== END EDITS ====\n";
    711 
    712   return 0;
    713 }
    714