diff options
4 files changed, 160 insertions, 0 deletions
diff --git a/tools/clang/rewrite_scoped_array/Makefile b/tools/clang/rewrite_scoped_array/Makefile new file mode 100644 index 0000000..d79329c --- /dev/null +++ b/tools/clang/rewrite_scoped_array/Makefile @@ -0,0 +1,23 @@ +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# This Makefile requires the LLVM build system. In order to build this tool, +# please run tools/clang/scripts/build_tool.py. + +CLANG_LEVEL := ../.. + +TOOLNAME = rewrite_scoped_array + +NO_INSTALL = 1 + +include $(CLANG_LEVEL)/../../Makefile.config + +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc +USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \ + clangRewriteFrontend.a clangRewriteCore.a clangParse.a clangSema.a \ + clangAnalysis.a clangAST.a clangASTMatchers.a clangEdit.a \ + clangLex.a clangBasic.a + +include $(CLANG_LEVEL)/Makefile + diff --git a/tools/clang/rewrite_scoped_array/RewriteScopedArray.cpp b/tools/clang/rewrite_scoped_array/RewriteScopedArray.cpp new file mode 100644 index 0000000..f465411 --- /dev/null +++ b/tools/clang/rewrite_scoped_array/RewriteScopedArray.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This implements a Clang tool to rewrite all instances of scoped_array<T> to +// scoped_ptr<T[]>. The former is being deprecated in favor of the latter, to +// allow for an eventual transition from scoped_ptr to unique_ptr. + +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Lex/Lexer.h" +#include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/Support/CommandLine.h" + +using clang::ast_matchers::MatchFinder; +using clang::ast_matchers::hasDeclaration; +using clang::ast_matchers::hasName; +using clang::ast_matchers::id; +using clang::ast_matchers::loc; +using clang::ast_matchers::qualType; +using clang::ast_matchers::recordDecl; +using clang::tooling::CommonOptionsParser; +using clang::tooling::Replacement; +using clang::tooling::Replacements; +using llvm::StringRef; + +namespace { + +class RewriterCallback : public MatchFinder::MatchCallback { + public: + RewriterCallback(Replacements* replacements) : replacements_(replacements) {} + virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE; + + private: + Replacements* const replacements_; +}; + +void RewriterCallback::run(const MatchFinder::MatchResult& result) { + const clang::TypeLoc type_location = + *result.Nodes.getNodeAs<clang::TypeLoc>("loc"); + clang::CharSourceRange range = clang::CharSourceRange::getTokenRange( + result.SourceManager->getSpellingLoc(type_location.getLocStart()), + result.SourceManager->getSpellingLoc(type_location.getLocEnd())); + // TODO(dcheng): Log an error? + if (!range.isValid()) + return; + std::string replacement_text = clang::Lexer::getSourceText( + range, *result.SourceManager, result.Context->getLangOpts()); + // TODO(dcheng): Log errors? + if (!StringRef(replacement_text).startswith("scoped_array<") || + !StringRef(replacement_text).endswith(">")) + return; + replacement_text.replace(strlen("scoped_"), strlen("array"), "ptr"); + replacement_text.insert(replacement_text.size() - 1, "[]"); + replacements_->insert( + Replacement(*result.SourceManager, range, replacement_text)); +} + +} // namespace + +static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); + +int main(int argc, const char* argv[]) { + CommonOptionsParser options(argc, argv); + clang::tooling::ClangTool tool(options.getCompilations(), + options.getSourcePathList()); + + Replacements replacements; + RewriterCallback callback(&replacements); + MatchFinder match_finder; + match_finder.addMatcher( + id("loc", + loc(qualType(hasDeclaration(recordDecl(hasName("::scoped_array")))))), + &callback); + + int result = + tool.run(clang::tooling::newFrontendActionFactory(&match_finder)); + if (result != 0) + return result; + + // Serialization format is documented in tools/clang/scripts/run_tool.py + llvm::outs() << "==== BEGIN EDITS ====\n"; + for (const Replacement& r : replacements) { + llvm::outs() << "r:" << r.getFilePath() << ":" << r.getOffset() << ":" + << r.getLength() << ":" << r.getReplacementText() << "\n"; + } + llvm::outs() << "==== END EDITS ====\n"; + + return 0; +} diff --git a/tools/clang/rewrite_scoped_array/tests/test-expected.cc b/tools/clang/rewrite_scoped_array/tests/test-expected.cc new file mode 100644 index 0000000..62c66ef --- /dev/null +++ b/tools/clang/rewrite_scoped_array/tests/test-expected.cc @@ -0,0 +1,21 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +template <class T> class scoped_array { + private: + T* data_; +}; + +class TestClass { + private: + scoped_ptr<int[]> test_field_; +}; + +scoped_ptr<int[]> TestFunction(scoped_ptr<int[]> x, scoped_ptr<int[]>) { + scoped_ptr<scoped_array<int>(scoped_array<int> test, scoped_array<int>)[]> y; + scoped_ptr<int[]>(*function_pointer)(scoped_ptr<int[]> test, + scoped_ptr<int[]>); + scoped_ptr<int[]> test_variable; +} + diff --git a/tools/clang/rewrite_scoped_array/tests/test-original.cc b/tools/clang/rewrite_scoped_array/tests/test-original.cc new file mode 100644 index 0000000..e0408ca --- /dev/null +++ b/tools/clang/rewrite_scoped_array/tests/test-original.cc @@ -0,0 +1,21 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +template <class T> class scoped_array { + private: + T* data_; +}; + +class TestClass { + private: + scoped_array<int> test_field_; +}; + +scoped_array<int> TestFunction(scoped_array<int> x, scoped_array<int>) { + scoped_array<scoped_array<int>(scoped_array<int> test, scoped_array<int>)> y; + scoped_array<int>(*function_pointer)(scoped_array<int> test, + scoped_array<int>); + scoped_array<int> test_variable; +} + |