1 //===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the ParentMap class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/AST/ParentMap.h" 15 #include "clang/AST/Decl.h" 16 #include "clang/AST/Expr.h" 17 #include "llvm/ADT/DenseMap.h" 18 19 using namespace clang; 20 21 typedef llvm::DenseMap<Stmt*, Stmt*> MapTy; 22 23 enum OpaqueValueMode { 24 OV_Transparent, 25 OV_Opaque 26 }; 27 28 static void BuildParentMap(MapTy& M, Stmt* S, 29 OpaqueValueMode OVMode = OV_Transparent) { 30 31 switch (S->getStmtClass()) { 32 case Stmt::PseudoObjectExprClass: { 33 assert(OVMode == OV_Transparent && "Should not appear alongside OVEs"); 34 PseudoObjectExpr *POE = cast<PseudoObjectExpr>(S); 35 36 M[POE->getSyntacticForm()] = S; 37 BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent); 38 39 for (PseudoObjectExpr::semantics_iterator I = POE->semantics_begin(), 40 E = POE->semantics_end(); 41 I != E; ++I) { 42 M[*I] = S; 43 BuildParentMap(M, *I, OV_Opaque); 44 } 45 break; 46 } 47 case Stmt::BinaryConditionalOperatorClass: { 48 assert(OVMode == OV_Transparent && "Should not appear alongside OVEs"); 49 BinaryConditionalOperator *BCO = cast<BinaryConditionalOperator>(S); 50 51 M[BCO->getCommon()] = S; 52 BuildParentMap(M, BCO->getCommon(), OV_Transparent); 53 54 M[BCO->getCond()] = S; 55 BuildParentMap(M, BCO->getCond(), OV_Opaque); 56 57 M[BCO->getTrueExpr()] = S; 58 BuildParentMap(M, BCO->getTrueExpr(), OV_Opaque); 59 60 M[BCO->getFalseExpr()] = S; 61 BuildParentMap(M, BCO->getFalseExpr(), OV_Transparent); 62 63 break; 64 } 65 case Stmt::OpaqueValueExprClass: 66 if (OVMode == OV_Transparent) { 67 OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(S); 68 M[OVE->getSourceExpr()] = S; 69 BuildParentMap(M, OVE->getSourceExpr(), OV_Transparent); 70 } 71 break; 72 default: 73 for (Stmt::child_range I = S->children(); I; ++I) { 74 if (*I) { 75 M[*I] = S; 76 BuildParentMap(M, *I, OVMode); 77 } 78 } 79 break; 80 } 81 } 82 83 ParentMap::ParentMap(Stmt* S) : Impl(0) { 84 if (S) { 85 MapTy *M = new MapTy(); 86 BuildParentMap(*M, S); 87 Impl = M; 88 } 89 } 90 91 ParentMap::~ParentMap() { 92 delete (MapTy*) Impl; 93 } 94 95 void ParentMap::addStmt(Stmt* S) { 96 if (S) { 97 BuildParentMap(*(MapTy*) Impl, S); 98 } 99 } 100 101 Stmt* ParentMap::getParent(Stmt* S) const { 102 MapTy* M = (MapTy*) Impl; 103 MapTy::iterator I = M->find(S); 104 return I == M->end() ? 0 : I->second; 105 } 106 107 Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const { 108 do { S = getParent(S); } while (S && isa<ParenExpr>(S)); 109 return S; 110 } 111 112 Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const { 113 do { 114 S = getParent(S); 115 } 116 while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S))); 117 118 return S; 119 } 120 121 Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const { 122 do { 123 S = getParent(S); 124 } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S); 125 126 return S; 127 } 128 129 Stmt *ParentMap::getOuterParenParent(Stmt *S) const { 130 Stmt *Paren = 0; 131 while (isa<ParenExpr>(S)) { 132 Paren = S; 133 S = getParent(S); 134 }; 135 return Paren; 136 } 137 138 bool ParentMap::isConsumedExpr(Expr* E) const { 139 Stmt *P = getParent(E); 140 Stmt *DirectChild = E; 141 142 // Ignore parents that are parentheses or casts. 143 while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P))) { 144 DirectChild = P; 145 P = getParent(P); 146 } 147 148 if (!P) 149 return false; 150 151 switch (P->getStmtClass()) { 152 default: 153 return isa<Expr>(P); 154 case Stmt::DeclStmtClass: 155 return true; 156 case Stmt::BinaryOperatorClass: { 157 BinaryOperator *BE = cast<BinaryOperator>(P); 158 // If it is a comma, only the right side is consumed. 159 // If it isn't a comma, both sides are consumed. 160 return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS(); 161 } 162 case Stmt::ForStmtClass: 163 return DirectChild == cast<ForStmt>(P)->getCond(); 164 case Stmt::WhileStmtClass: 165 return DirectChild == cast<WhileStmt>(P)->getCond(); 166 case Stmt::DoStmtClass: 167 return DirectChild == cast<DoStmt>(P)->getCond(); 168 case Stmt::IfStmtClass: 169 return DirectChild == cast<IfStmt>(P)->getCond(); 170 case Stmt::IndirectGotoStmtClass: 171 return DirectChild == cast<IndirectGotoStmt>(P)->getTarget(); 172 case Stmt::SwitchStmtClass: 173 return DirectChild == cast<SwitchStmt>(P)->getCond(); 174 case Stmt::ReturnStmtClass: 175 return true; 176 } 177 } 178 179