Transforms.h revision e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1a
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 removeRetainReleaseDealloc(MigrationPass &pass);
39void removeZeroOutPropsInDealloc(MigrationPass &pass);
40void rewriteProperties(MigrationPass &pass);
41void rewriteBlockObjCVariable(MigrationPass &pass);
42void rewriteUnusedInitDelegate(MigrationPass &pass);
43void checkAPIUses(MigrationPass &pass);
44
45void removeEmptyStatementsAndDealloc(MigrationPass &pass);
46
47class BodyContext {
48  MigrationContext &MigrateCtx;
49  ParentMap PMap;
50  Stmt *TopStmt;
51
52public:
53  BodyContext(MigrationContext &MigrateCtx, Stmt *S)
54    : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
55
56  MigrationContext &getMigrationContext() { return MigrateCtx; }
57  ParentMap &getParentMap() { return PMap; }
58  Stmt *getTopStmt() { return TopStmt; }
59};
60
61class ASTTraverser {
62public:
63  virtual ~ASTTraverser();
64  virtual void traverseBody(BodyContext &BodyCtx) { }
65};
66
67class MigrationContext {
68  MigrationPass &Pass;
69  std::vector<ASTTraverser *> Traversers;
70
71public:
72  explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
73  ~MigrationContext();
74
75  MigrationPass &getPass() { return Pass; }
76
77  typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
78  traverser_iterator traversers_begin() { return Traversers.begin(); }
79  traverser_iterator traversers_end() { return Traversers.end(); }
80
81  void addTraverser(ASTTraverser *traverser) {
82    Traversers.push_back(traverser);
83  }
84
85  void traverse(TranslationUnitDecl *TU);
86};
87
88// GC transformations
89
90class GCCollectableCallsTraverser : public ASTTraverser {
91public:
92  virtual void traverseBody(BodyContext &BodyCtx);
93};
94
95//===----------------------------------------------------------------------===//
96// Helpers.
97//===----------------------------------------------------------------------===//
98
99/// \brief Determine whether we can add weak to the given type.
100bool canApplyWeak(ASTContext &Ctx, QualType type);
101
102/// \brief 'Loc' is the end of a statement range. This returns the location
103/// immediately after the semicolon following the statement.
104/// If no semicolon is found or the location is inside a macro, the returned
105/// source location will be invalid.
106SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
107
108/// \brief \arg Loc is the end of a statement range. This returns the location
109/// of the semicolon following the statement.
110/// If no semicolon is found or the location is inside a macro, the returned
111/// source location will be invalid.
112SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx);
113
114bool hasSideEffects(Expr *E, ASTContext &Ctx);
115bool isGlobalVar(Expr *E);
116/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
117StringRef getNilString(ASTContext &Ctx);
118
119template <typename BODY_TRANS>
120class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
121  MigrationPass &Pass;
122
123public:
124  BodyTransform(MigrationPass &pass) : Pass(pass) { }
125
126  bool TraverseStmt(Stmt *rootS) {
127    if (rootS)
128      BODY_TRANS(Pass).transformBody(rootS);
129    return true;
130  }
131};
132
133typedef llvm::DenseSet<Expr *> ExprSet;
134
135void clearRefsIn(Stmt *S, ExprSet &refs);
136template <typename iterator>
137void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
138  for (; begin != end; ++begin)
139    clearRefsIn(*begin, refs);
140}
141
142void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
143
144void collectRemovables(Stmt *S, ExprSet &exprs);
145
146} // end namespace trans
147
148} // end namespace arcmt
149
150} // end namespace clang
151
152#endif
153