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