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