text: //===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- C++ -*-===//
  //
  //                     The LLVM Compiler Infrastructure
  //
  // This file is distributed under the University of Illinois Open Source
  // License. See LICENSE.TXT for details.
  //
  //===----------------------------------------------------------------------===//
  //
  //  This file defines the ParentMap class.
  //
  //===----------------------------------------------------------------------===//
  
  #include "clang/AST/ParentMap.h"
  #include "clang/AST/Decl.h"
  #include "clang/AST/Expr.h"
  #include "clang/AST/ExprCXX.h"
  #include "llvm/ADT/DenseMap.h"
  
  using namespace clang;
  
  typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
  
  enum OpaqueValueMode {
    OV_Transparent,
    OV_Opaque
  };
  
  static void BuildParentMap(MapTy& M, Stmt* S,
                             OpaqueValueMode OVMode = OV_Transparent) {
  
    switch (S->getStmtClass()) {
    case Stmt::PseudoObjectExprClass: {
      assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
      PseudoObjectExpr *POE = cast<PseudoObjectExpr>(S);
  
      // If we are rebuilding the map, clear out any existing state.
      if (M[POE->getSyntacticForm()])
        for (Stmt::child_range I = S->children(); I; ++I)
          M[*I] = nullptr;
  
      M[POE->getSyntacticForm()] = S;
      BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent);
  
      for (PseudoObjectExpr::semantics_iterator I = POE->semantics_begin(),
                                                E = POE->semantics_end();
           I != E; ++I) {
        M[*I] = S;
        BuildParentMap(M, *I, OV_Opaque);
      }
      break;
    }
    case Stmt::BinaryConditionalOperatorClass: {
      assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
      BinaryConditionalOperator *BCO = cast<BinaryConditionalOperator>(S);
  
      M[BCO->getCommon()] = S;
      BuildParentMap(M, BCO->getCommon(), OV_Transparent);
  
      M[BCO->getCond()] = S;
      BuildParentMap(M, BCO->getCond(), OV_Opaque);
  
      M[BCO->getTrueExpr()] = S;
      BuildParentMap(M, BCO->getTrueExpr(), OV_Opaque);
  
      M[BCO->getFalseExpr()] = S;
      BuildParentMap(M, BCO->getFalseExpr(), OV_Transparent);
  
      break;
    }
    case Stmt::OpaqueValueExprClass: {
      // FIXME: This isn't correct; it assumes that multiple OpaqueValueExprs
      // share a single source expression, but in the AST a single
      // OpaqueValueExpr is shared among multiple parent expressions.
      // The right thing to do is to give the OpaqueValueExpr its syntactic
      // parent, then not reassign that when traversing the semantic expressions.
      OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(S);
      if (OVMode == OV_Transparent || !M[OVE->getSourceExpr()]) {
        M[OVE->getSourceExpr()] = S;
        BuildParentMap(M, OVE->getSourceExpr(), OV_Transparent);
      }
      break;
    }
    default:
      for (Stmt::child_range I = S->children(); I; ++I) {
        if (*I) {
          M[*I] = S;
          BuildParentMap(M, *I, OVMode);
        }
      }
      break;
    }
  }
  
  ParentMap::ParentMap(Stmt *S) : Impl(nullptr) {
    if (S) {
      MapTy *M = new MapTy();
      BuildParentMap(*M, S);
      Impl = M;
    }
  }
  
  ParentMap::~ParentMap() {
    delete (MapTy*) Impl;
  }
  
  void ParentMap::addStmt(Stmt* S) {
    if (S) {
      BuildParentMap(*(MapTy*) Impl, S);
    }
  }
  
  void ParentMap::setParent(const Stmt *S, const Stmt *Parent) {
    assert(S);
    assert(Parent);
    MapTy *M = reinterpret_cast<MapTy *>(Impl);
    M->insert(std::make_pair(const_cast<Stmt *>(S), const_cast<Stmt *>(Parent)));
  }
  
  Stmt* ParentMap::getParent(Stmt* S) const {
    MapTy* M = (MapTy*) Impl;
    MapTy::iterator I = M->find(S);
    return I == M->end() ? nullptr : I->second;
  }
  
  Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
    do { S = getParent(S); } while (S && isa<ParenExpr>(S));
    return S;
  }
  
  Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
    do {
      S = getParent(S);
    }
    while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
  
    return S;
  }
  
  Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
    do {
      S = getParent(S);
    } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S);
  
    return S;
  }
  
  Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
    Stmt *Paren = nullptr;
    while (isa<ParenExpr>(S)) {
      Paren = S;
      S = getParent(S);
    };
    return Paren;
  }
  
  bool ParentMap::isConsumedExpr(Expr* E) const {
    Stmt *P = getParent(E);
    Stmt *DirectChild = E;
  
    // Ignore parents that don't guarantee consumption.
    while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P) ||
                 isa<ExprWithCleanups>(P))) {
      DirectChild = P;
      P = getParent(P);
    }
  
    if (!P)
      return false;
  
    switch (P->getStmtClass()) {
      default:
        return isa<Expr>(P);
      case Stmt::DeclStmtClass:
        return true;
      case Stmt::BinaryOperatorClass: {
        BinaryOperator *BE = cast<BinaryOperator>(P);
        // If it is a comma, only the right side is consumed.
        // If it isn't a comma, both sides are consumed.
        return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
      }
      case Stmt::ForStmtClass:
        return DirectChild == cast<ForStmt>(P)->getCond();
      case Stmt::WhileStmtClass:
        return DirectChild == cast<WhileStmt>(P)->getCond();
      case Stmt::DoStmtClass:
        return DirectChild == cast<DoStmt>(P)->getCond();
      case Stmt::IfStmtClass:
        return DirectChild == cast<IfStmt>(P)->getCond();
      case Stmt::IndirectGotoStmtClass:
        return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
      case Stmt::SwitchStmtClass:
        return DirectChild == cast<SwitchStmt>(P)->getCond();
      case Stmt::ReturnStmtClass:
        return true;
    }
  }
  
  