clang API Documentation
00001 //===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the ParentMap class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/AST/ParentMap.h" 00015 #include "clang/AST/Decl.h" 00016 #include "clang/AST/Expr.h" 00017 #include "llvm/ADT/DenseMap.h" 00018 00019 using namespace clang; 00020 00021 typedef llvm::DenseMap<Stmt*, Stmt*> MapTy; 00022 00023 static void BuildParentMap(MapTy& M, Stmt* S) { 00024 for (Stmt::child_range I = S->children(); I; ++I) 00025 if (*I) { 00026 M[*I] = S; 00027 BuildParentMap(M, *I); 00028 } 00029 00030 // Also include the source expr tree of an OpaqueValueExpr in the map. 00031 if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) 00032 BuildParentMap(M, OVE->getSourceExpr()); 00033 } 00034 00035 ParentMap::ParentMap(Stmt* S) : Impl(0) { 00036 if (S) { 00037 MapTy *M = new MapTy(); 00038 BuildParentMap(*M, S); 00039 Impl = M; 00040 } 00041 } 00042 00043 ParentMap::~ParentMap() { 00044 delete (MapTy*) Impl; 00045 } 00046 00047 void ParentMap::addStmt(Stmt* S) { 00048 if (S) { 00049 BuildParentMap(*(MapTy*) Impl, S); 00050 } 00051 } 00052 00053 Stmt* ParentMap::getParent(Stmt* S) const { 00054 MapTy* M = (MapTy*) Impl; 00055 MapTy::iterator I = M->find(S); 00056 return I == M->end() ? 0 : I->second; 00057 } 00058 00059 Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const { 00060 do { S = getParent(S); } while (S && isa<ParenExpr>(S)); 00061 return S; 00062 } 00063 00064 Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const { 00065 do { 00066 S = getParent(S); 00067 } 00068 while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S))); 00069 00070 return S; 00071 } 00072 00073 Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const { 00074 do { 00075 S = getParent(S); 00076 } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S); 00077 00078 return S; 00079 } 00080 00081 Stmt *ParentMap::getOuterParenParent(Stmt *S) const { 00082 Stmt *Paren = 0; 00083 while (isa<ParenExpr>(S)) { 00084 Paren = S; 00085 S = getParent(S); 00086 }; 00087 return Paren; 00088 } 00089 00090 bool ParentMap::isConsumedExpr(Expr* E) const { 00091 Stmt *P = getParent(E); 00092 Stmt *DirectChild = E; 00093 00094 // Ignore parents that are parentheses or casts. 00095 while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P))) { 00096 DirectChild = P; 00097 P = getParent(P); 00098 } 00099 00100 if (!P) 00101 return false; 00102 00103 switch (P->getStmtClass()) { 00104 default: 00105 return isa<Expr>(P); 00106 case Stmt::DeclStmtClass: 00107 return true; 00108 case Stmt::BinaryOperatorClass: { 00109 BinaryOperator *BE = cast<BinaryOperator>(P); 00110 // If it is a comma, only the right side is consumed. 00111 // If it isn't a comma, both sides are consumed. 00112 return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS(); 00113 } 00114 case Stmt::ForStmtClass: 00115 return DirectChild == cast<ForStmt>(P)->getCond(); 00116 case Stmt::WhileStmtClass: 00117 return DirectChild == cast<WhileStmt>(P)->getCond(); 00118 case Stmt::DoStmtClass: 00119 return DirectChild == cast<DoStmt>(P)->getCond(); 00120 case Stmt::IfStmtClass: 00121 return DirectChild == cast<IfStmt>(P)->getCond(); 00122 case Stmt::IndirectGotoStmtClass: 00123 return DirectChild == cast<IndirectGotoStmt>(P)->getTarget(); 00124 case Stmt::SwitchStmtClass: 00125 return DirectChild == cast<SwitchStmt>(P)->getCond(); 00126 case Stmt::ReturnStmtClass: 00127 return true; 00128 } 00129 } 00130