Home | History | Annotate | Download | only in ARCMigrate
      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 
     17 namespace clang {
     18   class Decl;
     19   class Stmt;
     20   class BlockDecl;
     21   class ObjCMethodDecl;
     22   class FunctionDecl;
     23 
     24 namespace arcmt {
     25   class MigrationPass;
     26 
     27 namespace trans {
     28 
     29   class MigrationContext;
     30 
     31 //===----------------------------------------------------------------------===//
     32 // Transformations.
     33 //===----------------------------------------------------------------------===//
     34 
     35 void rewriteAutoreleasePool(MigrationPass &pass);
     36 void rewriteUnbridgedCasts(MigrationPass &pass);
     37 void makeAssignARCSafe(MigrationPass &pass);
     38 void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
     39 void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
     40 void rewriteUnusedInitDelegate(MigrationPass &pass);
     41 void checkAPIUses(MigrationPass &pass);
     42 
     43 void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
     44 
     45 class BodyContext {
     46   MigrationContext &MigrateCtx;
     47   ParentMap PMap;
     48   Stmt *TopStmt;
     49 
     50 public:
     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 
     59 class ObjCImplementationContext {
     60   MigrationContext &MigrateCtx;
     61   ObjCImplementationDecl *ImpD;
     62 
     63 public:
     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 
     72 class ASTTraverser {
     73 public:
     74   virtual ~ASTTraverser();
     75   virtual void traverseTU(MigrationContext &MigrateCtx) { }
     76   virtual void traverseBody(BodyContext &BodyCtx) { }
     77   virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
     78 };
     79 
     80 class MigrationContext {
     81   std::vector<ASTTraverser *> Traversers;
     82 
     83 public:
     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 
    127 class PropertyRewriteTraverser : public ASTTraverser {
    128 public:
    129   virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx);
    130 };
    131 
    132 class BlockObjCVariableTraverser : public ASTTraverser {
    133 public:
    134   virtual void traverseBody(BodyContext &BodyCtx);
    135 };
    136 
    137 // GC transformations
    138 
    139 class GCAttrsTraverser : public ASTTraverser {
    140 public:
    141   virtual void traverseTU(MigrationContext &MigrateCtx);
    142 };
    143 
    144 class GCCollectableCallsTraverser : public ASTTraverser {
    145 public:
    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.
    154 bool canApplyWeak(ASTContext &Ctx, QualType type,
    155                   bool AllowOnUnknownClass = false);
    156 
    157 /// \brief 'Loc' is the end of a statement range. This returns the location
    158 /// immediately after the semicolon following the statement.
    159 /// If no semicolon is found or the location is inside a macro, the returned
    160 /// source location will be invalid.
    161 SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
    162 
    163 /// \brief \arg Loc is the end of a statement range. This returns the location
    164 /// of the semicolon following the statement.
    165 /// If no semicolon is found or the location is inside a macro, the returned
    166 /// source location will be invalid.
    167 SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx);
    168 
    169 bool hasSideEffects(Expr *E, ASTContext &Ctx);
    170 bool isGlobalVar(Expr *E);
    171 /// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
    172 StringRef getNilString(ASTContext &Ctx);
    173 
    174 template <typename BODY_TRANS>
    175 class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
    176   MigrationPass &Pass;
    177 
    178 public:
    179   BodyTransform(MigrationPass &pass) : Pass(pass) { }
    180 
    181   bool TraverseStmt(Stmt *rootS) {
    182     if (rootS)
    183       BODY_TRANS(Pass).transformBody(rootS);
    184     return true;
    185   }
    186 };
    187 
    188 typedef llvm::DenseSet<Expr *> ExprSet;
    189 
    190 void clearRefsIn(Stmt *S, ExprSet &refs);
    191 template <typename iterator>
    192 void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
    193   for (; begin != end; ++begin)
    194     clearRefsIn(*begin, refs);
    195 }
    196 
    197 void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
    198 
    199 void collectRemovables(Stmt *S, ExprSet &exprs);
    200 
    201 } // end namespace trans
    202 
    203 } // end namespace arcmt
    204 
    205 } // end namespace clang
    206 
    207 #endif
    208