1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This implements a Clang tool to convert all instances of std::string("") to
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// std::string(). The latter is more efficient (as std::string doesn't have to
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// take a copy of an empty string) and generates fewer instructions as well. It
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// should be run using the tools/clang/scripts/run_tool.py helper.
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/ASTMatchers/ASTMatchers.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/ASTMatchers/ASTMatchFinder.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/Basic/SourceManager.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/Frontend/FrontendActions.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/Tooling/CommonOptionsParser.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/Tooling/Refactoring.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/Tooling/Tooling.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "llvm/Support/CommandLine.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::MatchFinder;
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::argumentCountIs;
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::bindTemporaryExpr;
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::constructorDecl;
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::constructExpr;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::defaultArgExpr;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::expr;
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::forEach;
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::has;
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::hasArgument;
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::hasDeclaration;
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::hasName;
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::id;
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::methodDecl;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::newExpr;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::ofClass;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::stringLiteral;
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::ast_matchers::varDecl;
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::tooling::CommonOptionsParser;
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::tooling::Replacement;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using clang::tooling::Replacements;
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Handles replacements for stack and heap-allocated instances, e.g.:
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// std::string a("");
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// std::string* b = new std::string("");
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ConstructorCallback : public MatchFinder::MatchCallback {
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConstructorCallback(Replacements* replacements)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : replacements_(replacements) {}
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE;
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Replacements* const replacements_;
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Handles replacements for invocations of std::string("") in an initializer
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// list.
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class InitializerCallback : public MatchFinder::MatchCallback {
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InitializerCallback(Replacements* replacements)
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : replacements_(replacements) {}
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE;
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Replacements* const replacements_;
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Handles replacements for invocations of std::string("") in a temporary
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// context, e.g. FunctionThatTakesString(std::string("")). Note that this
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// handles implicits construction of std::string as well.
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class TemporaryCallback : public MatchFinder::MatchCallback {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TemporaryCallback(Replacements* replacements) : replacements_(replacements) {}
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Replacements* const replacements_;
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class EmptyStringConverter {
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit EmptyStringConverter(Replacements* replacements)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : constructor_callback_(replacements),
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        initializer_callback_(replacements),
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        temporary_callback_(replacements) {}
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void SetupMatchers(MatchFinder* match_finder);
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConstructorCallback constructor_callback_;
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InitializerCallback initializer_callback_;
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TemporaryCallback temporary_callback_;
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EmptyStringConverter::SetupMatchers(MatchFinder* match_finder) {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const clang::ast_matchers::StatementMatcher& constructor_call =
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      id("call",
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         constructExpr(
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             hasDeclaration(methodDecl(ofClass(hasName("std::basic_string")))),
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             argumentCountIs(2),
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             hasArgument(0, id("literal", stringLiteral())),
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             hasArgument(1, defaultArgExpr())));
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Note that expr(has()) in the matcher is significant; the Clang AST wraps
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // calls to the std::string constructor with exprWithCleanups nodes. Without
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the expr(has()) matcher, the first and last rules would not match anything!
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  match_finder->addMatcher(varDecl(forEach(expr(has(constructor_call)))),
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           &constructor_callback_);
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  match_finder->addMatcher(newExpr(has(constructor_call)),
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           &constructor_callback_);
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  match_finder->addMatcher(bindTemporaryExpr(has(constructor_call)),
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           &temporary_callback_);
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  match_finder->addMatcher(
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      constructorDecl(forEach(expr(has(constructor_call)))),
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &initializer_callback_);
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ConstructorCallback::run(const MatchFinder::MatchResult& result) {
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const clang::StringLiteral* literal =
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result.Nodes.getNodeAs<clang::StringLiteral>("literal");
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (literal->getLength() > 0)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const clang::CXXConstructExpr* call =
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result.Nodes.getNodeAs<clang::CXXConstructExpr>("call");
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  clang::CharSourceRange range =
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      clang::CharSourceRange::getTokenRange(call->getParenRange());
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  replacements_->insert(Replacement(*result.SourceManager, range, ""));
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void InitializerCallback::run(const MatchFinder::MatchResult& result) {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const clang::StringLiteral* literal =
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result.Nodes.getNodeAs<clang::StringLiteral>("literal");
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (literal->getLength() > 0)
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const clang::CXXConstructExpr* call =
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result.Nodes.getNodeAs<clang::CXXConstructExpr>("call");
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  replacements_->insert(Replacement(*result.SourceManager, call, ""));
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void TemporaryCallback::run(const MatchFinder::MatchResult& result) {
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const clang::StringLiteral* literal =
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result.Nodes.getNodeAs<clang::StringLiteral>("literal");
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (literal->getLength() > 0)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const clang::CXXConstructExpr* call =
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result.Nodes.getNodeAs<clang::CXXConstructExpr>("call");
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Differentiate between explicit and implicit calls to std::string's
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // constructor. An implicitly generated constructor won't have a valid
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // source range for the parenthesis. We do this because the matched expression
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // for |call| in the explicit case doesn't include the closing parenthesis.
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  clang::SourceRange range = call->getParenRange();
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (range.isValid()) {
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    replacements_->insert(Replacement(*result.SourceManager, literal, ""));
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    replacements_->insert(
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        Replacement(*result.SourceManager,
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    call,
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    literal->isWide() ? "std::wstring()" : "std::string()"));
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int main(int argc, const char* argv[]) {
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CommonOptionsParser options(argc, argv);
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  clang::tooling::ClangTool tool(options.getCompilations(),
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 options.getSourcePathList());
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Replacements replacements;
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EmptyStringConverter converter(&replacements);
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MatchFinder match_finder;
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  converter.SetupMatchers(&match_finder);
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int result =
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tool.run(clang::tooling::newFrontendActionFactory(&match_finder));
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (result != 0)
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return result;
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Each replacement line should have the following format:
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // r:<file path>:<offset>:<length>:<replacement text>
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Only the <replacement text> field can contain embedded ":" characters.
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(dcheng): Use a more clever serialization.
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  llvm::outs() << "==== BEGIN EDITS ====\n";
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (Replacements::const_iterator it = replacements.begin();
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       it != replacements.end(); ++it) {
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    llvm::outs() << "r:" << it->getFilePath() << ":" << it->getOffset() << ":"
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << it->getLength() << ":" << it->getReplacementText() << "\n";
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  llvm::outs() << "==== END EDITS ====\n";
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
201