• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- Transforms.h - Transformations 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/ParentMap.h"
14 #include "clang/AST/RecursiveASTVisitor.h"
15 #include "llvm/ADT/DenseSet.h"
16 #include "llvm/Support/SaveAndRestore.h"
17 
18 namespace clang {
19   class Decl;
20   class Stmt;
21   class BlockDecl;
22   class ObjCMethodDecl;
23   class FunctionDecl;
24 
25 namespace arcmt {
26   class MigrationPass;
27 
28 namespace trans {
29 
30   class MigrationContext;
31 
32 //===----------------------------------------------------------------------===//
33 // Transformations.
34 //===----------------------------------------------------------------------===//
35 
36 void rewriteAutoreleasePool(MigrationPass &pass);
37 void rewriteUnbridgedCasts(MigrationPass &pass);
38 void makeAssignARCSafe(MigrationPass &pass);
39 void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
40 void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
41 void rewriteUnusedInitDelegate(MigrationPass &pass);
42 void checkAPIUses(MigrationPass &pass);
43 
44 void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
45 
46 class BodyContext {
47   MigrationContext &MigrateCtx;
48   ParentMap PMap;
49   Stmt *TopStmt;
50 
51 public:
BodyContext(MigrationContext & MigrateCtx,Stmt * S)52   BodyContext(MigrationContext &MigrateCtx, Stmt *S)
53     : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
54 
getMigrationContext()55   MigrationContext &getMigrationContext() { return MigrateCtx; }
getParentMap()56   ParentMap &getParentMap() { return PMap; }
getTopStmt()57   Stmt *getTopStmt() { return TopStmt; }
58 };
59 
60 class ObjCImplementationContext {
61   MigrationContext &MigrateCtx;
62   ObjCImplementationDecl *ImpD;
63 
64 public:
ObjCImplementationContext(MigrationContext & MigrateCtx,ObjCImplementationDecl * D)65   ObjCImplementationContext(MigrationContext &MigrateCtx,
66                             ObjCImplementationDecl *D)
67     : MigrateCtx(MigrateCtx), ImpD(D) {}
68 
getMigrationContext()69   MigrationContext &getMigrationContext() { return MigrateCtx; }
getImplementationDecl()70   ObjCImplementationDecl *getImplementationDecl() { return ImpD; }
71 };
72 
73 class ASTTraverser {
74 public:
75   virtual ~ASTTraverser();
traverseTU(MigrationContext & MigrateCtx)76   virtual void traverseTU(MigrationContext &MigrateCtx) { }
traverseBody(BodyContext & BodyCtx)77   virtual void traverseBody(BodyContext &BodyCtx) { }
traverseObjCImplementation(ObjCImplementationContext & ImplCtx)78   virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
79 };
80 
81 class MigrationContext {
82   std::vector<ASTTraverser *> Traversers;
83 
84 public:
85   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   llvm::DenseSet<unsigned> AttrSet;
98   llvm::DenseSet<unsigned> RemovedAttrSet;
99 
100   /// \brief Set of raw '@' locations for 'assign' properties group that contain
101   /// GC __weak.
102   llvm::DenseSet<unsigned> AtPropsWeak;
103 
MigrationContext(MigrationPass & pass)104   explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
105   ~MigrationContext();
106 
107   typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
traversers_begin()108   traverser_iterator traversers_begin() { return Traversers.begin(); }
traversers_end()109   traverser_iterator traversers_end() { return Traversers.end(); }
110 
addTraverser(ASTTraverser * traverser)111   void addTraverser(ASTTraverser *traverser) {
112     Traversers.push_back(traverser);
113   }
114 
115   bool isGCOwnedNonObjC(QualType T);
removePropertyAttribute(StringRef fromAttr,SourceLocation atLoc)116   bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {
117     return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);
118   }
119   bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,
120                                 SourceLocation atLoc);
121   bool addPropertyAttribute(StringRef attr, SourceLocation atLoc);
122 
123   void traverse(TranslationUnitDecl *TU);
124 
125   void dumpGCAttrs();
126 };
127 
128 class PropertyRewriteTraverser : public ASTTraverser {
129 public:
130   virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx);
131 };
132 
133 class BlockObjCVariableTraverser : public ASTTraverser {
134 public:
135   virtual void traverseBody(BodyContext &BodyCtx);
136 };
137 
138 class ProtectedScopeTraverser : public ASTTraverser {
139 public:
140   virtual void traverseBody(BodyContext &BodyCtx);
141 };
142 
143 // GC transformations
144 
145 class GCAttrsTraverser : public ASTTraverser {
146 public:
147   virtual void traverseTU(MigrationContext &MigrateCtx);
148 };
149 
150 class GCCollectableCallsTraverser : public ASTTraverser {
151 public:
152   virtual void traverseBody(BodyContext &BodyCtx);
153 };
154 
155 //===----------------------------------------------------------------------===//
156 // Helpers.
157 //===----------------------------------------------------------------------===//
158 
159 /// \brief Determine whether we can add weak to the given type.
160 bool canApplyWeak(ASTContext &Ctx, QualType type,
161                   bool AllowOnUnknownClass = false);
162 
163 bool isPlusOneAssign(const BinaryOperator *E);
164 bool isPlusOne(const Expr *E);
165 
166 /// \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.
170 SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
171 
172 /// \brief \arg Loc is the end of a statement range. This returns the location
173 /// of the semicolon following the statement.
174 /// If no semicolon is found or the location is inside a macro, the returned
175 /// source location will be invalid.
176 SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx);
177 
178 bool hasSideEffects(Expr *E, ASTContext &Ctx);
179 bool isGlobalVar(Expr *E);
180 /// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
181 StringRef getNilString(ASTContext &Ctx);
182 
183 template <typename BODY_TRANS>
184 class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
185   MigrationPass &Pass;
186   Decl *ParentD;
187 
188   typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base;
189 public:
BodyTransform(MigrationPass & pass)190   BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(0) { }
191 
TraverseStmt(Stmt * rootS)192   bool TraverseStmt(Stmt *rootS) {
193     if (rootS)
194       BODY_TRANS(Pass).transformBody(rootS, ParentD);
195     return true;
196   }
197 
TraverseObjCMethodDecl(ObjCMethodDecl * D)198   bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
199     SaveAndRestore<Decl *> SetParent(ParentD, D);
200     return base::TraverseObjCMethodDecl(D);
201   }
202 };
203 
204 typedef llvm::DenseSet<Expr *> ExprSet;
205 
206 void clearRefsIn(Stmt *S, ExprSet &refs);
207 template <typename iterator>
clearRefsIn(iterator begin,iterator end,ExprSet & refs)208 void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
209   for (; begin != end; ++begin)
210     clearRefsIn(*begin, refs);
211 }
212 
213 void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
214 
215 void collectRemovables(Stmt *S, ExprSet &exprs);
216 
217 } // end namespace trans
218 
219 } // end namespace arcmt
220 
221 } // end namespace clang
222 
223 #endif
224