slang_rs_ast_replace.cpp revision 292e00a0259ac28cac1055cb6077cf6fc7c6743c
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
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
168