1accaf19bc1129c0273ec50dba52318e60bc29103Benjamin Kramer//===--- TransEmptyStatements.cpp - Transformations to ARC mode -----------===//
2fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//
3fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
4fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//
5fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
6fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis// License. See LICENSE.TXT for details.
7fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//
8fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
9fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//
10fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis// removeEmptyStatementsAndDealloc:
11fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//
12fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis// Removes empty statements that are leftovers from previous transformations.
13fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis// e.g for
14fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//
15fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//  [x retain];
16fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//
17fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis// removeRetainReleaseDealloc will leave an empty ";" that removeEmptyStatements
18fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis// will remove.
19fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//
20fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
21fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
22fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis#include "Transforms.h"
23fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis#include "Internals.h"
24471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h"
25fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis#include "clang/AST/StmtVisitor.h"
26aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis#include "clang/Basic/SourceManager.h"
27fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
28fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidisusing namespace clang;
29fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidisusing namespace arcmt;
30fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidisusing namespace trans;
31fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
32aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidisstatic bool isEmptyARCMTMacroStatement(NullStmt *S,
33aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis                                       std::vector<SourceLocation> &MacroLocs,
34aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis                                       ASTContext &Ctx) {
35aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  if (!S->hasLeadingEmptyMacro())
36aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    return false;
37aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis
38aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  SourceLocation SemiLoc = S->getSemiLoc();
39aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  if (SemiLoc.isInvalid() || SemiLoc.isMacroID())
40aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    return false;
41aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis
42aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  if (MacroLocs.empty())
43aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    return false;
44aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis
45aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  SourceManager &SM = Ctx.getSourceManager();
46aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  std::vector<SourceLocation>::iterator
47aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    I = std::upper_bound(MacroLocs.begin(), MacroLocs.end(), SemiLoc,
48aa0cd85838f2a024e589ea4e8c2094130065af21Dmitri Gribenko                         BeforeThanCompare<SourceLocation>(SM));
49aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  --I;
50aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  SourceLocation
51a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis      AfterMacroLoc = I->getLocWithOffset(getARCMTMacroName().size());
52aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  assert(AfterMacroLoc.isFileID());
53aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis
54aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  if (AfterMacroLoc == SemiLoc)
55aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    return true;
56aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis
57aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  int RelOffs = 0;
58aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  if (!SM.isInSameSLocAddrSpace(AfterMacroLoc, SemiLoc, &RelOffs))
59aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    return false;
60aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  if (RelOffs < 0)
61aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    return false;
62aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis
63aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  // We make the reasonable assumption that a semicolon after 100 characters
64aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  // means that it is not the next token after our macro. If this assumption
65aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  // fails it is not critical, we will just fail to clear out, e.g., an empty
66aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  // 'if'.
67aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  if (RelOffs - getARCMTMacroName().size() > 100)
68aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    return false;
69aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis
70aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  SourceLocation AfterMacroSemiLoc = findSemiAfterLocation(AfterMacroLoc, Ctx);
71aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  return AfterMacroSemiLoc == SemiLoc;
72aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis}
73aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis
74fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidisnamespace {
75fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
76fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis/// \brief Returns true if the statement became empty due to previous
77fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis/// transformations.
78fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidisclass EmptyChecker : public StmtVisitor<EmptyChecker, bool> {
79fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  ASTContext &Ctx;
80aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  std::vector<SourceLocation> &MacroLocs;
81fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
82fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidispublic:
83aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  EmptyChecker(ASTContext &ctx, std::vector<SourceLocation> &macroLocs)
84fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    : Ctx(ctx), MacroLocs(macroLocs) { }
85fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
86fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  bool VisitNullStmt(NullStmt *S) {
87aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    return isEmptyARCMTMacroStatement(S, MacroLocs, Ctx);
88fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
89fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  bool VisitCompoundStmt(CompoundStmt *S) {
90fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (S->body_empty())
91fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false; // was already empty, not because of transformations.
92651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto *I : S->body())
93651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (!Visit(I))
94fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis        return false;
95fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    return true;
96fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
97fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  bool VisitIfStmt(IfStmt *S) {
98fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (S->getConditionVariable())
99fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
100fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    Expr *condE = S->getCond();
101fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (!condE)
102fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
103fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (hasSideEffects(condE, Ctx))
104fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
105fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (!S->getThen() || !Visit(S->getThen()))
106fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
10787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    return !S->getElse() || Visit(S->getElse());
108fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
109fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  bool VisitWhileStmt(WhileStmt *S) {
110fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (S->getConditionVariable())
111fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
112fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    Expr *condE = S->getCond();
113fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (!condE)
114fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
115fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (hasSideEffects(condE, Ctx))
116fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
117fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (!S->getBody())
118fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
119fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    return Visit(S->getBody());
120fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
121fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  bool VisitDoStmt(DoStmt *S) {
122fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    Expr *condE = S->getCond();
123fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (!condE)
124fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
125fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (hasSideEffects(condE, Ctx))
126fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
127fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (!S->getBody())
128fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
129fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    return Visit(S->getBody());
130fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
131fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  bool VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
132fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    Expr *Exp = S->getCollection();
133fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (!Exp)
134fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
135fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (hasSideEffects(Exp, Ctx))
136fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
137fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (!S->getBody())
138fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
139fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    return Visit(S->getBody());
140fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
141fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
142fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (!S->getSubStmt())
143fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
144fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    return Visit(S->getSubStmt());
145fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
146fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis};
147fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
148fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidisclass EmptyStatementsRemover :
149fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis                            public RecursiveASTVisitor<EmptyStatementsRemover> {
150fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  MigrationPass &Pass;
151fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
152fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidispublic:
153aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  EmptyStatementsRemover(MigrationPass &pass) : Pass(pass) { }
154fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
155fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  bool TraverseStmtExpr(StmtExpr *E) {
156fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    CompoundStmt *S = E->getSubStmt();
157fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    for (CompoundStmt::body_iterator
158fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis           I = S->body_begin(), E = S->body_end(); I != E; ++I) {
159fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      if (I != E - 1)
160fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis        check(*I);
161fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      TraverseStmt(*I);
162fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    }
163fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    return true;
164fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
165fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
166fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  bool VisitCompoundStmt(CompoundStmt *S) {
167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto *I : S->body())
168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      check(I);
169fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    return true;
170fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
171fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
172fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  ASTContext &getContext() { return Pass.Ctx; }
173fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
174fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidisprivate:
175fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  void check(Stmt *S) {
176fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    if (!S) return;
177aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis    if (EmptyChecker(Pass.Ctx, Pass.ARCMTMacroLocs).Visit(S)) {
178fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      Transaction Trans(Pass.TA);
179fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      Pass.TA.removeStmt(S);
180fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    }
181fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
182fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis};
183fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
184fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis} // anonymous namespace
185fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
186aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidisstatic bool isBodyEmpty(CompoundStmt *body, ASTContext &Ctx,
187aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis                        std::vector<SourceLocation> &MacroLocs) {
188651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto *I : body->body())
189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!EmptyChecker(Ctx, MacroLocs).Visit(I))
190fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      return false;
191fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
192fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  return true;
193fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis}
194fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
195e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidisstatic void cleanupDeallocOrFinalize(MigrationPass &pass) {
196fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  ASTContext &Ctx = pass.Ctx;
197fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  TransformActions &TA = pass.TA;
198fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  DeclContext *DC = Ctx.getTranslationUnitDecl();
199e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis  Selector FinalizeSel =
200e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis      Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));
201fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
202fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
203fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    impl_iterator;
204fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  for (impl_iterator I = impl_iterator(DC->decls_begin()),
205fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis                     E = impl_iterator(DC->decls_end()); I != E; ++I) {
2066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    ObjCMethodDecl *DeallocM = nullptr;
2076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    ObjCMethodDecl *FinalizeM = nullptr;
208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto *MD : I->instance_methods()) {
209e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis      if (!MD->hasBody())
210e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        continue;
211e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis
212fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      if (MD->getMethodFamily() == OMF_dealloc) {
213e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        DeallocM = MD;
214e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis      } else if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
215e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        FinalizeM = MD;
216e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis      }
217e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis    }
218e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis
219e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis    if (DeallocM) {
220e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis      if (isBodyEmpty(DeallocM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
221e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        Transaction Trans(TA);
222e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        TA.remove(DeallocM->getSourceRange());
223e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis      }
224e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis
225e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis      if (FinalizeM) {
226e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        Transaction Trans(TA);
227e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        TA.remove(FinalizeM->getSourceRange());
228e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis      }
229e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis
230e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis    } else if (FinalizeM) {
231e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis      if (isBodyEmpty(FinalizeM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
232e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        Transaction Trans(TA);
233e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        TA.remove(FinalizeM->getSourceRange());
234e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis      } else {
235e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        Transaction Trans(TA);
236e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis        TA.replaceText(FinalizeM->getSelectorStartLoc(), "finalize", "dealloc");
237fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis      }
238fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    }
239fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
240fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis}
241fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
242e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidisvoid trans::removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass) {
243aec230d29835285777ecc467e268c83b33a2addeArgyrios Kyrtzidis  EmptyStatementsRemover(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
244fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
245e7ef8556f4ee3012a0479308c993af0fbee448dfArgyrios Kyrtzidis  cleanupDeallocOrFinalize(pass);
246fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis
247fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) {
248fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    Transaction Trans(pass.TA);
249fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis    pass.TA.remove(pass.ARCMTMacroLocs[i]);
250fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis  }
251fd3455a9ebecf67b9a1c46f0675697bf518e6b80Argyrios Kyrtzidis}
252