blob: 12551d261d36d414fee17f323915456a3565d072 [file] [log] [blame]
Benjamin Krameraccaf192012-11-14 15:08:31 +00001//===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===//
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +00002//
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
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000013#include "clang/AST/ParentMap.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000014#include "clang/AST/RecursiveASTVisitor.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:
Stephen Hines651f13c2014-04-23 16:59:28 -0700130 void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override;
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000131};
132
Argyrios Kyrtzidis2a278182012-03-05 08:46:24 +0000133class BlockObjCVariableTraverser : public ASTTraverser {
134public:
Stephen Hines651f13c2014-04-23 16:59:28 -0700135 void traverseBody(BodyContext &BodyCtx) override;
Argyrios Kyrtzidis2a278182012-03-05 08:46:24 +0000136};
137
Argyrios Kyrtzidisea2224d2013-01-04 18:30:08 +0000138class ProtectedScopeTraverser : public ASTTraverser {
139public:
Stephen Hines651f13c2014-04-23 16:59:28 -0700140 void traverseBody(BodyContext &BodyCtx) override;
Argyrios Kyrtzidisea2224d2013-01-04 18:30:08 +0000141};
142
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000143// GC transformations
144
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +0000145class GCAttrsTraverser : public ASTTraverser {
146public:
Stephen Hines651f13c2014-04-23 16:59:28 -0700147 void traverseTU(MigrationContext &MigrateCtx) override;
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +0000148};
149
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000150class GCCollectableCallsTraverser : public ASTTraverser {
151public:
Stephen Hines651f13c2014-04-23 16:59:28 -0700152 void traverseBody(BodyContext &BodyCtx) override;
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000153};
154
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000155//===----------------------------------------------------------------------===//
156// Helpers.
157//===----------------------------------------------------------------------===//
158
Argyrios Kyrtzidis86625b52011-07-12 22:05:17 +0000159/// \brief Determine whether we can add weak to the given type.
Argyrios Kyrtzidis12192cf2011-11-07 18:40:29 +0000160bool canApplyWeak(ASTContext &Ctx, QualType type,
161 bool AllowOnUnknownClass = false);
Argyrios Kyrtzidis86625b52011-07-12 22:05:17 +0000162
Argyrios Kyrtzidis1b8fbd32012-05-23 21:50:04 +0000163bool isPlusOneAssign(const BinaryOperator *E);
Argyrios Kyrtzidis20bcd4e2013-01-04 18:30:11 +0000164bool isPlusOne(const Expr *E);
Argyrios Kyrtzidis1b8fbd32012-05-23 21:50:04 +0000165
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000166/// \brief 'Loc' is the end of a statement range. This returns the location
167/// immediately after 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.
Fariborz Jahanian1f9a09d2013-10-11 17:35:22 +0000170SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx,
171 bool IsDecl = false);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000172
NAKAMURA Takumi8ef8f162013-04-11 04:16:11 +0000173/// \brief 'Loc' is the end of a statement range. This returns the location
Argyrios Kyrtzidisaec230d2011-09-01 20:53:18 +0000174/// of the semicolon following the statement.
175/// If no semicolon is found or the location is inside a macro, the returned
176/// source location will be invalid.
Fariborz Jahanian1f9a09d2013-10-11 17:35:22 +0000177SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx,
178 bool IsDecl = false);
Argyrios Kyrtzidisaec230d2011-09-01 20:53:18 +0000179
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000180bool hasSideEffects(Expr *E, ASTContext &Ctx);
Argyrios Kyrtzidis2c18ca02011-07-14 23:32:04 +0000181bool isGlobalVar(Expr *E);
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000182/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
183StringRef getNilString(ASTContext &Ctx);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000184
185template <typename BODY_TRANS>
186class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
187 MigrationPass &Pass;
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +0000188 Decl *ParentD;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000189
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +0000190 typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000191public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700192 BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000193
Argyrios Kyrtzidisb1094a02011-06-23 21:21:33 +0000194 bool TraverseStmt(Stmt *rootS) {
Argyrios Kyrtzidisfd103982011-07-18 07:44:45 +0000195 if (rootS)
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +0000196 BODY_TRANS(Pass).transformBody(rootS, ParentD);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000197 return true;
198 }
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +0000199
200 bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
201 SaveAndRestore<Decl *> SetParent(ParentD, D);
202 return base::TraverseObjCMethodDecl(D);
203 }
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000204};
205
206typedef llvm::DenseSet<Expr *> ExprSet;
207
208void clearRefsIn(Stmt *S, ExprSet &refs);
209template <typename iterator>
210void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
211 for (; begin != end; ++begin)
212 clearRefsIn(*begin, refs);
213}
214
215void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
216
217void collectRemovables(Stmt *S, ExprSet &exprs);
218
219} // end namespace trans
220
221} // end namespace arcmt
222
223} // end namespace clang
224
225#endif