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