Home | History | Annotate | Download | only in slang
      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 
     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 
     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, UpdatedStmtList, UpdatedStmtCount);
     58 
     59   delete [] UpdatedStmtList;
     60 }
     61 
     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 
     77 void RSASTReplace::VisitCompoundStmt(clang::CompoundStmt *CS) {
     78   VisitStmt(CS);
     79   ReplaceInCompoundStmt(CS);
     80 }
     81 
     82 void RSASTReplace::VisitCaseStmt(clang::CaseStmt *CS) {
     83   if (matchesStmt(CS->getSubStmt())) {
     84     CS->setSubStmt(mNewStmt);
     85   } else {
     86     VisitStmt(CS);
     87   }
     88 }
     89 
     90 void RSASTReplace::VisitDefaultStmt(clang::DefaultStmt *DS) {
     91   if (matchesStmt(DS->getSubStmt())) {
     92     DS->setSubStmt(mNewStmt);
     93   } else {
     94     VisitStmt(DS);
     95   }
     96 }
     97 
     98 void RSASTReplace::VisitDoStmt(clang::DoStmt *DS) {
     99   if (matchesExpr(DS->getCond())) {
    100     DS->setCond(mNewExpr);
    101   } else if (matchesStmt(DS->getBody())) {
    102     DS->setBody(mNewStmt);
    103   } else {
    104     VisitStmt(DS);
    105   }
    106 }
    107 
    108 void RSASTReplace::VisitForStmt(clang::ForStmt *FS) {
    109   if (matchesStmt(FS->getInit())) {
    110     FS->setInit(mNewStmt);
    111   } else if (matchesExpr(FS->getCond())) {
    112     FS->setCond(mNewExpr);
    113   } else if (matchesExpr(FS->getInc())) {
    114     FS->setInc(mNewExpr);
    115   } else if (matchesStmt(FS->getBody())) {
    116     FS->setBody(mNewStmt);
    117   } else {
    118     VisitStmt(FS);
    119   }
    120 }
    121 
    122 void RSASTReplace::VisitIfStmt(clang::IfStmt *IS) {
    123   if (matchesExpr(IS->getCond())) {
    124     IS->setCond(mNewExpr);
    125   } else if (matchesStmt(IS->getThen())) {
    126     IS->setThen(mNewStmt);
    127   } else if (matchesStmt(IS->getElse())) {
    128     IS->setElse(mNewStmt);
    129   } else {
    130     VisitStmt(IS);
    131   }
    132 }
    133 
    134 void RSASTReplace::VisitSwitchCase(clang::SwitchCase *SC) {
    135   slangAssert(false && "Both case and default have specialized handlers");
    136   VisitStmt(SC);
    137 }
    138 
    139 void RSASTReplace::VisitSwitchStmt(clang::SwitchStmt *SS) {
    140   if (matchesExpr(SS->getCond())) {
    141     SS->setCond(mNewExpr);
    142   } else {
    143     VisitStmt(SS);
    144   }
    145 }
    146 
    147 void RSASTReplace::VisitWhileStmt(clang::WhileStmt *WS) {
    148   if (matchesExpr(WS->getCond())) {
    149     WS->setCond(mNewExpr);
    150   } else if (matchesStmt(WS->getBody())) {
    151     WS->setBody(mNewStmt);
    152   } else {
    153     VisitStmt(WS);
    154   }
    155 }
    156 
    157 }  // namespace slang
    158