clang API Documentation

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