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