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