clang API Documentation
00001 //===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H 00011 #define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H 00012 00013 #include "clang/AST/ParentMap.h" 00014 #include "clang/AST/RecursiveASTVisitor.h" 00015 #include "llvm/ADT/DenseSet.h" 00016 #include "llvm/Support/SaveAndRestore.h" 00017 00018 namespace clang { 00019 class Decl; 00020 class Stmt; 00021 class BlockDecl; 00022 class ObjCMethodDecl; 00023 class FunctionDecl; 00024 00025 namespace arcmt { 00026 class MigrationPass; 00027 00028 namespace trans { 00029 00030 class MigrationContext; 00031 00032 //===----------------------------------------------------------------------===// 00033 // Transformations. 00034 //===----------------------------------------------------------------------===// 00035 00036 void rewriteAutoreleasePool(MigrationPass &pass); 00037 void rewriteUnbridgedCasts(MigrationPass &pass); 00038 void makeAssignARCSafe(MigrationPass &pass); 00039 void removeRetainReleaseDeallocFinalize(MigrationPass &pass); 00040 void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass); 00041 void rewriteUnusedInitDelegate(MigrationPass &pass); 00042 void checkAPIUses(MigrationPass &pass); 00043 00044 void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass); 00045 00046 class BodyContext { 00047 MigrationContext &MigrateCtx; 00048 ParentMap PMap; 00049 Stmt *TopStmt; 00050 00051 public: 00052 BodyContext(MigrationContext &MigrateCtx, Stmt *S) 00053 : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {} 00054 00055 MigrationContext &getMigrationContext() { return MigrateCtx; } 00056 ParentMap &getParentMap() { return PMap; } 00057 Stmt *getTopStmt() { return TopStmt; } 00058 }; 00059 00060 class ObjCImplementationContext { 00061 MigrationContext &MigrateCtx; 00062 ObjCImplementationDecl *ImpD; 00063 00064 public: 00065 ObjCImplementationContext(MigrationContext &MigrateCtx, 00066 ObjCImplementationDecl *D) 00067 : MigrateCtx(MigrateCtx), ImpD(D) {} 00068 00069 MigrationContext &getMigrationContext() { return MigrateCtx; } 00070 ObjCImplementationDecl *getImplementationDecl() { return ImpD; } 00071 }; 00072 00073 class ASTTraverser { 00074 public: 00075 virtual ~ASTTraverser(); 00076 virtual void traverseTU(MigrationContext &MigrateCtx) { } 00077 virtual void traverseBody(BodyContext &BodyCtx) { } 00078 virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {} 00079 }; 00080 00081 class MigrationContext { 00082 std::vector<ASTTraverser *> Traversers; 00083 00084 public: 00085 MigrationPass &Pass; 00086 00087 struct GCAttrOccurrence { 00088 enum AttrKind { Weak, Strong } Kind; 00089 SourceLocation Loc; 00090 QualType ModifiedType; 00091 Decl *Dcl; 00092 /// \brief true if the attribute is owned, e.g. it is in a body and not just 00093 /// in an interface. 00094 bool FullyMigratable; 00095 }; 00096 std::vector<GCAttrOccurrence> GCAttrs; 00097 llvm::DenseSet<unsigned> AttrSet; 00098 llvm::DenseSet<unsigned> RemovedAttrSet; 00099 00100 /// \brief Set of raw '@' locations for 'assign' properties group that contain 00101 /// GC __weak. 00102 llvm::DenseSet<unsigned> AtPropsWeak; 00103 00104 explicit MigrationContext(MigrationPass &pass) : Pass(pass) {} 00105 ~MigrationContext(); 00106 00107 typedef std::vector<ASTTraverser *>::iterator traverser_iterator; 00108 traverser_iterator traversers_begin() { return Traversers.begin(); } 00109 traverser_iterator traversers_end() { return Traversers.end(); } 00110 00111 void addTraverser(ASTTraverser *traverser) { 00112 Traversers.push_back(traverser); 00113 } 00114 00115 bool isGCOwnedNonObjC(QualType T); 00116 bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) { 00117 return rewritePropertyAttribute(fromAttr, StringRef(), atLoc); 00118 } 00119 bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr, 00120 SourceLocation atLoc); 00121 bool addPropertyAttribute(StringRef attr, SourceLocation atLoc); 00122 00123 void traverse(TranslationUnitDecl *TU); 00124 00125 void dumpGCAttrs(); 00126 }; 00127 00128 class PropertyRewriteTraverser : public ASTTraverser { 00129 public: 00130 void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override; 00131 }; 00132 00133 class BlockObjCVariableTraverser : public ASTTraverser { 00134 public: 00135 void traverseBody(BodyContext &BodyCtx) override; 00136 }; 00137 00138 class ProtectedScopeTraverser : public ASTTraverser { 00139 public: 00140 void traverseBody(BodyContext &BodyCtx) override; 00141 }; 00142 00143 // GC transformations 00144 00145 class GCAttrsTraverser : public ASTTraverser { 00146 public: 00147 void traverseTU(MigrationContext &MigrateCtx) override; 00148 }; 00149 00150 class GCCollectableCallsTraverser : public ASTTraverser { 00151 public: 00152 void traverseBody(BodyContext &BodyCtx) override; 00153 }; 00154 00155 //===----------------------------------------------------------------------===// 00156 // Helpers. 00157 //===----------------------------------------------------------------------===// 00158 00159 /// \brief Determine whether we can add weak to the given type. 00160 bool canApplyWeak(ASTContext &Ctx, QualType type, 00161 bool AllowOnUnknownClass = false); 00162 00163 bool isPlusOneAssign(const BinaryOperator *E); 00164 bool isPlusOne(const Expr *E); 00165 00166 /// \brief 'Loc' is the end of a statement range. This returns the location 00167 /// immediately after the semicolon following the statement. 00168 /// If no semicolon is found or the location is inside a macro, the returned 00169 /// source location will be invalid. 00170 SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx, 00171 bool IsDecl = false); 00172 00173 /// \brief 'Loc' is the end of a statement range. This returns the location 00174 /// of the semicolon following the statement. 00175 /// If no semicolon is found or the location is inside a macro, the returned 00176 /// source location will be invalid. 00177 SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx, 00178 bool IsDecl = false); 00179 00180 bool hasSideEffects(Expr *E, ASTContext &Ctx); 00181 bool isGlobalVar(Expr *E); 00182 /// \brief Returns "nil" or "0" if 'nil' macro is not actually defined. 00183 StringRef getNilString(ASTContext &Ctx); 00184 00185 template <typename BODY_TRANS> 00186 class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > { 00187 MigrationPass &Pass; 00188 Decl *ParentD; 00189 00190 typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base; 00191 public: 00192 BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { } 00193 00194 bool TraverseStmt(Stmt *rootS) { 00195 if (rootS) 00196 BODY_TRANS(Pass).transformBody(rootS, ParentD); 00197 return true; 00198 } 00199 00200 bool TraverseObjCMethodDecl(ObjCMethodDecl *D) { 00201 SaveAndRestore<Decl *> SetParent(ParentD, D); 00202 return base::TraverseObjCMethodDecl(D); 00203 } 00204 }; 00205 00206 typedef llvm::DenseSet<Expr *> ExprSet; 00207 00208 void clearRefsIn(Stmt *S, ExprSet &refs); 00209 template <typename iterator> 00210 void clearRefsIn(iterator begin, iterator end, ExprSet &refs) { 00211 for (; begin != end; ++begin) 00212 clearRefsIn(*begin, refs); 00213 } 00214 00215 void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs); 00216 00217 void collectRemovables(Stmt *S, ExprSet &exprs); 00218 00219 } // end namespace trans 00220 00221 } // end namespace arcmt 00222 00223 } // end namespace clang 00224 00225 #endif