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