/Users/buildslave/jenkins/workspace/coverage/llvm-project/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<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 | 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 |