• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  //===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- C++ -*-===//
2  //
3  //                     The LLVM Compiler Infrastructure
4  //
5  // This file is distributed under the University of Illinois Open Source
6  // License. See LICENSE.TXT for details.
7  //
8  //===----------------------------------------------------------------------===//
9  //
10  //  This file defines the ParentMap class.
11  //
12  //===----------------------------------------------------------------------===//
13  
14  #include "clang/AST/ParentMap.h"
15  #include "clang/AST/Decl.h"
16  #include "clang/AST/Expr.h"
17  #include "clang/AST/ExprCXX.h"
18  #include "llvm/ADT/DenseMap.h"
19  
20  using namespace clang;
21  
22  typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
23  
24  enum OpaqueValueMode {
25    OV_Transparent,
26    OV_Opaque
27  };
28  
BuildParentMap(MapTy & M,Stmt * S,OpaqueValueMode OVMode=OV_Transparent)29  static void BuildParentMap(MapTy& M, Stmt* S,
30                             OpaqueValueMode OVMode = OV_Transparent) {
31  
32    switch (S->getStmtClass()) {
33    case Stmt::PseudoObjectExprClass: {
34      assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
35      PseudoObjectExpr *POE = cast<PseudoObjectExpr>(S);
36  
37      // If we are rebuilding the map, clear out any existing state.
38      if (M[POE->getSyntacticForm()])
39        for (Stmt::child_range I = S->children(); I; ++I)
40          M[*I] = nullptr;
41  
42      M[POE->getSyntacticForm()] = S;
43      BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent);
44  
45      for (PseudoObjectExpr::semantics_iterator I = POE->semantics_begin(),
46                                                E = POE->semantics_end();
47           I != E; ++I) {
48        M[*I] = S;
49        BuildParentMap(M, *I, OV_Opaque);
50      }
51      break;
52    }
53    case Stmt::BinaryConditionalOperatorClass: {
54      assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
55      BinaryConditionalOperator *BCO = cast<BinaryConditionalOperator>(S);
56  
57      M[BCO->getCommon()] = S;
58      BuildParentMap(M, BCO->getCommon(), OV_Transparent);
59  
60      M[BCO->getCond()] = S;
61      BuildParentMap(M, BCO->getCond(), OV_Opaque);
62  
63      M[BCO->getTrueExpr()] = S;
64      BuildParentMap(M, BCO->getTrueExpr(), OV_Opaque);
65  
66      M[BCO->getFalseExpr()] = S;
67      BuildParentMap(M, BCO->getFalseExpr(), OV_Transparent);
68  
69      break;
70    }
71    case Stmt::OpaqueValueExprClass: {
72      // FIXME: This isn't correct; it assumes that multiple OpaqueValueExprs
73      // share a single source expression, but in the AST a single
74      // OpaqueValueExpr is shared among multiple parent expressions.
75      // The right thing to do is to give the OpaqueValueExpr its syntactic
76      // parent, then not reassign that when traversing the semantic expressions.
77      OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(S);
78      if (OVMode == OV_Transparent || !M[OVE->getSourceExpr()]) {
79        M[OVE->getSourceExpr()] = S;
80        BuildParentMap(M, OVE->getSourceExpr(), OV_Transparent);
81      }
82      break;
83    }
84    default:
85      for (Stmt::child_range I = S->children(); I; ++I) {
86        if (*I) {
87          M[*I] = S;
88          BuildParentMap(M, *I, OVMode);
89        }
90      }
91      break;
92    }
93  }
94  
ParentMap(Stmt * S)95  ParentMap::ParentMap(Stmt *S) : Impl(nullptr) {
96    if (S) {
97      MapTy *M = new MapTy();
98      BuildParentMap(*M, S);
99      Impl = M;
100    }
101  }
102  
~ParentMap()103  ParentMap::~ParentMap() {
104    delete (MapTy*) Impl;
105  }
106  
addStmt(Stmt * S)107  void ParentMap::addStmt(Stmt* S) {
108    if (S) {
109      BuildParentMap(*(MapTy*) Impl, S);
110    }
111  }
112  
setParent(const Stmt * S,const Stmt * Parent)113  void ParentMap::setParent(const Stmt *S, const Stmt *Parent) {
114    assert(S);
115    assert(Parent);
116    MapTy *M = reinterpret_cast<MapTy *>(Impl);
117    M->insert(std::make_pair(const_cast<Stmt *>(S), const_cast<Stmt *>(Parent)));
118  }
119  
getParent(Stmt * S) const120  Stmt* ParentMap::getParent(Stmt* S) const {
121    MapTy* M = (MapTy*) Impl;
122    MapTy::iterator I = M->find(S);
123    return I == M->end() ? nullptr : I->second;
124  }
125  
getParentIgnoreParens(Stmt * S) const126  Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
127    do { S = getParent(S); } while (S && isa<ParenExpr>(S));
128    return S;
129  }
130  
getParentIgnoreParenCasts(Stmt * S) const131  Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
132    do {
133      S = getParent(S);
134    }
135    while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
136  
137    return S;
138  }
139  
getParentIgnoreParenImpCasts(Stmt * S) const140  Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
141    do {
142      S = getParent(S);
143    } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S);
144  
145    return S;
146  }
147  
getOuterParenParent(Stmt * S) const148  Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
149    Stmt *Paren = nullptr;
150    while (isa<ParenExpr>(S)) {
151      Paren = S;
152      S = getParent(S);
153    };
154    return Paren;
155  }
156  
isConsumedExpr(Expr * E) const157  bool ParentMap::isConsumedExpr(Expr* E) const {
158    Stmt *P = getParent(E);
159    Stmt *DirectChild = E;
160  
161    // Ignore parents that don't guarantee consumption.
162    while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P) ||
163                 isa<ExprWithCleanups>(P))) {
164      DirectChild = P;
165      P = getParent(P);
166    }
167  
168    if (!P)
169      return false;
170  
171    switch (P->getStmtClass()) {
172      default:
173        return isa<Expr>(P);
174      case Stmt::DeclStmtClass:
175        return true;
176      case Stmt::BinaryOperatorClass: {
177        BinaryOperator *BE = cast<BinaryOperator>(P);
178        // If it is a comma, only the right side is consumed.
179        // If it isn't a comma, both sides are consumed.
180        return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
181      }
182      case Stmt::ForStmtClass:
183        return DirectChild == cast<ForStmt>(P)->getCond();
184      case Stmt::WhileStmtClass:
185        return DirectChild == cast<WhileStmt>(P)->getCond();
186      case Stmt::DoStmtClass:
187        return DirectChild == cast<DoStmt>(P)->getCond();
188      case Stmt::IfStmtClass:
189        return DirectChild == cast<IfStmt>(P)->getCond();
190      case Stmt::IndirectGotoStmtClass:
191        return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
192      case Stmt::SwitchStmtClass:
193        return DirectChild == cast<SwitchStmt>(P)->getCond();
194      case Stmt::ReturnStmtClass:
195        return true;
196    }
197  }
198  
199