Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/ARCMigrate/Transforms.h
35236 views
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
: MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
53
54
MigrationContext &getMigrationContext() { return MigrateCtx; }
55
ParentMap &getParentMap() { return PMap; }
56
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
: MigrateCtx(MigrateCtx), ImpD(D) {}
67
68
MigrationContext &getMigrationContext() { return MigrateCtx; }
69
ObjCImplementationDecl *getImplementationDecl() { return ImpD; }
70
};
71
72
class ASTTraverser {
73
public:
74
virtual ~ASTTraverser();
75
virtual void traverseTU(MigrationContext &MigrateCtx) { }
76
virtual void traverseBody(BodyContext &BodyCtx) { }
77
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<SourceLocation> AttrSet;
97
llvm::DenseSet<SourceLocation> RemovedAttrSet;
98
99
/// Set of raw '@' locations for 'assign' properties group that contain
100
/// GC __weak.
101
llvm::DenseSet<SourceLocation> 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
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
BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
192
193
bool TraverseStmt(Stmt *rootS) {
194
if (rootS)
195
BODY_TRANS(Pass).transformBody(rootS, ParentD);
196
return true;
197
}
198
199
bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
200
SaveAndRestore<Decl *> SetParent(ParentD, D);
201
return base::TraverseObjCMethodDecl(D);
202
}
203
};
204
205
typedef llvm::DenseSet<Expr *> ExprSet;
206
207
void clearRefsIn(Stmt *S, ExprSet &refs);
208
template <typename iterator>
209
void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
210
for (; begin != end; ++begin)
211
clearRefsIn(*begin, refs);
212
}
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
225
226