blob: 7bcdd17176022ca15a4861adaa8e40be15e26436 [file] [log] [blame]
Stephen Hines292e00a2011-03-18 19:11:30 -07001/*
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
21namespace slang {
22
23void RSASTReplace::ReplaceStmt(
24 clang::Stmt *OuterStmt,
25 clang::Stmt *OldStmt,
26 clang::Stmt *NewStmt) {
27 mOldStmt = OldStmt;
28 mNewStmt = NewStmt;
29 mOuterStmt = OuterStmt;
30
31 // This simplifies use in various Stmt visitor passes where the only
32 // valid type is an Expr.
33 mOldExpr = dyn_cast<clang::Expr>(OldStmt);
34 if (mOldExpr) {
35 mNewExpr = dyn_cast<clang::Expr>(NewStmt);
36 }
37 Visit(mOuterStmt);
38}
39
40void RSASTReplace::ReplaceInCompoundStmt(clang::CompoundStmt *CS) {
41 clang::Stmt **UpdatedStmtList = new clang::Stmt*[CS->size()];
42
43 unsigned UpdatedStmtCount = 0;
44 clang::CompoundStmt::body_iterator bI = CS->body_begin();
45 clang::CompoundStmt::body_iterator bE = CS->body_end();
46
47 for ( ; bI != bE; bI++) {
48 if (matchesStmt(*bI)) {
49 UpdatedStmtList[UpdatedStmtCount++] = mNewStmt;
50 } else {
51 UpdatedStmtList[UpdatedStmtCount++] = *bI;
52 }
53 }
54
55 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
56
57 delete [] UpdatedStmtList;
58
59 return;
60}
61
62void 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 return;
76}
77
78void RSASTReplace::VisitCompoundStmt(clang::CompoundStmt *CS) {
79 VisitStmt(CS);
80 ReplaceInCompoundStmt(CS);
81 return;
82}
83
84void RSASTReplace::VisitCaseStmt(clang::CaseStmt *CS) {
85 if (matchesStmt(CS->getSubStmt())) {
86 CS->setSubStmt(mNewStmt);
87 } else {
88 VisitStmt(CS);
89 }
90 return;
91}
92
93void RSASTReplace::VisitDefaultStmt(clang::DefaultStmt *DS) {
94 if (matchesStmt(DS->getSubStmt())) {
95 DS->setSubStmt(mNewStmt);
96 } else {
97 VisitStmt(DS);
98 }
99 return;
100}
101
102void RSASTReplace::VisitDoStmt(clang::DoStmt *DS) {
103 if (matchesExpr(DS->getCond())) {
104 DS->setCond(mNewExpr);
105 } else if (matchesStmt(DS->getBody())) {
106 DS->setBody(mNewStmt);
107 } else {
108 VisitStmt(DS);
109 }
110 return;
111}
112
113void RSASTReplace::VisitForStmt(clang::ForStmt *FS) {
114 if (matchesStmt(FS->getInit())) {
115 FS->setInit(mNewStmt);
116 } else if (matchesExpr(FS->getCond())) {
117 FS->setCond(mNewExpr);
118 } else if (matchesExpr(FS->getInc())) {
119 FS->setInc(mNewExpr);
120 } else if (matchesStmt(FS->getBody())) {
121 FS->setBody(mNewStmt);
122 } else {
123 VisitStmt(FS);
124 }
125 return;
126}
127
128void RSASTReplace::VisitIfStmt(clang::IfStmt *IS) {
129 if (matchesExpr(IS->getCond())) {
130 IS->setCond(mNewExpr);
131 } else if (matchesStmt(IS->getThen())) {
132 IS->setThen(mNewStmt);
133 } else if (matchesStmt(IS->getElse())) {
134 IS->setElse(mNewStmt);
135 } else {
136 VisitStmt(IS);
137 }
138 return;
139}
140
141void RSASTReplace::VisitSwitchCase(clang::SwitchCase *SC) {
142 slangAssert(false && "Both case and default have specialized handlers");
143 VisitStmt(SC);
144 return;
145}
146
147void RSASTReplace::VisitSwitchStmt(clang::SwitchStmt *SS) {
148 if (matchesExpr(SS->getCond())) {
149 SS->setCond(mNewExpr);
150 } else {
151 VisitStmt(SS);
152 }
153 return;
154}
155
156void RSASTReplace::VisitWhileStmt(clang::WhileStmt *WS) {
157 if (matchesExpr(WS->getCond())) {
158 WS->setCond(mNewExpr);
159 } else if (matchesStmt(WS->getBody())) {
160 WS->setBody(mNewStmt);
161 } else {
162 VisitStmt(WS);
163 }
164 return;
165}
166
167} // namespace slang