diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/ARCMigrate/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/TransDeallocMethod.cpp | 47 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/TransEmptyStatements.cpp | 161 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp | 211 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/Transforms.cpp | 7 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/Transforms.h | 4 |
6 files changed, 215 insertions, 216 deletions
diff --git a/clang/lib/ARCMigrate/CMakeLists.txt b/clang/lib/ARCMigrate/CMakeLists.txt index 56db384bef2..7e5fc13bba4 100644 --- a/clang/lib/ARCMigrate/CMakeLists.txt +++ b/clang/lib/ARCMigrate/CMakeLists.txt @@ -8,7 +8,6 @@ add_clang_library(clangARCMigrate TransARCAssign.cpp TransAutoreleasePool.cpp TransBlockObjCVariable.cpp - TransDeallocMethod.cpp TransEmptyStatements.cpp TransformActions.cpp Transforms.cpp diff --git a/clang/lib/ARCMigrate/TransDeallocMethod.cpp b/clang/lib/ARCMigrate/TransDeallocMethod.cpp deleted file mode 100644 index a7c3c1e9d64..00000000000 --- a/clang/lib/ARCMigrate/TransDeallocMethod.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//===--- TransDeallocMethod.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" - -using namespace clang; -using namespace arcmt; -using namespace trans; -using llvm::StringRef; - -void trans::removeDeallocMethod(MigrationPass &pass) { - ASTContext &Ctx = pass.Ctx; - TransformActions &TA = pass.TA; - DeclContext *DC = Ctx.getTranslationUnitDecl(); - ObjCMethodDecl *DeallocMethodDecl = 0; - IdentifierInfo *II = &Ctx.Idents.get("dealloc"); - - for (DeclContext::decl_iterator - I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { - Decl *D = *I; - if (ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(D)) { - DeallocMethodDecl = 0; - for (ObjCImplementationDecl::instmeth_iterator - I = IMD->instmeth_begin(), E = IMD->instmeth_end(); - I != E; ++I) { - ObjCMethodDecl *OMD = *I; - if (OMD->isInstanceMethod() && - OMD->getSelector() == Ctx.Selectors.getSelector(0, &II)) { - DeallocMethodDecl = OMD; - break; - } - } - if (DeallocMethodDecl && - DeallocMethodDecl->getCompoundBody()->body_empty()) { - Transaction Trans(TA); - TA.remove(DeallocMethodDecl->getSourceRange()); - } - } - } -} diff --git a/clang/lib/ARCMigrate/TransEmptyStatements.cpp b/clang/lib/ARCMigrate/TransEmptyStatements.cpp deleted file mode 100644 index 1b62bbf0354..00000000000 --- a/clang/lib/ARCMigrate/TransEmptyStatements.cpp +++ /dev/null @@ -1,161 +0,0 @@ -//===--- TransEmptyStatements.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. -// -//===----------------------------------------------------------------------===// -// -// removeEmptyStatements: -// -// Removes empty statements that are leftovers from previous transformations. -// e.g for -// -// [x retain]; -// -// removeRetainReleaseDealloc will leave an empty ";" that removeEmptyStatements -// will remove. -// -//===----------------------------------------------------------------------===// - -#include "Transforms.h" -#include "Internals.h" -#include "clang/AST/StmtVisitor.h" - -using namespace clang; -using namespace arcmt; -using namespace trans; -using llvm::StringRef; - -namespace { - -class EmptyStatementsRemover : - public RecursiveASTVisitor<EmptyStatementsRemover> { - MigrationPass &Pass; - llvm::DenseSet<unsigned> MacroLocs; - -public: - EmptyStatementsRemover(MigrationPass &pass) : Pass(pass) { - for (unsigned i = 0, e = Pass.ARCMTMacroLocs.size(); i != e; ++i) - MacroLocs.insert(Pass.ARCMTMacroLocs[i].getRawEncoding()); - } - - bool TraverseStmtExpr(StmtExpr *E) { - CompoundStmt *S = E->getSubStmt(); - for (CompoundStmt::body_iterator - I = S->body_begin(), E = S->body_end(); I != E; ++I) { - if (I != E - 1) - check(*I); - TraverseStmt(*I); - } - return true; - } - - bool VisitCompoundStmt(CompoundStmt *S) { - for (CompoundStmt::body_iterator - I = S->body_begin(), E = S->body_end(); I != E; ++I) - check(*I); - return true; - } - - bool isMacroLoc(SourceLocation loc) { - if (loc.isInvalid()) return false; - return MacroLocs.count(loc.getRawEncoding()); - } - - ASTContext &getContext() { return Pass.Ctx; } - -private: - /// \brief Returns true if the statement became empty due to previous - /// transformations. - class EmptyChecker : public StmtVisitor<EmptyChecker, bool> { - EmptyStatementsRemover &Trans; - - public: - EmptyChecker(EmptyStatementsRemover &trans) : Trans(trans) { } - - bool VisitNullStmt(NullStmt *S) { - return Trans.isMacroLoc(S->getLeadingEmptyMacroLoc()); - } - bool VisitCompoundStmt(CompoundStmt *S) { - if (S->body_empty()) - return false; // was already empty, not because of transformations. - for (CompoundStmt::body_iterator - I = S->body_begin(), E = S->body_end(); I != E; ++I) - if (!Visit(*I)) - return false; - return true; - } - bool VisitIfStmt(IfStmt *S) { - if (S->getConditionVariable()) - return false; - Expr *condE = S->getCond(); - if (!condE) - return false; - if (hasSideEffects(condE, Trans.getContext())) - return false; - if (!S->getThen() || !Visit(S->getThen())) - return false; - if (S->getElse() && !Visit(S->getElse())) - return false; - return true; - } - bool VisitWhileStmt(WhileStmt *S) { - if (S->getConditionVariable()) - return false; - Expr *condE = S->getCond(); - if (!condE) - return false; - if (hasSideEffects(condE, Trans.getContext())) - return false; - if (!S->getBody()) - return false; - return Visit(S->getBody()); - } - bool VisitDoStmt(DoStmt *S) { - Expr *condE = S->getCond(); - if (!condE) - return false; - if (hasSideEffects(condE, Trans.getContext())) - return false; - if (!S->getBody()) - return false; - return Visit(S->getBody()); - } - bool VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { - Expr *Exp = S->getCollection(); - if (!Exp) - return false; - if (hasSideEffects(Exp, Trans.getContext())) - return false; - if (!S->getBody()) - return false; - return Visit(S->getBody()); - } - bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { - if (!S->getSubStmt()) - return false; - return Visit(S->getSubStmt()); - } - }; - - void check(Stmt *S) { - if (!S) return; - if (EmptyChecker(*this).Visit(S)) { - Transaction Trans(Pass.TA); - Pass.TA.removeStmt(S); - } - } -}; - -} // anonymous namespace - -void trans::removeEmptyStatements(MigrationPass &pass) { - EmptyStatementsRemover(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl()); - - for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) { - Transaction Trans(pass.TA); - pass.TA.remove(pass.ARCMTMacroLocs[i]); - } -} diff --git a/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp new file mode 100644 index 00000000000..d0bc332ff16 --- /dev/null +++ b/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp @@ -0,0 +1,211 @@ +//===--- TransEmptyStatements.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. +// +//===----------------------------------------------------------------------===// +// +// removeEmptyStatementsAndDealloc: +// +// Removes empty statements that are leftovers from previous transformations. +// e.g for +// +// [x retain]; +// +// removeRetainReleaseDealloc will leave an empty ";" that removeEmptyStatements +// will remove. +// +//===----------------------------------------------------------------------===// + +#include "Transforms.h" +#include "Internals.h" +#include "clang/AST/StmtVisitor.h" + +using namespace clang; +using namespace arcmt; +using namespace trans; +using llvm::StringRef; + +namespace { + +/// \brief Returns true if the statement became empty due to previous +/// transformations. +class EmptyChecker : public StmtVisitor<EmptyChecker, bool> { + ASTContext &Ctx; + llvm::DenseSet<unsigned> &MacroLocs; + +public: + EmptyChecker(ASTContext &ctx, llvm::DenseSet<unsigned> ¯oLocs) + : Ctx(ctx), MacroLocs(macroLocs) { } + + bool VisitNullStmt(NullStmt *S) { + return isMacroLoc(S->getLeadingEmptyMacroLoc()); + } + bool VisitCompoundStmt(CompoundStmt *S) { + if (S->body_empty()) + return false; // was already empty, not because of transformations. + for (CompoundStmt::body_iterator + I = S->body_begin(), E = S->body_end(); I != E; ++I) + if (!Visit(*I)) + return false; + return true; + } + bool VisitIfStmt(IfStmt *S) { + if (S->getConditionVariable()) + return false; + Expr *condE = S->getCond(); + if (!condE) + return false; + if (hasSideEffects(condE, Ctx)) + return false; + if (!S->getThen() || !Visit(S->getThen())) + return false; + if (S->getElse() && !Visit(S->getElse())) + return false; + return true; + } + bool VisitWhileStmt(WhileStmt *S) { + if (S->getConditionVariable()) + return false; + Expr *condE = S->getCond(); + if (!condE) + return false; + if (hasSideEffects(condE, Ctx)) + return false; + if (!S->getBody()) + return false; + return Visit(S->getBody()); + } + bool VisitDoStmt(DoStmt *S) { + Expr *condE = S->getCond(); + if (!condE) + return false; + if (hasSideEffects(condE, Ctx)) + return false; + if (!S->getBody()) + return false; + return Visit(S->getBody()); + } + bool VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { + Expr *Exp = S->getCollection(); + if (!Exp) + return false; + if (hasSideEffects(Exp, Ctx)) + return false; + if (!S->getBody()) + return false; + return Visit(S->getBody()); + } + bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { + if (!S->getSubStmt()) + return false; + return Visit(S->getSubStmt()); + } + +private: + bool isMacroLoc(SourceLocation loc) { + if (loc.isInvalid()) return false; + return MacroLocs.count(loc.getRawEncoding()); + } +}; + +class EmptyStatementsRemover : + public RecursiveASTVisitor<EmptyStatementsRemover> { + MigrationPass &Pass; + llvm::DenseSet<unsigned> &MacroLocs; + +public: + EmptyStatementsRemover(MigrationPass &pass, + llvm::DenseSet<unsigned> ¯oLocs) + : Pass(pass), MacroLocs(macroLocs) { } + + bool TraverseStmtExpr(StmtExpr *E) { + CompoundStmt *S = E->getSubStmt(); + for (CompoundStmt::body_iterator + I = S->body_begin(), E = S->body_end(); I != E; ++I) { + if (I != E - 1) + check(*I); + TraverseStmt(*I); + } + return true; + } + + bool VisitCompoundStmt(CompoundStmt *S) { + for (CompoundStmt::body_iterator + I = S->body_begin(), E = S->body_end(); I != E; ++I) + check(*I); + return true; + } + + bool isMacroLoc(SourceLocation loc) { + if (loc.isInvalid()) return false; + return MacroLocs.count(loc.getRawEncoding()); + } + + ASTContext &getContext() { return Pass.Ctx; } + +private: + void check(Stmt *S) { + if (!S) return; + if (EmptyChecker(Pass.Ctx, MacroLocs).Visit(S)) { + Transaction Trans(Pass.TA); + Pass.TA.removeStmt(S); + } + } +}; + +} // anonymous namespace + +static bool isBodyEmpty(CompoundStmt *body, + ASTContext &Ctx, llvm::DenseSet<unsigned> &MacroLocs) { + for (CompoundStmt::body_iterator + I = body->body_begin(), E = body->body_end(); I != E; ++I) + if (!EmptyChecker(Ctx, MacroLocs).Visit(*I)) + return false; + + return true; +} + +static void removeDeallocMethod(MigrationPass &pass, + llvm::DenseSet<unsigned> &MacroLocs) { + ASTContext &Ctx = pass.Ctx; + TransformActions &TA = pass.TA; + DeclContext *DC = Ctx.getTranslationUnitDecl(); + + typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl> + impl_iterator; + for (impl_iterator I = impl_iterator(DC->decls_begin()), + E = impl_iterator(DC->decls_end()); I != E; ++I) { + for (ObjCImplementationDecl::instmeth_iterator + MI = (*I)->instmeth_begin(), + ME = (*I)->instmeth_end(); MI != ME; ++MI) { + ObjCMethodDecl *MD = *MI; + if (MD->getMethodFamily() == OMF_dealloc) { + if (MD->hasBody() && + isBodyEmpty(MD->getCompoundBody(), Ctx, MacroLocs)) { + Transaction Trans(TA); + TA.remove(MD->getSourceRange()); + } + break; + } + } + } +} + +void trans::removeEmptyStatementsAndDealloc(MigrationPass &pass) { + llvm::DenseSet<unsigned> MacroLocs; + for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) + MacroLocs.insert(pass.ARCMTMacroLocs[i].getRawEncoding()); + + EmptyStatementsRemover(pass, MacroLocs) + .TraverseDecl(pass.Ctx.getTranslationUnitDecl()); + + removeDeallocMethod(pass, MacroLocs); + + for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) { + Transaction Trans(pass.TA); + pass.TA.remove(pass.ARCMTMacroLocs[i]); + } +} diff --git a/clang/lib/ARCMigrate/Transforms.cpp b/clang/lib/ARCMigrate/Transforms.cpp index 0650e3b94fb..3c2e3fc5323 100644 --- a/clang/lib/ARCMigrate/Transforms.cpp +++ b/clang/lib/ARCMigrate/Transforms.cpp @@ -224,12 +224,9 @@ static void independentTransforms(MigrationPass &pass) { std::vector<TransformFn> arcmt::getAllTransformations() { std::vector<TransformFn> transforms; - // This must come first since rewriteAutoreleasePool depends on -release - // calls being present to determine the @autorelease ending scope. transforms.push_back(independentTransforms); - - transforms.push_back(removeEmptyStatements); - transforms.push_back(removeDeallocMethod); + // This depends on previous transformations removing various expressions. + transforms.push_back(removeEmptyStatementsAndDealloc); return transforms; } diff --git a/clang/lib/ARCMigrate/Transforms.h b/clang/lib/ARCMigrate/Transforms.h index d95b1bc3234..6cc6085d617 100644 --- a/clang/lib/ARCMigrate/Transforms.h +++ b/clang/lib/ARCMigrate/Transforms.h @@ -34,13 +34,13 @@ void rewriteUnbridgedCasts(MigrationPass &pass); void rewriteAllocCopyWithZone(MigrationPass &pass); void makeAssignARCSafe(MigrationPass &pass); void removeRetainReleaseDealloc(MigrationPass &pass); -void removeEmptyStatements(MigrationPass &pass); void removeZeroOutPropsInDealloc(MigrationPass &pass); void changeIvarsOfAssignProperties(MigrationPass &pass); void rewriteBlockObjCVariable(MigrationPass &pass); -void removeDeallocMethod(MigrationPass &pass); void rewriteUnusedInitDelegate(MigrationPass &pass); +void removeEmptyStatementsAndDealloc(MigrationPass &pass); + //===----------------------------------------------------------------------===// // Helpers. //===----------------------------------------------------------------------===// |