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 52*fe6060f1SDimitry Andric template <typename T, typename... U> 53*fe6060f1SDimitry Andric std::tuple<bool, DynTypedNodeList, const T *, const U *...> 54*fe6060f1SDimitry Andric matchParents(const DynTypedNodeList &NodeList, 55*fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap); 56*fe6060f1SDimitry Andric 57*fe6060f1SDimitry Andric template <typename, typename...> struct MatchParents; 58*fe6060f1SDimitry Andric 595ffd83dbSDimitry Andric class ParentMapContext::ParentMap { 60*fe6060f1SDimitry Andric 61*fe6060f1SDimitry Andric template <typename, typename...> friend struct ::MatchParents; 62*fe6060f1SDimitry 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 *>()) { 1025ffd83dbSDimitry Andric return llvm::makeArrayRef(*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); 130*fe6060f1SDimitry Andric if (ParentList.size() > 0 && TK == TK_IgnoreUnlessSpelledInSource) { 131*fe6060f1SDimitry Andric 132*fe6060f1SDimitry Andric const auto *ChildExpr = Node.get<Expr>(); 133*fe6060f1SDimitry Andric 134*fe6060f1SDimitry Andric { 135*fe6060f1SDimitry Andric // Don't match explicit node types because different stdlib 136*fe6060f1SDimitry Andric // implementations implement this in different ways and have 137*fe6060f1SDimitry Andric // different intermediate nodes. 138*fe6060f1SDimitry Andric // Look up 4 levels for a cxxRewrittenBinaryOperator as that is 139*fe6060f1SDimitry Andric // enough for the major stdlib implementations. 140*fe6060f1SDimitry Andric auto RewrittenBinOpParentsList = ParentList; 141*fe6060f1SDimitry Andric int I = 0; 142*fe6060f1SDimitry Andric while (ChildExpr && RewrittenBinOpParentsList.size() == 1 && 143*fe6060f1SDimitry Andric I++ < 4) { 144*fe6060f1SDimitry Andric const auto *S = RewrittenBinOpParentsList[0].get<Stmt>(); 145*fe6060f1SDimitry Andric if (!S) 146*fe6060f1SDimitry Andric break; 147*fe6060f1SDimitry Andric 148*fe6060f1SDimitry Andric const auto *RWBO = dyn_cast<CXXRewrittenBinaryOperator>(S); 149*fe6060f1SDimitry Andric if (!RWBO) { 150*fe6060f1SDimitry Andric RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents); 151*fe6060f1SDimitry Andric continue; 152*fe6060f1SDimitry Andric } 153*fe6060f1SDimitry Andric if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr && 154*fe6060f1SDimitry Andric RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr) 155*fe6060f1SDimitry Andric break; 156*fe6060f1SDimitry Andric return DynTypedNode::create(*RWBO); 157*fe6060f1SDimitry Andric } 158*fe6060f1SDimitry Andric } 159*fe6060f1SDimitry Andric 160*fe6060f1SDimitry Andric const auto *ParentExpr = ParentList[0].get<Expr>(); 161*fe6060f1SDimitry Andric if (ParentExpr && ChildExpr) 162*fe6060f1SDimitry Andric return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr); 163*fe6060f1SDimitry Andric 164*fe6060f1SDimitry Andric { 165*fe6060f1SDimitry Andric auto AncestorNodes = 166*fe6060f1SDimitry Andric matchParents<DeclStmt, CXXForRangeStmt>(ParentList, this); 167*fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes) && 168*fe6060f1SDimitry Andric std::get<const CXXForRangeStmt *>(AncestorNodes) 169*fe6060f1SDimitry Andric ->getLoopVarStmt() == 170*fe6060f1SDimitry Andric std::get<const DeclStmt *>(AncestorNodes)) 171*fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 172*fe6060f1SDimitry Andric } 173*fe6060f1SDimitry Andric { 174*fe6060f1SDimitry Andric auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>( 175*fe6060f1SDimitry Andric ParentList, this); 176*fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes) && 177*fe6060f1SDimitry Andric std::get<const CXXForRangeStmt *>(AncestorNodes) 178*fe6060f1SDimitry Andric ->getRangeStmt() == 179*fe6060f1SDimitry Andric std::get<const DeclStmt *>(AncestorNodes)) 180*fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 181*fe6060f1SDimitry Andric } 182*fe6060f1SDimitry Andric { 183*fe6060f1SDimitry Andric auto AncestorNodes = 184*fe6060f1SDimitry Andric matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList, 185*fe6060f1SDimitry Andric this); 186*fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes)) 187*fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 188*fe6060f1SDimitry Andric } 189*fe6060f1SDimitry Andric { 190*fe6060f1SDimitry Andric auto AncestorNodes = 191*fe6060f1SDimitry Andric matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>( 192*fe6060f1SDimitry Andric ParentList, this); 193*fe6060f1SDimitry Andric if (std::get<bool>(AncestorNodes)) 194*fe6060f1SDimitry Andric return std::get<DynTypedNodeList>(AncestorNodes); 195*fe6060f1SDimitry 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 *>()) 2555ffd83dbSDimitry Andric return llvm::makeArrayRef(*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 268*fe6060f1SDimitry Andric template <typename Tuple, std::size_t... Is> 269*fe6060f1SDimitry Andric auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) { 270*fe6060f1SDimitry Andric return std::make_tuple(std::get<1 + Is>(tuple)...); 271*fe6060f1SDimitry Andric } 272*fe6060f1SDimitry Andric 273*fe6060f1SDimitry Andric template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) { 274*fe6060f1SDimitry Andric return tuple_pop_front_impl( 275*fe6060f1SDimitry Andric tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>()); 276*fe6060f1SDimitry Andric } 277*fe6060f1SDimitry Andric 278*fe6060f1SDimitry Andric template <typename T, typename... U> struct MatchParents { 279*fe6060f1SDimitry Andric static std::tuple<bool, DynTypedNodeList, const T *, const U *...> 280*fe6060f1SDimitry Andric match(const DynTypedNodeList &NodeList, 281*fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap) { 282*fe6060f1SDimitry Andric if (const auto *TypedNode = NodeList[0].get<T>()) { 283*fe6060f1SDimitry Andric auto NextParentList = 284*fe6060f1SDimitry Andric ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents); 285*fe6060f1SDimitry Andric if (NextParentList.size() == 1) { 286*fe6060f1SDimitry Andric auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap); 287*fe6060f1SDimitry Andric if (std::get<bool>(TailTuple)) { 288*fe6060f1SDimitry Andric return std::tuple_cat( 289*fe6060f1SDimitry Andric std::make_tuple(true, std::get<DynTypedNodeList>(TailTuple), 290*fe6060f1SDimitry Andric TypedNode), 291*fe6060f1SDimitry Andric tuple_pop_front(tuple_pop_front(TailTuple))); 292*fe6060f1SDimitry Andric } 293*fe6060f1SDimitry Andric } 294*fe6060f1SDimitry Andric } 295*fe6060f1SDimitry Andric return std::tuple_cat(std::make_tuple(false, NodeList), 296*fe6060f1SDimitry Andric std::tuple<const T *, const U *...>()); 297*fe6060f1SDimitry Andric } 298*fe6060f1SDimitry Andric }; 299*fe6060f1SDimitry Andric 300*fe6060f1SDimitry Andric template <typename T> struct MatchParents<T> { 301*fe6060f1SDimitry Andric static std::tuple<bool, DynTypedNodeList, const T *> 302*fe6060f1SDimitry Andric match(const DynTypedNodeList &NodeList, 303*fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap) { 304*fe6060f1SDimitry Andric if (const auto *TypedNode = NodeList[0].get<T>()) { 305*fe6060f1SDimitry Andric auto NextParentList = 306*fe6060f1SDimitry Andric ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents); 307*fe6060f1SDimitry Andric if (NextParentList.size() == 1) 308*fe6060f1SDimitry Andric return std::make_tuple(true, NodeList, TypedNode); 309*fe6060f1SDimitry Andric } 310*fe6060f1SDimitry Andric return std::make_tuple(false, NodeList, nullptr); 311*fe6060f1SDimitry Andric } 312*fe6060f1SDimitry Andric }; 313*fe6060f1SDimitry Andric 314*fe6060f1SDimitry Andric template <typename T, typename... U> 315*fe6060f1SDimitry Andric std::tuple<bool, DynTypedNodeList, const T *, const U *...> 316*fe6060f1SDimitry Andric matchParents(const DynTypedNodeList &NodeList, 317*fe6060f1SDimitry Andric ParentMapContext::ParentMap *ParentMap) { 318*fe6060f1SDimitry Andric return MatchParents<T, U...>::match(NodeList, ParentMap); 319*fe6060f1SDimitry Andric } 320*fe6060f1SDimitry Andric 3215ffd83dbSDimitry Andric /// Template specializations to abstract away from pointers and TypeLocs. 3225ffd83dbSDimitry Andric /// @{ 3235ffd83dbSDimitry Andric template <typename T> static DynTypedNode createDynTypedNode(const T &Node) { 3245ffd83dbSDimitry Andric return DynTypedNode::create(*Node); 3255ffd83dbSDimitry Andric } 3265ffd83dbSDimitry Andric template <> DynTypedNode createDynTypedNode(const TypeLoc &Node) { 3275ffd83dbSDimitry Andric return DynTypedNode::create(Node); 3285ffd83dbSDimitry Andric } 3295ffd83dbSDimitry Andric template <> 3305ffd83dbSDimitry Andric DynTypedNode createDynTypedNode(const NestedNameSpecifierLoc &Node) { 3315ffd83dbSDimitry Andric return DynTypedNode::create(Node); 3325ffd83dbSDimitry Andric } 3335ffd83dbSDimitry Andric /// @} 3345ffd83dbSDimitry Andric 3355ffd83dbSDimitry Andric /// A \c RecursiveASTVisitor that builds a map from nodes to their 3365ffd83dbSDimitry Andric /// parents as defined by the \c RecursiveASTVisitor. 3375ffd83dbSDimitry Andric /// 3385ffd83dbSDimitry Andric /// Note that the relationship described here is purely in terms of AST 3395ffd83dbSDimitry Andric /// traversal - there are other relationships (for example declaration context) 3405ffd83dbSDimitry Andric /// in the AST that are better modeled by special matchers. 3415ffd83dbSDimitry Andric class ParentMapContext::ParentMap::ASTVisitor 3425ffd83dbSDimitry Andric : public RecursiveASTVisitor<ASTVisitor> { 3435ffd83dbSDimitry Andric public: 3445ffd83dbSDimitry Andric ASTVisitor(ParentMap &Map) : Map(Map) {} 3455ffd83dbSDimitry Andric 3465ffd83dbSDimitry Andric private: 3475ffd83dbSDimitry Andric friend class RecursiveASTVisitor<ASTVisitor>; 3485ffd83dbSDimitry Andric 3495ffd83dbSDimitry Andric using VisitorBase = RecursiveASTVisitor<ASTVisitor>; 3505ffd83dbSDimitry Andric 3515ffd83dbSDimitry Andric bool shouldVisitTemplateInstantiations() const { return true; } 3525ffd83dbSDimitry Andric 3535ffd83dbSDimitry Andric bool shouldVisitImplicitCode() const { return true; } 3545ffd83dbSDimitry Andric 355e8d8bef9SDimitry Andric /// Record the parent of the node we're visiting. 356e8d8bef9SDimitry Andric /// MapNode is the child, the parent is on top of ParentStack. 357e8d8bef9SDimitry Andric /// Parents is the parent storage (either PointerParents or OtherParents). 358e8d8bef9SDimitry Andric template <typename MapNodeTy, typename MapTy> 359e8d8bef9SDimitry Andric void addParent(MapNodeTy MapNode, MapTy *Parents) { 360e8d8bef9SDimitry Andric if (ParentStack.empty()) 361e8d8bef9SDimitry Andric return; 362e8d8bef9SDimitry Andric 3635ffd83dbSDimitry Andric // FIXME: Currently we add the same parent multiple times, but only 3645ffd83dbSDimitry Andric // when no memoization data is available for the type. 3655ffd83dbSDimitry Andric // For example when we visit all subexpressions of template 3665ffd83dbSDimitry Andric // instantiations; this is suboptimal, but benign: the only way to 3675ffd83dbSDimitry Andric // visit those is with hasAncestor / hasParent, and those do not create 3685ffd83dbSDimitry Andric // new matches. 3695ffd83dbSDimitry Andric // The plan is to enable DynTypedNode to be storable in a map or hash 3705ffd83dbSDimitry Andric // map. The main problem there is to implement hash functions / 3715ffd83dbSDimitry Andric // comparison operators for all types that DynTypedNode supports that 3725ffd83dbSDimitry Andric // do not have pointer identity. 3735ffd83dbSDimitry Andric auto &NodeOrVector = (*Parents)[MapNode]; 3745ffd83dbSDimitry Andric if (NodeOrVector.isNull()) { 3755ffd83dbSDimitry Andric if (const auto *D = ParentStack.back().get<Decl>()) 3765ffd83dbSDimitry Andric NodeOrVector = D; 3775ffd83dbSDimitry Andric else if (const auto *S = ParentStack.back().get<Stmt>()) 3785ffd83dbSDimitry Andric NodeOrVector = S; 3795ffd83dbSDimitry Andric else 3805ffd83dbSDimitry Andric NodeOrVector = new DynTypedNode(ParentStack.back()); 3815ffd83dbSDimitry Andric } else { 3825ffd83dbSDimitry Andric if (!NodeOrVector.template is<ParentVector *>()) { 3835ffd83dbSDimitry Andric auto *Vector = new ParentVector( 3845ffd83dbSDimitry Andric 1, getSingleDynTypedNodeFromParentMap(NodeOrVector)); 3855ffd83dbSDimitry Andric delete NodeOrVector.template dyn_cast<DynTypedNode *>(); 3865ffd83dbSDimitry Andric NodeOrVector = Vector; 3875ffd83dbSDimitry Andric } 3885ffd83dbSDimitry Andric 3895ffd83dbSDimitry Andric auto *Vector = NodeOrVector.template get<ParentVector *>(); 3905ffd83dbSDimitry Andric // Skip duplicates for types that have memoization data. 3915ffd83dbSDimitry Andric // We must check that the type has memoization data before calling 3925ffd83dbSDimitry Andric // std::find() because DynTypedNode::operator== can't compare all 3935ffd83dbSDimitry Andric // types. 3945ffd83dbSDimitry Andric bool Found = ParentStack.back().getMemoizationData() && 3955ffd83dbSDimitry Andric std::find(Vector->begin(), Vector->end(), 3965ffd83dbSDimitry Andric ParentStack.back()) != Vector->end(); 3975ffd83dbSDimitry Andric if (!Found) 3985ffd83dbSDimitry Andric Vector->push_back(ParentStack.back()); 3995ffd83dbSDimitry Andric } 4005ffd83dbSDimitry Andric } 401e8d8bef9SDimitry Andric 402e8d8bef9SDimitry Andric template <typename T, typename MapNodeTy, typename BaseTraverseFn, 403e8d8bef9SDimitry Andric typename MapTy> 404e8d8bef9SDimitry Andric bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse, 405e8d8bef9SDimitry Andric MapTy *Parents) { 406e8d8bef9SDimitry Andric if (!Node) 407e8d8bef9SDimitry Andric return true; 408e8d8bef9SDimitry Andric addParent(MapNode, Parents); 4095ffd83dbSDimitry Andric ParentStack.push_back(createDynTypedNode(Node)); 4105ffd83dbSDimitry Andric bool Result = BaseTraverse(); 4115ffd83dbSDimitry Andric ParentStack.pop_back(); 4125ffd83dbSDimitry Andric return Result; 4135ffd83dbSDimitry Andric } 4145ffd83dbSDimitry Andric 4155ffd83dbSDimitry Andric bool TraverseDecl(Decl *DeclNode) { 4165ffd83dbSDimitry Andric return TraverseNode( 4175ffd83dbSDimitry Andric DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); }, 4185ffd83dbSDimitry Andric &Map.PointerParents); 4195ffd83dbSDimitry Andric } 4205ffd83dbSDimitry Andric bool TraverseTypeLoc(TypeLoc TypeLocNode) { 4215ffd83dbSDimitry Andric return TraverseNode( 4225ffd83dbSDimitry Andric TypeLocNode, DynTypedNode::create(TypeLocNode), 4235ffd83dbSDimitry Andric [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); }, 4245ffd83dbSDimitry Andric &Map.OtherParents); 4255ffd83dbSDimitry Andric } 4265ffd83dbSDimitry Andric bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) { 4275ffd83dbSDimitry Andric return TraverseNode( 4285ffd83dbSDimitry Andric NNSLocNode, DynTypedNode::create(NNSLocNode), 4295ffd83dbSDimitry Andric [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); }, 4305ffd83dbSDimitry Andric &Map.OtherParents); 4315ffd83dbSDimitry Andric } 4325ffd83dbSDimitry Andric 433e8d8bef9SDimitry Andric // Using generic TraverseNode for Stmt would prevent data-recursion. 434e8d8bef9SDimitry Andric bool dataTraverseStmtPre(Stmt *StmtNode) { 435e8d8bef9SDimitry Andric addParent(StmtNode, &Map.PointerParents); 436e8d8bef9SDimitry Andric ParentStack.push_back(DynTypedNode::create(*StmtNode)); 437e8d8bef9SDimitry Andric return true; 438e8d8bef9SDimitry Andric } 439e8d8bef9SDimitry Andric bool dataTraverseStmtPost(Stmt *StmtNode) { 440e8d8bef9SDimitry Andric ParentStack.pop_back(); 441e8d8bef9SDimitry Andric return true; 442e8d8bef9SDimitry Andric } 443e8d8bef9SDimitry Andric 4445ffd83dbSDimitry Andric ParentMap ⤅ 4455ffd83dbSDimitry Andric llvm::SmallVector<DynTypedNode, 16> ParentStack; 4465ffd83dbSDimitry Andric }; 4475ffd83dbSDimitry Andric 4485ffd83dbSDimitry Andric ParentMapContext::ParentMap::ParentMap(ASTContext &Ctx) { 4495ffd83dbSDimitry Andric ASTVisitor(*this).TraverseAST(Ctx); 4505ffd83dbSDimitry Andric } 4515ffd83dbSDimitry Andric 4525ffd83dbSDimitry Andric DynTypedNodeList ParentMapContext::getParents(const DynTypedNode &Node) { 4535ffd83dbSDimitry Andric if (!Parents) 4545ffd83dbSDimitry Andric // We build the parent map for the traversal scope (usually whole TU), as 4555ffd83dbSDimitry Andric // hasAncestor can escape any subtree. 4565ffd83dbSDimitry Andric Parents = std::make_unique<ParentMap>(ASTCtx); 4575ffd83dbSDimitry Andric return Parents->getParents(getTraversalKind(), Node); 4585ffd83dbSDimitry Andric } 459