Transforms.h 6.8 KB

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