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