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