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