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. 645ffd83dbSDimitry Andric using ParentVector = llvm::SmallVector<DynTypedNode, 2>; 655ffd83dbSDimitry Andric 665ffd83dbSDimitry Andric /// Maps from a node to its parents. This is used for nodes that have 675ffd83dbSDimitry Andric /// pointer identity only, which are more common and we can save space by 685ffd83dbSDimitry Andric /// only storing a unique pointer to them. 695ffd83dbSDimitry Andric using ParentMapPointers = 705ffd83dbSDimitry Andric llvm::DenseMap<const void *, 715ffd83dbSDimitry Andric llvm::PointerUnion<const Decl *, const Stmt *, 725ffd83dbSDimitry Andric DynTypedNode *, ParentVector *>>; 735ffd83dbSDimitry Andric 745ffd83dbSDimitry Andric /// Parent map for nodes without pointer identity. We store a full 755ffd83dbSDimitry Andric /// DynTypedNode for all keys. 765ffd83dbSDimitry Andric using ParentMapOtherNodes = 775ffd83dbSDimitry Andric llvm::DenseMap<DynTypedNode, 785ffd83dbSDimitry Andric llvm::PointerUnion<const Decl *, const Stmt *, 795ffd83dbSDimitry Andric DynTypedNode *, ParentVector *>>; 805ffd83dbSDimitry Andric 815ffd83dbSDimitry Andric ParentMapPointers PointerParents; 825ffd83dbSDimitry Andric ParentMapOtherNodes OtherParents; 835ffd83dbSDimitry Andric class ASTVisitor; 845ffd83dbSDimitry Andric 855ffd83dbSDimitry Andric static DynTypedNode 865ffd83dbSDimitry Andric getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) { 875ffd83dbSDimitry Andric if (const auto *D = U.dyn_cast<const Decl *>()) 885ffd83dbSDimitry Andric return DynTypedNode::create(*D); 895ffd83dbSDimitry Andric if (const auto *S = U.dyn_cast<const Stmt *>()) 905ffd83dbSDimitry Andric return DynTypedNode::create(*S); 915ffd83dbSDimitry Andric return *U.get<DynTypedNode *>(); 925ffd83dbSDimitry Andric } 935ffd83dbSDimitry Andric 945ffd83dbSDimitry Andric template <typename NodeTy, typename MapTy> 955ffd83dbSDimitry Andric static DynTypedNodeList getDynNodeFromMap(const NodeTy &Node, 965ffd83dbSDimitry Andric const MapTy &Map) { 975ffd83dbSDimitry Andric auto I = Map.find(Node); 985ffd83dbSDimitry Andric if (I == Map.end()) { 995ffd83dbSDimitry Andric return llvm::ArrayRef<DynTypedNode>(); 1005ffd83dbSDimitry Andric } 1015ffd83dbSDimitry Andric if (const auto *V = I->second.template dyn_cast<ParentVector *>()) { 102*bdd1243dSDimitry Andric return llvm::ArrayRef(*V); 1035ffd83dbSDimitry Andric } 1045ffd83dbSDimitry Andric return getSingleDynTypedNodeFromParentMap(I->second); 1055ffd83dbSDimitry Andric } 1065ffd83dbSDimitry Andric 1075ffd83dbSDimitry Andric public: 1085ffd83dbSDimitry Andric ParentMap(ASTContext &Ctx); 1095ffd83dbSDimitry Andric ~ParentMap() { 1105ffd83dbSDimitry Andric for (const auto &Entry : PointerParents) { 1115ffd83dbSDimitry Andric if (Entry.second.is<DynTypedNode *>()) { 1125ffd83dbSDimitry Andric delete Entry.second.get<DynTypedNode *>(); 1135ffd83dbSDimitry Andric } else if (Entry.second.is<ParentVector *>()) { 1145ffd83dbSDimitry Andric delete Entry.second.get<ParentVector *>(); 1155ffd83dbSDimitry Andric } 1165ffd83dbSDimitry Andric } 1175ffd83dbSDimitry Andric for (const auto &Entry : OtherParents) { 1185ffd83dbSDimitry Andric if (Entry.second.is<DynTypedNode *>()) { 1195ffd83dbSDimitry Andric delete Entry.second.get<DynTypedNode *>(); 1205ffd83dbSDimitry Andric } else if (Entry.second.is<ParentVector *>()) { 1215ffd83dbSDimitry Andric delete Entry.second.get<ParentVector *>(); 1225ffd83dbSDimitry Andric } 1235ffd83dbSDimitry Andric } 1245ffd83dbSDimitry Andric } 1255ffd83dbSDimitry Andric 1265ffd83dbSDimitry Andric DynTypedNodeList getParents(TraversalKind TK, const DynTypedNode &Node) { 1275ffd83dbSDimitry Andric if (Node.getNodeKind().hasPointerIdentity()) { 1285ffd83dbSDimitry Andric auto ParentList = 1295ffd83dbSDimitry Andric getDynNodeFromMap(Node.getMemoizationData(), PointerParents); 130fe6060f1SDimitry Andric if (ParentList.size() > 0 && TK == TK_IgnoreUnlessSpelledInSource) { 131fe6060f1SDimitry Andric 132fe6060f1SDimitry Andric const auto *ChildExpr = Node.get<Expr>(); 133fe6060f1SDimitry Andric 134fe6060f1SDimitry Andric { 135fe6060f1SDimitry Andric // Don't match explicit node types because different stdlib 136fe6060f1SDimitry Andric // implementations implement this in different ways and have 137fe6060f1SDimitry Andric // different intermediate nodes. 138fe6060f1SDimitry Andric // Look up 4 levels for a cxxRewrittenBinaryOperator as that is 139fe6060f1SDimitry Andric // enough for the major stdlib implementations. 140fe6060f1SDimitry Andric auto RewrittenBinOpParentsList = ParentList; 141fe6060f1SDimitry Andric int I = 0; 142fe6060f1SDimitry Andric while (ChildExpr && RewrittenBinOpParentsList.size() == 1 && 143fe6060f1SDimitry Andric I++ < 4) { 144fe6060f1SDimitry Andric const auto *S = RewrittenBinOpParentsList[0].get<Stmt>(); 145fe6060f1SDimitry Andric if (!S) 146fe6060f1SDimitry Andric break; 147fe6060f1SDimitry Andric 148fe6060f1SDimitry Andric const auto *RWBO = dyn_cast<CXXRewrittenBinaryOperator>(S); 149fe6060f1SDimitry Andric if (!RWBO) { 150fe6060f1SDimitry Andric RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents); 151fe6060f1SDimitry Andric continue; 152fe6060f1SDimitry Andric } 153fe6060f1SDimitry Andric if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr && 154fe6060f1SDimitry Andric RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr) 155fe6060f1SDimitry Andric break; 156fe6060f1SDimitry Andric return DynTypedNode::create(*RWBO); 157fe6060f1SDimitry Andric } 158fe6060f1SDimitry Andric } 159fe6060f1SDimitry Andric 160fe6060f1SDimitry Andric const auto *ParentExpr = ParentList[0].get<Expr>(); 161fe6060f1SDimitry Andric if (ParentExpr && ChildExpr) 162fe6060f1SDimitry Andric return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr); 163fe6060f1SDimitry Andric 164fe6060f1SDimitry Andric { 165fe6060f1SDimitry Andric auto AncestorNodes = 166fe6060f1SDimitry Andric matchParents<DeclStmt, CXXForRangeStmt>(ParentList, this); 167fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes) && 168fe6060f1SDimitry Andric std::get<const CXXForRangeStmt *>(AncestorNodes) 169fe6060f1SDimitry Andric ->getLoopVarStmt() == 170fe6060f1SDimitry Andric std::get<const DeclStmt *>(AncestorNodes)) 171fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 172fe6060f1SDimitry Andric } 173fe6060f1SDimitry Andric { 174fe6060f1SDimitry Andric auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>( 175fe6060f1SDimitry Andric ParentList, this); 176fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes) && 177fe6060f1SDimitry Andric std::get<const CXXForRangeStmt *>(AncestorNodes) 178fe6060f1SDimitry Andric ->getRangeStmt() == 179fe6060f1SDimitry Andric std::get<const DeclStmt *>(AncestorNodes)) 180fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 181fe6060f1SDimitry Andric } 182fe6060f1SDimitry Andric { 183fe6060f1SDimitry Andric auto AncestorNodes = 184fe6060f1SDimitry Andric matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList, 185fe6060f1SDimitry Andric this); 186fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes)) 187fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 188fe6060f1SDimitry Andric } 189fe6060f1SDimitry Andric { 190fe6060f1SDimitry Andric auto AncestorNodes = 191fe6060f1SDimitry Andric matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>( 192fe6060f1SDimitry Andric ParentList, this); 193fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes)) 194fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 195fe6060f1SDimitry Andric } 1965ffd83dbSDimitry Andric } 1975ffd83dbSDimitry Andric return ParentList; 1985ffd83dbSDimitry Andric } 1995ffd83dbSDimitry Andric return getDynNodeFromMap(Node, OtherParents); 2005ffd83dbSDimitry Andric } 2015ffd83dbSDimitry Andric 2025ffd83dbSDimitry Andric DynTypedNodeList AscendIgnoreUnlessSpelledInSource(const Expr *E, 2035ffd83dbSDimitry Andric const Expr *Child) { 2045ffd83dbSDimitry Andric 2055ffd83dbSDimitry Andric auto ShouldSkip = [](const Expr *E, const Expr *Child) { 2065ffd83dbSDimitry Andric if (isa<ImplicitCastExpr>(E)) 2075ffd83dbSDimitry Andric return true; 2085ffd83dbSDimitry Andric 2095ffd83dbSDimitry Andric if (isa<FullExpr>(E)) 2105ffd83dbSDimitry Andric return true; 2115ffd83dbSDimitry Andric 2125ffd83dbSDimitry Andric if (isa<MaterializeTemporaryExpr>(E)) 2135ffd83dbSDimitry Andric return true; 2145ffd83dbSDimitry Andric 2155ffd83dbSDimitry Andric if (isa<CXXBindTemporaryExpr>(E)) 2165ffd83dbSDimitry Andric return true; 2175ffd83dbSDimitry Andric 2185ffd83dbSDimitry Andric if (isa<ParenExpr>(E)) 2195ffd83dbSDimitry Andric return true; 2205ffd83dbSDimitry Andric 2215ffd83dbSDimitry Andric if (isa<ExprWithCleanups>(E)) 2225ffd83dbSDimitry Andric return true; 2235ffd83dbSDimitry Andric 2245ffd83dbSDimitry Andric auto SR = Child->getSourceRange(); 2255ffd83dbSDimitry Andric 226e8d8bef9SDimitry Andric if (const auto *C = dyn_cast<CXXFunctionalCastExpr>(E)) { 227e8d8bef9SDimitry Andric if (C->getSourceRange() == SR) 228e8d8bef9SDimitry Andric return true; 229e8d8bef9SDimitry Andric } 230e8d8bef9SDimitry Andric 2315ffd83dbSDimitry Andric if (const auto *C = dyn_cast<CXXConstructExpr>(E)) { 232e8d8bef9SDimitry Andric if (C->getSourceRange() == SR || C->isElidable()) 2335ffd83dbSDimitry Andric return true; 2345ffd83dbSDimitry Andric } 2355ffd83dbSDimitry Andric 2365ffd83dbSDimitry Andric if (const auto *C = dyn_cast<CXXMemberCallExpr>(E)) { 2375ffd83dbSDimitry Andric if (C->getSourceRange() == SR) 2385ffd83dbSDimitry Andric return true; 2395ffd83dbSDimitry Andric } 2405ffd83dbSDimitry Andric 2415ffd83dbSDimitry Andric if (const auto *C = dyn_cast<MemberExpr>(E)) { 2425ffd83dbSDimitry Andric if (C->getSourceRange() == SR) 2435ffd83dbSDimitry Andric return true; 2445ffd83dbSDimitry Andric } 2455ffd83dbSDimitry Andric return false; 2465ffd83dbSDimitry Andric }; 2475ffd83dbSDimitry Andric 2485ffd83dbSDimitry Andric while (ShouldSkip(E, Child)) { 2495ffd83dbSDimitry Andric auto It = PointerParents.find(E); 2505ffd83dbSDimitry Andric if (It == PointerParents.end()) 2515ffd83dbSDimitry Andric break; 2525ffd83dbSDimitry Andric const auto *S = It->second.dyn_cast<const Stmt *>(); 2535ffd83dbSDimitry Andric if (!S) { 2545ffd83dbSDimitry Andric if (auto *Vec = It->second.dyn_cast<ParentVector *>()) 255*bdd1243dSDimitry Andric return llvm::ArrayRef(*Vec); 2565ffd83dbSDimitry Andric return getSingleDynTypedNodeFromParentMap(It->second); 2575ffd83dbSDimitry Andric } 2585ffd83dbSDimitry Andric const auto *P = dyn_cast<Expr>(S); 2595ffd83dbSDimitry Andric if (!P) 2605ffd83dbSDimitry Andric return DynTypedNode::create(*S); 2615ffd83dbSDimitry Andric Child = E; 2625ffd83dbSDimitry Andric E = P; 2635ffd83dbSDimitry Andric } 2645ffd83dbSDimitry Andric return DynTypedNode::create(*E); 2655ffd83dbSDimitry Andric } 2665ffd83dbSDimitry Andric }; 2675ffd83dbSDimitry Andric 268fe6060f1SDimitry Andric template <typename T, typename... U> struct MatchParents { 269fe6060f1SDimitry Andric static std::tuple<bool, DynTypedNodeList, const T *, const U *...> 270fe6060f1SDimitry Andric match(const DynTypedNodeList &NodeList, 271fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap) { 272fe6060f1SDimitry Andric if (const auto *TypedNode = NodeList[0].get<T>()) { 273fe6060f1SDimitry Andric auto NextParentList = 274fe6060f1SDimitry Andric ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents); 275fe6060f1SDimitry Andric if (NextParentList.size() == 1) { 276fe6060f1SDimitry Andric auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap); 277fe6060f1SDimitry Andric if (std::get<bool>(TailTuple)) { 278*bdd1243dSDimitry Andric return std::apply( 279*bdd1243dSDimitry Andric [TypedNode](bool, DynTypedNodeList NodeList, auto... TupleTail) { 280*bdd1243dSDimitry Andric return std::make_tuple(true, NodeList, TypedNode, TupleTail...); 281*bdd1243dSDimitry Andric }, 282*bdd1243dSDimitry Andric TailTuple); 283fe6060f1SDimitry Andric } 284fe6060f1SDimitry Andric } 285fe6060f1SDimitry Andric } 286fe6060f1SDimitry Andric return std::tuple_cat(std::make_tuple(false, NodeList), 287fe6060f1SDimitry Andric std::tuple<const T *, const U *...>()); 288fe6060f1SDimitry Andric } 289fe6060f1SDimitry Andric }; 290fe6060f1SDimitry Andric 291fe6060f1SDimitry Andric template <typename T> struct MatchParents<T> { 292fe6060f1SDimitry Andric static std::tuple<bool, DynTypedNodeList, const T *> 293fe6060f1SDimitry Andric match(const DynTypedNodeList &NodeList, 294fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap) { 295fe6060f1SDimitry Andric if (const auto *TypedNode = NodeList[0].get<T>()) { 296fe6060f1SDimitry Andric auto NextParentList = 297fe6060f1SDimitry Andric ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents); 298fe6060f1SDimitry Andric if (NextParentList.size() == 1) 299fe6060f1SDimitry Andric return std::make_tuple(true, NodeList, TypedNode); 300fe6060f1SDimitry Andric } 301fe6060f1SDimitry Andric return std::make_tuple(false, NodeList, nullptr); 302fe6060f1SDimitry Andric } 303fe6060f1SDimitry Andric }; 304fe6060f1SDimitry Andric 305fe6060f1SDimitry Andric template <typename T, typename... U> 306fe6060f1SDimitry Andric std::tuple<bool, DynTypedNodeList, const T *, const U *...> 307fe6060f1SDimitry Andric matchParents(const DynTypedNodeList &NodeList, 308fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap) { 309fe6060f1SDimitry Andric return MatchParents<T, U...>::match(NodeList, ParentMap); 310fe6060f1SDimitry Andric } 311fe6060f1SDimitry Andric 3125ffd83dbSDimitry Andric /// Template specializations to abstract away from pointers and TypeLocs. 3135ffd83dbSDimitry Andric /// @{ 3145ffd83dbSDimitry Andric template <typename T> static DynTypedNode createDynTypedNode(const T &Node) { 3155ffd83dbSDimitry Andric return DynTypedNode::create(*Node); 3165ffd83dbSDimitry Andric } 3175ffd83dbSDimitry Andric template <> DynTypedNode createDynTypedNode(const TypeLoc &Node) { 3185ffd83dbSDimitry Andric return DynTypedNode::create(Node); 3195ffd83dbSDimitry Andric } 3205ffd83dbSDimitry Andric template <> 3215ffd83dbSDimitry Andric DynTypedNode createDynTypedNode(const NestedNameSpecifierLoc &Node) { 3225ffd83dbSDimitry Andric return DynTypedNode::create(Node); 3235ffd83dbSDimitry Andric } 32481ad6265SDimitry Andric template <> DynTypedNode createDynTypedNode(const ObjCProtocolLoc &Node) { 32581ad6265SDimitry Andric return DynTypedNode::create(Node); 32681ad6265SDimitry Andric } 3275ffd83dbSDimitry Andric /// @} 3285ffd83dbSDimitry Andric 3295ffd83dbSDimitry Andric /// A \c RecursiveASTVisitor that builds a map from nodes to their 3305ffd83dbSDimitry Andric /// parents as defined by the \c RecursiveASTVisitor. 3315ffd83dbSDimitry Andric /// 3325ffd83dbSDimitry Andric /// Note that the relationship described here is purely in terms of AST 3335ffd83dbSDimitry Andric /// traversal - there are other relationships (for example declaration context) 3345ffd83dbSDimitry Andric /// in the AST that are better modeled by special matchers. 3355ffd83dbSDimitry Andric class ParentMapContext::ParentMap::ASTVisitor 3365ffd83dbSDimitry Andric : public RecursiveASTVisitor<ASTVisitor> { 3375ffd83dbSDimitry Andric public: 3385ffd83dbSDimitry Andric ASTVisitor(ParentMap &Map) : Map(Map) {} 3395ffd83dbSDimitry Andric 3405ffd83dbSDimitry Andric private: 3415ffd83dbSDimitry Andric friend class RecursiveASTVisitor<ASTVisitor>; 3425ffd83dbSDimitry Andric 3435ffd83dbSDimitry Andric using VisitorBase = RecursiveASTVisitor<ASTVisitor>; 3445ffd83dbSDimitry Andric 3455ffd83dbSDimitry Andric bool shouldVisitTemplateInstantiations() const { return true; } 3465ffd83dbSDimitry Andric 3475ffd83dbSDimitry Andric bool shouldVisitImplicitCode() const { return true; } 3485ffd83dbSDimitry Andric 349e8d8bef9SDimitry Andric /// Record the parent of the node we're visiting. 350e8d8bef9SDimitry Andric /// MapNode is the child, the parent is on top of ParentStack. 351e8d8bef9SDimitry Andric /// Parents is the parent storage (either PointerParents or OtherParents). 352e8d8bef9SDimitry Andric template <typename MapNodeTy, typename MapTy> 353e8d8bef9SDimitry Andric void addParent(MapNodeTy MapNode, MapTy *Parents) { 354e8d8bef9SDimitry Andric if (ParentStack.empty()) 355e8d8bef9SDimitry Andric return; 356e8d8bef9SDimitry Andric 3575ffd83dbSDimitry Andric // FIXME: Currently we add the same parent multiple times, but only 3585ffd83dbSDimitry Andric // when no memoization data is available for the type. 3595ffd83dbSDimitry Andric // For example when we visit all subexpressions of template 3605ffd83dbSDimitry Andric // instantiations; this is suboptimal, but benign: the only way to 3615ffd83dbSDimitry Andric // visit those is with hasAncestor / hasParent, and those do not create 3625ffd83dbSDimitry Andric // new matches. 3635ffd83dbSDimitry Andric // The plan is to enable DynTypedNode to be storable in a map or hash 3645ffd83dbSDimitry Andric // map. The main problem there is to implement hash functions / 3655ffd83dbSDimitry Andric // comparison operators for all types that DynTypedNode supports that 3665ffd83dbSDimitry Andric // do not have pointer identity. 3675ffd83dbSDimitry Andric auto &NodeOrVector = (*Parents)[MapNode]; 3685ffd83dbSDimitry Andric if (NodeOrVector.isNull()) { 3695ffd83dbSDimitry Andric if (const auto *D = ParentStack.back().get<Decl>()) 3705ffd83dbSDimitry Andric NodeOrVector = D; 3715ffd83dbSDimitry Andric else if (const auto *S = ParentStack.back().get<Stmt>()) 3725ffd83dbSDimitry Andric NodeOrVector = S; 3735ffd83dbSDimitry Andric else 3745ffd83dbSDimitry Andric NodeOrVector = new DynTypedNode(ParentStack.back()); 3755ffd83dbSDimitry Andric } else { 3765ffd83dbSDimitry Andric if (!NodeOrVector.template is<ParentVector *>()) { 3775ffd83dbSDimitry Andric auto *Vector = new ParentVector( 3785ffd83dbSDimitry Andric 1, getSingleDynTypedNodeFromParentMap(NodeOrVector)); 3795ffd83dbSDimitry Andric delete NodeOrVector.template dyn_cast<DynTypedNode *>(); 3805ffd83dbSDimitry Andric NodeOrVector = Vector; 3815ffd83dbSDimitry Andric } 3825ffd83dbSDimitry Andric 3835ffd83dbSDimitry Andric auto *Vector = NodeOrVector.template get<ParentVector *>(); 3845ffd83dbSDimitry Andric // Skip duplicates for types that have memoization data. 3855ffd83dbSDimitry Andric // We must check that the type has memoization data before calling 386349cc55cSDimitry Andric // llvm::is_contained() because DynTypedNode::operator== can't compare all 3875ffd83dbSDimitry Andric // types. 3885ffd83dbSDimitry Andric bool Found = ParentStack.back().getMemoizationData() && 389349cc55cSDimitry Andric llvm::is_contained(*Vector, ParentStack.back()); 3905ffd83dbSDimitry Andric if (!Found) 3915ffd83dbSDimitry Andric Vector->push_back(ParentStack.back()); 3925ffd83dbSDimitry Andric } 3935ffd83dbSDimitry Andric } 394e8d8bef9SDimitry Andric 39581ad6265SDimitry Andric template <typename T> static bool isNull(T Node) { return !Node; } 39681ad6265SDimitry Andric static bool isNull(ObjCProtocolLoc Node) { return false; } 39781ad6265SDimitry Andric 398e8d8bef9SDimitry Andric template <typename T, typename MapNodeTy, typename BaseTraverseFn, 399e8d8bef9SDimitry Andric typename MapTy> 400e8d8bef9SDimitry Andric bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse, 401e8d8bef9SDimitry Andric MapTy *Parents) { 40281ad6265SDimitry Andric if (isNull(Node)) 403e8d8bef9SDimitry Andric return true; 404e8d8bef9SDimitry Andric addParent(MapNode, Parents); 4055ffd83dbSDimitry Andric ParentStack.push_back(createDynTypedNode(Node)); 4065ffd83dbSDimitry Andric bool Result = BaseTraverse(); 4075ffd83dbSDimitry Andric ParentStack.pop_back(); 4085ffd83dbSDimitry Andric return Result; 4095ffd83dbSDimitry Andric } 4105ffd83dbSDimitry Andric 4115ffd83dbSDimitry Andric bool TraverseDecl(Decl *DeclNode) { 4125ffd83dbSDimitry Andric return TraverseNode( 4135ffd83dbSDimitry Andric DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); }, 4145ffd83dbSDimitry Andric &Map.PointerParents); 4155ffd83dbSDimitry Andric } 4165ffd83dbSDimitry Andric bool TraverseTypeLoc(TypeLoc TypeLocNode) { 4175ffd83dbSDimitry Andric return TraverseNode( 4185ffd83dbSDimitry Andric TypeLocNode, DynTypedNode::create(TypeLocNode), 4195ffd83dbSDimitry Andric [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); }, 4205ffd83dbSDimitry Andric &Map.OtherParents); 4215ffd83dbSDimitry Andric } 4225ffd83dbSDimitry Andric bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) { 4235ffd83dbSDimitry Andric return TraverseNode( 4245ffd83dbSDimitry Andric NNSLocNode, DynTypedNode::create(NNSLocNode), 4255ffd83dbSDimitry Andric [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); }, 4265ffd83dbSDimitry Andric &Map.OtherParents); 4275ffd83dbSDimitry Andric } 428349cc55cSDimitry Andric bool TraverseAttr(Attr *AttrNode) { 429349cc55cSDimitry Andric return TraverseNode( 430349cc55cSDimitry Andric AttrNode, AttrNode, [&] { return VisitorBase::TraverseAttr(AttrNode); }, 431349cc55cSDimitry Andric &Map.PointerParents); 432349cc55cSDimitry Andric } 43381ad6265SDimitry Andric bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) { 43481ad6265SDimitry Andric return TraverseNode( 43581ad6265SDimitry Andric ProtocolLocNode, DynTypedNode::create(ProtocolLocNode), 43681ad6265SDimitry Andric [&] { return VisitorBase::TraverseObjCProtocolLoc(ProtocolLocNode); }, 43781ad6265SDimitry Andric &Map.OtherParents); 43881ad6265SDimitry Andric } 4395ffd83dbSDimitry Andric 440e8d8bef9SDimitry Andric // Using generic TraverseNode for Stmt would prevent data-recursion. 441e8d8bef9SDimitry Andric bool dataTraverseStmtPre(Stmt *StmtNode) { 442e8d8bef9SDimitry Andric addParent(StmtNode, &Map.PointerParents); 443e8d8bef9SDimitry Andric ParentStack.push_back(DynTypedNode::create(*StmtNode)); 444e8d8bef9SDimitry Andric return true; 445e8d8bef9SDimitry Andric } 446e8d8bef9SDimitry Andric bool dataTraverseStmtPost(Stmt *StmtNode) { 447e8d8bef9SDimitry Andric ParentStack.pop_back(); 448e8d8bef9SDimitry Andric return true; 449e8d8bef9SDimitry Andric } 450e8d8bef9SDimitry Andric 4515ffd83dbSDimitry Andric ParentMap ⤅ 4525ffd83dbSDimitry Andric llvm::SmallVector<DynTypedNode, 16> ParentStack; 4535ffd83dbSDimitry Andric }; 4545ffd83dbSDimitry Andric 4555ffd83dbSDimitry Andric ParentMapContext::ParentMap::ParentMap(ASTContext &Ctx) { 4565ffd83dbSDimitry Andric ASTVisitor(*this).TraverseAST(Ctx); 4575ffd83dbSDimitry Andric } 4585ffd83dbSDimitry Andric 4595ffd83dbSDimitry Andric DynTypedNodeList ParentMapContext::getParents(const DynTypedNode &Node) { 4605ffd83dbSDimitry Andric if (!Parents) 4615ffd83dbSDimitry Andric // We build the parent map for the traversal scope (usually whole TU), as 4625ffd83dbSDimitry Andric // hasAncestor can escape any subtree. 4635ffd83dbSDimitry Andric Parents = std::make_unique<ParentMap>(ASTCtx); 4645ffd83dbSDimitry Andric return Parents->getParents(getTraversalKind(), Node); 4655ffd83dbSDimitry Andric } 466