blob: 3f1e737e23e0437720cdcfbdc514a12c04070996 [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 rewriteBlockObjCVariable(MigrationPass &pass);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000041void rewriteUnusedInitDelegate(MigrationPass &pass);
Argyrios Kyrtzidisfd103982011-07-18 07:44:45 +000042void checkAPIUses(MigrationPass &pass);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000043
Argyrios Kyrtzidise7ef8552011-11-04 15:58:22 +000044void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
Argyrios Kyrtzidisfd3455a2011-06-21 20:20:42 +000045
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000046class BodyContext {
47 MigrationContext &MigrateCtx;
48 ParentMap PMap;
49 Stmt *TopStmt;
50
51public:
52 BodyContext(MigrationContext &MigrateCtx, Stmt *S)
53 : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
54
55 MigrationContext &getMigrationContext() { return MigrateCtx; }
56 ParentMap &getParentMap() { return PMap; }
57 Stmt *getTopStmt() { return TopStmt; }
58};
59
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +000060class ObjCImplementationContext {
61 MigrationContext &MigrateCtx;
62 ObjCImplementationDecl *ImpD;
63
64public:
65 ObjCImplementationContext(MigrationContext &MigrateCtx,
66 ObjCImplementationDecl *D)
67 : MigrateCtx(MigrateCtx), ImpD(D) {}
68
69 MigrationContext &getMigrationContext() { return MigrateCtx; }
70 ObjCImplementationDecl *getImplementationDecl() { return ImpD; }
71};
72
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000073class ASTTraverser {
74public:
75 virtual ~ASTTraverser();
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +000076 virtual void traverseTU(MigrationContext &MigrateCtx) { }
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000077 virtual void traverseBody(BodyContext &BodyCtx) { }
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +000078 virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000079};
80
81class MigrationContext {
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000082 std::vector<ASTTraverser *> Traversers;
83
84public:
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +000085 MigrationPass &Pass;
86
87 struct GCAttrOccurrence {
88 enum AttrKind { Weak, Strong } Kind;
89 SourceLocation Loc;
90 QualType ModifiedType;
91 Decl *Dcl;
92 /// \brief true if the attribute is owned, e.g. it is in a body and not just
93 /// in an interface.
94 bool FullyMigratable;
95 };
96 std::vector<GCAttrOccurrence> GCAttrs;
97
98 llvm::DenseSet<unsigned> AttrSet;
99
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000100 explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
101 ~MigrationContext();
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000102
103 typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
104 traverser_iterator traversers_begin() { return Traversers.begin(); }
105 traverser_iterator traversers_end() { return Traversers.end(); }
106
107 void addTraverser(ASTTraverser *traverser) {
108 Traversers.push_back(traverser);
109 }
110
Argyrios Kyrtzidis1fe42032011-11-04 23:43:03 +0000111 bool isGCOwnedNonObjC(QualType T);
112
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000113 void traverse(TranslationUnitDecl *TU);
Argyrios Kyrtzidis17ac3192011-11-06 18:58:17 +0000114
115 void dumpGCAttrs();
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000116};
117
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000118class PropertyRewriteTraverser : public ASTTraverser {
119public:
120 virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx);
121};
122
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000123// GC transformations
124
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +0000125class GCAttrsTraverser : public ASTTraverser {
126public:
127 virtual void traverseTU(MigrationContext &MigrateCtx);
128};
129
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000130class GCCollectableCallsTraverser : public ASTTraverser {
131public:
132 virtual void traverseBody(BodyContext &BodyCtx);
133};
134
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000135//===----------------------------------------------------------------------===//
136// Helpers.
137//===----------------------------------------------------------------------===//
138
Argyrios Kyrtzidis86625b52011-07-12 22:05:17 +0000139/// \brief Determine whether we can add weak to the given type.
140bool canApplyWeak(ASTContext &Ctx, QualType type);
141
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000142/// \brief 'Loc' is the end of a statement range. This returns the location
143/// immediately after the semicolon following the statement.
144/// If no semicolon is found or the location is inside a macro, the returned
145/// source location will be invalid.
146SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
147
Argyrios Kyrtzidisaec230d2011-09-01 20:53:18 +0000148/// \brief \arg Loc is the end of a statement range. This returns the location
149/// of the semicolon following the statement.
150/// If no semicolon is found or the location is inside a macro, the returned
151/// source location will be invalid.
152SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx);
153
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000154bool hasSideEffects(Expr *E, ASTContext &Ctx);
Argyrios Kyrtzidis2c18ca02011-07-14 23:32:04 +0000155bool isGlobalVar(Expr *E);
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000156/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
157StringRef getNilString(ASTContext &Ctx);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000158
159template <typename BODY_TRANS>
160class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
161 MigrationPass &Pass;
162
163public:
164 BodyTransform(MigrationPass &pass) : Pass(pass) { }
165
Argyrios Kyrtzidisb1094a02011-06-23 21:21:33 +0000166 bool TraverseStmt(Stmt *rootS) {
Argyrios Kyrtzidisfd103982011-07-18 07:44:45 +0000167 if (rootS)
168 BODY_TRANS(Pass).transformBody(rootS);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000169 return true;
170 }
171};
172
173typedef llvm::DenseSet<Expr *> ExprSet;
174
175void clearRefsIn(Stmt *S, ExprSet &refs);
176template <typename iterator>
177void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
178 for (; begin != end; ++begin)
179 clearRefsIn(*begin, refs);
180}
181
182void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
183
184void collectRemovables(Stmt *S, ExprSet &exprs);
185
186} // end namespace trans
187
188} // end namespace arcmt
189
190} // end namespace clang
191
192#endif