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 "clang/AST/ExprCXX.h"
00018 #include "llvm/ADT/DenseMap.h"
00019 
00020 using namespace clang;
00021 
00022 typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
00023 
00024 enum OpaqueValueMode {
00025   OV_Transparent,
00026   OV_Opaque
00027 };
00028 
00029 static void BuildParentMap(MapTy& M, Stmt* S,
00030                            OpaqueValueMode OVMode = OV_Transparent) {
00031 
00032   switch (S->getStmtClass()) {
00033   case Stmt::PseudoObjectExprClass: {
00034     assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
00035     PseudoObjectExpr *POE = cast<PseudoObjectExpr>(S);
00036 
00037     // If we are rebuilding the map, clear out any existing state.
00038     if (M[POE->getSyntacticForm()])
00039       for (Stmt::child_range I = S->children(); I; ++I)
00040         M[*I] = nullptr;
00041 
00042     M[POE->getSyntacticForm()] = S;
00043     BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent);
00044 
00045     for (PseudoObjectExpr::semantics_iterator I = POE->semantics_begin(),
00046                                               E = POE->semantics_end();
00047          I != E; ++I) {
00048       M[*I] = S;
00049       BuildParentMap(M, *I, OV_Opaque);
00050     }
00051     break;
00052   }
00053   case Stmt::BinaryConditionalOperatorClass: {
00054     assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
00055     BinaryConditionalOperator *BCO = cast<BinaryConditionalOperator>(S);
00056 
00057     M[BCO->getCommon()] = S;
00058     BuildParentMap(M, BCO->getCommon(), OV_Transparent);
00059 
00060     M[BCO->getCond()] = S;
00061     BuildParentMap(M, BCO->getCond(), OV_Opaque);
00062 
00063     M[BCO->getTrueExpr()] = S;
00064     BuildParentMap(M, BCO->getTrueExpr(), OV_Opaque);
00065 
00066     M[BCO->getFalseExpr()] = S;
00067     BuildParentMap(M, BCO->getFalseExpr(), OV_Transparent);
00068 
00069     break;
00070   }
00071   case Stmt::OpaqueValueExprClass: {
00072     // FIXME: This isn't correct; it assumes that multiple OpaqueValueExprs
00073     // share a single source expression, but in the AST a single
00074     // OpaqueValueExpr is shared among multiple parent expressions.
00075     // The right thing to do is to give the OpaqueValueExpr its syntactic
00076     // parent, then not reassign that when traversing the semantic expressions.
00077     OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(S);
00078     if (OVMode == OV_Transparent || !M[OVE->getSourceExpr()]) {
00079       M[OVE->getSourceExpr()] = S;
00080       BuildParentMap(M, OVE->getSourceExpr(), OV_Transparent);
00081     }
00082     break;
00083   }
00084   default:
00085     for (Stmt::child_range I = S->children(); I; ++I) {
00086       if (*I) {
00087         M[*I] = S;
00088         BuildParentMap(M, *I, OVMode);
00089       }
00090     }
00091     break;
00092   }
00093 }
00094 
00095 ParentMap::ParentMap(Stmt *S) : Impl(nullptr) {
00096   if (S) {
00097     MapTy *M = new MapTy();
00098     BuildParentMap(*M, S);
00099     Impl = M;
00100   }
00101 }
00102 
00103 ParentMap::~ParentMap() {
00104   delete (MapTy*) Impl;
00105 }
00106 
00107 void ParentMap::addStmt(Stmt* S) {
00108   if (S) {
00109     BuildParentMap(*(MapTy*) Impl, S);
00110   }
00111 }
00112 
00113 void ParentMap::setParent(const Stmt *S, const Stmt *Parent) {
00114   assert(S);
00115   assert(Parent);
00116   MapTy *M = reinterpret_cast<MapTy *>(Impl);
00117   M->insert(std::make_pair(const_cast<Stmt *>(S), const_cast<Stmt *>(Parent)));
00118 }
00119 
00120 Stmt* ParentMap::getParent(Stmt* S) const {
00121   MapTy* M = (MapTy*) Impl;
00122   MapTy::iterator I = M->find(S);
00123   return I == M->end() ? nullptr : I->second;
00124 }
00125 
00126 Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
00127   do { S = getParent(S); } while (S && isa<ParenExpr>(S));
00128   return S;
00129 }
00130 
00131 Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
00132   do {
00133     S = getParent(S);
00134   }
00135   while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
00136 
00137   return S;  
00138 }
00139 
00140 Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
00141   do {
00142     S = getParent(S);
00143   } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S);
00144 
00145   return S;
00146 }
00147 
00148 Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
00149   Stmt *Paren = nullptr;
00150   while (isa<ParenExpr>(S)) {
00151     Paren = S;
00152     S = getParent(S);
00153   };
00154   return Paren;
00155 }
00156 
00157 bool ParentMap::isConsumedExpr(Expr* E) const {
00158   Stmt *P = getParent(E);
00159   Stmt *DirectChild = E;
00160 
00161   // Ignore parents that don't guarantee consumption.
00162   while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P) ||
00163                isa<ExprWithCleanups>(P))) {
00164     DirectChild = P;
00165     P = getParent(P);
00166   }
00167 
00168   if (!P)
00169     return false;
00170 
00171   switch (P->getStmtClass()) {
00172     default:
00173       return isa<Expr>(P);
00174     case Stmt::DeclStmtClass:
00175       return true;
00176     case Stmt::BinaryOperatorClass: {
00177       BinaryOperator *BE = cast<BinaryOperator>(P);
00178       // If it is a comma, only the right side is consumed.
00179       // If it isn't a comma, both sides are consumed.
00180       return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
00181     }
00182     case Stmt::ForStmtClass:
00183       return DirectChild == cast<ForStmt>(P)->getCond();
00184     case Stmt::WhileStmtClass:
00185       return DirectChild == cast<WhileStmt>(P)->getCond();
00186     case Stmt::DoStmtClass:
00187       return DirectChild == cast<DoStmt>(P)->getCond();
00188     case Stmt::IfStmtClass:
00189       return DirectChild == cast<IfStmt>(P)->getCond();
00190     case Stmt::IndirectGotoStmtClass:
00191       return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
00192     case Stmt::SwitchStmtClass:
00193       return DirectChild == cast<SwitchStmt>(P)->getCond();
00194     case Stmt::ReturnStmtClass:
00195       return true;
00196   }
00197 }
00198