1193326Sed//===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- C++ -*-===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file defines the ParentMap class.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#include "clang/AST/ParentMap.h"
15193326Sed#include "clang/AST/Decl.h"
16193326Sed#include "clang/AST/Expr.h"
17193326Sed#include "llvm/ADT/DenseMap.h"
18193326Sed
19193326Sedusing namespace clang;
20193326Sed
21193326Sedtypedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
22193326Sed
23243830Sdimenum OpaqueValueMode {
24243830Sdim  OV_Transparent,
25243830Sdim  OV_Opaque
26243830Sdim};
27243830Sdim
28243830Sdimstatic void BuildParentMap(MapTy& M, Stmt* S,
29243830Sdim                           OpaqueValueMode OVMode = OV_Transparent) {
30243830Sdim
31243830Sdim  switch (S->getStmtClass()) {
32243830Sdim  case Stmt::PseudoObjectExprClass: {
33243830Sdim    assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
34243830Sdim    PseudoObjectExpr *POE = cast<PseudoObjectExpr>(S);
35243830Sdim
36243830Sdim    M[POE->getSyntacticForm()] = S;
37243830Sdim    BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent);
38243830Sdim
39243830Sdim    for (PseudoObjectExpr::semantics_iterator I = POE->semantics_begin(),
40243830Sdim                                              E = POE->semantics_end();
41243830Sdim         I != E; ++I) {
42243830Sdim      M[*I] = S;
43243830Sdim      BuildParentMap(M, *I, OV_Opaque);
44243830Sdim    }
45243830Sdim    break;
46243830Sdim  }
47243830Sdim  case Stmt::BinaryConditionalOperatorClass: {
48243830Sdim    assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
49243830Sdim    BinaryConditionalOperator *BCO = cast<BinaryConditionalOperator>(S);
50243830Sdim
51243830Sdim    M[BCO->getCommon()] = S;
52243830Sdim    BuildParentMap(M, BCO->getCommon(), OV_Transparent);
53243830Sdim
54243830Sdim    M[BCO->getCond()] = S;
55243830Sdim    BuildParentMap(M, BCO->getCond(), OV_Opaque);
56243830Sdim
57243830Sdim    M[BCO->getTrueExpr()] = S;
58243830Sdim    BuildParentMap(M, BCO->getTrueExpr(), OV_Opaque);
59243830Sdim
60243830Sdim    M[BCO->getFalseExpr()] = S;
61243830Sdim    BuildParentMap(M, BCO->getFalseExpr(), OV_Transparent);
62243830Sdim
63243830Sdim    break;
64243830Sdim  }
65243830Sdim  case Stmt::OpaqueValueExprClass:
66243830Sdim    if (OVMode == OV_Transparent) {
67243830Sdim      OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(S);
68243830Sdim      M[OVE->getSourceExpr()] = S;
69243830Sdim      BuildParentMap(M, OVE->getSourceExpr(), OV_Transparent);
70243830Sdim    }
71243830Sdim    break;
72243830Sdim  default:
73243830Sdim    for (Stmt::child_range I = S->children(); I; ++I) {
74243830Sdim      if (*I) {
75243830Sdim        M[*I] = S;
76243830Sdim        BuildParentMap(M, *I, OVMode);
77239462Sdim      }
78193326Sed    }
79243830Sdim    break;
80239462Sdim  }
81193326Sed}
82193326Sed
83193326SedParentMap::ParentMap(Stmt* S) : Impl(0) {
84193326Sed  if (S) {
85193326Sed    MapTy *M = new MapTy();
86193326Sed    BuildParentMap(*M, S);
87198092Srdivacky    Impl = M;
88193326Sed  }
89193326Sed}
90193326Sed
91193326SedParentMap::~ParentMap() {
92193326Sed  delete (MapTy*) Impl;
93193326Sed}
94193326Sed
95218893Sdimvoid ParentMap::addStmt(Stmt* S) {
96218893Sdim  if (S) {
97218893Sdim    BuildParentMap(*(MapTy*) Impl, S);
98218893Sdim  }
99218893Sdim}
100218893Sdim
101193326SedStmt* ParentMap::getParent(Stmt* S) const {
102193326Sed  MapTy* M = (MapTy*) Impl;
103193326Sed  MapTy::iterator I = M->find(S);
104193326Sed  return I == M->end() ? 0 : I->second;
105193326Sed}
106193326Sed
107193326SedStmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
108193326Sed  do { S = getParent(S); } while (S && isa<ParenExpr>(S));
109193326Sed  return S;
110193326Sed}
111193326Sed
112218893SdimStmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
113218893Sdim  do {
114218893Sdim    S = getParent(S);
115218893Sdim  }
116218893Sdim  while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
117218893Sdim
118218893Sdim  return S;
119218893Sdim}
120218893Sdim
121226633SdimStmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
122226633Sdim  do {
123226633Sdim    S = getParent(S);
124226633Sdim  } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S);
125226633Sdim
126226633Sdim  return S;
127226633Sdim}
128226633Sdim
129224145SdimStmt *ParentMap::getOuterParenParent(Stmt *S) const {
130224145Sdim  Stmt *Paren = 0;
131224145Sdim  while (isa<ParenExpr>(S)) {
132224145Sdim    Paren = S;
133224145Sdim    S = getParent(S);
134224145Sdim  };
135224145Sdim  return Paren;
136224145Sdim}
137224145Sdim
138193326Sedbool ParentMap::isConsumedExpr(Expr* E) const {
139193326Sed  Stmt *P = getParent(E);
140193326Sed  Stmt *DirectChild = E;
141198092Srdivacky
142193326Sed  // Ignore parents that are parentheses or casts.
143193326Sed  while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P))) {
144193326Sed    DirectChild = P;
145193326Sed    P = getParent(P);
146193326Sed  }
147198092Srdivacky
148193326Sed  if (!P)
149193326Sed    return false;
150198092Srdivacky
151193326Sed  switch (P->getStmtClass()) {
152193326Sed    default:
153193326Sed      return isa<Expr>(P);
154193326Sed    case Stmt::DeclStmtClass:
155193326Sed      return true;
156193326Sed    case Stmt::BinaryOperatorClass: {
157193326Sed      BinaryOperator *BE = cast<BinaryOperator>(P);
158193326Sed      // If it is a comma, only the right side is consumed.
159193326Sed      // If it isn't a comma, both sides are consumed.
160212904Sdim      return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
161193326Sed    }
162193326Sed    case Stmt::ForStmtClass:
163193326Sed      return DirectChild == cast<ForStmt>(P)->getCond();
164193326Sed    case Stmt::WhileStmtClass:
165198092Srdivacky      return DirectChild == cast<WhileStmt>(P)->getCond();
166193326Sed    case Stmt::DoStmtClass:
167193326Sed      return DirectChild == cast<DoStmt>(P)->getCond();
168193326Sed    case Stmt::IfStmtClass:
169193326Sed      return DirectChild == cast<IfStmt>(P)->getCond();
170193326Sed    case Stmt::IndirectGotoStmtClass:
171193326Sed      return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
172193326Sed    case Stmt::SwitchStmtClass:
173193326Sed      return DirectChild == cast<SwitchStmt>(P)->getCond();
174193326Sed    case Stmt::ReturnStmtClass:
175193326Sed      return true;
176193326Sed  }
177193326Sed}
178193326Sed
179