1 // Copyright (c) 2013 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.
5 // This implements a Clang tool to rewrite all instances of scoped_array<T> to
6 // scoped_ptr<T[]>. The former is being deprecated in favor of the latter, to
7 // allow for an eventual transition from scoped_ptr to unique_ptr.
9 #include "clang/AST/ASTContext.h"
10 #include "clang/ASTMatchers/ASTMatchers.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Basic/SourceManager.h"
13 #include "clang/Frontend/FrontendActions.h"
14 #include "clang/Lex/Lexer.h"
15 #include "clang/Tooling/CommonOptionsParser.h"
16 #include "clang/Tooling/Refactoring.h"
17 #include "clang/Tooling/Tooling.h"
18 #include "llvm/Support/CommandLine.h"
20 using clang::ast_matchers::MatchFinder
;
21 using clang::ast_matchers::hasDeclaration
;
22 using clang::ast_matchers::hasName
;
23 using clang::ast_matchers::id
;
24 using clang::ast_matchers::loc
;
25 using clang::ast_matchers::qualType
;
26 using clang::ast_matchers::recordDecl
;
27 using clang::tooling::CommonOptionsParser
;
28 using clang::tooling::Replacement
;
29 using clang::tooling::Replacements
;
30 using llvm::StringRef
;
34 class RewriterCallback
: public MatchFinder::MatchCallback
{
36 RewriterCallback(Replacements
* replacements
) : replacements_(replacements
) {}
37 virtual void run(const MatchFinder::MatchResult
& result
) LLVM_OVERRIDE
;
40 Replacements
* const replacements_
;
43 void RewriterCallback::run(const MatchFinder::MatchResult
& result
) {
44 const clang::TypeLoc type_location
=
45 *result
.Nodes
.getNodeAs
<clang::TypeLoc
>("loc");
46 clang::CharSourceRange range
= clang::CharSourceRange::getTokenRange(
47 result
.SourceManager
->getSpellingLoc(type_location
.getLocStart()),
48 result
.SourceManager
->getSpellingLoc(type_location
.getLocEnd()));
49 // TODO(dcheng): Log an error?
52 std::string replacement_text
= clang::Lexer::getSourceText(
53 range
, *result
.SourceManager
, result
.Context
->getLangOpts());
54 // TODO(dcheng): Log errors?
55 if (!StringRef(replacement_text
).startswith("scoped_array<") ||
56 !StringRef(replacement_text
).endswith(">"))
58 replacement_text
.replace(strlen("scoped_"), strlen("array"), "ptr");
59 replacement_text
.insert(replacement_text
.size() - 1, "[]");
60 replacements_
->insert(
61 Replacement(*result
.SourceManager
, range
, replacement_text
));
66 static llvm::cl::extrahelp
common_help(CommonOptionsParser::HelpMessage
);
68 int main(int argc
, const char* argv
[]) {
69 CommonOptionsParser
options(argc
, argv
);
70 clang::tooling::ClangTool
tool(options
.getCompilations(),
71 options
.getSourcePathList());
73 Replacements replacements
;
74 RewriterCallback
callback(&replacements
);
75 MatchFinder match_finder
;
76 match_finder
.addMatcher(
78 loc(qualType(hasDeclaration(recordDecl(hasName("::scoped_array")))))),
82 tool
.run(clang::tooling::newFrontendActionFactory(&match_finder
));
86 // Serialization format is documented in tools/clang/scripts/run_tool.py
87 llvm::outs() << "==== BEGIN EDITS ====\n";
88 for (Replacements::const_iterator it
= replacements
.begin();
89 it
!= replacements
.end(); ++it
) {
90 llvm::outs() << "r:" << it
->getFilePath() << ":" << it
->getOffset() << ":"
91 << it
->getLength() << ":" << it
->getReplacementText() << "\n";
93 llvm::outs() << "==== END EDITS ====\n";