ParentMap.cpp revision 224145
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 "llvm/ADT/DenseMap.h"
18
19using namespace clang;
20
21typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
22
23static void BuildParentMap(MapTy& M, Stmt* S) {
24  for (Stmt::child_range I = S->children(); I; ++I)
25    if (*I) {
26      M[*I] = S;
27      BuildParentMap(M, *I);
28    }
29}
30
31ParentMap::ParentMap(Stmt* S) : Impl(0) {
32  if (S) {
33    MapTy *M = new MapTy();
34    BuildParentMap(*M, S);
35    Impl = M;
36  }
37}
38
39ParentMap::~ParentMap() {
40  delete (MapTy*) Impl;
41}
42
43void ParentMap::addStmt(Stmt* S) {
44  if (S) {
45    BuildParentMap(*(MapTy*) Impl, S);
46  }
47}
48
49Stmt* ParentMap::getParent(Stmt* S) const {
50  MapTy* M = (MapTy*) Impl;
51  MapTy::iterator I = M->find(S);
52  return I == M->end() ? 0 : I->second;
53}
54
55Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
56  do { S = getParent(S); } while (S && isa<ParenExpr>(S));
57  return S;
58}
59
60Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
61  do {
62    S = getParent(S);
63  }
64  while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
65
66  return S;
67}
68
69Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
70  Stmt *Paren = 0;
71  while (isa<ParenExpr>(S)) {
72    Paren = S;
73    S = getParent(S);
74  };
75  return Paren;
76}
77
78bool ParentMap::isConsumedExpr(Expr* E) const {
79  Stmt *P = getParent(E);
80  Stmt *DirectChild = E;
81
82  // Ignore parents that are parentheses or casts.
83  while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P))) {
84    DirectChild = P;
85    P = getParent(P);
86  }
87
88  if (!P)
89    return false;
90
91  switch (P->getStmtClass()) {
92    default:
93      return isa<Expr>(P);
94    case Stmt::DeclStmtClass:
95      return true;
96    case Stmt::BinaryOperatorClass: {
97      BinaryOperator *BE = cast<BinaryOperator>(P);
98      // If it is a comma, only the right side is consumed.
99      // If it isn't a comma, both sides are consumed.
100      return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
101    }
102    case Stmt::ForStmtClass:
103      return DirectChild == cast<ForStmt>(P)->getCond();
104    case Stmt::WhileStmtClass:
105      return DirectChild == cast<WhileStmt>(P)->getCond();
106    case Stmt::DoStmtClass:
107      return DirectChild == cast<DoStmt>(P)->getCond();
108    case Stmt::IfStmtClass:
109      return DirectChild == cast<IfStmt>(P)->getCond();
110    case Stmt::IndirectGotoStmtClass:
111      return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
112    case Stmt::SwitchStmtClass:
113      return DirectChild == cast<SwitchStmt>(P)->getCond();
114    case Stmt::ReturnStmtClass:
115      return true;
116  }
117}
118
119