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