1 //===--- TransEmptyStatements.cpp - Tranformations to ARC mode ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // removeEmptyStatements:
12 // Removes empty statements that are leftovers from previous transformations.
17 // removeRetainReleaseDealloc will leave an empty ";" that removeEmptyStatements
20 //===----------------------------------------------------------------------===//
22 #include "Transforms.h"
23 #include "Internals.h"
24 #include "clang/AST/StmtVisitor.h"
26 using namespace clang
;
27 using namespace arcmt
;
28 using namespace trans
;
29 using llvm::StringRef
;
33 class EmptyStatementsRemover
:
34 public RecursiveASTVisitor
<EmptyStatementsRemover
> {
36 llvm::DenseSet
<unsigned> MacroLocs
;
39 EmptyStatementsRemover(MigrationPass
&pass
) : Pass(pass
) {
40 for (unsigned i
= 0, e
= Pass
.ARCMTMacroLocs
.size(); i
!= e
; ++i
)
41 MacroLocs
.insert(Pass
.ARCMTMacroLocs
[i
].getRawEncoding());
44 bool TraverseStmtExpr(StmtExpr
*E
) {
45 CompoundStmt
*S
= E
->getSubStmt();
46 for (CompoundStmt::body_iterator
47 I
= S
->body_begin(), E
= S
->body_end(); I
!= E
; ++I
) {
55 bool VisitCompoundStmt(CompoundStmt
*S
) {
56 for (CompoundStmt::body_iterator
57 I
= S
->body_begin(), E
= S
->body_end(); I
!= E
; ++I
)
62 bool isMacroLoc(SourceLocation loc
) {
63 if (loc
.isInvalid()) return false;
64 return MacroLocs
.count(loc
.getRawEncoding());
67 ASTContext
&getContext() { return Pass
.Ctx
; }
70 /// \brief Returns true if the statement became empty due to previous
72 class EmptyChecker
: public StmtVisitor
<EmptyChecker
, bool> {
73 EmptyStatementsRemover
&Trans
;
76 EmptyChecker(EmptyStatementsRemover
&trans
) : Trans(trans
) { }
78 bool VisitNullStmt(NullStmt
*S
) {
79 return Trans
.isMacroLoc(S
->getLeadingEmptyMacroLoc());
81 bool VisitCompoundStmt(CompoundStmt
*S
) {
83 return false; // was already empty, not because of transformations.
84 for (CompoundStmt::body_iterator
85 I
= S
->body_begin(), E
= S
->body_end(); I
!= E
; ++I
)
90 bool VisitIfStmt(IfStmt
*S
) {
91 if (S
->getConditionVariable())
93 Expr
*condE
= S
->getCond();
96 if (hasSideEffects(condE
, Trans
.getContext()))
98 if (!S
->getThen() || !Visit(S
->getThen()))
100 if (S
->getElse() && !Visit(S
->getElse()))
104 bool VisitWhileStmt(WhileStmt
*S
) {
105 if (S
->getConditionVariable())
107 Expr
*condE
= S
->getCond();
110 if (hasSideEffects(condE
, Trans
.getContext()))
114 return Visit(S
->getBody());
116 bool VisitDoStmt(DoStmt
*S
) {
117 Expr
*condE
= S
->getCond();
120 if (hasSideEffects(condE
, Trans
.getContext()))
124 return Visit(S
->getBody());
126 bool VisitObjCForCollectionStmt(ObjCForCollectionStmt
*S
) {
127 Expr
*Exp
= S
->getCollection();
130 if (hasSideEffects(Exp
, Trans
.getContext()))
134 return Visit(S
->getBody());
136 bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt
*S
) {
137 if (!S
->getSubStmt())
139 return Visit(S
->getSubStmt());
143 void check(Stmt
*S
) {
145 if (EmptyChecker(*this).Visit(S
)) {
146 Transaction
Trans(Pass
.TA
);
147 Pass
.TA
.removeStmt(S
);
152 } // anonymous namespace
154 void trans::removeEmptyStatements(MigrationPass
&pass
) {
155 EmptyStatementsRemover(pass
).TraverseDecl(pass
.Ctx
.getTranslationUnitDecl());
157 for (unsigned i
= 0, e
= pass
.ARCMTMacroLocs
.size(); i
!= e
; ++i
) {
158 Transaction
Trans(pass
.TA
);
159 pass
.TA
.remove(pass
.ARCMTMacroLocs
[i
]);