Transforms.h revision e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1a
1//===-- Transforms.h - Tranformations to ARC mode ---------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H 11#define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H 12 13#include "clang/AST/RecursiveASTVisitor.h" 14#include "clang/AST/ParentMap.h" 15#include "llvm/ADT/DenseSet.h" 16 17namespace clang { 18 class Decl; 19 class Stmt; 20 class BlockDecl; 21 class ObjCMethodDecl; 22 class FunctionDecl; 23 24namespace arcmt { 25 class MigrationPass; 26 27namespace trans { 28 29 class MigrationContext; 30 31//===----------------------------------------------------------------------===// 32// Transformations. 33//===----------------------------------------------------------------------===// 34 35void rewriteAutoreleasePool(MigrationPass &pass); 36void rewriteUnbridgedCasts(MigrationPass &pass); 37void makeAssignARCSafe(MigrationPass &pass); 38void removeRetainReleaseDealloc(MigrationPass &pass); 39void removeZeroOutPropsInDealloc(MigrationPass &pass); 40void rewriteProperties(MigrationPass &pass); 41void rewriteBlockObjCVariable(MigrationPass &pass); 42void rewriteUnusedInitDelegate(MigrationPass &pass); 43void checkAPIUses(MigrationPass &pass); 44 45void removeEmptyStatementsAndDealloc(MigrationPass &pass); 46 47class BodyContext { 48 MigrationContext &MigrateCtx; 49 ParentMap PMap; 50 Stmt *TopStmt; 51 52public: 53 BodyContext(MigrationContext &MigrateCtx, Stmt *S) 54 : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {} 55 56 MigrationContext &getMigrationContext() { return MigrateCtx; } 57 ParentMap &getParentMap() { return PMap; } 58 Stmt *getTopStmt() { return TopStmt; } 59}; 60 61class ASTTraverser { 62public: 63 virtual ~ASTTraverser(); 64 virtual void traverseBody(BodyContext &BodyCtx) { } 65}; 66 67class MigrationContext { 68 MigrationPass &Pass; 69 std::vector<ASTTraverser *> Traversers; 70 71public: 72 explicit MigrationContext(MigrationPass &pass) : Pass(pass) {} 73 ~MigrationContext(); 74 75 MigrationPass &getPass() { return Pass; } 76 77 typedef std::vector<ASTTraverser *>::iterator traverser_iterator; 78 traverser_iterator traversers_begin() { return Traversers.begin(); } 79 traverser_iterator traversers_end() { return Traversers.end(); } 80 81 void addTraverser(ASTTraverser *traverser) { 82 Traversers.push_back(traverser); 83 } 84 85 void traverse(TranslationUnitDecl *TU); 86}; 87 88// GC transformations 89 90class GCCollectableCallsTraverser : public ASTTraverser { 91public: 92 virtual void traverseBody(BodyContext &BodyCtx); 93}; 94 95//===----------------------------------------------------------------------===// 96// Helpers. 97//===----------------------------------------------------------------------===// 98 99/// \brief Determine whether we can add weak to the given type. 100bool canApplyWeak(ASTContext &Ctx, QualType type); 101 102/// \brief 'Loc' is the end of a statement range. This returns the location 103/// immediately after the semicolon following the statement. 104/// If no semicolon is found or the location is inside a macro, the returned 105/// source location will be invalid. 106SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx); 107 108/// \brief \arg Loc is the end of a statement range. This returns the location 109/// of the semicolon following the statement. 110/// If no semicolon is found or the location is inside a macro, the returned 111/// source location will be invalid. 112SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx); 113 114bool hasSideEffects(Expr *E, ASTContext &Ctx); 115bool isGlobalVar(Expr *E); 116/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined. 117StringRef getNilString(ASTContext &Ctx); 118 119template <typename BODY_TRANS> 120class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > { 121 MigrationPass &Pass; 122 123public: 124 BodyTransform(MigrationPass &pass) : Pass(pass) { } 125 126 bool TraverseStmt(Stmt *rootS) { 127 if (rootS) 128 BODY_TRANS(Pass).transformBody(rootS); 129 return true; 130 } 131}; 132 133typedef llvm::DenseSet<Expr *> ExprSet; 134 135void clearRefsIn(Stmt *S, ExprSet &refs); 136template <typename iterator> 137void clearRefsIn(iterator begin, iterator end, ExprSet &refs) { 138 for (; begin != end; ++begin) 139 clearRefsIn(*begin, refs); 140} 141 142void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs); 143 144void collectRemovables(Stmt *S, ExprSet &exprs); 145 146} // end namespace trans 147 148} // end namespace arcmt 149 150} // end namespace clang 151 152#endif 153