xref: /minix3/external/bsd/llvm/dist/clang/lib/AST/ParentMap.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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