15ffd83dbSDimitry Andric //===- ParentMapContext.cpp - Map of parents using DynTypedNode -*- C++ -*-===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric // Similar to ParentMap.cpp, but generalizes to non-Stmt nodes, which can have 105ffd83dbSDimitry Andric // multiple parents. 115ffd83dbSDimitry Andric // 125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 135ffd83dbSDimitry Andric 145ffd83dbSDimitry Andric #include "clang/AST/ParentMapContext.h" 155ffd83dbSDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 165ffd83dbSDimitry Andric #include "clang/AST/Decl.h" 175ffd83dbSDimitry Andric #include "clang/AST/Expr.h" 185ffd83dbSDimitry Andric #include "clang/AST/TemplateBase.h" 195ffd83dbSDimitry Andric 205ffd83dbSDimitry Andric using namespace clang; 215ffd83dbSDimitry Andric 225ffd83dbSDimitry Andric ParentMapContext::ParentMapContext(ASTContext &Ctx) : ASTCtx(Ctx) {} 235ffd83dbSDimitry Andric 245ffd83dbSDimitry Andric ParentMapContext::~ParentMapContext() = default; 255ffd83dbSDimitry Andric 265ffd83dbSDimitry Andric void ParentMapContext::clear() { Parents.reset(); } 275ffd83dbSDimitry Andric 285ffd83dbSDimitry Andric const Expr *ParentMapContext::traverseIgnored(const Expr *E) const { 295ffd83dbSDimitry Andric return traverseIgnored(const_cast<Expr *>(E)); 305ffd83dbSDimitry Andric } 315ffd83dbSDimitry Andric 325ffd83dbSDimitry Andric Expr *ParentMapContext::traverseIgnored(Expr *E) const { 335ffd83dbSDimitry Andric if (!E) 345ffd83dbSDimitry Andric return nullptr; 355ffd83dbSDimitry Andric 365ffd83dbSDimitry Andric switch (Traversal) { 375ffd83dbSDimitry Andric case TK_AsIs: 385ffd83dbSDimitry Andric return E; 395ffd83dbSDimitry Andric case TK_IgnoreUnlessSpelledInSource: 405ffd83dbSDimitry Andric return E->IgnoreUnlessSpelledInSource(); 415ffd83dbSDimitry Andric } 425ffd83dbSDimitry Andric llvm_unreachable("Invalid Traversal type!"); 435ffd83dbSDimitry Andric } 445ffd83dbSDimitry Andric 455ffd83dbSDimitry Andric DynTypedNode ParentMapContext::traverseIgnored(const DynTypedNode &N) const { 465ffd83dbSDimitry Andric if (const auto *E = N.get<Expr>()) { 475ffd83dbSDimitry Andric return DynTypedNode::create(*traverseIgnored(E)); 485ffd83dbSDimitry Andric } 495ffd83dbSDimitry Andric return N; 505ffd83dbSDimitry Andric } 515ffd83dbSDimitry Andric 52fe6060f1SDimitry Andric template <typename T, typename... U> 53fe6060f1SDimitry Andric std::tuple<bool, DynTypedNodeList, const T *, const U *...> 54fe6060f1SDimitry Andric matchParents(const DynTypedNodeList &NodeList, 55fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap); 56fe6060f1SDimitry Andric 57fe6060f1SDimitry Andric template <typename, typename...> struct MatchParents; 58fe6060f1SDimitry Andric 595ffd83dbSDimitry Andric class ParentMapContext::ParentMap { 60fe6060f1SDimitry Andric 61fe6060f1SDimitry Andric template <typename, typename...> friend struct ::MatchParents; 62fe6060f1SDimitry Andric 635ffd83dbSDimitry Andric /// Contains parents of a node. 64*0fca6ea1SDimitry Andric class ParentVector { 65*0fca6ea1SDimitry Andric public: 66*0fca6ea1SDimitry Andric ParentVector() = default; 67*0fca6ea1SDimitry Andric explicit ParentVector(size_t N, const DynTypedNode &Value) { 68*0fca6ea1SDimitry Andric Items.reserve(N); 69*0fca6ea1SDimitry Andric for (; N > 0; --N) 70*0fca6ea1SDimitry Andric push_back(Value); 71*0fca6ea1SDimitry Andric } 72*0fca6ea1SDimitry Andric bool contains(const DynTypedNode &Value) { 73*0fca6ea1SDimitry Andric return Seen.contains(Value); 74*0fca6ea1SDimitry Andric } 75*0fca6ea1SDimitry Andric void push_back(const DynTypedNode &Value) { 76*0fca6ea1SDimitry Andric if (!Value.getMemoizationData() || Seen.insert(Value).second) 77*0fca6ea1SDimitry Andric Items.push_back(Value); 78*0fca6ea1SDimitry Andric } 79*0fca6ea1SDimitry Andric llvm::ArrayRef<DynTypedNode> view() const { return Items; } 80*0fca6ea1SDimitry Andric private: 81*0fca6ea1SDimitry Andric llvm::SmallVector<DynTypedNode, 2> Items; 82*0fca6ea1SDimitry Andric llvm::SmallDenseSet<DynTypedNode, 2> Seen; 83*0fca6ea1SDimitry Andric }; 845ffd83dbSDimitry Andric 855ffd83dbSDimitry Andric /// Maps from a node to its parents. This is used for nodes that have 865ffd83dbSDimitry Andric /// pointer identity only, which are more common and we can save space by 875ffd83dbSDimitry Andric /// only storing a unique pointer to them. 885ffd83dbSDimitry Andric using ParentMapPointers = 895ffd83dbSDimitry Andric llvm::DenseMap<const void *, 905ffd83dbSDimitry Andric llvm::PointerUnion<const Decl *, const Stmt *, 915ffd83dbSDimitry Andric DynTypedNode *, ParentVector *>>; 925ffd83dbSDimitry Andric 935ffd83dbSDimitry Andric /// Parent map for nodes without pointer identity. We store a full 945ffd83dbSDimitry Andric /// DynTypedNode for all keys. 955ffd83dbSDimitry Andric using ParentMapOtherNodes = 965ffd83dbSDimitry Andric llvm::DenseMap<DynTypedNode, 975ffd83dbSDimitry Andric llvm::PointerUnion<const Decl *, const Stmt *, 985ffd83dbSDimitry Andric DynTypedNode *, ParentVector *>>; 995ffd83dbSDimitry Andric 1005ffd83dbSDimitry Andric ParentMapPointers PointerParents; 1015ffd83dbSDimitry Andric ParentMapOtherNodes OtherParents; 1025ffd83dbSDimitry Andric class ASTVisitor; 1035ffd83dbSDimitry Andric 1045ffd83dbSDimitry Andric static DynTypedNode 1055ffd83dbSDimitry Andric getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) { 1065ffd83dbSDimitry Andric if (const auto *D = U.dyn_cast<const Decl *>()) 1075ffd83dbSDimitry Andric return DynTypedNode::create(*D); 1085ffd83dbSDimitry Andric if (const auto *S = U.dyn_cast<const Stmt *>()) 1095ffd83dbSDimitry Andric return DynTypedNode::create(*S); 1105ffd83dbSDimitry Andric return *U.get<DynTypedNode *>(); 1115ffd83dbSDimitry Andric } 1125ffd83dbSDimitry Andric 1135ffd83dbSDimitry Andric template <typename NodeTy, typename MapTy> 1145ffd83dbSDimitry Andric static DynTypedNodeList getDynNodeFromMap(const NodeTy &Node, 1155ffd83dbSDimitry Andric const MapTy &Map) { 1165ffd83dbSDimitry Andric auto I = Map.find(Node); 1175ffd83dbSDimitry Andric if (I == Map.end()) { 1185ffd83dbSDimitry Andric return llvm::ArrayRef<DynTypedNode>(); 1195ffd83dbSDimitry Andric } 1205ffd83dbSDimitry Andric if (const auto *V = I->second.template dyn_cast<ParentVector *>()) { 121*0fca6ea1SDimitry Andric return V->view(); 1225ffd83dbSDimitry Andric } 1235ffd83dbSDimitry Andric return getSingleDynTypedNodeFromParentMap(I->second); 1245ffd83dbSDimitry Andric } 1255ffd83dbSDimitry Andric 1265ffd83dbSDimitry Andric public: 1275ffd83dbSDimitry Andric ParentMap(ASTContext &Ctx); 1285ffd83dbSDimitry Andric ~ParentMap() { 1295ffd83dbSDimitry Andric for (const auto &Entry : PointerParents) { 1305ffd83dbSDimitry Andric if (Entry.second.is<DynTypedNode *>()) { 1315ffd83dbSDimitry Andric delete Entry.second.get<DynTypedNode *>(); 1325ffd83dbSDimitry Andric } else if (Entry.second.is<ParentVector *>()) { 1335ffd83dbSDimitry Andric delete Entry.second.get<ParentVector *>(); 1345ffd83dbSDimitry Andric } 1355ffd83dbSDimitry Andric } 1365ffd83dbSDimitry Andric for (const auto &Entry : OtherParents) { 1375ffd83dbSDimitry Andric if (Entry.second.is<DynTypedNode *>()) { 1385ffd83dbSDimitry Andric delete Entry.second.get<DynTypedNode *>(); 1395ffd83dbSDimitry Andric } else if (Entry.second.is<ParentVector *>()) { 1405ffd83dbSDimitry Andric delete Entry.second.get<ParentVector *>(); 1415ffd83dbSDimitry Andric } 1425ffd83dbSDimitry Andric } 1435ffd83dbSDimitry Andric } 1445ffd83dbSDimitry Andric 1455ffd83dbSDimitry Andric DynTypedNodeList getParents(TraversalKind TK, const DynTypedNode &Node) { 1465ffd83dbSDimitry Andric if (Node.getNodeKind().hasPointerIdentity()) { 1475ffd83dbSDimitry Andric auto ParentList = 1485ffd83dbSDimitry Andric getDynNodeFromMap(Node.getMemoizationData(), PointerParents); 149fe6060f1SDimitry Andric if (ParentList.size() > 0 && TK == TK_IgnoreUnlessSpelledInSource) { 150fe6060f1SDimitry Andric 151fe6060f1SDimitry Andric const auto *ChildExpr = Node.get<Expr>(); 152fe6060f1SDimitry Andric 153fe6060f1SDimitry Andric { 154fe6060f1SDimitry Andric // Don't match explicit node types because different stdlib 155fe6060f1SDimitry Andric // implementations implement this in different ways and have 156fe6060f1SDimitry Andric // different intermediate nodes. 157fe6060f1SDimitry Andric // Look up 4 levels for a cxxRewrittenBinaryOperator as that is 158fe6060f1SDimitry Andric // enough for the major stdlib implementations. 159fe6060f1SDimitry Andric auto RewrittenBinOpParentsList = ParentList; 160fe6060f1SDimitry Andric int I = 0; 161fe6060f1SDimitry Andric while (ChildExpr && RewrittenBinOpParentsList.size() == 1 && 162fe6060f1SDimitry Andric I++ < 4) { 163fe6060f1SDimitry Andric const auto *S = RewrittenBinOpParentsList[0].get<Stmt>(); 164fe6060f1SDimitry Andric if (!S) 165fe6060f1SDimitry Andric break; 166fe6060f1SDimitry Andric 167fe6060f1SDimitry Andric const auto *RWBO = dyn_cast<CXXRewrittenBinaryOperator>(S); 168fe6060f1SDimitry Andric if (!RWBO) { 169fe6060f1SDimitry Andric RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents); 170fe6060f1SDimitry Andric continue; 171fe6060f1SDimitry Andric } 172fe6060f1SDimitry Andric if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr && 173fe6060f1SDimitry Andric RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr) 174fe6060f1SDimitry Andric break; 175fe6060f1SDimitry Andric return DynTypedNode::create(*RWBO); 176fe6060f1SDimitry Andric } 177fe6060f1SDimitry Andric } 178fe6060f1SDimitry Andric 179fe6060f1SDimitry Andric const auto *ParentExpr = ParentList[0].get<Expr>(); 180fe6060f1SDimitry Andric if (ParentExpr && ChildExpr) 181fe6060f1SDimitry Andric return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr); 182fe6060f1SDimitry Andric 183fe6060f1SDimitry Andric { 184fe6060f1SDimitry Andric auto AncestorNodes = 185fe6060f1SDimitry Andric matchParents<DeclStmt, CXXForRangeStmt>(ParentList, this); 186fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes) && 187fe6060f1SDimitry Andric std::get<const CXXForRangeStmt *>(AncestorNodes) 188fe6060f1SDimitry Andric ->getLoopVarStmt() == 189fe6060f1SDimitry Andric std::get<const DeclStmt *>(AncestorNodes)) 190fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 191fe6060f1SDimitry Andric } 192fe6060f1SDimitry Andric { 193fe6060f1SDimitry Andric auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>( 194fe6060f1SDimitry Andric ParentList, this); 195fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes) && 196fe6060f1SDimitry Andric std::get<const CXXForRangeStmt *>(AncestorNodes) 197fe6060f1SDimitry Andric ->getRangeStmt() == 198fe6060f1SDimitry Andric std::get<const DeclStmt *>(AncestorNodes)) 199fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 200fe6060f1SDimitry Andric } 201fe6060f1SDimitry Andric { 202fe6060f1SDimitry Andric auto AncestorNodes = 203fe6060f1SDimitry Andric matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList, 204fe6060f1SDimitry Andric this); 205fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes)) 206fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 207fe6060f1SDimitry Andric } 208fe6060f1SDimitry Andric { 209fe6060f1SDimitry Andric auto AncestorNodes = 210fe6060f1SDimitry Andric matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>( 211fe6060f1SDimitry Andric ParentList, this); 212fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes)) 213fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 214fe6060f1SDimitry Andric } 2155ffd83dbSDimitry Andric } 2165ffd83dbSDimitry Andric return ParentList; 2175ffd83dbSDimitry Andric } 2185ffd83dbSDimitry Andric return getDynNodeFromMap(Node, OtherParents); 2195ffd83dbSDimitry Andric } 2205ffd83dbSDimitry Andric 2215ffd83dbSDimitry Andric DynTypedNodeList AscendIgnoreUnlessSpelledInSource(const Expr *E, 2225ffd83dbSDimitry Andric const Expr *Child) { 2235ffd83dbSDimitry Andric 2245ffd83dbSDimitry Andric auto ShouldSkip = [](const Expr *E, const Expr *Child) { 2255ffd83dbSDimitry Andric if (isa<ImplicitCastExpr>(E)) 2265ffd83dbSDimitry Andric return true; 2275ffd83dbSDimitry Andric 2285ffd83dbSDimitry Andric if (isa<FullExpr>(E)) 2295ffd83dbSDimitry Andric return true; 2305ffd83dbSDimitry Andric 2315ffd83dbSDimitry Andric if (isa<MaterializeTemporaryExpr>(E)) 2325ffd83dbSDimitry Andric return true; 2335ffd83dbSDimitry Andric 2345ffd83dbSDimitry Andric if (isa<CXXBindTemporaryExpr>(E)) 2355ffd83dbSDimitry Andric return true; 2365ffd83dbSDimitry Andric 2375ffd83dbSDimitry Andric if (isa<ParenExpr>(E)) 2385ffd83dbSDimitry Andric return true; 2395ffd83dbSDimitry Andric 2405ffd83dbSDimitry Andric if (isa<ExprWithCleanups>(E)) 2415ffd83dbSDimitry Andric return true; 2425ffd83dbSDimitry Andric 2435ffd83dbSDimitry Andric auto SR = Child->getSourceRange(); 2445ffd83dbSDimitry Andric 245e8d8bef9SDimitry Andric if (const auto *C = dyn_cast<CXXFunctionalCastExpr>(E)) { 246e8d8bef9SDimitry Andric if (C->getSourceRange() == SR) 247e8d8bef9SDimitry Andric return true; 248e8d8bef9SDimitry Andric } 249e8d8bef9SDimitry Andric 2505ffd83dbSDimitry Andric if (const auto *C = dyn_cast<CXXConstructExpr>(E)) { 251e8d8bef9SDimitry Andric if (C->getSourceRange() == SR || C->isElidable()) 2525ffd83dbSDimitry Andric return true; 2535ffd83dbSDimitry Andric } 2545ffd83dbSDimitry Andric 2555ffd83dbSDimitry Andric if (const auto *C = dyn_cast<CXXMemberCallExpr>(E)) { 2565ffd83dbSDimitry Andric if (C->getSourceRange() == SR) 2575ffd83dbSDimitry Andric return true; 2585ffd83dbSDimitry Andric } 2595ffd83dbSDimitry Andric 2605ffd83dbSDimitry Andric if (const auto *C = dyn_cast<MemberExpr>(E)) { 2615ffd83dbSDimitry Andric if (C->getSourceRange() == SR) 2625ffd83dbSDimitry Andric return true; 2635ffd83dbSDimitry Andric } 2645ffd83dbSDimitry Andric return false; 2655ffd83dbSDimitry Andric }; 2665ffd83dbSDimitry Andric 2675ffd83dbSDimitry Andric while (ShouldSkip(E, Child)) { 2685ffd83dbSDimitry Andric auto It = PointerParents.find(E); 2695ffd83dbSDimitry Andric if (It == PointerParents.end()) 2705ffd83dbSDimitry Andric break; 2715ffd83dbSDimitry Andric const auto *S = It->second.dyn_cast<const Stmt *>(); 2725ffd83dbSDimitry Andric if (!S) { 2735ffd83dbSDimitry Andric if (auto *Vec = It->second.dyn_cast<ParentVector *>()) 274*0fca6ea1SDimitry Andric return Vec->view(); 2755ffd83dbSDimitry Andric return getSingleDynTypedNodeFromParentMap(It->second); 2765ffd83dbSDimitry Andric } 2775ffd83dbSDimitry Andric const auto *P = dyn_cast<Expr>(S); 2785ffd83dbSDimitry Andric if (!P) 2795ffd83dbSDimitry Andric return DynTypedNode::create(*S); 2805ffd83dbSDimitry Andric Child = E; 2815ffd83dbSDimitry Andric E = P; 2825ffd83dbSDimitry Andric } 2835ffd83dbSDimitry Andric return DynTypedNode::create(*E); 2845ffd83dbSDimitry Andric } 2855ffd83dbSDimitry Andric }; 2865ffd83dbSDimitry Andric 287fe6060f1SDimitry Andric template <typename T, typename... U> struct MatchParents { 288fe6060f1SDimitry Andric static std::tuple<bool, DynTypedNodeList, const T *, const U *...> 289fe6060f1SDimitry Andric match(const DynTypedNodeList &NodeList, 290fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap) { 291fe6060f1SDimitry Andric if (const auto *TypedNode = NodeList[0].get<T>()) { 292fe6060f1SDimitry Andric auto NextParentList = 293fe6060f1SDimitry Andric ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents); 294fe6060f1SDimitry Andric if (NextParentList.size() == 1) { 295fe6060f1SDimitry Andric auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap); 296fe6060f1SDimitry Andric if (std::get<bool>(TailTuple)) { 297bdd1243dSDimitry Andric return std::apply( 298bdd1243dSDimitry Andric [TypedNode](bool, DynTypedNodeList NodeList, auto... TupleTail) { 299bdd1243dSDimitry Andric return std::make_tuple(true, NodeList, TypedNode, TupleTail...); 300bdd1243dSDimitry Andric }, 301bdd1243dSDimitry Andric TailTuple); 302fe6060f1SDimitry Andric } 303fe6060f1SDimitry Andric } 304fe6060f1SDimitry Andric } 305fe6060f1SDimitry Andric return std::tuple_cat(std::make_tuple(false, NodeList), 306fe6060f1SDimitry Andric std::tuple<const T *, const U *...>()); 307fe6060f1SDimitry Andric } 308fe6060f1SDimitry Andric }; 309fe6060f1SDimitry Andric 310fe6060f1SDimitry Andric template <typename T> struct MatchParents<T> { 311fe6060f1SDimitry Andric static std::tuple<bool, DynTypedNodeList, const T *> 312fe6060f1SDimitry Andric match(const DynTypedNodeList &NodeList, 313fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap) { 314fe6060f1SDimitry Andric if (const auto *TypedNode = NodeList[0].get<T>()) { 315fe6060f1SDimitry Andric auto NextParentList = 316fe6060f1SDimitry Andric ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents); 317fe6060f1SDimitry Andric if (NextParentList.size() == 1) 318fe6060f1SDimitry Andric return std::make_tuple(true, NodeList, TypedNode); 319fe6060f1SDimitry Andric } 320fe6060f1SDimitry Andric return std::make_tuple(false, NodeList, nullptr); 321fe6060f1SDimitry Andric } 322fe6060f1SDimitry Andric }; 323fe6060f1SDimitry Andric 324fe6060f1SDimitry Andric template <typename T, typename... U> 325fe6060f1SDimitry Andric std::tuple<bool, DynTypedNodeList, const T *, const U *...> 326fe6060f1SDimitry Andric matchParents(const DynTypedNodeList &NodeList, 327fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap) { 328fe6060f1SDimitry Andric return MatchParents<T, U...>::match(NodeList, ParentMap); 329fe6060f1SDimitry Andric } 330fe6060f1SDimitry Andric 3315ffd83dbSDimitry Andric /// Template specializations to abstract away from pointers and TypeLocs. 3325ffd83dbSDimitry Andric /// @{ 3335ffd83dbSDimitry Andric template <typename T> static DynTypedNode createDynTypedNode(const T &Node) { 3345ffd83dbSDimitry Andric return DynTypedNode::create(*Node); 3355ffd83dbSDimitry Andric } 3365ffd83dbSDimitry Andric template <> DynTypedNode createDynTypedNode(const TypeLoc &Node) { 3375ffd83dbSDimitry Andric return DynTypedNode::create(Node); 3385ffd83dbSDimitry Andric } 3395ffd83dbSDimitry Andric template <> 3405ffd83dbSDimitry Andric DynTypedNode createDynTypedNode(const NestedNameSpecifierLoc &Node) { 3415ffd83dbSDimitry Andric return DynTypedNode::create(Node); 3425ffd83dbSDimitry Andric } 34381ad6265SDimitry Andric template <> DynTypedNode createDynTypedNode(const ObjCProtocolLoc &Node) { 34481ad6265SDimitry Andric return DynTypedNode::create(Node); 34581ad6265SDimitry Andric } 3465ffd83dbSDimitry Andric /// @} 3475ffd83dbSDimitry Andric 3485ffd83dbSDimitry Andric /// A \c RecursiveASTVisitor that builds a map from nodes to their 3495ffd83dbSDimitry Andric /// parents as defined by the \c RecursiveASTVisitor. 3505ffd83dbSDimitry Andric /// 3515ffd83dbSDimitry Andric /// Note that the relationship described here is purely in terms of AST 3525ffd83dbSDimitry Andric /// traversal - there are other relationships (for example declaration context) 3535ffd83dbSDimitry Andric /// in the AST that are better modeled by special matchers. 3545ffd83dbSDimitry Andric class ParentMapContext::ParentMap::ASTVisitor 3555ffd83dbSDimitry Andric : public RecursiveASTVisitor<ASTVisitor> { 3565ffd83dbSDimitry Andric public: 3575ffd83dbSDimitry Andric ASTVisitor(ParentMap &Map) : Map(Map) {} 3585ffd83dbSDimitry Andric 3595ffd83dbSDimitry Andric private: 3605ffd83dbSDimitry Andric friend class RecursiveASTVisitor<ASTVisitor>; 3615ffd83dbSDimitry Andric 3625ffd83dbSDimitry Andric using VisitorBase = RecursiveASTVisitor<ASTVisitor>; 3635ffd83dbSDimitry Andric 3645ffd83dbSDimitry Andric bool shouldVisitTemplateInstantiations() const { return true; } 3655ffd83dbSDimitry Andric 3665ffd83dbSDimitry Andric bool shouldVisitImplicitCode() const { return true; } 3675ffd83dbSDimitry Andric 368e8d8bef9SDimitry Andric /// Record the parent of the node we're visiting. 369e8d8bef9SDimitry Andric /// MapNode is the child, the parent is on top of ParentStack. 370e8d8bef9SDimitry Andric /// Parents is the parent storage (either PointerParents or OtherParents). 371e8d8bef9SDimitry Andric template <typename MapNodeTy, typename MapTy> 372e8d8bef9SDimitry Andric void addParent(MapNodeTy MapNode, MapTy *Parents) { 373e8d8bef9SDimitry Andric if (ParentStack.empty()) 374e8d8bef9SDimitry Andric return; 375e8d8bef9SDimitry Andric 3765ffd83dbSDimitry Andric // FIXME: Currently we add the same parent multiple times, but only 3775ffd83dbSDimitry Andric // when no memoization data is available for the type. 3785ffd83dbSDimitry Andric // For example when we visit all subexpressions of template 3795ffd83dbSDimitry Andric // instantiations; this is suboptimal, but benign: the only way to 3805ffd83dbSDimitry Andric // visit those is with hasAncestor / hasParent, and those do not create 3815ffd83dbSDimitry Andric // new matches. 3825ffd83dbSDimitry Andric // The plan is to enable DynTypedNode to be storable in a map or hash 3835ffd83dbSDimitry Andric // map. The main problem there is to implement hash functions / 3845ffd83dbSDimitry Andric // comparison operators for all types that DynTypedNode supports that 3855ffd83dbSDimitry Andric // do not have pointer identity. 3865ffd83dbSDimitry Andric auto &NodeOrVector = (*Parents)[MapNode]; 3875ffd83dbSDimitry Andric if (NodeOrVector.isNull()) { 3885ffd83dbSDimitry Andric if (const auto *D = ParentStack.back().get<Decl>()) 3895ffd83dbSDimitry Andric NodeOrVector = D; 3905ffd83dbSDimitry Andric else if (const auto *S = ParentStack.back().get<Stmt>()) 3915ffd83dbSDimitry Andric NodeOrVector = S; 3925ffd83dbSDimitry Andric else 3935ffd83dbSDimitry Andric NodeOrVector = new DynTypedNode(ParentStack.back()); 3945ffd83dbSDimitry Andric } else { 3955ffd83dbSDimitry Andric if (!NodeOrVector.template is<ParentVector *>()) { 3965ffd83dbSDimitry Andric auto *Vector = new ParentVector( 3975ffd83dbSDimitry Andric 1, getSingleDynTypedNodeFromParentMap(NodeOrVector)); 3985ffd83dbSDimitry Andric delete NodeOrVector.template dyn_cast<DynTypedNode *>(); 3995ffd83dbSDimitry Andric NodeOrVector = Vector; 4005ffd83dbSDimitry Andric } 4015ffd83dbSDimitry Andric 4025ffd83dbSDimitry Andric auto *Vector = NodeOrVector.template get<ParentVector *>(); 4035ffd83dbSDimitry Andric // Skip duplicates for types that have memoization data. 4045ffd83dbSDimitry Andric // We must check that the type has memoization data before calling 405349cc55cSDimitry Andric // llvm::is_contained() because DynTypedNode::operator== can't compare all 4065ffd83dbSDimitry Andric // types. 4075ffd83dbSDimitry Andric bool Found = ParentStack.back().getMemoizationData() && 408349cc55cSDimitry Andric llvm::is_contained(*Vector, ParentStack.back()); 4095ffd83dbSDimitry Andric if (!Found) 4105ffd83dbSDimitry Andric Vector->push_back(ParentStack.back()); 4115ffd83dbSDimitry Andric } 4125ffd83dbSDimitry Andric } 413e8d8bef9SDimitry Andric 41481ad6265SDimitry Andric template <typename T> static bool isNull(T Node) { return !Node; } 41581ad6265SDimitry Andric static bool isNull(ObjCProtocolLoc Node) { return false; } 41681ad6265SDimitry Andric 417e8d8bef9SDimitry Andric template <typename T, typename MapNodeTy, typename BaseTraverseFn, 418e8d8bef9SDimitry Andric typename MapTy> 419e8d8bef9SDimitry Andric bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse, 420e8d8bef9SDimitry Andric MapTy *Parents) { 42181ad6265SDimitry Andric if (isNull(Node)) 422e8d8bef9SDimitry Andric return true; 423e8d8bef9SDimitry Andric addParent(MapNode, Parents); 4245ffd83dbSDimitry Andric ParentStack.push_back(createDynTypedNode(Node)); 4255ffd83dbSDimitry Andric bool Result = BaseTraverse(); 4265ffd83dbSDimitry Andric ParentStack.pop_back(); 4275ffd83dbSDimitry Andric return Result; 4285ffd83dbSDimitry Andric } 4295ffd83dbSDimitry Andric 4305ffd83dbSDimitry Andric bool TraverseDecl(Decl *DeclNode) { 4315ffd83dbSDimitry Andric return TraverseNode( 4325ffd83dbSDimitry Andric DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); }, 4335ffd83dbSDimitry Andric &Map.PointerParents); 4345ffd83dbSDimitry Andric } 4355ffd83dbSDimitry Andric bool TraverseTypeLoc(TypeLoc TypeLocNode) { 4365ffd83dbSDimitry Andric return TraverseNode( 4375ffd83dbSDimitry Andric TypeLocNode, DynTypedNode::create(TypeLocNode), 4385ffd83dbSDimitry Andric [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); }, 4395ffd83dbSDimitry Andric &Map.OtherParents); 4405ffd83dbSDimitry Andric } 4415ffd83dbSDimitry Andric bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) { 4425ffd83dbSDimitry Andric return TraverseNode( 4435ffd83dbSDimitry Andric NNSLocNode, DynTypedNode::create(NNSLocNode), 4445ffd83dbSDimitry Andric [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); }, 4455ffd83dbSDimitry Andric &Map.OtherParents); 4465ffd83dbSDimitry Andric } 447349cc55cSDimitry Andric bool TraverseAttr(Attr *AttrNode) { 448349cc55cSDimitry Andric return TraverseNode( 449349cc55cSDimitry Andric AttrNode, AttrNode, [&] { return VisitorBase::TraverseAttr(AttrNode); }, 450349cc55cSDimitry Andric &Map.PointerParents); 451349cc55cSDimitry Andric } 45281ad6265SDimitry Andric bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) { 45381ad6265SDimitry Andric return TraverseNode( 45481ad6265SDimitry Andric ProtocolLocNode, DynTypedNode::create(ProtocolLocNode), 45581ad6265SDimitry Andric [&] { return VisitorBase::TraverseObjCProtocolLoc(ProtocolLocNode); }, 45681ad6265SDimitry Andric &Map.OtherParents); 45781ad6265SDimitry Andric } 4585ffd83dbSDimitry Andric 459e8d8bef9SDimitry Andric // Using generic TraverseNode for Stmt would prevent data-recursion. 460e8d8bef9SDimitry Andric bool dataTraverseStmtPre(Stmt *StmtNode) { 461e8d8bef9SDimitry Andric addParent(StmtNode, &Map.PointerParents); 462e8d8bef9SDimitry Andric ParentStack.push_back(DynTypedNode::create(*StmtNode)); 463e8d8bef9SDimitry Andric return true; 464e8d8bef9SDimitry Andric } 465e8d8bef9SDimitry Andric bool dataTraverseStmtPost(Stmt *StmtNode) { 466e8d8bef9SDimitry Andric ParentStack.pop_back(); 467e8d8bef9SDimitry Andric return true; 468e8d8bef9SDimitry Andric } 469e8d8bef9SDimitry Andric 4705ffd83dbSDimitry Andric ParentMap ⤅ 4715ffd83dbSDimitry Andric llvm::SmallVector<DynTypedNode, 16> ParentStack; 4725ffd83dbSDimitry Andric }; 4735ffd83dbSDimitry Andric 4745ffd83dbSDimitry Andric ParentMapContext::ParentMap::ParentMap(ASTContext &Ctx) { 4755ffd83dbSDimitry Andric ASTVisitor(*this).TraverseAST(Ctx); 4765ffd83dbSDimitry Andric } 4775ffd83dbSDimitry Andric 4785ffd83dbSDimitry Andric DynTypedNodeList ParentMapContext::getParents(const DynTypedNode &Node) { 4795ffd83dbSDimitry Andric if (!Parents) 4805ffd83dbSDimitry Andric // We build the parent map for the traversal scope (usually whole TU), as 4815ffd83dbSDimitry Andric // hasAncestor can escape any subtree. 4825ffd83dbSDimitry Andric Parents = std::make_unique<ParentMap>(ASTCtx); 4835ffd83dbSDimitry Andric return Parents->getParents(getTraversalKind(), Node); 4845ffd83dbSDimitry Andric } 485