clang API Documentation

ParentMap.cpp
Go to the documentation of this file.
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