• 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       // Prefer the first time we see this statement in the traversal.
27       // This is important for PseudoObjectExprs.
28       Stmt *&Parent = M[*I];
29       if (!Parent) {
30         Parent = S;
31         BuildParentMap(M, *I);
32       }
33     }
34 
35   // Also include the source expr tree of an OpaqueValueExpr in the map.
36   if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) {
37     M[OVE->getSourceExpr()] = S;
38     BuildParentMap(M, OVE->getSourceExpr());
39   }
40 }
41 
ParentMap(Stmt * S)42 ParentMap::ParentMap(Stmt* S) : Impl(0) {
43   if (S) {
44     MapTy *M = new MapTy();
45     BuildParentMap(*M, S);
46     Impl = M;
47   }
48 }
49 
~ParentMap()50 ParentMap::~ParentMap() {
51   delete (MapTy*) Impl;
52 }
53 
addStmt(Stmt * S)54 void ParentMap::addStmt(Stmt* S) {
55   if (S) {
56     BuildParentMap(*(MapTy*) Impl, S);
57   }
58 }
59 
getParent(Stmt * S) const60 Stmt* ParentMap::getParent(Stmt* S) const {
61   MapTy* M = (MapTy*) Impl;
62   MapTy::iterator I = M->find(S);
63   return I == M->end() ? 0 : I->second;
64 }
65 
getParentIgnoreParens(Stmt * S) const66 Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
67   do { S = getParent(S); } while (S && isa<ParenExpr>(S));
68   return S;
69 }
70 
getParentIgnoreParenCasts(Stmt * S) const71 Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
72   do {
73     S = getParent(S);
74   }
75   while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
76 
77   return S;
78 }
79 
getParentIgnoreParenImpCasts(Stmt * S) const80 Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
81   do {
82     S = getParent(S);
83   } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S);
84 
85   return S;
86 }
87 
getOuterParenParent(Stmt * S) const88 Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
89   Stmt *Paren = 0;
90   while (isa<ParenExpr>(S)) {
91     Paren = S;
92     S = getParent(S);
93   };
94   return Paren;
95 }
96 
isConsumedExpr(Expr * E) const97 bool ParentMap::isConsumedExpr(Expr* E) const {
98   Stmt *P = getParent(E);
99   Stmt *DirectChild = E;
100 
101   // Ignore parents that are parentheses or casts.
102   while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P))) {
103     DirectChild = P;
104     P = getParent(P);
105   }
106 
107   if (!P)
108     return false;
109 
110   switch (P->getStmtClass()) {
111     default:
112       return isa<Expr>(P);
113     case Stmt::DeclStmtClass:
114       return true;
115     case Stmt::BinaryOperatorClass: {
116       BinaryOperator *BE = cast<BinaryOperator>(P);
117       // If it is a comma, only the right side is consumed.
118       // If it isn't a comma, both sides are consumed.
119       return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
120     }
121     case Stmt::ForStmtClass:
122       return DirectChild == cast<ForStmt>(P)->getCond();
123     case Stmt::WhileStmtClass:
124       return DirectChild == cast<WhileStmt>(P)->getCond();
125     case Stmt::DoStmtClass:
126       return DirectChild == cast<DoStmt>(P)->getCond();
127     case Stmt::IfStmtClass:
128       return DirectChild == cast<IfStmt>(P)->getCond();
129     case Stmt::IndirectGotoStmtClass:
130       return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
131     case Stmt::SwitchStmtClass:
132       return DirectChild == cast<SwitchStmt>(P)->getCond();
133     case Stmt::ReturnStmtClass:
134       return true;
135   }
136 }
137 
138