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