| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 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" | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 14 | #include "clang/AST/ParentMap.h" | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 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 |  | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 29 | class MigrationContext; | 
|  | 30 |  | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 31 | //===----------------------------------------------------------------------===// | 
|  | 32 | // Transformations. | 
|  | 33 | //===----------------------------------------------------------------------===// | 
|  | 34 |  | 
|  | 35 | void rewriteAutoreleasePool(MigrationPass &pass); | 
|  | 36 | void rewriteUnbridgedCasts(MigrationPass &pass); | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 37 | void makeAssignARCSafe(MigrationPass &pass); | 
| Argyrios Kyrtzidis | e7ef855 | 2011-11-04 15:58:22 +0000 | [diff] [blame] | 38 | void removeRetainReleaseDeallocFinalize(MigrationPass &pass); | 
|  | 39 | void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass); | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 40 | void rewriteBlockObjCVariable(MigrationPass &pass); | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 41 | void rewriteUnusedInitDelegate(MigrationPass &pass); | 
| Argyrios Kyrtzidis | fd10398 | 2011-07-18 07:44:45 +0000 | [diff] [blame] | 42 | void checkAPIUses(MigrationPass &pass); | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 43 |  | 
| Argyrios Kyrtzidis | e7ef855 | 2011-11-04 15:58:22 +0000 | [diff] [blame] | 44 | void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass); | 
| Argyrios Kyrtzidis | fd3455a | 2011-06-21 20:20:42 +0000 | [diff] [blame] | 45 |  | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 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 |  | 
| Argyrios Kyrtzidis | b0d5db1 | 2011-11-06 18:57:57 +0000 | [diff] [blame] | 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 |  | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 73 | class ASTTraverser { | 
|  | 74 | public: | 
|  | 75 | virtual ~ASTTraverser(); | 
| Argyrios Kyrtzidis | b0d5db1 | 2011-11-06 18:57:57 +0000 | [diff] [blame] | 76 | virtual void traverseTU(MigrationContext &MigrateCtx) { } | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 77 | virtual void traverseBody(BodyContext &BodyCtx) { } | 
| Argyrios Kyrtzidis | b0d5db1 | 2011-11-06 18:57:57 +0000 | [diff] [blame] | 78 | virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {} | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 79 | }; | 
|  | 80 |  | 
|  | 81 | class MigrationContext { | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 82 | std::vector<ASTTraverser *> Traversers; | 
|  | 83 |  | 
|  | 84 | public: | 
| Argyrios Kyrtzidis | f38fa73 | 2011-11-06 18:58:03 +0000 | [diff] [blame] | 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 |  | 
|  | 98 | llvm::DenseSet<unsigned> AttrSet; | 
|  | 99 |  | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 100 | explicit MigrationContext(MigrationPass &pass) : Pass(pass) {} | 
|  | 101 | ~MigrationContext(); | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 102 |  | 
|  | 103 | typedef std::vector<ASTTraverser *>::iterator traverser_iterator; | 
|  | 104 | traverser_iterator traversers_begin() { return Traversers.begin(); } | 
|  | 105 | traverser_iterator traversers_end() { return Traversers.end(); } | 
|  | 106 |  | 
|  | 107 | void addTraverser(ASTTraverser *traverser) { | 
|  | 108 | Traversers.push_back(traverser); | 
|  | 109 | } | 
|  | 110 |  | 
| Argyrios Kyrtzidis | 1fe4203 | 2011-11-04 23:43:03 +0000 | [diff] [blame] | 111 | bool isGCOwnedNonObjC(QualType T); | 
|  | 112 |  | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 113 | void traverse(TranslationUnitDecl *TU); | 
| Argyrios Kyrtzidis | 17ac319 | 2011-11-06 18:58:17 +0000 | [diff] [blame^] | 114 |  | 
|  | 115 | void dumpGCAttrs(); | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 116 | }; | 
|  | 117 |  | 
| Argyrios Kyrtzidis | b0d5db1 | 2011-11-06 18:57:57 +0000 | [diff] [blame] | 118 | class PropertyRewriteTraverser : public ASTTraverser { | 
|  | 119 | public: | 
|  | 120 | virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx); | 
|  | 121 | }; | 
|  | 122 |  | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 123 | // GC transformations | 
|  | 124 |  | 
| Argyrios Kyrtzidis | f38fa73 | 2011-11-06 18:58:03 +0000 | [diff] [blame] | 125 | class GCAttrsTraverser : public ASTTraverser { | 
|  | 126 | public: | 
|  | 127 | virtual void traverseTU(MigrationContext &MigrateCtx); | 
|  | 128 | }; | 
|  | 129 |  | 
| Argyrios Kyrtzidis | e0ac745 | 2011-11-04 15:58:08 +0000 | [diff] [blame] | 130 | class GCCollectableCallsTraverser : public ASTTraverser { | 
|  | 131 | public: | 
|  | 132 | virtual void traverseBody(BodyContext &BodyCtx); | 
|  | 133 | }; | 
|  | 134 |  | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 135 | //===----------------------------------------------------------------------===// | 
|  | 136 | // Helpers. | 
|  | 137 | //===----------------------------------------------------------------------===// | 
|  | 138 |  | 
| Argyrios Kyrtzidis | 86625b5 | 2011-07-12 22:05:17 +0000 | [diff] [blame] | 139 | /// \brief Determine whether we can add weak to the given type. | 
|  | 140 | bool canApplyWeak(ASTContext &Ctx, QualType type); | 
|  | 141 |  | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 142 | /// \brief 'Loc' is the end of a statement range. This returns the location | 
|  | 143 | /// immediately after the semicolon following the statement. | 
|  | 144 | /// If no semicolon is found or the location is inside a macro, the returned | 
|  | 145 | /// source location will be invalid. | 
|  | 146 | SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx); | 
|  | 147 |  | 
| Argyrios Kyrtzidis | aec230d | 2011-09-01 20:53:18 +0000 | [diff] [blame] | 148 | /// \brief \arg Loc is the end of a statement range. This returns the location | 
|  | 149 | /// of the semicolon following the statement. | 
|  | 150 | /// If no semicolon is found or the location is inside a macro, the returned | 
|  | 151 | /// source location will be invalid. | 
|  | 152 | SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx); | 
|  | 153 |  | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 154 | bool hasSideEffects(Expr *E, ASTContext &Ctx); | 
| Argyrios Kyrtzidis | 2c18ca0 | 2011-07-14 23:32:04 +0000 | [diff] [blame] | 155 | bool isGlobalVar(Expr *E); | 
| Argyrios Kyrtzidis | 18fd0c6 | 2011-07-27 05:28:18 +0000 | [diff] [blame] | 156 | /// \brief Returns "nil" or "0" if 'nil' macro is not actually defined. | 
|  | 157 | StringRef getNilString(ASTContext &Ctx); | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 158 |  | 
|  | 159 | template <typename BODY_TRANS> | 
|  | 160 | class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > { | 
|  | 161 | MigrationPass &Pass; | 
|  | 162 |  | 
|  | 163 | public: | 
|  | 164 | BodyTransform(MigrationPass &pass) : Pass(pass) { } | 
|  | 165 |  | 
| Argyrios Kyrtzidis | b1094a0 | 2011-06-23 21:21:33 +0000 | [diff] [blame] | 166 | bool TraverseStmt(Stmt *rootS) { | 
| Argyrios Kyrtzidis | fd10398 | 2011-07-18 07:44:45 +0000 | [diff] [blame] | 167 | if (rootS) | 
|  | 168 | BODY_TRANS(Pass).transformBody(rootS); | 
| Argyrios Kyrtzidis | 7196d06 | 2011-06-21 20:20:39 +0000 | [diff] [blame] | 169 | return true; | 
|  | 170 | } | 
|  | 171 | }; | 
|  | 172 |  | 
|  | 173 | typedef llvm::DenseSet<Expr *> ExprSet; | 
|  | 174 |  | 
|  | 175 | void clearRefsIn(Stmt *S, ExprSet &refs); | 
|  | 176 | template <typename iterator> | 
|  | 177 | void clearRefsIn(iterator begin, iterator end, ExprSet &refs) { | 
|  | 178 | for (; begin != end; ++begin) | 
|  | 179 | clearRefsIn(*begin, refs); | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs); | 
|  | 183 |  | 
|  | 184 | void collectRemovables(Stmt *S, ExprSet &exprs); | 
|  | 185 |  | 
|  | 186 | } // end namespace trans | 
|  | 187 |  | 
|  | 188 | } // end namespace arcmt | 
|  | 189 |  | 
|  | 190 | } // end namespace clang | 
|  | 191 |  | 
|  | 192 | #endif |