diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-11-04 15:58:08 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-11-04 15:58:08 +0000 |
commit | e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1a (patch) | |
tree | 0af8bd854f88593bafddcc8ac41fee7637aaf1cc /lib/ARCMigrate | |
parent | 92d3dda09f72b700e15b7b652a7bb47718989994 (diff) |
[arcmt] In GC, transform NSMakeCollectable to CFBridgingRelease.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143698 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ARCMigrate')
-rw-r--r-- | lib/ARCMigrate/ARCMT.cpp | 14 | ||||
-rw-r--r-- | lib/ARCMigrate/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/ARCMigrate/Internals.h | 9 | ||||
-rw-r--r-- | lib/ARCMigrate/TransGCCalls.cpp | 59 | ||||
-rw-r--r-- | lib/ARCMigrate/Transforms.cpp | 55 | ||||
-rw-r--r-- | lib/ARCMigrate/Transforms.h | 51 |
6 files changed, 181 insertions, 8 deletions
diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp index a588d54b87..f35f2577ed 100644 --- a/lib/ARCMigrate/ARCMT.cpp +++ b/lib/ARCMigrate/ARCMT.cpp @@ -192,6 +192,7 @@ createInvocationForMigration(CompilerInvocation &origCI) { define += '='; CInvok->getPreprocessorOpts().addMacroDef(define); CInvok->getLangOpts().ObjCAutoRefCount = true; + CInvok->getLangOpts().setGC(LangOptions::NonGC); CInvok->getDiagnosticOpts().ErrorLimit = 0; CInvok->getDiagnosticOpts().Warnings.push_back( "error=arc-unsafe-retained-assign"); @@ -226,7 +227,9 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, if (!origCI.getLangOpts().ObjC1) return false; - std::vector<TransformFn> transforms = arcmt::getAllTransformations(); + LangOptions::GCMode OrigGCMode = origCI.getLangOpts().getGC(); + + std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode); assert(!transforms.empty()); llvm::OwningPtr<CompilerInvocation> CInvok; @@ -287,7 +290,7 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, std::vector<SourceLocation> ARCMTMacroLocs; TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor()); - MigrationPass pass(Ctx, Unit->getSema(), testAct, ARCMTMacroLocs); + MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, ARCMTMacroLocs); for (unsigned i=0, e = transforms.size(); i != e; ++i) transforms[i](pass); @@ -316,6 +319,8 @@ static bool applyTransforms(CompilerInvocation &origCI, if (!origCI.getLangOpts().ObjC1) return false; + LangOptions::GCMode OrigGCMode = origCI.getLangOpts().getGC(); + // Make sure checking is successful first. CompilerInvocation CInvokForCheck(origCI); if (arcmt::checkForManualIssues(CInvokForCheck, Filename, Kind, DiagClient, @@ -328,7 +333,7 @@ static bool applyTransforms(CompilerInvocation &origCI, MigrationProcess migration(CInvok, DiagClient, outputDir); - std::vector<TransformFn> transforms = arcmt::getAllTransformations(); + std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode); assert(!transforms.empty()); for (unsigned i=0, e = transforms.size(); i != e; ++i) { @@ -537,7 +542,8 @@ bool MigrationProcess::applyTransform(TransformFn trans, Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOptions()); TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor()); - MigrationPass pass(Ctx, Unit->getSema(), TA, ARCMTMacroLocs); + MigrationPass pass(Ctx, OrigCI.getLangOpts().getGC(), + Unit->getSema(), TA, ARCMTMacroLocs); trans(pass); diff --git a/lib/ARCMigrate/CMakeLists.txt b/lib/ARCMigrate/CMakeLists.txt index f6d404ee13..90c2bbf54e 100644 --- a/lib/ARCMigrate/CMakeLists.txt +++ b/lib/ARCMigrate/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_library(clangARCMigrate TransEmptyStatementsAndDealloc.cpp TransformActions.cpp Transforms.cpp + TransGCCalls.cpp TransProperties.cpp TransRetainReleaseDealloc.cpp TransUnbridgedCasts.cpp diff --git a/lib/ARCMigrate/Internals.h b/lib/ARCMigrate/Internals.h index 99b5f59679..06d9f8259f 100644 --- a/lib/ARCMigrate/Internals.h +++ b/lib/ARCMigrate/Internals.h @@ -137,13 +137,18 @@ public: class MigrationPass { public: ASTContext &Ctx; + LangOptions::GCMode OrigGCMode; Sema &SemaRef; TransformActions &TA; std::vector<SourceLocation> &ARCMTMacroLocs; - MigrationPass(ASTContext &Ctx, Sema &sema, TransformActions &TA, + MigrationPass(ASTContext &Ctx, LangOptions::GCMode OrigGCMode, + Sema &sema, TransformActions &TA, std::vector<SourceLocation> &ARCMTMacroLocs) - : Ctx(Ctx), SemaRef(sema), TA(TA), ARCMTMacroLocs(ARCMTMacroLocs) { } + : Ctx(Ctx), OrigGCMode(OrigGCMode), SemaRef(sema), TA(TA), + ARCMTMacroLocs(ARCMTMacroLocs) { } + + bool isGCMigration() const { return OrigGCMode != LangOptions::NonGC; } }; static inline StringRef getARCMTMacroName() { diff --git a/lib/ARCMigrate/TransGCCalls.cpp b/lib/ARCMigrate/TransGCCalls.cpp new file mode 100644 index 0000000000..71dc6dc357 --- /dev/null +++ b/lib/ARCMigrate/TransGCCalls.cpp @@ -0,0 +1,59 @@ +//===--- TransGCCalls.cpp - Tranformations to ARC mode --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Transforms.h" +#include "Internals.h" +#include "clang/Sema/SemaDiagnostic.h" + +using namespace clang; +using namespace arcmt; +using namespace trans; + +namespace { + +class GCCollectableCallsChecker : + public RecursiveASTVisitor<GCCollectableCallsChecker> { + MigrationContext &MigrateCtx; + ParentMap &PMap; + IdentifierInfo *NSMakeCollectableII; + +public: + GCCollectableCallsChecker(MigrationContext &ctx, ParentMap &map) + : MigrateCtx(ctx), PMap(map) { + NSMakeCollectableII = + &MigrateCtx.getPass().Ctx.Idents.get("NSMakeCollectable"); + } + + bool VisitCallExpr(CallExpr *E) { + Expr *CEE = E->getCallee()->IgnoreParenImpCasts(); + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { + if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) { + if (FD->getDeclContext()->getRedeclContext()->isFileContext() && + FD->getIdentifier() == NSMakeCollectableII) { + TransformActions &TA = MigrateCtx.getPass().TA; + Transaction Trans(TA); + TA.clearDiagnostic(diag::err_unavailable, + diag::err_unavailable_message, + DRE->getSourceRange()); + TA.replace(DRE->getSourceRange(), "CFBridgingRelease"); + } + } + } + + return true; + } +}; + +} // anonymous namespace + +void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) { + GCCollectableCallsChecker(BodyCtx.getMigrationContext(), + BodyCtx.getParentMap()) + .TraverseStmt(BodyCtx.getTopStmt()); +} diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp index 4244fafe07..792bb0cc9a 100644 --- a/lib/ARCMigrate/Transforms.cpp +++ b/lib/ARCMigrate/Transforms.cpp @@ -12,7 +12,6 @@ #include "clang/Sema/SemaDiagnostic.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" -#include "clang/AST/ParentMap.h" #include "clang/Analysis/DomainSpecific/CocoaConventions.h" #include "clang/Lex/Lexer.h" #include "clang/Basic/SourceManager.h" @@ -24,6 +23,8 @@ using namespace clang; using namespace arcmt; using namespace trans; +ASTTraverser::~ASTTraverser() { } + //===----------------------------------------------------------------------===// // Helpers. //===----------------------------------------------------------------------===// @@ -290,9 +291,57 @@ void trans::collectRemovables(Stmt *S, ExprSet &exprs) { } //===----------------------------------------------------------------------===// +// MigrationContext +//===----------------------------------------------------------------------===// + +namespace { + +class ASTTransform : public RecursiveASTVisitor<ASTTransform> { + MigrationContext &MigrateCtx; + +public: + ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { } + + bool TraverseStmt(Stmt *rootS) { + if (!rootS) + return true; + + BodyContext BodyCtx(MigrateCtx, rootS); + for (MigrationContext::traverser_iterator + I = MigrateCtx.traversers_begin(), + E = MigrateCtx.traversers_end(); I != E; ++I) + (*I)->traverseBody(BodyCtx); + + return true; + } +}; + +} + +MigrationContext::~MigrationContext() { + for (traverser_iterator + I = traversers_begin(), E = traversers_end(); I != E; ++I) + delete *I; +} + +void MigrationContext::traverse(TranslationUnitDecl *TU) { + ASTTransform(*this).TraverseDecl(TU); +} + +//===----------------------------------------------------------------------===// // getAllTransformations. //===----------------------------------------------------------------------===// +static void traverseAST(MigrationPass &pass) { + MigrationContext MigrateCtx(pass); + + if (pass.isGCMigration()) { + MigrateCtx.addTraverser(new GCCollectableCallsTraverser); + } + + MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl()); +} + static void independentTransforms(MigrationPass &pass) { rewriteAutoreleasePool(pass); rewriteProperties(pass); @@ -303,9 +352,11 @@ static void independentTransforms(MigrationPass &pass) { rewriteUnbridgedCasts(pass); rewriteBlockObjCVariable(pass); checkAPIUses(pass); + traverseAST(pass); } -std::vector<TransformFn> arcmt::getAllTransformations() { +std::vector<TransformFn> arcmt::getAllTransformations( + LangOptions::GCMode OrigGCMode) { std::vector<TransformFn> transforms; transforms.push_back(independentTransforms); diff --git a/lib/ARCMigrate/Transforms.h b/lib/ARCMigrate/Transforms.h index 5e4db56dc8..0eabb21196 100644 --- a/lib/ARCMigrate/Transforms.h +++ b/lib/ARCMigrate/Transforms.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/ParentMap.h" #include "llvm/ADT/DenseSet.h" namespace clang { @@ -25,6 +26,8 @@ namespace arcmt { namespace trans { + class MigrationContext; + //===----------------------------------------------------------------------===// // Transformations. //===----------------------------------------------------------------------===// @@ -41,6 +44,54 @@ void checkAPIUses(MigrationPass &pass); void removeEmptyStatementsAndDealloc(MigrationPass &pass); +class BodyContext { + MigrationContext &MigrateCtx; + ParentMap PMap; + Stmt *TopStmt; + +public: + BodyContext(MigrationContext &MigrateCtx, Stmt *S) + : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {} + + MigrationContext &getMigrationContext() { return MigrateCtx; } + ParentMap &getParentMap() { return PMap; } + Stmt *getTopStmt() { return TopStmt; } +}; + +class ASTTraverser { +public: + virtual ~ASTTraverser(); + virtual void traverseBody(BodyContext &BodyCtx) { } +}; + +class MigrationContext { + MigrationPass &Pass; + std::vector<ASTTraverser *> Traversers; + +public: + explicit MigrationContext(MigrationPass &pass) : Pass(pass) {} + ~MigrationContext(); + + MigrationPass &getPass() { return Pass; } + + typedef std::vector<ASTTraverser *>::iterator traverser_iterator; + traverser_iterator traversers_begin() { return Traversers.begin(); } + traverser_iterator traversers_end() { return Traversers.end(); } + + void addTraverser(ASTTraverser *traverser) { + Traversers.push_back(traverser); + } + + void traverse(TranslationUnitDecl *TU); +}; + +// GC transformations + +class GCCollectableCallsTraverser : public ASTTraverser { +public: + virtual void traverseBody(BodyContext &BodyCtx); +}; + //===----------------------------------------------------------------------===// // Helpers. //===----------------------------------------------------------------------===// |