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 17 namespace clang { 18 class Decl; 19 class Stmt; 20 class BlockDecl; 21 class ObjCMethodDecl; 22 class FunctionDecl; 23 24 namespace arcmt { 25 class MigrationPass; 26 27 namespace trans { 28 29 class MigrationContext; 30 31 //===----------------------------------------------------------------------===// 32 // Transformations. 33 //===----------------------------------------------------------------------===// 34 35 void rewriteAutoreleasePool(MigrationPass &pass); 36 void rewriteUnbridgedCasts(MigrationPass &pass); 37 void makeAssignARCSafe(MigrationPass &pass); 38 void removeRetainReleaseDeallocFinalize(MigrationPass &pass); 39 void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass); 40 void rewriteUnusedInitDelegate(MigrationPass &pass); 41 void checkAPIUses(MigrationPass &pass); 42 43 void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass); 44 45 class BodyContext { 46 MigrationContext &MigrateCtx; 47 ParentMap PMap; 48 Stmt *TopStmt; 49 50 public: 51 BodyContext(MigrationContext &MigrateCtx, Stmt *S) 52 : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {} 53 54 MigrationContext &getMigrationContext() { return MigrateCtx; } 55 ParentMap &getParentMap() { return PMap; } 56 Stmt *getTopStmt() { return TopStmt; } 57 }; 58 59 class ObjCImplementationContext { 60 MigrationContext &MigrateCtx; 61 ObjCImplementationDecl *ImpD; 62 63 public: 64 ObjCImplementationContext(MigrationContext &MigrateCtx, 65 ObjCImplementationDecl *D) 66 : MigrateCtx(MigrateCtx), ImpD(D) {} 67 68 MigrationContext &getMigrationContext() { return MigrateCtx; } 69 ObjCImplementationDecl *getImplementationDecl() { return ImpD; } 70 }; 71 72 class ASTTraverser { 73 public: 74 virtual ~ASTTraverser(); 75 virtual void traverseTU(MigrationContext &MigrateCtx) { } 76 virtual void traverseBody(BodyContext &BodyCtx) { } 77 virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {} 78 }; 79 80 class MigrationContext { 81 std::vector<ASTTraverser *> Traversers; 82 83 public: 84 MigrationPass &Pass; 85 86 struct GCAttrOccurrence { 87 enum AttrKind { Weak, Strong } Kind; 88 SourceLocation Loc; 89 QualType ModifiedType; 90 Decl *Dcl; 91 /// \brief true if the attribute is owned, e.g. it is in a body and not just 92 /// in an interface. 93 bool FullyMigratable; 94 }; 95 std::vector<GCAttrOccurrence> GCAttrs; 96 llvm::DenseSet<unsigned> AttrSet; 97 llvm::DenseSet<unsigned> RemovedAttrSet; 98 99 /// \brief Set of raw '@' locations for 'assign' properties group that contain 100 /// GC __weak. 101 llvm::DenseSet<unsigned> AtPropsWeak; 102 103 explicit MigrationContext(MigrationPass &pass) : Pass(pass) {} 104 ~MigrationContext(); 105 106 typedef std::vector<ASTTraverser *>::iterator traverser_iterator; 107 traverser_iterator traversers_begin() { return Traversers.begin(); } 108 traverser_iterator traversers_end() { return Traversers.end(); } 109 110 void addTraverser(ASTTraverser *traverser) { 111 Traversers.push_back(traverser); 112 } 113 114 bool isGCOwnedNonObjC(QualType T); 115 bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) { 116 return rewritePropertyAttribute(fromAttr, StringRef(), atLoc); 117 } 118 bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr, 119 SourceLocation atLoc); 120 bool addPropertyAttribute(StringRef attr, SourceLocation atLoc); 121 122 void traverse(TranslationUnitDecl *TU); 123 124 void dumpGCAttrs(); 125 }; 126 127 class PropertyRewriteTraverser : public ASTTraverser { 128 public: 129 virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx); 130 }; 131 132 class BlockObjCVariableTraverser : public ASTTraverser { 133 public: 134 virtual void traverseBody(BodyContext &BodyCtx); 135 }; 136 137 // GC transformations 138 139 class GCAttrsTraverser : public ASTTraverser { 140 public: 141 virtual void traverseTU(MigrationContext &MigrateCtx); 142 }; 143 144 class GCCollectableCallsTraverser : public ASTTraverser { 145 public: 146 virtual void traverseBody(BodyContext &BodyCtx); 147 }; 148 149 //===----------------------------------------------------------------------===// 150 // Helpers. 151 //===----------------------------------------------------------------------===// 152 153 /// \brief Determine whether we can add weak to the given type. 154 bool canApplyWeak(ASTContext &Ctx, QualType type, 155 bool AllowOnUnknownClass = false); 156 157 /// \brief 'Loc' is the end of a statement range. This returns the location 158 /// immediately after the semicolon following the statement. 159 /// If no semicolon is found or the location is inside a macro, the returned 160 /// source location will be invalid. 161 SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx); 162 163 /// \brief \arg Loc is the end of a statement range. This returns the location 164 /// of the semicolon following the statement. 165 /// If no semicolon is found or the location is inside a macro, the returned 166 /// source location will be invalid. 167 SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx); 168 169 bool hasSideEffects(Expr *E, ASTContext &Ctx); 170 bool isGlobalVar(Expr *E); 171 /// \brief Returns "nil" or "0" if 'nil' macro is not actually defined. 172 StringRef getNilString(ASTContext &Ctx); 173 174 template <typename BODY_TRANS> 175 class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > { 176 MigrationPass &Pass; 177 178 public: 179 BodyTransform(MigrationPass &pass) : Pass(pass) { } 180 181 bool TraverseStmt(Stmt *rootS) { 182 if (rootS) 183 BODY_TRANS(Pass).transformBody(rootS); 184 return true; 185 } 186 }; 187 188 typedef llvm::DenseSet<Expr *> ExprSet; 189 190 void clearRefsIn(Stmt *S, ExprSet &refs); 191 template <typename iterator> 192 void clearRefsIn(iterator begin, iterator end, ExprSet &refs) { 193 for (; begin != end; ++begin) 194 clearRefsIn(*begin, refs); 195 } 196 197 void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs); 198 199 void collectRemovables(Stmt *S, ExprSet &exprs); 200 201 } // end namespace trans 202 203 } // end namespace arcmt 204 205 } // end namespace clang 206 207 #endif 208