Transforms.h revision 1b8fbd3601e009803565e74d2ec54abecb5cbf73
1//===-- 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"
14#include "clang/AST/ParentMap.h"
15#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
29  class MigrationContext;
30
31//===----------------------------------------------------------------------===//
32// Transformations.
33//===----------------------------------------------------------------------===//
34
35void rewriteAutoreleasePool(MigrationPass &pass);
36void rewriteUnbridgedCasts(MigrationPass &pass);
37void makeAssignARCSafe(MigrationPass &pass);
38void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
39void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
40void rewriteUnusedInitDelegate(MigrationPass &pass);
41void checkAPIUses(MigrationPass &pass);
42
43void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
44
45class 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
59class 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
72class ASTTraverser {
73public:
74  virtual ~ASTTraverser();
75  virtual void traverseTU(MigrationContext &MigrateCtx) { }
76  virtual void traverseBody(BodyContext &BodyCtx) { }
77  virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
78};
79
80class MigrationContext {
81  std::vector<ASTTraverser *> Traversers;
82
83public:
84  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;
96  llvm::DenseSet<unsigned> AttrSet;
97  llvm::DenseSet<unsigned> RemovedAttrSet;
98
99  /// \brief Set of raw '@' locations for 'assign' properties group that contain
100  /// GC __weak.
101  llvm::DenseSet<unsigned> AtPropsWeak;
102
103  explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
104  ~MigrationContext();
105
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
114  bool isGCOwnedNonObjC(QualType T);
115  bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {
116    return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);
117  }
118  bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,
119                                SourceLocation atLoc);
120  bool addPropertyAttribute(StringRef attr, SourceLocation atLoc);
121
122  void traverse(TranslationUnitDecl *TU);
123
124  void dumpGCAttrs();
125};
126
127class PropertyRewriteTraverser : public ASTTraverser {
128public:
129  virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx);
130};
131
132class BlockObjCVariableTraverser : public ASTTraverser {
133public:
134  virtual void traverseBody(BodyContext &BodyCtx);
135};
136
137// GC transformations
138
139class GCAttrsTraverser : public ASTTraverser {
140public:
141  virtual void traverseTU(MigrationContext &MigrateCtx);
142};
143
144class GCCollectableCallsTraverser : public ASTTraverser {
145public:
146  virtual void traverseBody(BodyContext &BodyCtx);
147};
148
149//===----------------------------------------------------------------------===//
150// Helpers.
151//===----------------------------------------------------------------------===//
152
153/// \brief Determine whether we can add weak to the given type.
154bool canApplyWeak(ASTContext &Ctx, QualType type,
155                  bool AllowOnUnknownClass = false);
156
157bool isPlusOneAssign(const BinaryOperator *E);
158
159/// \brief 'Loc' is the end of a statement range. This returns the location
160/// immediately after the semicolon following the statement.
161/// If no semicolon is found or the location is inside a macro, the returned
162/// source location will be invalid.
163SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
164
165/// \brief \arg Loc is the end of a statement range. This returns the location
166/// of the semicolon following the statement.
167/// If no semicolon is found or the location is inside a macro, the returned
168/// source location will be invalid.
169SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx);
170
171bool hasSideEffects(Expr *E, ASTContext &Ctx);
172bool isGlobalVar(Expr *E);
173/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
174StringRef getNilString(ASTContext &Ctx);
175
176template <typename BODY_TRANS>
177class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
178  MigrationPass &Pass;
179
180public:
181  BodyTransform(MigrationPass &pass) : Pass(pass) { }
182
183  bool TraverseStmt(Stmt *rootS) {
184    if (rootS)
185      BODY_TRANS(Pass).transformBody(rootS);
186    return true;
187  }
188};
189
190typedef llvm::DenseSet<Expr *> ExprSet;
191
192void clearRefsIn(Stmt *S, ExprSet &refs);
193template <typename iterator>
194void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
195  for (; begin != end; ++begin)
196    clearRefsIn(*begin, refs);
197}
198
199void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
200
201void collectRemovables(Stmt *S, ExprSet &exprs);
202
203} // end namespace trans
204
205} // end namespace arcmt
206
207} // end namespace clang
208
209#endif
210