Index: tools/clang/BindMigrate/BindMigrateConsumer.cpp |
diff --git a/tools/clang/BindMigrate/BindMigrateConsumer.cpp b/tools/clang/BindMigrate/BindMigrateConsumer.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..873948913c32300510579b5f4e5f45701fcdc70c |
--- /dev/null |
+++ b/tools/clang/BindMigrate/BindMigrateConsumer.cpp |
@@ -0,0 +1,155 @@ |
+// Copyright (c) 2011 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. |
+ |
+#include <iostream> |
+#include <string> |
+ |
+#include "BindMigrateConsumer.h" |
+ |
+#include "clang/AST/AST.h" |
+#include "clang/AST/Decl.h" |
+#include "clang/AST/DeclGroup.h" |
+#include "clang/AST/DeclVisitor.h" |
+#include "clang/AST/DeclarationName.h" |
+#include "clang/AST/ExprCXX.h" |
+#include "clang/AST/ParentMap.h" |
+#include "clang/AST/StmtVisitor.h" |
+#include "clang/AST/RecursiveASTVisitor.h" |
+#include "clang/AST/TypeLocVisitor.h" |
+#include "clang/Basic/FileManager.h" |
+#include "clang/Basic/IdentifierTable.h" |
+#include "clang/Basic/SourceManager.h" |
+#include "clang/Index/DeclReferenceMap.h" |
+#include "clang/Lex/Lexer.h" |
+#include "clang/Rewrite/ASTConsumers.h" |
+#include "llvm/ADT/DenseSet.h" |
+#include "llvm/ADT/OwningPtr.h" |
+#include "llvm/ADT/SmallPtrSet.h" |
+#include "llvm/ADT/StringExtras.h" |
+#include "llvm/Support/MemoryBuffer.h" |
+#include "llvm/Support/FileSystem.h" |
+#include "llvm/Support/raw_ostream.h" |
+#include "clang/Frontend/CompilerInstance.h" |
+ |
+#include "BindMigrateOptions.h" |
+#include "OldCallbackTransform.h" |
+#include "PostTaskTransform.h" |
+#include "Util.h" |
+ |
+using namespace std; |
+ |
+namespace clang { |
+ |
+BindMigrateConsumer::BindMigrateConsumer(CompilerInstance* instance, |
+ const BindMigrateOptions& options) |
+ : instance_(instance), |
+ error_emitter_(instance, "[bind-migrate] "), |
+ options_(options) { |
+} |
+ |
+BindMigrateConsumer::~BindMigrateConsumer() { |
+} |
+ |
+void BindMigrateConsumer::Initialize(ASTContext &context) { |
+ remapper_.initFromDisk(options_.out_dir, |
+ instance_->getDiagnostics(), |
+ /*ignoreIfFilesChanges=*/true); |
+ |
+ rewriter_.setSourceMgr(context.getSourceManager(), context.getLangOptions()); |
+} |
+ |
+void BindMigrateConsumer::HandleTranslationUnit(ASTContext &context) { |
+ OldCallbackTransform old_callback_tf(&context, &rewriter_, &error_emitter_); |
+ PostTaskTransform post_task_tf(&context, &rewriter_, &error_emitter_); |
+ |
+ // Create actual TransformApplier with all the wanted transforms. |
+ std::vector<Transform*> transforms; |
+ transforms.push_back(&old_callback_tf); |
+ transforms.push_back(&post_task_tf); |
+ TransformApplier transform_applier(transforms); |
+ TransformCandidatePrinter transform_candidate_printer( |
+ transforms, &context.getSourceManager()); |
+ |
+ // modify calls |
+ TranslationUnitDecl *translation_unit = context.getTranslationUnitDecl(); |
+ for (DeclContext::decl_iterator it = translation_unit->decls_begin(), |
+ end = translation_unit->decls_end(); it != end; ++it) { |
+ |
+ SourceManager& source_manager = context.getSourceManager(); |
+ |
+ // Only consider our files. |
+ const FileEntry* file_entry = |
+ GetValidFile(source_manager, (*it)->getLocation()); |
+ if (!file_entry) { |
+ continue; |
+ } |
+ |
+ // Apply blacklist. |
+ string file_name = file_entry->getName(); |
+ bool in_blacklist = false; |
+ for (vector<string>::const_iterator path = |
+ options_.ignore_path_prefix.begin(); |
+ path != options_.ignore_path_prefix.end(); |
+ ++path) { |
+ llvm::SmallString<512> abs_path; |
+ llvm::Twine(*path).toVector(abs_path); |
+ llvm::sys::fs::make_absolute(abs_path); |
+ if (file_name.find(abs_path.c_str()) != string::npos) { |
+ in_blacklist = true; |
+ break; |
+ } |
+ } |
+ if (in_blacklist) continue; |
+ |
+ // Apply whitelist. |
+ bool in_whitelist = options_.only_path_prefix.empty(); |
+ for (vector<string>::const_iterator path = |
+ options_.only_path_prefix.begin(); |
+ path != options_.only_path_prefix.end(); |
+ ++path) { |
+ llvm::SmallString<512> abs_path; |
+ llvm::Twine(*path).toVector(abs_path); |
+ llvm::sys::fs::make_absolute(abs_path); |
+ if (file_name.find(abs_path.c_str()) != string::npos) { |
+ in_whitelist = true; |
+ break; |
+ } |
+ } |
+ if (!in_whitelist) continue; |
+ |
+ if (options_.mode == "print") { |
+ transform_candidate_printer.TraverseDecl(*it); |
+ } else if (options_.mode == "transform") { |
+ transform_applier.TraverseDecl(*it); |
+ } |
+ } |
+ |
+ // Get the buffer corresponding to MainFileID. |
+ for (Rewriter::buffer_iterator it = rewriter_.buffer_begin(); |
+ it != rewriter_.buffer_end(); |
+ ++it) { |
+ const FileEntry *file = |
+ context.getSourceManager().getFileEntryForID(it->first); |
+ assert(file); |
+ |
+ std::string new_filename = file->getName(); |
+ new_filename += "-trans"; |
+ llvm::SmallString<512> new_text; |
+ llvm::raw_svector_ostream vecOS(new_text); |
+ it->second.write(vecOS); |
+ vecOS.flush(); |
+ llvm::MemoryBuffer *mem_buf = llvm::MemoryBuffer::getMemBufferCopy( |
+ StringRef(new_text.data(), new_text.size()), new_filename); |
+ llvm::SmallString<64> orig_filename(file->getName()); |
+ instance_->getFileManager().FixupRelativePath(orig_filename); |
+ remapper_.remap(orig_filename.str(), mem_buf); |
+ } |
+ |
+ // TODO(ajwong): We should just hook into BeginInvocation() like ARCMigrate |
+ // does. As is, it is hard to flush at the end of the compilation sequence |
+ // because there's no such thing as EndInvocation(). |
+ remapper_.writeParallelTree(options_.out_dir, instance_->getDiagnostics()); |
+} |
+ |
+} // namespace clang |