blob: 5d4ac944604540cb04d78360d866005f568e5e54 [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"
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +000016#include "llvm/Support/SaveAndRestore.h"
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000017
18namespace clang {
19 class Decl;
20 class Stmt;
21 class BlockDecl;
22 class ObjCMethodDecl;
23 class FunctionDecl;
24
25namespace arcmt {
26 class MigrationPass;
27
28namespace trans {
29
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000030 class MigrationContext;
31
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000032//===----------------------------------------------------------------------===//
33// Transformations.
34//===----------------------------------------------------------------------===//
35
36void rewriteAutoreleasePool(MigrationPass &pass);
37void rewriteUnbridgedCasts(MigrationPass &pass);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000038void makeAssignARCSafe(MigrationPass &pass);
Argyrios Kyrtzidise7ef8552011-11-04 15:58:22 +000039void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
40void removeZeroOutPropsInDeallocFinalize(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;
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +000097 llvm::DenseSet<unsigned> AttrSet;
Argyrios Kyrtzidis7cfd7fe2011-11-08 02:02:38 +000098 llvm::DenseSet<unsigned> RemovedAttrSet;
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +000099
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000100 /// \brief Set of raw '@' locations for 'assign' properties group that contain
101 /// GC __weak.
102 llvm::DenseSet<unsigned> AtPropsWeak;
Argyrios Kyrtzidisbf8455c2011-11-07 18:40:32 +0000103
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000104 explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
105 ~MigrationContext();
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000106
107 typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
108 traverser_iterator traversers_begin() { return Traversers.begin(); }
109 traverser_iterator traversers_end() { return Traversers.end(); }
110
111 void addTraverser(ASTTraverser *traverser) {
112 Traversers.push_back(traverser);
113 }
114
Argyrios Kyrtzidis1fe42032011-11-04 23:43:03 +0000115 bool isGCOwnedNonObjC(QualType T);
Argyrios Kyrtzidis6da42742011-11-28 02:04:36 +0000116 bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {
117 return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);
118 }
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000119 bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,
120 SourceLocation atLoc);
Argyrios Kyrtzidis6da42742011-11-28 02:04:36 +0000121 bool addPropertyAttribute(StringRef attr, SourceLocation atLoc);
Argyrios Kyrtzidis1fe42032011-11-04 23:43:03 +0000122
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000123 void traverse(TranslationUnitDecl *TU);
Argyrios Kyrtzidis17ac3192011-11-06 18:58:17 +0000124
125 void dumpGCAttrs();
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000126};
127
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000128class PropertyRewriteTraverser : public ASTTraverser {
129public:
130 virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx);
131};
132
Argyrios Kyrtzidis2a278182012-03-05 08:46:24 +0000133class BlockObjCVariableTraverser : public ASTTraverser {
134public:
135 virtual void traverseBody(BodyContext &BodyCtx);
136};
137
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000138// GC transformations
139
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +0000140class GCAttrsTraverser : public ASTTraverser {
141public:
142 virtual void traverseTU(MigrationContext &MigrateCtx);
143};
144
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000145class GCCollectableCallsTraverser : public ASTTraverser {
146public:
147 virtual void traverseBody(BodyContext &BodyCtx);
148};
149
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000150//===----------------------------------------------------------------------===//
151// Helpers.
152//===----------------------------------------------------------------------===//
153
Argyrios Kyrtzidis86625b52011-07-12 22:05:17 +0000154/// \brief Determine whether we can add weak to the given type.
Argyrios Kyrtzidis12192cf2011-11-07 18:40:29 +0000155bool canApplyWeak(ASTContext &Ctx, QualType type,
156 bool AllowOnUnknownClass = false);
Argyrios Kyrtzidis86625b52011-07-12 22:05:17 +0000157
Argyrios Kyrtzidis1b8fbd32012-05-23 21:50:04 +0000158bool isPlusOneAssign(const BinaryOperator *E);
159
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000160/// \brief 'Loc' is the end of a statement range. This returns the location
161/// immediately after the semicolon following the statement.
162/// If no semicolon is found or the location is inside a macro, the returned
163/// source location will be invalid.
164SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
165
Argyrios Kyrtzidisaec230d2011-09-01 20:53:18 +0000166/// \brief \arg Loc is the end of a statement range. This returns the location
167/// of the semicolon following the statement.
168/// If no semicolon is found or the location is inside a macro, the returned
169/// source location will be invalid.
170SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx);
171
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000172bool hasSideEffects(Expr *E, ASTContext &Ctx);
Argyrios Kyrtzidis2c18ca02011-07-14 23:32:04 +0000173bool isGlobalVar(Expr *E);
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000174/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
175StringRef getNilString(ASTContext &Ctx);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000176
177template <typename BODY_TRANS>
178class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
179 MigrationPass &Pass;
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +0000180 Decl *ParentD;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000181
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +0000182 typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000183public:
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +0000184 BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(0) { }
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000185
Argyrios Kyrtzidisb1094a02011-06-23 21:21:33 +0000186 bool TraverseStmt(Stmt *rootS) {
Argyrios Kyrtzidisfd103982011-07-18 07:44:45 +0000187 if (rootS)
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +0000188 BODY_TRANS(Pass).transformBody(rootS, ParentD);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000189 return true;
190 }
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +0000191
192 bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
193 SaveAndRestore<Decl *> SetParent(ParentD, D);
194 return base::TraverseObjCMethodDecl(D);
195 }
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000196};
197
198typedef llvm::DenseSet<Expr *> ExprSet;
199
200void clearRefsIn(Stmt *S, ExprSet &refs);
201template <typename iterator>
202void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
203 for (; begin != end; ++begin)
204 clearRefsIn(*begin, refs);
205}
206
207void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
208
209void collectRemovables(Stmt *S, ExprSet &exprs);
210
211} // end namespace trans
212
213} // end namespace arcmt
214
215} // end namespace clang
216
217#endif