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 BuildParentMap(MapTy & M,Stmt * S)23static void BuildParentMap(MapTy& M, Stmt* S) { 24 for (Stmt::child_range I = S->children(); I; ++I) 25 if (*I) { 26 // Prefer the first time we see this statement in the traversal. 27 // This is important for PseudoObjectExprs. 28 Stmt *&Parent = M[*I]; 29 if (!Parent) { 30 Parent = S; 31 BuildParentMap(M, *I); 32 } 33 } 34 35 // Also include the source expr tree of an OpaqueValueExpr in the map. 36 if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) { 37 M[OVE->getSourceExpr()] = S; 38 BuildParentMap(M, OVE->getSourceExpr()); 39 } 40 } 41 ParentMap(Stmt * S)42ParentMap::ParentMap(Stmt* S) : Impl(0) { 43 if (S) { 44 MapTy *M = new MapTy(); 45 BuildParentMap(*M, S); 46 Impl = M; 47 } 48 } 49 ~ParentMap()50ParentMap::~ParentMap() { 51 delete (MapTy*) Impl; 52 } 53 addStmt(Stmt * S)54void ParentMap::addStmt(Stmt* S) { 55 if (S) { 56 BuildParentMap(*(MapTy*) Impl, S); 57 } 58 } 59 getParent(Stmt * S) const60Stmt* ParentMap::getParent(Stmt* S) const { 61 MapTy* M = (MapTy*) Impl; 62 MapTy::iterator I = M->find(S); 63 return I == M->end() ? 0 : I->second; 64 } 65 getParentIgnoreParens(Stmt * S) const66Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const { 67 do { S = getParent(S); } while (S && isa<ParenExpr>(S)); 68 return S; 69 } 70 getParentIgnoreParenCasts(Stmt * S) const71Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const { 72 do { 73 S = getParent(S); 74 } 75 while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S))); 76 77 return S; 78 } 79 getParentIgnoreParenImpCasts(Stmt * S) const80Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const { 81 do { 82 S = getParent(S); 83 } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S); 84 85 return S; 86 } 87 getOuterParenParent(Stmt * S) const88Stmt *ParentMap::getOuterParenParent(Stmt *S) const { 89 Stmt *Paren = 0; 90 while (isa<ParenExpr>(S)) { 91 Paren = S; 92 S = getParent(S); 93 }; 94 return Paren; 95 } 96 isConsumedExpr(Expr * E) const97bool ParentMap::isConsumedExpr(Expr* E) const { 98 Stmt *P = getParent(E); 99 Stmt *DirectChild = E; 100 101 // Ignore parents that are parentheses or casts. 102 while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P))) { 103 DirectChild = P; 104 P = getParent(P); 105 } 106 107 if (!P) 108 return false; 109 110 switch (P->getStmtClass()) { 111 default: 112 return isa<Expr>(P); 113 case Stmt::DeclStmtClass: 114 return true; 115 case Stmt::BinaryOperatorClass: { 116 BinaryOperator *BE = cast<BinaryOperator>(P); 117 // If it is a comma, only the right side is consumed. 118 // If it isn't a comma, both sides are consumed. 119 return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS(); 120 } 121 case Stmt::ForStmtClass: 122 return DirectChild == cast<ForStmt>(P)->getCond(); 123 case Stmt::WhileStmtClass: 124 return DirectChild == cast<WhileStmt>(P)->getCond(); 125 case Stmt::DoStmtClass: 126 return DirectChild == cast<DoStmt>(P)->getCond(); 127 case Stmt::IfStmtClass: 128 return DirectChild == cast<IfStmt>(P)->getCond(); 129 case Stmt::IndirectGotoStmtClass: 130 return DirectChild == cast<IndirectGotoStmt>(P)->getTarget(); 131 case Stmt::SwitchStmtClass: 132 return DirectChild == cast<SwitchStmt>(P)->getCond(); 133 case Stmt::ReturnStmtClass: 134 return true; 135 } 136 } 137 138