blob: 445c3e599d65b4613b06c9873dce4c2914ceffec [file] [log] [blame]
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +00001//===-- Transforms.h - Tranformations 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
10#ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
11#define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
12
13#include "clang/AST/RecursiveASTVisitor.h"
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000014#include "clang/AST/ParentMap.h"
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000015#include "llvm/ADT/DenseSet.h"
16
17namespace clang {
18 class Decl;
19 class Stmt;
20 class BlockDecl;
21 class ObjCMethodDecl;
22 class FunctionDecl;
23
24namespace arcmt {
25 class MigrationPass;
26
27namespace trans {
28
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000029 class MigrationContext;
30
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000031//===----------------------------------------------------------------------===//
32// Transformations.
33//===----------------------------------------------------------------------===//
34
35void rewriteAutoreleasePool(MigrationPass &pass);
36void rewriteUnbridgedCasts(MigrationPass &pass);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000037void makeAssignARCSafe(MigrationPass &pass);
Argyrios Kyrtzidise7ef8552011-11-04 15:58:22 +000038void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
39void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000040void rewriteUnusedInitDelegate(MigrationPass &pass);
Argyrios Kyrtzidisfd103982011-07-18 07:44:45 +000041void checkAPIUses(MigrationPass &pass);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000042
Argyrios Kyrtzidise7ef8552011-11-04 15:58:22 +000043void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
Argyrios Kyrtzidisfd3455a2011-06-21 20:20:42 +000044
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000045class BodyContext {
46 MigrationContext &MigrateCtx;
47 ParentMap PMap;
48 Stmt *TopStmt;
49
50public:
51 BodyContext(MigrationContext &MigrateCtx, Stmt *S)
52 : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
53
54 MigrationContext &getMigrationContext() { return MigrateCtx; }
55 ParentMap &getParentMap() { return PMap; }
56 Stmt *getTopStmt() { return TopStmt; }
57};
58
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +000059class ObjCImplementationContext {
60 MigrationContext &MigrateCtx;
61 ObjCImplementationDecl *ImpD;
62
63public:
64 ObjCImplementationContext(MigrationContext &MigrateCtx,
65 ObjCImplementationDecl *D)
66 : MigrateCtx(MigrateCtx), ImpD(D) {}
67
68 MigrationContext &getMigrationContext() { return MigrateCtx; }
69 ObjCImplementationDecl *getImplementationDecl() { return ImpD; }
70};
71
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000072class ASTTraverser {
73public:
74 virtual ~ASTTraverser();
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +000075 virtual void traverseTU(MigrationContext &MigrateCtx) { }
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000076 virtual void traverseBody(BodyContext &BodyCtx) { }
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +000077 virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000078};
79
80class MigrationContext {
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000081 std::vector<ASTTraverser *> Traversers;
82
83public:
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +000084 MigrationPass &Pass;
85
86 struct GCAttrOccurrence {
87 enum AttrKind { Weak, Strong } Kind;
88 SourceLocation Loc;
89 QualType ModifiedType;
90 Decl *Dcl;
91 /// \brief true if the attribute is owned, e.g. it is in a body and not just
92 /// in an interface.
93 bool FullyMigratable;
94 };
95 std::vector<GCAttrOccurrence> GCAttrs;
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +000096 llvm::DenseSet<unsigned> AttrSet;
Argyrios Kyrtzidis7cfd7fe2011-11-08 02:02:38 +000097 llvm::DenseSet<unsigned> RemovedAttrSet;
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +000098
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +000099 /// \brief Set of raw '@' locations for 'assign' properties group that contain
100 /// GC __weak.
101 llvm::DenseSet<unsigned> AtPropsWeak;
Argyrios Kyrtzidisbf8455c2011-11-07 18:40:32 +0000102
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000103 explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
104 ~MigrationContext();
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000105
106 typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
107 traverser_iterator traversers_begin() { return Traversers.begin(); }
108 traverser_iterator traversers_end() { return Traversers.end(); }
109
110 void addTraverser(ASTTraverser *traverser) {
111 Traversers.push_back(traverser);
112 }
113
Argyrios Kyrtzidis1fe42032011-11-04 23:43:03 +0000114 bool isGCOwnedNonObjC(QualType T);
Argyrios Kyrtzidis6da42742011-11-28 02:04:36 +0000115 bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {
116 return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);
117 }
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000118 bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,
119 SourceLocation atLoc);
Argyrios Kyrtzidis6da42742011-11-28 02:04:36 +0000120 bool addPropertyAttribute(StringRef attr, SourceLocation atLoc);
Argyrios Kyrtzidis1fe42032011-11-04 23:43:03 +0000121
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000122 void traverse(TranslationUnitDecl *TU);
Argyrios Kyrtzidis17ac3192011-11-06 18:58:17 +0000123
124 void dumpGCAttrs();
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000125};
126
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000127class PropertyRewriteTraverser : public ASTTraverser {
128public:
129 virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx);
130};
131
Argyrios Kyrtzidis2a278182012-03-05 08:46:24 +0000132class BlockObjCVariableTraverser : public ASTTraverser {
133public:
134 virtual void traverseBody(BodyContext &BodyCtx);
135};
136
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000137// GC transformations
138
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +0000139class GCAttrsTraverser : public ASTTraverser {
140public:
141 virtual void traverseTU(MigrationContext &MigrateCtx);
142};
143
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000144class GCCollectableCallsTraverser : public ASTTraverser {
145public:
146 virtual void traverseBody(BodyContext &BodyCtx);
147};
148
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000149//===----------------------------------------------------------------------===//
150// Helpers.
151//===----------------------------------------------------------------------===//
152
Argyrios Kyrtzidis86625b52011-07-12 22:05:17 +0000153/// \brief Determine whether we can add weak to the given type.
Argyrios Kyrtzidis12192cf2011-11-07 18:40:29 +0000154bool canApplyWeak(ASTContext &Ctx, QualType type,
155 bool AllowOnUnknownClass = false);
Argyrios Kyrtzidis86625b52011-07-12 22:05:17 +0000156
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000157/// \brief 'Loc' is the end of a statement range. This returns the location
158/// immediately after the semicolon following the statement.
159/// If no semicolon is found or the location is inside a macro, the returned
160/// source location will be invalid.
161SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
162
Argyrios Kyrtzidisaec230d2011-09-01 20:53:18 +0000163/// \brief \arg Loc is the end of a statement range. This returns the location
164/// of the semicolon following the statement.
165/// If no semicolon is found or the location is inside a macro, the returned
166/// source location will be invalid.
167SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx);
168
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000169bool hasSideEffects(Expr *E, ASTContext &Ctx);
Argyrios Kyrtzidis2c18ca02011-07-14 23:32:04 +0000170bool isGlobalVar(Expr *E);
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000171/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
172StringRef getNilString(ASTContext &Ctx);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000173
174template <typename BODY_TRANS>
175class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
176 MigrationPass &Pass;
177
178public:
179 BodyTransform(MigrationPass &pass) : Pass(pass) { }
180
Argyrios Kyrtzidisb1094a02011-06-23 21:21:33 +0000181 bool TraverseStmt(Stmt *rootS) {
Argyrios Kyrtzidisfd103982011-07-18 07:44:45 +0000182 if (rootS)
183 BODY_TRANS(Pass).transformBody(rootS);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000184 return true;
185 }
186};
187
188typedef llvm::DenseSet<Expr *> ExprSet;
189
190void clearRefsIn(Stmt *S, ExprSet &refs);
191template <typename iterator>
192void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
193 for (; begin != end; ++begin)
194 clearRefsIn(*begin, refs);
195}
196
197void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
198
199void collectRemovables(Stmt *S, ExprSet &exprs);
200
201} // end namespace trans
202
203} // end namespace arcmt
204
205} // end namespace clang
206
207#endif