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