• 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 "llvm/ADT/DenseMap.h"
18 
19 using namespace clang;
20 
21 typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
22 
BuildParentMap(MapTy & M,Stmt * S)23 static 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   // Also include the source expr tree of an OpaqueValueExpr in the map.
31   if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S))
32     BuildParentMap(M, OVE->getSourceExpr());
33 }
34 
ParentMap(Stmt * S)35 ParentMap::ParentMap(Stmt* S) : Impl(0) {
36   if (S) {
37     MapTy *M = new MapTy();
38     BuildParentMap(*M, S);
39     Impl = M;
40   }
41 }
42 
~ParentMap()43 ParentMap::~ParentMap() {
44   delete (MapTy*) Impl;
45 }
46 
addStmt(Stmt * S)47 void ParentMap::addStmt(Stmt* S) {
48   if (S) {
49     BuildParentMap(*(MapTy*) Impl, S);
50   }
51 }
52 
getParent(Stmt * S) const53 Stmt* ParentMap::getParent(Stmt* S) const {
54   MapTy* M = (MapTy*) Impl;
55   MapTy::iterator I = M->find(S);
56   return I == M->end() ? 0 : I->second;
57 }
58 
getParentIgnoreParens(Stmt * S) const59 Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
60   do { S = getParent(S); } while (S && isa<ParenExpr>(S));
61   return S;
62 }
63 
getParentIgnoreParenCasts(Stmt * S) const64 Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
65   do {
66     S = getParent(S);
67   }
68   while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
69 
70   return S;
71 }
72 
getParentIgnoreParenImpCasts(Stmt * S) const73 Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
74   do {
75     S = getParent(S);
76   } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S);
77 
78   return S;
79 }
80 
getOuterParenParent(Stmt * S) const81 Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
82   Stmt *Paren = 0;
83   while (isa<ParenExpr>(S)) {
84     Paren = S;
85     S = getParent(S);
86   };
87   return Paren;
88 }
89 
isConsumedExpr(Expr * E) const90 bool ParentMap::isConsumedExpr(Expr* E) const {
91   Stmt *P = getParent(E);
92   Stmt *DirectChild = E;
93 
94   // Ignore parents that are parentheses or casts.
95   while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P))) {
96     DirectChild = P;
97     P = getParent(P);
98   }
99 
100   if (!P)
101     return false;
102 
103   switch (P->getStmtClass()) {
104     default:
105       return isa<Expr>(P);
106     case Stmt::DeclStmtClass:
107       return true;
108     case Stmt::BinaryOperatorClass: {
109       BinaryOperator *BE = cast<BinaryOperator>(P);
110       // If it is a comma, only the right side is consumed.
111       // If it isn't a comma, both sides are consumed.
112       return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
113     }
114     case Stmt::ForStmtClass:
115       return DirectChild == cast<ForStmt>(P)->getCond();
116     case Stmt::WhileStmtClass:
117       return DirectChild == cast<WhileStmt>(P)->getCond();
118     case Stmt::DoStmtClass:
119       return DirectChild == cast<DoStmt>(P)->getCond();
120     case Stmt::IfStmtClass:
121       return DirectChild == cast<IfStmt>(P)->getCond();
122     case Stmt::IndirectGotoStmtClass:
123       return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
124     case Stmt::SwitchStmtClass:
125       return DirectChild == cast<SwitchStmt>(P)->getCond();
126     case Stmt::ReturnStmtClass:
127       return true;
128   }
129 }
130 
131