Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/ARCMigrate/Transforms.h
Line
Count
Source
1
//===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
10
#define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
11
12
#include "clang/AST/ParentMap.h"
13
#include "clang/AST/RecursiveASTVisitor.h"
14
#include "llvm/ADT/DenseSet.h"
15
#include "llvm/Support/SaveAndRestore.h"
16
17
namespace clang {
18
  class Decl;
19
  class Stmt;
20
  class BlockDecl;
21
  class ObjCMethodDecl;
22
  class FunctionDecl;
23
24
namespace arcmt {
25
  class MigrationPass;
26
27
namespace trans {
28
29
  class MigrationContext;
30
31
//===----------------------------------------------------------------------===//
32
// Transformations.
33
//===----------------------------------------------------------------------===//
34
35
void rewriteAutoreleasePool(MigrationPass &pass);
36
void rewriteUnbridgedCasts(MigrationPass &pass);
37
void makeAssignARCSafe(MigrationPass &pass);
38
void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
39
void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
40
void rewriteUnusedInitDelegate(MigrationPass &pass);
41
void checkAPIUses(MigrationPass &pass);
42
43
void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
44
45
class BodyContext {
46
  MigrationContext &MigrateCtx;
47
  ParentMap PMap;
48
  Stmt *TopStmt;
49
50
public:
51
  BodyContext(MigrationContext &MigrateCtx, Stmt *S)
52
403
    : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
53
54
877
  MigrationContext &getMigrationContext() { return MigrateCtx; }
55
403
  ParentMap &getParentMap() { return PMap; }
56
1.68k
  Stmt *getTopStmt() { return TopStmt; }
57
};
58
59
class ObjCImplementationContext {
60
  MigrationContext &MigrateCtx;
61
  ObjCImplementationDecl *ImpD;
62
63
public:
64
  ObjCImplementationContext(MigrationContext &MigrateCtx,
65
                            ObjCImplementationDecl *D)
66
88
    : MigrateCtx(MigrateCtx), ImpD(D) {}
67
68
88
  MigrationContext &getMigrationContext() { return MigrateCtx; }
69
88
  ObjCImplementationDecl *getImplementationDecl() { return ImpD; }
70
};
71
72
class ASTTraverser {
73
public:
74
  virtual ~ASTTraverser();
75
268
  virtual void traverseTU(MigrationContext &MigrateCtx) { }
76
474
  virtual void traverseBody(BodyContext &BodyCtx) { }
77
246
  virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
78
};
79
80
class MigrationContext {
81
  std::vector<ASTTraverser *> Traversers;
82
83
public:
84
  MigrationPass &Pass;
85
86
  struct GCAttrOccurrence {
87
    enum AttrKind { Weak, Strong } Kind;
88
    SourceLocation Loc;
89
    QualType ModifiedType;
90
    Decl *Dcl;
91
    /// 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
  /// Set of raw '@' locations for 'assign' properties group that contain
100
  /// GC __weak.
101
  llvm::DenseSet<unsigned> AtPropsWeak;
102
103
85
  explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
104
  ~MigrationContext();
105
106
  typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
107
661
  traverser_iterator traversers_begin() { return Traversers.begin(); }
108
661
  traverser_iterator traversers_end() { return Traversers.end(); }
109
110
281
  void addTraverser(ASTTraverser *traverser) {
111
281
    Traversers.push_back(traverser);
112
281
  }
113
114
  bool isGCOwnedNonObjC(QualType T);
115
2
  bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {
116
2
    return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);
117
2
  }
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
127
class PropertyRewriteTraverser : public ASTTraverser {
128
public:
129
  void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override;
130
};
131
132
class BlockObjCVariableTraverser : public ASTTraverser {
133
public:
134
  void traverseBody(BodyContext &BodyCtx) override;
135
};
136
137
class ProtectedScopeTraverser : public ASTTraverser {
138
public:
139
  void traverseBody(BodyContext &BodyCtx) override;
140
};
141
142
// GC transformations
143
144
class GCAttrsTraverser : public ASTTraverser {
145
public:
146
  void traverseTU(MigrationContext &MigrateCtx) override;
147
};
148
149
class GCCollectableCallsTraverser : public ASTTraverser {
150
public:
151
  void traverseBody(BodyContext &BodyCtx) override;
152
};
153
154
//===----------------------------------------------------------------------===//
155
// Helpers.
156
//===----------------------------------------------------------------------===//
157
158
/// Determine whether we can add weak to the given type.
159
bool canApplyWeak(ASTContext &Ctx, QualType type,
160
                  bool AllowOnUnknownClass = false);
161
162
bool isPlusOneAssign(const BinaryOperator *E);
163
bool isPlusOne(const Expr *E);
164
165
/// 'Loc' is the end of a statement range. This returns the location
166
/// immediately after 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.
169
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx,
170
                                     bool IsDecl = false);
171
172
/// '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
                                     bool IsDecl = false);
178
179
bool hasSideEffects(Expr *E, ASTContext &Ctx);
180
bool isGlobalVar(Expr *E);
181
/// Returns "nil" or "0" if 'nil' macro is not actually defined.
182
StringRef getNilString(MigrationPass &Pass);
183
184
template <typename BODY_TRANS>
185
class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
186
  MigrationPass &Pass;
187
  Decl *ParentD;
188
189
  typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base;
190
public:
191
340
  BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
TransAutoreleasePool.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::AutoreleasePoolRewriter>::BodyTransform(clang::arcmt::MigrationPass&)
Line
Count
Source
191
85
  BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
TransRetainReleaseDealloc.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::RetainReleaseDeallocRemover>::BodyTransform(clang::arcmt::MigrationPass&)
Line
Count
Source
191
85
  BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
TransUnbridgedCasts.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::UnbridgedCastRewriter>::BodyTransform(clang::arcmt::MigrationPass&)
Line
Count
Source
191
85
  BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
TransUnusedInitDelegate.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::UnusedInitRewriter>::BodyTransform(clang::arcmt::MigrationPass&)
Line
Count
Source
191
85
  BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
192
193
1.76k
  bool TraverseStmt(Stmt *rootS) {
194
1.76k
    if (rootS)
195
1.61k
      BODY_TRANS(Pass).transformBody(rootS, ParentD);
196
1.76k
    return true;
197
1.76k
  }
TransAutoreleasePool.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::AutoreleasePoolRewriter>::TraverseStmt(clang::Stmt*)
Line
Count
Source
193
441
  bool TraverseStmt(Stmt *rootS) {
194
441
    if (rootS)
195
403
      BODY_TRANS(Pass).transformBody(rootS, ParentD);
196
441
    return true;
197
441
  }
TransRetainReleaseDealloc.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::RetainReleaseDeallocRemover>::TraverseStmt(clang::Stmt*)
Line
Count
Source
193
441
  bool TraverseStmt(Stmt *rootS) {
194
441
    if (rootS)
195
403
      BODY_TRANS(Pass).transformBody(rootS, ParentD);
196
441
    return true;
197
441
  }
TransUnbridgedCasts.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::UnbridgedCastRewriter>::TraverseStmt(clang::Stmt*)
Line
Count
Source
193
441
  bool TraverseStmt(Stmt *rootS) {
194
441
    if (rootS)
195
403
      BODY_TRANS(Pass).transformBody(rootS, ParentD);
196
441
    return true;
197
441
  }
TransUnusedInitDelegate.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::UnusedInitRewriter>::TraverseStmt(clang::Stmt*)
Line
Count
Source
193
441
  bool TraverseStmt(Stmt *rootS) {
194
441
    if (rootS)
195
403
      BODY_TRANS(Pass).transformBody(rootS, ParentD);
196
441
    return true;
197
441
  }
198
199
4.13k
  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
200
4.13k
    SaveAndRestore<Decl *> SetParent(ParentD, D);
201
4.13k
    return base::TraverseObjCMethodDecl(D);
202
4.13k
  }
TransAutoreleasePool.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::AutoreleasePoolRewriter>::TraverseObjCMethodDecl(clang::ObjCMethodDecl*)
Line
Count
Source
199
1.03k
  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
200
1.03k
    SaveAndRestore<Decl *> SetParent(ParentD, D);
201
1.03k
    return base::TraverseObjCMethodDecl(D);
202
1.03k
  }
TransRetainReleaseDealloc.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::RetainReleaseDeallocRemover>::TraverseObjCMethodDecl(clang::ObjCMethodDecl*)
Line
Count
Source
199
1.03k
  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
200
1.03k
    SaveAndRestore<Decl *> SetParent(ParentD, D);
201
1.03k
    return base::TraverseObjCMethodDecl(D);
202
1.03k
  }
TransUnbridgedCasts.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::UnbridgedCastRewriter>::TraverseObjCMethodDecl(clang::ObjCMethodDecl*)
Line
Count
Source
199
1.03k
  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
200
1.03k
    SaveAndRestore<Decl *> SetParent(ParentD, D);
201
1.03k
    return base::TraverseObjCMethodDecl(D);
202
1.03k
  }
TransUnusedInitDelegate.cpp:clang::arcmt::trans::BodyTransform<(anonymous namespace)::UnusedInitRewriter>::TraverseObjCMethodDecl(clang::ObjCMethodDecl*)
Line
Count
Source
199
1.03k
  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
200
1.03k
    SaveAndRestore<Decl *> SetParent(ParentD, D);
201
1.03k
    return base::TraverseObjCMethodDecl(D);
202
1.03k
  }
203
};
204
205
typedef llvm::DenseSet<Expr *> ExprSet;
206
207
void clearRefsIn(Stmt *S, ExprSet &refs);
208
template <typename iterator>
209
39
void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
210
46
  for (; begin != end; 
++begin7
)
211
7
    clearRefsIn(*begin, refs);
212
39
}
213
214
void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
215
216
void collectRemovables(Stmt *S, ExprSet &exprs);
217
218
} // end namespace trans
219
220
} // end namespace arcmt
221
222
} // end namespace clang
223
224
#endif