Transforms.h revision 249423
1249423Sdim//===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===//
2224135Sdim//
3224135Sdim//                     The LLVM Compiler Infrastructure
4224135Sdim//
5224135Sdim// This file is distributed under the University of Illinois Open Source
6224135Sdim// License. See LICENSE.TXT for details.
7224135Sdim//
8224135Sdim//===----------------------------------------------------------------------===//
9224135Sdim
10224135Sdim#ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
11224135Sdim#define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
12224135Sdim
13249423Sdim#include "clang/AST/ParentMap.h"
14224135Sdim#include "clang/AST/RecursiveASTVisitor.h"
15224135Sdim#include "llvm/ADT/DenseSet.h"
16239462Sdim#include "llvm/Support/SaveAndRestore.h"
17224135Sdim
18224135Sdimnamespace clang {
19224135Sdim  class Decl;
20224135Sdim  class Stmt;
21224135Sdim  class BlockDecl;
22224135Sdim  class ObjCMethodDecl;
23224135Sdim  class FunctionDecl;
24224135Sdim
25224135Sdimnamespace arcmt {
26224135Sdim  class MigrationPass;
27224135Sdim
28224135Sdimnamespace trans {
29224135Sdim
30234353Sdim  class MigrationContext;
31234353Sdim
32224135Sdim//===----------------------------------------------------------------------===//
33224135Sdim// Transformations.
34224135Sdim//===----------------------------------------------------------------------===//
35224135Sdim
36224135Sdimvoid rewriteAutoreleasePool(MigrationPass &pass);
37224135Sdimvoid rewriteUnbridgedCasts(MigrationPass &pass);
38224135Sdimvoid makeAssignARCSafe(MigrationPass &pass);
39234353Sdimvoid removeRetainReleaseDeallocFinalize(MigrationPass &pass);
40234353Sdimvoid removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
41224135Sdimvoid rewriteUnusedInitDelegate(MigrationPass &pass);
42226633Sdimvoid checkAPIUses(MigrationPass &pass);
43224135Sdim
44234353Sdimvoid removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
45224135Sdim
46234353Sdimclass BodyContext {
47234353Sdim  MigrationContext &MigrateCtx;
48234353Sdim  ParentMap PMap;
49234353Sdim  Stmt *TopStmt;
50234353Sdim
51234353Sdimpublic:
52234353Sdim  BodyContext(MigrationContext &MigrateCtx, Stmt *S)
53234353Sdim    : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
54234353Sdim
55234353Sdim  MigrationContext &getMigrationContext() { return MigrateCtx; }
56234353Sdim  ParentMap &getParentMap() { return PMap; }
57234353Sdim  Stmt *getTopStmt() { return TopStmt; }
58234353Sdim};
59234353Sdim
60234353Sdimclass ObjCImplementationContext {
61234353Sdim  MigrationContext &MigrateCtx;
62234353Sdim  ObjCImplementationDecl *ImpD;
63234353Sdim
64234353Sdimpublic:
65234353Sdim  ObjCImplementationContext(MigrationContext &MigrateCtx,
66234353Sdim                            ObjCImplementationDecl *D)
67234353Sdim    : MigrateCtx(MigrateCtx), ImpD(D) {}
68234353Sdim
69234353Sdim  MigrationContext &getMigrationContext() { return MigrateCtx; }
70234353Sdim  ObjCImplementationDecl *getImplementationDecl() { return ImpD; }
71234353Sdim};
72234353Sdim
73234353Sdimclass ASTTraverser {
74234353Sdimpublic:
75234353Sdim  virtual ~ASTTraverser();
76234353Sdim  virtual void traverseTU(MigrationContext &MigrateCtx) { }
77234353Sdim  virtual void traverseBody(BodyContext &BodyCtx) { }
78234353Sdim  virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
79234353Sdim};
80234353Sdim
81234353Sdimclass MigrationContext {
82234353Sdim  std::vector<ASTTraverser *> Traversers;
83234353Sdim
84234353Sdimpublic:
85234353Sdim  MigrationPass &Pass;
86234353Sdim
87234353Sdim  struct GCAttrOccurrence {
88234353Sdim    enum AttrKind { Weak, Strong } Kind;
89234353Sdim    SourceLocation Loc;
90234353Sdim    QualType ModifiedType;
91234353Sdim    Decl *Dcl;
92234353Sdim    /// \brief true if the attribute is owned, e.g. it is in a body and not just
93234353Sdim    /// in an interface.
94234353Sdim    bool FullyMigratable;
95234353Sdim  };
96234353Sdim  std::vector<GCAttrOccurrence> GCAttrs;
97234353Sdim  llvm::DenseSet<unsigned> AttrSet;
98234353Sdim  llvm::DenseSet<unsigned> RemovedAttrSet;
99234353Sdim
100234353Sdim  /// \brief Set of raw '@' locations for 'assign' properties group that contain
101234353Sdim  /// GC __weak.
102234353Sdim  llvm::DenseSet<unsigned> AtPropsWeak;
103234353Sdim
104234353Sdim  explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
105234353Sdim  ~MigrationContext();
106234353Sdim
107234353Sdim  typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
108234353Sdim  traverser_iterator traversers_begin() { return Traversers.begin(); }
109234353Sdim  traverser_iterator traversers_end() { return Traversers.end(); }
110234353Sdim
111234353Sdim  void addTraverser(ASTTraverser *traverser) {
112234353Sdim    Traversers.push_back(traverser);
113234353Sdim  }
114234353Sdim
115234353Sdim  bool isGCOwnedNonObjC(QualType T);
116234353Sdim  bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {
117234353Sdim    return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);
118234353Sdim  }
119234353Sdim  bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,
120234353Sdim                                SourceLocation atLoc);
121234353Sdim  bool addPropertyAttribute(StringRef attr, SourceLocation atLoc);
122234353Sdim
123234353Sdim  void traverse(TranslationUnitDecl *TU);
124234353Sdim
125234353Sdim  void dumpGCAttrs();
126234353Sdim};
127234353Sdim
128234353Sdimclass PropertyRewriteTraverser : public ASTTraverser {
129234353Sdimpublic:
130234353Sdim  virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx);
131234353Sdim};
132234353Sdim
133234353Sdimclass BlockObjCVariableTraverser : public ASTTraverser {
134234353Sdimpublic:
135234353Sdim  virtual void traverseBody(BodyContext &BodyCtx);
136234353Sdim};
137234353Sdim
138249423Sdimclass ProtectedScopeTraverser : public ASTTraverser {
139249423Sdimpublic:
140249423Sdim  virtual void traverseBody(BodyContext &BodyCtx);
141249423Sdim};
142249423Sdim
143234353Sdim// GC transformations
144234353Sdim
145234353Sdimclass GCAttrsTraverser : public ASTTraverser {
146234353Sdimpublic:
147234353Sdim  virtual void traverseTU(MigrationContext &MigrateCtx);
148234353Sdim};
149234353Sdim
150234353Sdimclass GCCollectableCallsTraverser : public ASTTraverser {
151234353Sdimpublic:
152234353Sdim  virtual void traverseBody(BodyContext &BodyCtx);
153234353Sdim};
154234353Sdim
155224135Sdim//===----------------------------------------------------------------------===//
156224135Sdim// Helpers.
157224135Sdim//===----------------------------------------------------------------------===//
158224135Sdim
159224135Sdim/// \brief Determine whether we can add weak to the given type.
160234353Sdimbool canApplyWeak(ASTContext &Ctx, QualType type,
161234353Sdim                  bool AllowOnUnknownClass = false);
162224135Sdim
163239462Sdimbool isPlusOneAssign(const BinaryOperator *E);
164249423Sdimbool isPlusOne(const Expr *E);
165239462Sdim
166224135Sdim/// \brief 'Loc' is the end of a statement range. This returns the location
167224135Sdim/// immediately after the semicolon following the statement.
168224135Sdim/// If no semicolon is found or the location is inside a macro, the returned
169224135Sdim/// source location will be invalid.
170224135SdimSourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
171224135Sdim
172226633Sdim/// \brief \arg Loc is the end of a statement range. This returns the location
173226633Sdim/// of the semicolon following the statement.
174226633Sdim/// If no semicolon is found or the location is inside a macro, the returned
175226633Sdim/// source location will be invalid.
176226633SdimSourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx);
177226633Sdim
178224135Sdimbool hasSideEffects(Expr *E, ASTContext &Ctx);
179224135Sdimbool isGlobalVar(Expr *E);
180226633Sdim/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
181226633SdimStringRef getNilString(ASTContext &Ctx);
182224135Sdim
183224135Sdimtemplate <typename BODY_TRANS>
184224135Sdimclass BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
185224135Sdim  MigrationPass &Pass;
186239462Sdim  Decl *ParentD;
187224135Sdim
188239462Sdim  typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base;
189224135Sdimpublic:
190239462Sdim  BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(0) { }
191224135Sdim
192224135Sdim  bool TraverseStmt(Stmt *rootS) {
193226633Sdim    if (rootS)
194239462Sdim      BODY_TRANS(Pass).transformBody(rootS, ParentD);
195224135Sdim    return true;
196224135Sdim  }
197239462Sdim
198239462Sdim  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
199239462Sdim    SaveAndRestore<Decl *> SetParent(ParentD, D);
200239462Sdim    return base::TraverseObjCMethodDecl(D);
201239462Sdim  }
202224135Sdim};
203224135Sdim
204224135Sdimtypedef llvm::DenseSet<Expr *> ExprSet;
205224135Sdim
206224135Sdimvoid clearRefsIn(Stmt *S, ExprSet &refs);
207224135Sdimtemplate <typename iterator>
208224135Sdimvoid clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
209224135Sdim  for (; begin != end; ++begin)
210224135Sdim    clearRefsIn(*begin, refs);
211224135Sdim}
212224135Sdim
213224135Sdimvoid collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
214224135Sdim
215224135Sdimvoid collectRemovables(Stmt *S, ExprSet &exprs);
216224135Sdim
217224135Sdim} // end namespace trans
218224135Sdim
219224135Sdim} // end namespace arcmt
220224135Sdim
221224135Sdim} // end namespace clang
222224135Sdim
223224135Sdim#endif
224