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