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:
~Rewriter()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:
PassedToMoveRewriter(Replacements * replacements)64   explicit PassedToMoveRewriter(Replacements* replacements)
65       : replacements_(replacements) {}
66 
GetMatcher()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 
run(const MatchFinder::MatchResult & result)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->getBeginLoc()),
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->getBeginLoc()),
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->getBeginLoc()),
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() and base::BindRepeating() to base::BindOnce() where
135 // resulting callbacks are implicitly converted into base::OnceCallback.
136 // Example:
137 //   // Before
138 //   base::PostTask(FROM_HERE, base::BindRepeating(&Foo));
139 //   base::OnceCallback<void()> cb = base::BindRepeating(&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:
BindOnceRewriter(Replacements * replacements)146   explicit BindOnceRewriter(Replacements* replacements)
147       : replacements_(replacements) {}
148 
GetMatcher()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(anyOf(hasName("::base::Bind"),
158                                         hasName("::base::BindRepeating")))))
159             .bind("target");
160     auto parameter_construction =
161         cxxConstructExpr(is_repeating_callback, argumentCountIs(1),
162                          hasArgument(0, ignoringImplicit(bind_call)));
163     auto constructor_conversion = cxxConstructExpr(
164         is_once_callback, argumentCountIs(1),
165         hasArgument(0, ignoringImplicit(parameter_construction)));
166     return implicitCastExpr(is_once_callback,
167                             hasSourceExpression(constructor_conversion));
168   }
169 
run(const MatchFinder::MatchResult & result)170   void run(const MatchFinder::MatchResult& result) override {
171     auto* target = result.Nodes.getNodeAs<clang::CallExpr>("target");
172     auto* callee = target->getCallee();
173     auto range = clang::CharSourceRange::getTokenRange(
174         result.SourceManager->getSpellingLoc(callee->getEndLoc()),
175         result.SourceManager->getSpellingLoc(callee->getEndLoc()));
176     replacements_->emplace_back(*result.SourceManager, range, "BindOnce");
177   }
178 
179  private:
180   Replacements* replacements_;
181 };
182 
183 // Converts pass-by-const-ref base::RepeatingCallback's to
184 // pass-by-value. Example:
185 //   // Before
186 //   using BarCallback = base::RepeatingCallback<void(void*)>;
187 //   void Foo(const base::RepeatingCallback<void(int)>& cb);
188 //   void Bar(const BarCallback& cb);
189 //
190 //   // After
191 //   using BarCallback = base::RepeatingCallback<void(void*)>;
192 //   void Foo(base::RepeatingCallback<void(int)> cb);
193 //   void Bar(BarCallback cb);
194 class PassByValueRewriter : public MatchFinder::MatchCallback, public Rewriter {
195  public:
PassByValueRewriter(Replacements * replacements)196   explicit PassByValueRewriter(Replacements* replacements)
197       : replacements_(replacements) {}
198 
GetMatcher()199   DeclarationMatcher GetMatcher() {
200     auto is_repeating_callback =
201         namedDecl(hasName("::base::RepeatingCallback"));
202     return parmVarDecl(
203                hasType(hasCanonicalType(references(is_repeating_callback))))
204         .bind("target");
205   }
206 
run(const MatchFinder::MatchResult & result)207   void run(const MatchFinder::MatchResult& result) override {
208     auto* target = result.Nodes.getNodeAs<clang::ParmVarDecl>("target");
209     auto qual_type = target->getType();
210     auto* ref_type =
211         clang::dyn_cast<clang::LValueReferenceType>(qual_type.getTypePtr());
212     if (!ref_type || !ref_type->getPointeeType().isLocalConstQualified())
213       return;
214 
215     // Remove the leading `const` and the following `&`.
216     auto type_loc = target->getTypeSourceInfo()->getTypeLoc();
217     auto const_keyword = clang::CharSourceRange::getTokenRange(
218         result.SourceManager->getSpellingLoc(target->getBeginLoc()),
219         result.SourceManager->getSpellingLoc(target->getBeginLoc()));
220     auto lvalue_ref = clang::CharSourceRange::getTokenRange(
221         result.SourceManager->getSpellingLoc(type_loc.getEndLoc()),
222         result.SourceManager->getSpellingLoc(type_loc.getEndLoc()));
223     replacements_->emplace_back(*result.SourceManager, const_keyword, " ");
224     replacements_->emplace_back(*result.SourceManager, lvalue_ref, " ");
225   }
226 
227  private:
228   Replacements* replacements_;
229 };
230 
231 // Adds std::move() to base::RepeatingCallback<> where it looks relevant.
232 // Example:
233 //   // Before
234 //   void Foo(base::RepeatingCallback<void(int)> cb1) {
235 //     base::RepeatingClosure cb2 = base::BindRepeating(cb1, 42);
236 //     PostTask(FROM_HERE, cb2);
237 //   }
238 //
239 //   // After
240 //   void Foo(base::RepeatingCallback<void(int)> cb1) {
241 //     base::RepeatingClosure cb2 = base::BindRepeating(std::move(cb1), 42);
242 //     PostTask(FROM_HERE, std::move(cb2));
243 //   }
244 class AddStdMoveRewriter : public MatchFinder::MatchCallback, public Rewriter {
245  public:
AddStdMoveRewriter(Replacements * replacements)246   explicit AddStdMoveRewriter(Replacements* replacements)
247       : replacements_(replacements) {}
248 
GetMatcher()249   StatementMatcher GetMatcher() {
250     return declRefExpr(
251                hasType(hasCanonicalType(hasDeclaration(
252                    namedDecl(hasName("::base::RepeatingCallback"))))),
253                anyOf(hasAncestor(cxxConstructorDecl().bind("enclosing_ctor")),
254                      hasAncestor(functionDecl().bind("enclosing_func")),
255                      hasAncestor(lambdaExpr().bind("enclosing_lambda"))))
256         .bind("target");
257   }
258 
259   // Build Control Flow Graph (CFG) for |stmt| and populate class members with
260   // the content of the graph. Returns true if the analysis finished
261   // successfully.
ExtractCFGContentToMembers(Stmt * stmt,ASTContext * context)262   bool ExtractCFGContentToMembers(Stmt* stmt, ASTContext* context) {
263     // Try to make a cache entry. The failure implies it's already in the cache.
264     auto inserted = cfg_cache_.emplace(stmt, nullptr);
265     if (!inserted.second)
266       return !!inserted.first->second;
267 
268     std::unique_ptr<CFG>& cfg = inserted.first->second;
269     CFG::BuildOptions opts;
270     opts.AddInitializers = true;
271     opts.AddLifetime = true;
272     opts.AddStaticInitBranches = true;
273     cfg = CFG::buildCFG(nullptr, stmt, context, opts);
274 
275     // CFG construction may fail. Report it to the caller.
276     if (!cfg)
277       return false;
278     if (!parent_map_)
279       parent_map_ = std::make_unique<clang::ParentMap>(stmt);
280     else
281       parent_map_->addStmt(stmt);
282 
283     // Populate |top_stmts_|, that contains Stmts that is evaluated in its own
284     // CFGElement.
285     for (auto* block : *cfg) {
286       for (auto& elem : *block) {
287         if (auto stmt = elem.getAs<CFGStmt>())
288           top_stmts_.insert(stmt->getStmt());
289       }
290     }
291 
292     // Populate |enclosing_block_|, that maps a Stmt to a CFGBlock that contains
293     // the Stmt.
294     std::function<void(const CFGBlock*, const Stmt*)> recursive_set_enclosing =
295         [&](const CFGBlock* block, const Stmt* stmt) {
296           enclosing_block_[stmt] = block;
297           for (auto* c : stmt->children()) {
298             if (!c)
299               continue;
300             if (top_stmts_.find(c) != top_stmts_.end())
301               continue;
302             recursive_set_enclosing(block, c);
303           }
304         };
305     for (auto* block : *cfg) {
306       for (auto& elem : *block) {
307         if (auto stmt = elem.getAs<CFGStmt>())
308           recursive_set_enclosing(block, stmt->getStmt());
309       }
310     }
311 
312     return true;
313   }
314 
EnclosingCxxStatement(const Stmt * stmt)315   const Stmt* EnclosingCxxStatement(const Stmt* stmt) {
316     while (true) {
317       const Stmt* parent = parent_map_->getParentIgnoreParenCasts(stmt);
318       assert(parent);
319       switch (parent->getStmtClass()) {
320         case Stmt::CompoundStmtClass:
321         case Stmt::ForStmtClass:
322         case Stmt::CXXForRangeStmtClass:
323         case Stmt::WhileStmtClass:
324         case Stmt::DoStmtClass:
325         case Stmt::IfStmtClass:
326 
327           // Other candidates:
328           //   Stmt::CXXTryStmtClass
329           //   Stmt::CXXCatchStmtClass
330           //   Stmt::CapturedStmtClass
331           //   Stmt::SwitchStmtClass
332           //   Stmt::SwitchCaseClass
333           return stmt;
334         default:
335           stmt = parent;
336           break;
337       }
338     }
339   }
340 
WasPointerTaken(const Stmt * stmt,const Decl * decl)341   bool WasPointerTaken(const Stmt* stmt, const Decl* decl) {
342     std::function<bool(const Stmt*)> visit_stmt = [&](const Stmt* stmt) {
343       if (auto* op = clang::dyn_cast<UnaryOperator>(stmt)) {
344         if (op->getOpcode() == clang::UO_AddrOf) {
345           auto* ref = clang::dyn_cast<DeclRefExpr>(op->getSubExpr());
346           // |ref| may be null if the sub-expr has a dependent type.
347           if (ref && ref->getDecl() == decl)
348             return true;
349         }
350       }
351 
352       for (auto* c : stmt->children()) {
353         if (!c)
354           continue;
355         if (visit_stmt(c))
356           return true;
357       }
358       return false;
359     };
360     return visit_stmt(stmt);
361   }
362 
HasCapturingLambda(const Stmt * stmt,const Decl * decl)363   bool HasCapturingLambda(const Stmt* stmt, const Decl* decl) {
364     std::function<bool(const Stmt*)> visit_stmt = [&](const Stmt* stmt) {
365       if (auto* l = clang::dyn_cast<LambdaExpr>(stmt)) {
366         for (auto c : l->captures()) {
367           if (c.getCapturedVar() == decl)
368             return true;
369         }
370       }
371 
372       for (auto* c : stmt->children()) {
373         if (!c)
374           continue;
375 
376         if (visit_stmt(c))
377           return true;
378       }
379 
380       return false;
381     };
382     return visit_stmt(stmt);
383   }
384 
385   // Returns true if there are multiple occurrences to |decl| in one of C++
386   // statements in |stmt|.
HasUnorderedOccurrences(const Decl * decl,const Stmt * stmt)387   bool HasUnorderedOccurrences(const Decl* decl, const Stmt* stmt) {
388     int count = 0;
389     std::function<void(const Stmt*)> visit_stmt = [&](const Stmt* s) {
390       if (auto* ref = clang::dyn_cast<DeclRefExpr>(s)) {
391         if (ref->getDecl() == decl)
392           ++count;
393       }
394       for (auto* c : s->children()) {
395         if (!c)
396           continue;
397         visit_stmt(c);
398       }
399     };
400 
401     visit_stmt(EnclosingCxxStatement(stmt));
402     return count > 1;
403   }
404 
run(const MatchFinder::MatchResult & result)405   void run(const MatchFinder::MatchResult& result) override {
406     auto* target = result.Nodes.getNodeAs<clang::DeclRefExpr>("target");
407     auto* decl = clang::dyn_cast<clang::VarDecl>(target->getDecl());
408 
409     // Other than local variables and parameters are out-of-scope.
410     if (!decl || !decl->isLocalVarDeclOrParm())
411       return;
412 
413     auto qual_type = decl->getType();
414     // Qualified variables are out-of-scope. They are likely not movable.
415     if (qual_type.getCanonicalType().hasQualifiers())
416       return;
417 
418     auto* type = qual_type.getTypePtr();
419     // References and pointers are out-of-scope.
420     if (type->isReferenceType() || type->isPointerType())
421       return;
422 
423     Stmt* body = nullptr;
424     if (auto* ctor = result.Nodes.getNodeAs<LambdaExpr>("enclosing_ctor"))
425       return;  // Skip constructor case for now. TBD.
426     else if (auto* func =
427                  result.Nodes.getNodeAs<FunctionDecl>("enclosing_func"))
428       body = func->getBody();
429     else if (auto* lambda =
430                  result.Nodes.getNodeAs<LambdaExpr>("enclosing_lambda"))
431       body = lambda->getBody();
432     else
433       return;
434 
435     // Disable the replacement if there is a lambda that captures |decl|.
436     if (HasCapturingLambda(body, decl))
437       return;
438 
439     // Disable the replacement if the pointer to |decl| is taken in the scope.
440     if (WasPointerTaken(body, decl))
441       return;
442 
443     if (!ExtractCFGContentToMembers(body, result.Context))
444       return;
445 
446     auto* parent = parent_map_->getParentIgnoreParenCasts(target);
447     if (auto* p = clang::dyn_cast<CallExpr>(parent)) {
448       auto* callee = p->getCalleeDecl();
449       // |callee| may be null if the CallExpr has an unresolved look up.
450       if (!callee)
451         return;
452       auto* callee_decl = clang::dyn_cast<clang::NamedDecl>(callee);
453       auto name = callee_decl->getQualifiedNameAsString();
454 
455       // Disable the replacement if it's already in std::move() or
456       // std::forward().
457       if (name == "std::__1::move" || name == "std::__1::forward")
458         return;
459     } else if (parent->getStmtClass() == Stmt::ReturnStmtClass) {
460       // Disable the replacement if it's in a return statement.
461       return;
462     }
463 
464     // If the same C++ statement contains multiple reference to the variable,
465     // don't insert std::move() to be conservative.
466     if (HasUnorderedOccurrences(decl, target))
467       return;
468 
469     bool saw_reuse = false;
470     ForEachFollowingStmts(target, [&](const Stmt* stmt) {
471       if (auto* ref = clang::dyn_cast<DeclRefExpr>(stmt)) {
472         if (ref->getDecl() == decl) {
473           saw_reuse = true;
474           return false;
475         }
476       }
477 
478       // TODO: Detect Reset() and operator=() to stop the traversal.
479       return true;
480     });
481     if (saw_reuse)
482       return;
483 
484     replacements_->emplace_back(
485         *result.SourceManager,
486         result.SourceManager->getSpellingLoc(target->getBeginLoc()), 0,
487         "std::move(");
488     replacements_->emplace_back(
489         *result.SourceManager,
490         clang::Lexer::getLocForEndOfToken(target->getEndLoc(), 0,
491                                           *result.SourceManager,
492                                           result.Context->getLangOpts()),
493         0, ")");
494   }
495 
496   // Invokes |handler| for each Stmt that follows |target| until it reaches the
497   // end of the lifetime of the variable that |target| references.
498   // If |handler| returns false, stops following the current control flow.
ForEachFollowingStmts(const DeclRefExpr * target,std::function<bool (const Stmt *)> handler)499   void ForEachFollowingStmts(const DeclRefExpr* target,
500                              std::function<bool(const Stmt*)> handler) {
501     auto* decl = target->getDecl();
502     auto* block = enclosing_block_[target];
503 
504     std::set<const clang::CFGBlock*> visited;
505     std::vector<const clang::CFGBlock*> stack = {block};
506 
507     bool saw_target = false;
508     std::function<bool(const Stmt*)> visit_stmt = [&](const Stmt* s) {
509       for (auto* t : s->children()) {
510         if (!t)
511           continue;
512 
513         // |t| is evaluated elsewhere if a sub-Stmt is in |top_stmt_|.
514         if (top_stmts_.find(t) != top_stmts_.end())
515           continue;
516 
517         if (!visit_stmt(t))
518           return false;
519       }
520 
521       if (!saw_target) {
522         if (s == target)
523           saw_target = true;
524         return true;
525       }
526 
527       return handler(s);
528     };
529 
530     bool visited_initial_block_twice = false;
531     while (!stack.empty()) {
532       auto* b = stack.back();
533       stack.pop_back();
534       if (!visited.insert(b).second) {
535         if (b != block || visited_initial_block_twice)
536           continue;
537         visited_initial_block_twice = true;
538       }
539 
540       bool cont = true;
541       for (auto e : *b) {
542         if (auto s = e.getAs<CFGStmt>()) {
543           if (!visit_stmt(s->getStmt())) {
544             cont = false;
545             break;
546           }
547         } else if (auto l = e.getAs<CFGLifetimeEnds>()) {
548           if (l->getVarDecl() == decl) {
549             cont = false;
550             break;
551           }
552         }
553       }
554 
555       if (cont) {
556         for (auto s : b->succs()) {
557           if (!s)
558             continue;  // Unreachable block.
559           stack.push_back(s);
560         }
561       }
562     }
563   }
564 
565  private:
566   // Function body to CFG.
567   std::map<const Stmt*, std::unique_ptr<CFG>> cfg_cache_;
568 
569   // Statement to the enclosing CFGBlock.
570   std::map<const Stmt*, const CFGBlock*> enclosing_block_;
571 
572   // Stmt to its parent Stmt.
573   std::unique_ptr<clang::ParentMap> parent_map_;
574 
575   // A set of Stmt that a CFGElement has it directly.
576   std::set<const Stmt*> top_stmts_;
577 
578   Replacements* replacements_;
579 };
580 
581 llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
582 llvm::cl::OptionCategory rewriter_category("Rewriter Options");
583 
584 llvm::cl::opt<std::string> rewriter_option(
585     "rewriter",
586     llvm::cl::desc(R"(One of the name of rewriter to apply.
587 Available rewriters are:
588     remove_unneeded_passed
589     bind_to_bind_once
590     pass_by_value
591     add_std_move
592 The default is remove_unneeded_passed.
593 )"),
594     llvm::cl::init("remove_unneeded_passed"),
595     llvm::cl::cat(rewriter_category));
596 
597 }  // namespace.
598 
main(int argc,const char * argv[])599 int main(int argc, const char* argv[]) {
600   llvm::InitializeNativeTarget();
601   llvm::InitializeNativeTargetAsmParser();
602   CommonOptionsParser options(argc, argv, rewriter_category);
603   clang::tooling::ClangTool tool(options.getCompilations(),
604                                  options.getSourcePathList());
605 
606   MatchFinder match_finder;
607   std::vector<clang::tooling::Replacement> replacements;
608 
609   std::unique_ptr<Rewriter> rewriter;
610   if (rewriter_option == "remove_unneeded_passed") {
611     auto passed_to_move = std::make_unique<PassedToMoveRewriter>(&replacements);
612     match_finder.addMatcher(passed_to_move->GetMatcher(), passed_to_move.get());
613     rewriter = std::move(passed_to_move);
614   } else if (rewriter_option == "bind_to_bind_once") {
615     auto bind_once = std::make_unique<BindOnceRewriter>(&replacements);
616     match_finder.addMatcher(bind_once->GetMatcher(), bind_once.get());
617     rewriter = std::move(bind_once);
618   } else if (rewriter_option == "pass_by_value") {
619     auto pass_by_value = std::make_unique<PassByValueRewriter>(&replacements);
620     match_finder.addMatcher(pass_by_value->GetMatcher(), pass_by_value.get());
621     rewriter = std::move(pass_by_value);
622   } else if (rewriter_option == "add_std_move") {
623     auto add_std_move = std::make_unique<AddStdMoveRewriter>(&replacements);
624     match_finder.addMatcher(add_std_move->GetMatcher(), add_std_move.get());
625     rewriter = std::move(add_std_move);
626   } else {
627     abort();
628   }
629 
630   std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
631       clang::tooling::newFrontendActionFactory(&match_finder);
632   int result = tool.run(factory.get());
633   if (result != 0)
634     return result;
635 
636   if (replacements.empty())
637     return 0;
638 
639   // Serialization format is documented in tools/clang/scripts/run_tool.py
640   llvm::outs() << "==== BEGIN EDITS ====\n";
641   for (const auto& r : replacements) {
642     std::string replacement_text = r.getReplacementText().str();
643     std::replace(replacement_text.begin(), replacement_text.end(), '\n', '\0');
644     llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset()
645                  << ":::" << r.getLength() << ":::" << replacement_text << "\n";
646   }
647   llvm::outs() << "==== END EDITS ====\n";
648 
649   return 0;
650 }
651