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