xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/ParentMap.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file defines the ParentMap class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/AST/ParentMap.h"
140b57cec5SDimitry Andric #include "clang/AST/Decl.h"
150b57cec5SDimitry Andric #include "clang/AST/Expr.h"
160b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
170b57cec5SDimitry Andric #include "clang/AST/StmtObjC.h"
180b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace clang;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric enum OpaqueValueMode {
250b57cec5SDimitry Andric   OV_Transparent,
260b57cec5SDimitry Andric   OV_Opaque
270b57cec5SDimitry Andric };
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric static void BuildParentMap(MapTy& M, Stmt* S,
300b57cec5SDimitry Andric                            OpaqueValueMode OVMode = OV_Transparent) {
310b57cec5SDimitry Andric   if (!S)
320b57cec5SDimitry Andric     return;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric   switch (S->getStmtClass()) {
350b57cec5SDimitry Andric   case Stmt::PseudoObjectExprClass: {
360b57cec5SDimitry Andric     PseudoObjectExpr *POE = cast<PseudoObjectExpr>(S);
370b57cec5SDimitry Andric 
38bdd1243dSDimitry Andric     if (OVMode == OV_Opaque && M[POE->getSyntacticForm()])
39bdd1243dSDimitry Andric       break;
40bdd1243dSDimitry Andric 
410b57cec5SDimitry Andric     // If we are rebuilding the map, clear out any existing state.
420b57cec5SDimitry Andric     if (M[POE->getSyntacticForm()])
430b57cec5SDimitry Andric       for (Stmt *SubStmt : S->children())
440b57cec5SDimitry Andric         M[SubStmt] = nullptr;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric     M[POE->getSyntacticForm()] = S;
470b57cec5SDimitry Andric     BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent);
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric     for (PseudoObjectExpr::semantics_iterator I = POE->semantics_begin(),
500b57cec5SDimitry Andric                                               E = POE->semantics_end();
510b57cec5SDimitry Andric          I != E; ++I) {
520b57cec5SDimitry Andric       M[*I] = S;
530b57cec5SDimitry Andric       BuildParentMap(M, *I, OV_Opaque);
540b57cec5SDimitry Andric     }
550b57cec5SDimitry Andric     break;
560b57cec5SDimitry Andric   }
570b57cec5SDimitry Andric   case Stmt::BinaryConditionalOperatorClass: {
580b57cec5SDimitry Andric     assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
590b57cec5SDimitry Andric     BinaryConditionalOperator *BCO = cast<BinaryConditionalOperator>(S);
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric     M[BCO->getCommon()] = S;
620b57cec5SDimitry Andric     BuildParentMap(M, BCO->getCommon(), OV_Transparent);
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric     M[BCO->getCond()] = S;
650b57cec5SDimitry Andric     BuildParentMap(M, BCO->getCond(), OV_Opaque);
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric     M[BCO->getTrueExpr()] = S;
680b57cec5SDimitry Andric     BuildParentMap(M, BCO->getTrueExpr(), OV_Opaque);
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric     M[BCO->getFalseExpr()] = S;
710b57cec5SDimitry Andric     BuildParentMap(M, BCO->getFalseExpr(), OV_Transparent);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric     break;
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric   case Stmt::OpaqueValueExprClass: {
760b57cec5SDimitry Andric     // FIXME: This isn't correct; it assumes that multiple OpaqueValueExprs
770b57cec5SDimitry Andric     // share a single source expression, but in the AST a single
780b57cec5SDimitry Andric     // OpaqueValueExpr is shared among multiple parent expressions.
790b57cec5SDimitry Andric     // The right thing to do is to give the OpaqueValueExpr its syntactic
800b57cec5SDimitry Andric     // parent, then not reassign that when traversing the semantic expressions.
810b57cec5SDimitry Andric     OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(S);
820b57cec5SDimitry Andric     if (OVMode == OV_Transparent || !M[OVE->getSourceExpr()]) {
830b57cec5SDimitry Andric       M[OVE->getSourceExpr()] = S;
840b57cec5SDimitry Andric       BuildParentMap(M, OVE->getSourceExpr(), OV_Transparent);
850b57cec5SDimitry Andric     }
860b57cec5SDimitry Andric     break;
870b57cec5SDimitry Andric   }
880b57cec5SDimitry Andric   case Stmt::CapturedStmtClass:
890b57cec5SDimitry Andric     for (Stmt *SubStmt : S->children()) {
900b57cec5SDimitry Andric       if (SubStmt) {
910b57cec5SDimitry Andric         M[SubStmt] = S;
920b57cec5SDimitry Andric         BuildParentMap(M, SubStmt, OVMode);
930b57cec5SDimitry Andric       }
940b57cec5SDimitry Andric     }
950b57cec5SDimitry Andric     if (Stmt *SubStmt = cast<CapturedStmt>(S)->getCapturedStmt()) {
960b57cec5SDimitry Andric       M[SubStmt] = S;
970b57cec5SDimitry Andric       BuildParentMap(M, SubStmt, OVMode);
980b57cec5SDimitry Andric     }
990b57cec5SDimitry Andric     break;
1000b57cec5SDimitry Andric   default:
1010b57cec5SDimitry Andric     for (Stmt *SubStmt : S->children()) {
1020b57cec5SDimitry Andric       if (SubStmt) {
1030b57cec5SDimitry Andric         M[SubStmt] = S;
1040b57cec5SDimitry Andric         BuildParentMap(M, SubStmt, OVMode);
1050b57cec5SDimitry Andric       }
1060b57cec5SDimitry Andric     }
1070b57cec5SDimitry Andric     break;
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric ParentMap::ParentMap(Stmt *S) : Impl(nullptr) {
1120b57cec5SDimitry Andric   if (S) {
1130b57cec5SDimitry Andric     MapTy *M = new MapTy();
1140b57cec5SDimitry Andric     BuildParentMap(*M, S);
1150b57cec5SDimitry Andric     Impl = M;
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric ParentMap::~ParentMap() {
1200b57cec5SDimitry Andric   delete (MapTy*) Impl;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric void ParentMap::addStmt(Stmt* S) {
1240b57cec5SDimitry Andric   if (S) {
1250b57cec5SDimitry Andric     BuildParentMap(*(MapTy*) Impl, S);
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric void ParentMap::setParent(const Stmt *S, const Stmt *Parent) {
1300b57cec5SDimitry Andric   assert(S);
1310b57cec5SDimitry Andric   assert(Parent);
1320b57cec5SDimitry Andric   MapTy *M = reinterpret_cast<MapTy *>(Impl);
1330b57cec5SDimitry Andric   M->insert(std::make_pair(const_cast<Stmt *>(S), const_cast<Stmt *>(Parent)));
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric Stmt* ParentMap::getParent(Stmt* S) const {
1370b57cec5SDimitry Andric   MapTy* M = (MapTy*) Impl;
1380eae32dcSDimitry Andric   return M->lookup(S);
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
142*0fca6ea1SDimitry Andric   do {
143*0fca6ea1SDimitry Andric     S = getParent(S);
144*0fca6ea1SDimitry Andric   } while (isa_and_nonnull<ParenExpr>(S));
1450b57cec5SDimitry Andric   return S;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
1490b57cec5SDimitry Andric   do {
1500b57cec5SDimitry Andric     S = getParent(S);
1510b57cec5SDimitry Andric   }
1520b57cec5SDimitry Andric   while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   return S;
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
1580b57cec5SDimitry Andric   do {
1590b57cec5SDimitry Andric     S = getParent(S);
160*0fca6ea1SDimitry Andric   } while (isa_and_nonnull<Expr>(S) &&
161*0fca6ea1SDimitry Andric            cast<Expr>(S)->IgnoreParenImpCasts() != S);
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   return S;
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
1670b57cec5SDimitry Andric   Stmt *Paren = nullptr;
1680b57cec5SDimitry Andric   while (isa<ParenExpr>(S)) {
1690b57cec5SDimitry Andric     Paren = S;
1700b57cec5SDimitry Andric     S = getParent(S);
1710b57cec5SDimitry Andric   };
1720b57cec5SDimitry Andric   return Paren;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric bool ParentMap::isConsumedExpr(Expr* E) const {
1760b57cec5SDimitry Andric   Stmt *P = getParent(E);
1770b57cec5SDimitry Andric   Stmt *DirectChild = E;
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   // Ignore parents that don't guarantee consumption.
1800b57cec5SDimitry Andric   while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P) ||
1810b57cec5SDimitry Andric                isa<FullExpr>(P))) {
1820b57cec5SDimitry Andric     DirectChild = P;
1830b57cec5SDimitry Andric     P = getParent(P);
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   if (!P)
1870b57cec5SDimitry Andric     return false;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   switch (P->getStmtClass()) {
1900b57cec5SDimitry Andric     default:
1910b57cec5SDimitry Andric       return isa<Expr>(P);
1920b57cec5SDimitry Andric     case Stmt::DeclStmtClass:
1930b57cec5SDimitry Andric       return true;
1940b57cec5SDimitry Andric     case Stmt::BinaryOperatorClass: {
1950b57cec5SDimitry Andric       BinaryOperator *BE = cast<BinaryOperator>(P);
1960b57cec5SDimitry Andric       // If it is a comma, only the right side is consumed.
1970b57cec5SDimitry Andric       // If it isn't a comma, both sides are consumed.
1980b57cec5SDimitry Andric       return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
1990b57cec5SDimitry Andric     }
2000b57cec5SDimitry Andric     case Stmt::ForStmtClass:
2010b57cec5SDimitry Andric       return DirectChild == cast<ForStmt>(P)->getCond();
2020b57cec5SDimitry Andric     case Stmt::WhileStmtClass:
2030b57cec5SDimitry Andric       return DirectChild == cast<WhileStmt>(P)->getCond();
2040b57cec5SDimitry Andric     case Stmt::DoStmtClass:
2050b57cec5SDimitry Andric       return DirectChild == cast<DoStmt>(P)->getCond();
2060b57cec5SDimitry Andric     case Stmt::IfStmtClass:
2070b57cec5SDimitry Andric       return DirectChild == cast<IfStmt>(P)->getCond();
2080b57cec5SDimitry Andric     case Stmt::IndirectGotoStmtClass:
2090b57cec5SDimitry Andric       return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
2100b57cec5SDimitry Andric     case Stmt::SwitchStmtClass:
2110b57cec5SDimitry Andric       return DirectChild == cast<SwitchStmt>(P)->getCond();
2120b57cec5SDimitry Andric     case Stmt::ObjCForCollectionStmtClass:
2130b57cec5SDimitry Andric       return DirectChild == cast<ObjCForCollectionStmt>(P)->getCollection();
2140b57cec5SDimitry Andric     case Stmt::ReturnStmtClass:
2150b57cec5SDimitry Andric       return true;
2160b57cec5SDimitry Andric   }
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric 
219