Transforms.h 6.7 KB

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