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