annotate clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp @ 225:f7655407a6ba

remove unnecessary files
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 19 Jul 2021 03:48:36 +0900
parents 1d019706d866
children c4bab56944e8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===-- TransEmptyStatementsAndDealloc.cpp - Transformations to ARC mode --===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8 //
anatofuz
parents:
diff changeset
9 // removeEmptyStatementsAndDealloc:
anatofuz
parents:
diff changeset
10 //
anatofuz
parents:
diff changeset
11 // Removes empty statements that are leftovers from previous transformations.
anatofuz
parents:
diff changeset
12 // e.g for
anatofuz
parents:
diff changeset
13 //
anatofuz
parents:
diff changeset
14 // [x retain];
anatofuz
parents:
diff changeset
15 //
anatofuz
parents:
diff changeset
16 // removeRetainReleaseDealloc will leave an empty ";" that removeEmptyStatements
anatofuz
parents:
diff changeset
17 // will remove.
anatofuz
parents:
diff changeset
18 //
anatofuz
parents:
diff changeset
19 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
20
anatofuz
parents:
diff changeset
21 #include "Transforms.h"
anatofuz
parents:
diff changeset
22 #include "Internals.h"
anatofuz
parents:
diff changeset
23 #include "clang/AST/ASTContext.h"
anatofuz
parents:
diff changeset
24 #include "clang/AST/StmtVisitor.h"
anatofuz
parents:
diff changeset
25 #include "clang/Basic/SourceManager.h"
anatofuz
parents:
diff changeset
26
anatofuz
parents:
diff changeset
27 using namespace clang;
anatofuz
parents:
diff changeset
28 using namespace arcmt;
anatofuz
parents:
diff changeset
29 using namespace trans;
anatofuz
parents:
diff changeset
30
anatofuz
parents:
diff changeset
31 static bool isEmptyARCMTMacroStatement(NullStmt *S,
anatofuz
parents:
diff changeset
32 std::vector<SourceLocation> &MacroLocs,
anatofuz
parents:
diff changeset
33 ASTContext &Ctx) {
anatofuz
parents:
diff changeset
34 if (!S->hasLeadingEmptyMacro())
anatofuz
parents:
diff changeset
35 return false;
anatofuz
parents:
diff changeset
36
anatofuz
parents:
diff changeset
37 SourceLocation SemiLoc = S->getSemiLoc();
anatofuz
parents:
diff changeset
38 if (SemiLoc.isInvalid() || SemiLoc.isMacroID())
anatofuz
parents:
diff changeset
39 return false;
anatofuz
parents:
diff changeset
40
anatofuz
parents:
diff changeset
41 if (MacroLocs.empty())
anatofuz
parents:
diff changeset
42 return false;
anatofuz
parents:
diff changeset
43
anatofuz
parents:
diff changeset
44 SourceManager &SM = Ctx.getSourceManager();
anatofuz
parents:
diff changeset
45 std::vector<SourceLocation>::iterator I = llvm::upper_bound(
anatofuz
parents:
diff changeset
46 MacroLocs, SemiLoc, BeforeThanCompare<SourceLocation>(SM));
anatofuz
parents:
diff changeset
47 --I;
anatofuz
parents:
diff changeset
48 SourceLocation
anatofuz
parents:
diff changeset
49 AfterMacroLoc = I->getLocWithOffset(getARCMTMacroName().size());
anatofuz
parents:
diff changeset
50 assert(AfterMacroLoc.isFileID());
anatofuz
parents:
diff changeset
51
anatofuz
parents:
diff changeset
52 if (AfterMacroLoc == SemiLoc)
anatofuz
parents:
diff changeset
53 return true;
anatofuz
parents:
diff changeset
54
anatofuz
parents:
diff changeset
55 int RelOffs = 0;
anatofuz
parents:
diff changeset
56 if (!SM.isInSameSLocAddrSpace(AfterMacroLoc, SemiLoc, &RelOffs))
anatofuz
parents:
diff changeset
57 return false;
anatofuz
parents:
diff changeset
58 if (RelOffs < 0)
anatofuz
parents:
diff changeset
59 return false;
anatofuz
parents:
diff changeset
60
anatofuz
parents:
diff changeset
61 // We make the reasonable assumption that a semicolon after 100 characters
anatofuz
parents:
diff changeset
62 // means that it is not the next token after our macro. If this assumption
anatofuz
parents:
diff changeset
63 // fails it is not critical, we will just fail to clear out, e.g., an empty
anatofuz
parents:
diff changeset
64 // 'if'.
anatofuz
parents:
diff changeset
65 if (RelOffs - getARCMTMacroName().size() > 100)
anatofuz
parents:
diff changeset
66 return false;
anatofuz
parents:
diff changeset
67
anatofuz
parents:
diff changeset
68 SourceLocation AfterMacroSemiLoc = findSemiAfterLocation(AfterMacroLoc, Ctx);
anatofuz
parents:
diff changeset
69 return AfterMacroSemiLoc == SemiLoc;
anatofuz
parents:
diff changeset
70 }
anatofuz
parents:
diff changeset
71
anatofuz
parents:
diff changeset
72 namespace {
anatofuz
parents:
diff changeset
73
anatofuz
parents:
diff changeset
74 /// Returns true if the statement became empty due to previous
anatofuz
parents:
diff changeset
75 /// transformations.
anatofuz
parents:
diff changeset
76 class EmptyChecker : public StmtVisitor<EmptyChecker, bool> {
anatofuz
parents:
diff changeset
77 ASTContext &Ctx;
anatofuz
parents:
diff changeset
78 std::vector<SourceLocation> &MacroLocs;
anatofuz
parents:
diff changeset
79
anatofuz
parents:
diff changeset
80 public:
anatofuz
parents:
diff changeset
81 EmptyChecker(ASTContext &ctx, std::vector<SourceLocation> &macroLocs)
anatofuz
parents:
diff changeset
82 : Ctx(ctx), MacroLocs(macroLocs) { }
anatofuz
parents:
diff changeset
83
anatofuz
parents:
diff changeset
84 bool VisitNullStmt(NullStmt *S) {
anatofuz
parents:
diff changeset
85 return isEmptyARCMTMacroStatement(S, MacroLocs, Ctx);
anatofuz
parents:
diff changeset
86 }
anatofuz
parents:
diff changeset
87 bool VisitCompoundStmt(CompoundStmt *S) {
anatofuz
parents:
diff changeset
88 if (S->body_empty())
anatofuz
parents:
diff changeset
89 return false; // was already empty, not because of transformations.
anatofuz
parents:
diff changeset
90 for (auto *I : S->body())
anatofuz
parents:
diff changeset
91 if (!Visit(I))
anatofuz
parents:
diff changeset
92 return false;
anatofuz
parents:
diff changeset
93 return true;
anatofuz
parents:
diff changeset
94 }
anatofuz
parents:
diff changeset
95 bool VisitIfStmt(IfStmt *S) {
anatofuz
parents:
diff changeset
96 if (S->getConditionVariable())
anatofuz
parents:
diff changeset
97 return false;
anatofuz
parents:
diff changeset
98 Expr *condE = S->getCond();
anatofuz
parents:
diff changeset
99 if (!condE)
anatofuz
parents:
diff changeset
100 return false;
anatofuz
parents:
diff changeset
101 if (hasSideEffects(condE, Ctx))
anatofuz
parents:
diff changeset
102 return false;
anatofuz
parents:
diff changeset
103 if (!S->getThen() || !Visit(S->getThen()))
anatofuz
parents:
diff changeset
104 return false;
anatofuz
parents:
diff changeset
105 return !S->getElse() || Visit(S->getElse());
anatofuz
parents:
diff changeset
106 }
anatofuz
parents:
diff changeset
107 bool VisitWhileStmt(WhileStmt *S) {
anatofuz
parents:
diff changeset
108 if (S->getConditionVariable())
anatofuz
parents:
diff changeset
109 return false;
anatofuz
parents:
diff changeset
110 Expr *condE = S->getCond();
anatofuz
parents:
diff changeset
111 if (!condE)
anatofuz
parents:
diff changeset
112 return false;
anatofuz
parents:
diff changeset
113 if (hasSideEffects(condE, Ctx))
anatofuz
parents:
diff changeset
114 return false;
anatofuz
parents:
diff changeset
115 if (!S->getBody())
anatofuz
parents:
diff changeset
116 return false;
anatofuz
parents:
diff changeset
117 return Visit(S->getBody());
anatofuz
parents:
diff changeset
118 }
anatofuz
parents:
diff changeset
119 bool VisitDoStmt(DoStmt *S) {
anatofuz
parents:
diff changeset
120 Expr *condE = S->getCond();
anatofuz
parents:
diff changeset
121 if (!condE)
anatofuz
parents:
diff changeset
122 return false;
anatofuz
parents:
diff changeset
123 if (hasSideEffects(condE, Ctx))
anatofuz
parents:
diff changeset
124 return false;
anatofuz
parents:
diff changeset
125 if (!S->getBody())
anatofuz
parents:
diff changeset
126 return false;
anatofuz
parents:
diff changeset
127 return Visit(S->getBody());
anatofuz
parents:
diff changeset
128 }
anatofuz
parents:
diff changeset
129 bool VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
anatofuz
parents:
diff changeset
130 Expr *Exp = S->getCollection();
anatofuz
parents:
diff changeset
131 if (!Exp)
anatofuz
parents:
diff changeset
132 return false;
anatofuz
parents:
diff changeset
133 if (hasSideEffects(Exp, Ctx))
anatofuz
parents:
diff changeset
134 return false;
anatofuz
parents:
diff changeset
135 if (!S->getBody())
anatofuz
parents:
diff changeset
136 return false;
anatofuz
parents:
diff changeset
137 return Visit(S->getBody());
anatofuz
parents:
diff changeset
138 }
anatofuz
parents:
diff changeset
139 bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
anatofuz
parents:
diff changeset
140 if (!S->getSubStmt())
anatofuz
parents:
diff changeset
141 return false;
anatofuz
parents:
diff changeset
142 return Visit(S->getSubStmt());
anatofuz
parents:
diff changeset
143 }
anatofuz
parents:
diff changeset
144 };
anatofuz
parents:
diff changeset
145
anatofuz
parents:
diff changeset
146 class EmptyStatementsRemover :
anatofuz
parents:
diff changeset
147 public RecursiveASTVisitor<EmptyStatementsRemover> {
anatofuz
parents:
diff changeset
148 MigrationPass &Pass;
anatofuz
parents:
diff changeset
149
anatofuz
parents:
diff changeset
150 public:
anatofuz
parents:
diff changeset
151 EmptyStatementsRemover(MigrationPass &pass) : Pass(pass) { }
anatofuz
parents:
diff changeset
152
anatofuz
parents:
diff changeset
153 bool TraverseStmtExpr(StmtExpr *E) {
anatofuz
parents:
diff changeset
154 CompoundStmt *S = E->getSubStmt();
anatofuz
parents:
diff changeset
155 for (CompoundStmt::body_iterator
anatofuz
parents:
diff changeset
156 I = S->body_begin(), E = S->body_end(); I != E; ++I) {
anatofuz
parents:
diff changeset
157 if (I != E - 1)
anatofuz
parents:
diff changeset
158 check(*I);
anatofuz
parents:
diff changeset
159 TraverseStmt(*I);
anatofuz
parents:
diff changeset
160 }
anatofuz
parents:
diff changeset
161 return true;
anatofuz
parents:
diff changeset
162 }
anatofuz
parents:
diff changeset
163
anatofuz
parents:
diff changeset
164 bool VisitCompoundStmt(CompoundStmt *S) {
anatofuz
parents:
diff changeset
165 for (auto *I : S->body())
anatofuz
parents:
diff changeset
166 check(I);
anatofuz
parents:
diff changeset
167 return true;
anatofuz
parents:
diff changeset
168 }
anatofuz
parents:
diff changeset
169
anatofuz
parents:
diff changeset
170 ASTContext &getContext() { return Pass.Ctx; }
anatofuz
parents:
diff changeset
171
anatofuz
parents:
diff changeset
172 private:
anatofuz
parents:
diff changeset
173 void check(Stmt *S) {
anatofuz
parents:
diff changeset
174 if (!S) return;
anatofuz
parents:
diff changeset
175 if (EmptyChecker(Pass.Ctx, Pass.ARCMTMacroLocs).Visit(S)) {
anatofuz
parents:
diff changeset
176 Transaction Trans(Pass.TA);
anatofuz
parents:
diff changeset
177 Pass.TA.removeStmt(S);
anatofuz
parents:
diff changeset
178 }
anatofuz
parents:
diff changeset
179 }
anatofuz
parents:
diff changeset
180 };
anatofuz
parents:
diff changeset
181
anatofuz
parents:
diff changeset
182 } // anonymous namespace
anatofuz
parents:
diff changeset
183
anatofuz
parents:
diff changeset
184 static bool isBodyEmpty(CompoundStmt *body, ASTContext &Ctx,
anatofuz
parents:
diff changeset
185 std::vector<SourceLocation> &MacroLocs) {
anatofuz
parents:
diff changeset
186 for (auto *I : body->body())
anatofuz
parents:
diff changeset
187 if (!EmptyChecker(Ctx, MacroLocs).Visit(I))
anatofuz
parents:
diff changeset
188 return false;
anatofuz
parents:
diff changeset
189
anatofuz
parents:
diff changeset
190 return true;
anatofuz
parents:
diff changeset
191 }
anatofuz
parents:
diff changeset
192
anatofuz
parents:
diff changeset
193 static void cleanupDeallocOrFinalize(MigrationPass &pass) {
anatofuz
parents:
diff changeset
194 ASTContext &Ctx = pass.Ctx;
anatofuz
parents:
diff changeset
195 TransformActions &TA = pass.TA;
anatofuz
parents:
diff changeset
196 DeclContext *DC = Ctx.getTranslationUnitDecl();
anatofuz
parents:
diff changeset
197 Selector FinalizeSel =
anatofuz
parents:
diff changeset
198 Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));
anatofuz
parents:
diff changeset
199
anatofuz
parents:
diff changeset
200 typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
anatofuz
parents:
diff changeset
201 impl_iterator;
anatofuz
parents:
diff changeset
202 for (impl_iterator I = impl_iterator(DC->decls_begin()),
anatofuz
parents:
diff changeset
203 E = impl_iterator(DC->decls_end()); I != E; ++I) {
anatofuz
parents:
diff changeset
204 ObjCMethodDecl *DeallocM = nullptr;
anatofuz
parents:
diff changeset
205 ObjCMethodDecl *FinalizeM = nullptr;
anatofuz
parents:
diff changeset
206 for (auto *MD : I->instance_methods()) {
anatofuz
parents:
diff changeset
207 if (!MD->hasBody())
anatofuz
parents:
diff changeset
208 continue;
anatofuz
parents:
diff changeset
209
anatofuz
parents:
diff changeset
210 if (MD->getMethodFamily() == OMF_dealloc) {
anatofuz
parents:
diff changeset
211 DeallocM = MD;
anatofuz
parents:
diff changeset
212 } else if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
anatofuz
parents:
diff changeset
213 FinalizeM = MD;
anatofuz
parents:
diff changeset
214 }
anatofuz
parents:
diff changeset
215 }
anatofuz
parents:
diff changeset
216
anatofuz
parents:
diff changeset
217 if (DeallocM) {
anatofuz
parents:
diff changeset
218 if (isBodyEmpty(DeallocM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
anatofuz
parents:
diff changeset
219 Transaction Trans(TA);
anatofuz
parents:
diff changeset
220 TA.remove(DeallocM->getSourceRange());
anatofuz
parents:
diff changeset
221 }
anatofuz
parents:
diff changeset
222
anatofuz
parents:
diff changeset
223 if (FinalizeM) {
anatofuz
parents:
diff changeset
224 Transaction Trans(TA);
anatofuz
parents:
diff changeset
225 TA.remove(FinalizeM->getSourceRange());
anatofuz
parents:
diff changeset
226 }
anatofuz
parents:
diff changeset
227
anatofuz
parents:
diff changeset
228 } else if (FinalizeM) {
anatofuz
parents:
diff changeset
229 if (isBodyEmpty(FinalizeM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
anatofuz
parents:
diff changeset
230 Transaction Trans(TA);
anatofuz
parents:
diff changeset
231 TA.remove(FinalizeM->getSourceRange());
anatofuz
parents:
diff changeset
232 } else {
anatofuz
parents:
diff changeset
233 Transaction Trans(TA);
anatofuz
parents:
diff changeset
234 TA.replaceText(FinalizeM->getSelectorStartLoc(), "finalize", "dealloc");
anatofuz
parents:
diff changeset
235 }
anatofuz
parents:
diff changeset
236 }
anatofuz
parents:
diff changeset
237 }
anatofuz
parents:
diff changeset
238 }
anatofuz
parents:
diff changeset
239
anatofuz
parents:
diff changeset
240 void trans::removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass) {
anatofuz
parents:
diff changeset
241 EmptyStatementsRemover(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
anatofuz
parents:
diff changeset
242
anatofuz
parents:
diff changeset
243 cleanupDeallocOrFinalize(pass);
anatofuz
parents:
diff changeset
244
anatofuz
parents:
diff changeset
245 for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) {
anatofuz
parents:
diff changeset
246 Transaction Trans(pass.TA);
anatofuz
parents:
diff changeset
247 pass.TA.remove(pass.ARCMTMacroLocs[i]);
anatofuz
parents:
diff changeset
248 }
anatofuz
parents:
diff changeset
249 }