Transforms.h revision 249423
1249423Sdim//===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===// 2224135Sdim// 3224135Sdim// The LLVM Compiler Infrastructure 4224135Sdim// 5224135Sdim// This file is distributed under the University of Illinois Open Source 6224135Sdim// License. See LICENSE.TXT for details. 7224135Sdim// 8224135Sdim//===----------------------------------------------------------------------===// 9224135Sdim 10224135Sdim#ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H 11224135Sdim#define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H 12224135Sdim 13249423Sdim#include "clang/AST/ParentMap.h" 14224135Sdim#include "clang/AST/RecursiveASTVisitor.h" 15224135Sdim#include "llvm/ADT/DenseSet.h" 16239462Sdim#include "llvm/Support/SaveAndRestore.h" 17224135Sdim 18224135Sdimnamespace clang { 19224135Sdim class Decl; 20224135Sdim class Stmt; 21224135Sdim class BlockDecl; 22224135Sdim class ObjCMethodDecl; 23224135Sdim class FunctionDecl; 24224135Sdim 25224135Sdimnamespace arcmt { 26224135Sdim class MigrationPass; 27224135Sdim 28224135Sdimnamespace trans { 29224135Sdim 30234353Sdim class MigrationContext; 31234353Sdim 32224135Sdim//===----------------------------------------------------------------------===// 33224135Sdim// Transformations. 34224135Sdim//===----------------------------------------------------------------------===// 35224135Sdim 36224135Sdimvoid rewriteAutoreleasePool(MigrationPass &pass); 37224135Sdimvoid rewriteUnbridgedCasts(MigrationPass &pass); 38224135Sdimvoid makeAssignARCSafe(MigrationPass &pass); 39234353Sdimvoid removeRetainReleaseDeallocFinalize(MigrationPass &pass); 40234353Sdimvoid removeZeroOutPropsInDeallocFinalize(MigrationPass &pass); 41224135Sdimvoid rewriteUnusedInitDelegate(MigrationPass &pass); 42226633Sdimvoid checkAPIUses(MigrationPass &pass); 43224135Sdim 44234353Sdimvoid removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass); 45224135Sdim 46234353Sdimclass BodyContext { 47234353Sdim MigrationContext &MigrateCtx; 48234353Sdim ParentMap PMap; 49234353Sdim Stmt *TopStmt; 50234353Sdim 51234353Sdimpublic: 52234353Sdim BodyContext(MigrationContext &MigrateCtx, Stmt *S) 53234353Sdim : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {} 54234353Sdim 55234353Sdim MigrationContext &getMigrationContext() { return MigrateCtx; } 56234353Sdim ParentMap &getParentMap() { return PMap; } 57234353Sdim Stmt *getTopStmt() { return TopStmt; } 58234353Sdim}; 59234353Sdim 60234353Sdimclass ObjCImplementationContext { 61234353Sdim MigrationContext &MigrateCtx; 62234353Sdim ObjCImplementationDecl *ImpD; 63234353Sdim 64234353Sdimpublic: 65234353Sdim ObjCImplementationContext(MigrationContext &MigrateCtx, 66234353Sdim ObjCImplementationDecl *D) 67234353Sdim : MigrateCtx(MigrateCtx), ImpD(D) {} 68234353Sdim 69234353Sdim MigrationContext &getMigrationContext() { return MigrateCtx; } 70234353Sdim ObjCImplementationDecl *getImplementationDecl() { return ImpD; } 71234353Sdim}; 72234353Sdim 73234353Sdimclass ASTTraverser { 74234353Sdimpublic: 75234353Sdim virtual ~ASTTraverser(); 76234353Sdim virtual void traverseTU(MigrationContext &MigrateCtx) { } 77234353Sdim virtual void traverseBody(BodyContext &BodyCtx) { } 78234353Sdim virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {} 79234353Sdim}; 80234353Sdim 81234353Sdimclass MigrationContext { 82234353Sdim std::vector<ASTTraverser *> Traversers; 83234353Sdim 84234353Sdimpublic: 85234353Sdim MigrationPass &Pass; 86234353Sdim 87234353Sdim struct GCAttrOccurrence { 88234353Sdim enum AttrKind { Weak, Strong } Kind; 89234353Sdim SourceLocation Loc; 90234353Sdim QualType ModifiedType; 91234353Sdim Decl *Dcl; 92234353Sdim /// \brief true if the attribute is owned, e.g. it is in a body and not just 93234353Sdim /// in an interface. 94234353Sdim bool FullyMigratable; 95234353Sdim }; 96234353Sdim std::vector<GCAttrOccurrence> GCAttrs; 97234353Sdim llvm::DenseSet<unsigned> AttrSet; 98234353Sdim llvm::DenseSet<unsigned> RemovedAttrSet; 99234353Sdim 100234353Sdim /// \brief Set of raw '@' locations for 'assign' properties group that contain 101234353Sdim /// GC __weak. 102234353Sdim llvm::DenseSet<unsigned> AtPropsWeak; 103234353Sdim 104234353Sdim explicit MigrationContext(MigrationPass &pass) : Pass(pass) {} 105234353Sdim ~MigrationContext(); 106234353Sdim 107234353Sdim typedef std::vector<ASTTraverser *>::iterator traverser_iterator; 108234353Sdim traverser_iterator traversers_begin() { return Traversers.begin(); } 109234353Sdim traverser_iterator traversers_end() { return Traversers.end(); } 110234353Sdim 111234353Sdim void addTraverser(ASTTraverser *traverser) { 112234353Sdim Traversers.push_back(traverser); 113234353Sdim } 114234353Sdim 115234353Sdim bool isGCOwnedNonObjC(QualType T); 116234353Sdim bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) { 117234353Sdim return rewritePropertyAttribute(fromAttr, StringRef(), atLoc); 118234353Sdim } 119234353Sdim bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr, 120234353Sdim SourceLocation atLoc); 121234353Sdim bool addPropertyAttribute(StringRef attr, SourceLocation atLoc); 122234353Sdim 123234353Sdim void traverse(TranslationUnitDecl *TU); 124234353Sdim 125234353Sdim void dumpGCAttrs(); 126234353Sdim}; 127234353Sdim 128234353Sdimclass PropertyRewriteTraverser : public ASTTraverser { 129234353Sdimpublic: 130234353Sdim virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx); 131234353Sdim}; 132234353Sdim 133234353Sdimclass BlockObjCVariableTraverser : public ASTTraverser { 134234353Sdimpublic: 135234353Sdim virtual void traverseBody(BodyContext &BodyCtx); 136234353Sdim}; 137234353Sdim 138249423Sdimclass ProtectedScopeTraverser : public ASTTraverser { 139249423Sdimpublic: 140249423Sdim virtual void traverseBody(BodyContext &BodyCtx); 141249423Sdim}; 142249423Sdim 143234353Sdim// GC transformations 144234353Sdim 145234353Sdimclass GCAttrsTraverser : public ASTTraverser { 146234353Sdimpublic: 147234353Sdim virtual void traverseTU(MigrationContext &MigrateCtx); 148234353Sdim}; 149234353Sdim 150234353Sdimclass GCCollectableCallsTraverser : public ASTTraverser { 151234353Sdimpublic: 152234353Sdim virtual void traverseBody(BodyContext &BodyCtx); 153234353Sdim}; 154234353Sdim 155224135Sdim//===----------------------------------------------------------------------===// 156224135Sdim// Helpers. 157224135Sdim//===----------------------------------------------------------------------===// 158224135Sdim 159224135Sdim/// \brief Determine whether we can add weak to the given type. 160234353Sdimbool canApplyWeak(ASTContext &Ctx, QualType type, 161234353Sdim bool AllowOnUnknownClass = false); 162224135Sdim 163239462Sdimbool isPlusOneAssign(const BinaryOperator *E); 164249423Sdimbool isPlusOne(const Expr *E); 165239462Sdim 166224135Sdim/// \brief 'Loc' is the end of a statement range. This returns the location 167224135Sdim/// immediately after the semicolon following the statement. 168224135Sdim/// If no semicolon is found or the location is inside a macro, the returned 169224135Sdim/// source location will be invalid. 170224135SdimSourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx); 171224135Sdim 172226633Sdim/// \brief \arg Loc is the end of a statement range. This returns the location 173226633Sdim/// of the semicolon following the statement. 174226633Sdim/// If no semicolon is found or the location is inside a macro, the returned 175226633Sdim/// source location will be invalid. 176226633SdimSourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx); 177226633Sdim 178224135Sdimbool hasSideEffects(Expr *E, ASTContext &Ctx); 179224135Sdimbool isGlobalVar(Expr *E); 180226633Sdim/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined. 181226633SdimStringRef getNilString(ASTContext &Ctx); 182224135Sdim 183224135Sdimtemplate <typename BODY_TRANS> 184224135Sdimclass BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > { 185224135Sdim MigrationPass &Pass; 186239462Sdim Decl *ParentD; 187224135Sdim 188239462Sdim typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base; 189224135Sdimpublic: 190239462Sdim BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(0) { } 191224135Sdim 192224135Sdim bool TraverseStmt(Stmt *rootS) { 193226633Sdim if (rootS) 194239462Sdim BODY_TRANS(Pass).transformBody(rootS, ParentD); 195224135Sdim return true; 196224135Sdim } 197239462Sdim 198239462Sdim bool TraverseObjCMethodDecl(ObjCMethodDecl *D) { 199239462Sdim SaveAndRestore<Decl *> SetParent(ParentD, D); 200239462Sdim return base::TraverseObjCMethodDecl(D); 201239462Sdim } 202224135Sdim}; 203224135Sdim 204224135Sdimtypedef llvm::DenseSet<Expr *> ExprSet; 205224135Sdim 206224135Sdimvoid clearRefsIn(Stmt *S, ExprSet &refs); 207224135Sdimtemplate <typename iterator> 208224135Sdimvoid clearRefsIn(iterator begin, iterator end, ExprSet &refs) { 209224135Sdim for (; begin != end; ++begin) 210224135Sdim clearRefsIn(*begin, refs); 211224135Sdim} 212224135Sdim 213224135Sdimvoid collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs); 214224135Sdim 215224135Sdimvoid collectRemovables(Stmt *S, ExprSet &exprs); 216224135Sdim 217224135Sdim} // end namespace trans 218224135Sdim 219224135Sdim} // end namespace arcmt 220224135Sdim 221224135Sdim} // end namespace clang 222224135Sdim 223224135Sdim#endif 224