1 /*
2 * Copyright 2011, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "slang_rs_ast_replace.h"
18
19 #include "slang_assert.h"
20
21 #include "llvm/Support/Casting.h"
22
23 namespace slang {
24
ReplaceStmt(clang::Stmt * OuterStmt,clang::Stmt * OldStmt,clang::Stmt * NewStmt)25 void RSASTReplace::ReplaceStmt(
26 clang::Stmt *OuterStmt,
27 clang::Stmt *OldStmt,
28 clang::Stmt *NewStmt) {
29 mOldStmt = OldStmt;
30 mNewStmt = NewStmt;
31 mOuterStmt = OuterStmt;
32
33 // This simplifies use in various Stmt visitor passes where the only
34 // valid type is an Expr.
35 mOldExpr = llvm::dyn_cast<clang::Expr>(OldStmt);
36 if (mOldExpr) {
37 mNewExpr = llvm::dyn_cast<clang::Expr>(NewStmt);
38 }
39 Visit(mOuterStmt);
40 }
41
ReplaceInCompoundStmt(clang::CompoundStmt * CS)42 void RSASTReplace::ReplaceInCompoundStmt(clang::CompoundStmt *CS) {
43 clang::Stmt **UpdatedStmtList = new clang::Stmt*[CS->size()];
44
45 unsigned UpdatedStmtCount = 0;
46 clang::CompoundStmt::body_iterator bI = CS->body_begin();
47 clang::CompoundStmt::body_iterator bE = CS->body_end();
48
49 for ( ; bI != bE; bI++) {
50 if (matchesStmt(*bI)) {
51 UpdatedStmtList[UpdatedStmtCount++] = mNewStmt;
52 } else {
53 UpdatedStmtList[UpdatedStmtCount++] = *bI;
54 }
55 }
56
57 CS->setStmts(C, llvm::makeArrayRef(UpdatedStmtList, UpdatedStmtCount));
58
59 delete [] UpdatedStmtList;
60 }
61
VisitStmt(clang::Stmt * S)62 void RSASTReplace::VisitStmt(clang::Stmt *S) {
63 // This function does the actual iteration through all sub-Stmt's within
64 // a given Stmt. Note that this function is skipped by all of the other
65 // Visit* functions if we have already found a higher-level match.
66 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
67 I != E;
68 I++) {
69 if (clang::Stmt *Child = *I) {
70 if (!matchesStmt(Child)) {
71 Visit(Child);
72 }
73 }
74 }
75 }
76
VisitCompoundStmt(clang::CompoundStmt * CS)77 void RSASTReplace::VisitCompoundStmt(clang::CompoundStmt *CS) {
78 VisitStmt(CS);
79 ReplaceInCompoundStmt(CS);
80 }
81
VisitCaseStmt(clang::CaseStmt * CS)82 void RSASTReplace::VisitCaseStmt(clang::CaseStmt *CS) {
83 if (matchesStmt(CS->getSubStmt())) {
84 CS->setSubStmt(mNewStmt);
85 } else {
86 VisitStmt(CS);
87 }
88 }
89
VisitDeclStmt(clang::DeclStmt * DS)90 void RSASTReplace::VisitDeclStmt(clang::DeclStmt* DS) {
91 VisitStmt(DS);
92 for (clang::Decl* D : DS->decls()) {
93 clang::VarDecl* VD;
94 if ((VD = llvm::dyn_cast<clang::VarDecl>(D))) {
95 if (matchesExpr(VD->getInit())) {
96 VD->setInit(mNewExpr);
97 }
98 }
99 }
100 }
101
VisitDefaultStmt(clang::DefaultStmt * DS)102 void RSASTReplace::VisitDefaultStmt(clang::DefaultStmt *DS) {
103 if (matchesStmt(DS->getSubStmt())) {
104 DS->setSubStmt(mNewStmt);
105 } else {
106 VisitStmt(DS);
107 }
108 }
109
VisitDoStmt(clang::DoStmt * DS)110 void RSASTReplace::VisitDoStmt(clang::DoStmt *DS) {
111 if (matchesExpr(DS->getCond())) {
112 DS->setCond(mNewExpr);
113 } else if (matchesStmt(DS->getBody())) {
114 DS->setBody(mNewStmt);
115 } else {
116 VisitStmt(DS);
117 }
118 }
119
VisitForStmt(clang::ForStmt * FS)120 void RSASTReplace::VisitForStmt(clang::ForStmt *FS) {
121 if (matchesStmt(FS->getInit())) {
122 FS->setInit(mNewStmt);
123 } else if (matchesExpr(FS->getCond())) {
124 FS->setCond(mNewExpr);
125 } else if (matchesExpr(FS->getInc())) {
126 FS->setInc(mNewExpr);
127 } else if (matchesStmt(FS->getBody())) {
128 FS->setBody(mNewStmt);
129 } else {
130 VisitStmt(FS);
131 }
132 }
133
VisitIfStmt(clang::IfStmt * IS)134 void RSASTReplace::VisitIfStmt(clang::IfStmt *IS) {
135 if (matchesExpr(IS->getCond())) {
136 IS->setCond(mNewExpr);
137 } else if (matchesStmt(IS->getThen())) {
138 IS->setThen(mNewStmt);
139 } else if (matchesStmt(IS->getElse())) {
140 IS->setElse(mNewStmt);
141 } else {
142 VisitStmt(IS);
143 }
144 }
145
VisitSwitchCase(clang::SwitchCase * SC)146 void RSASTReplace::VisitSwitchCase(clang::SwitchCase *SC) {
147 slangAssert(false && "Both case and default have specialized handlers");
148 VisitStmt(SC);
149 }
150
VisitSwitchStmt(clang::SwitchStmt * SS)151 void RSASTReplace::VisitSwitchStmt(clang::SwitchStmt *SS) {
152 if (matchesExpr(SS->getCond())) {
153 SS->setCond(mNewExpr);
154 } else {
155 VisitStmt(SS);
156 }
157 }
158
VisitWhileStmt(clang::WhileStmt * WS)159 void RSASTReplace::VisitWhileStmt(clang::WhileStmt *WS) {
160 if (matchesExpr(WS->getCond())) {
161 WS->setCond(mNewExpr);
162 } else if (matchesStmt(WS->getBody())) {
163 WS->setBody(mNewStmt);
164 } else {
165 VisitStmt(WS);
166 }
167 }
168
169 } // namespace slang
170