/src/llvm-project/clang/lib/AST/ParentMapContext.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ParentMapContext.cpp - Map of parents using DynTypedNode -*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // Similar to ParentMap.cpp, but generalizes to non-Stmt nodes, which can have |
10 | | // multiple parents. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "clang/AST/ParentMapContext.h" |
15 | | #include "clang/AST/RecursiveASTVisitor.h" |
16 | | #include "clang/AST/Decl.h" |
17 | | #include "clang/AST/Expr.h" |
18 | | #include "clang/AST/TemplateBase.h" |
19 | | |
20 | | using namespace clang; |
21 | | |
22 | 0 | ParentMapContext::ParentMapContext(ASTContext &Ctx) : ASTCtx(Ctx) {} |
23 | | |
24 | 0 | ParentMapContext::~ParentMapContext() = default; |
25 | | |
26 | 0 | void ParentMapContext::clear() { Parents.reset(); } |
27 | | |
28 | 0 | const Expr *ParentMapContext::traverseIgnored(const Expr *E) const { |
29 | 0 | return traverseIgnored(const_cast<Expr *>(E)); |
30 | 0 | } |
31 | | |
32 | 0 | Expr *ParentMapContext::traverseIgnored(Expr *E) const { |
33 | 0 | if (!E) |
34 | 0 | return nullptr; |
35 | | |
36 | 0 | switch (Traversal) { |
37 | 0 | case TK_AsIs: |
38 | 0 | return E; |
39 | 0 | case TK_IgnoreUnlessSpelledInSource: |
40 | 0 | return E->IgnoreUnlessSpelledInSource(); |
41 | 0 | } |
42 | 0 | llvm_unreachable("Invalid Traversal type!"); |
43 | 0 | } |
44 | | |
45 | 0 | DynTypedNode ParentMapContext::traverseIgnored(const DynTypedNode &N) const { |
46 | 0 | if (const auto *E = N.get<Expr>()) { |
47 | 0 | return DynTypedNode::create(*traverseIgnored(E)); |
48 | 0 | } |
49 | 0 | return N; |
50 | 0 | } |
51 | | |
52 | | template <typename T, typename... U> |
53 | | std::tuple<bool, DynTypedNodeList, const T *, const U *...> |
54 | | matchParents(const DynTypedNodeList &NodeList, |
55 | | ParentMapContext::ParentMap *ParentMap); |
56 | | |
57 | | template <typename, typename...> struct MatchParents; |
58 | | |
59 | | class ParentMapContext::ParentMap { |
60 | | |
61 | | template <typename, typename...> friend struct ::MatchParents; |
62 | | |
63 | | /// Contains parents of a node. |
64 | | using ParentVector = llvm::SmallVector<DynTypedNode, 2>; |
65 | | |
66 | | /// Maps from a node to its parents. This is used for nodes that have |
67 | | /// pointer identity only, which are more common and we can save space by |
68 | | /// only storing a unique pointer to them. |
69 | | using ParentMapPointers = |
70 | | llvm::DenseMap<const void *, |
71 | | llvm::PointerUnion<const Decl *, const Stmt *, |
72 | | DynTypedNode *, ParentVector *>>; |
73 | | |
74 | | /// Parent map for nodes without pointer identity. We store a full |
75 | | /// DynTypedNode for all keys. |
76 | | using ParentMapOtherNodes = |
77 | | llvm::DenseMap<DynTypedNode, |
78 | | llvm::PointerUnion<const Decl *, const Stmt *, |
79 | | DynTypedNode *, ParentVector *>>; |
80 | | |
81 | | ParentMapPointers PointerParents; |
82 | | ParentMapOtherNodes OtherParents; |
83 | | class ASTVisitor; |
84 | | |
85 | | static DynTypedNode |
86 | 0 | getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) { |
87 | 0 | if (const auto *D = U.dyn_cast<const Decl *>()) |
88 | 0 | return DynTypedNode::create(*D); |
89 | 0 | if (const auto *S = U.dyn_cast<const Stmt *>()) |
90 | 0 | return DynTypedNode::create(*S); |
91 | 0 | return *U.get<DynTypedNode *>(); |
92 | 0 | } |
93 | | |
94 | | template <typename NodeTy, typename MapTy> |
95 | | static DynTypedNodeList getDynNodeFromMap(const NodeTy &Node, |
96 | 0 | const MapTy &Map) { |
97 | 0 | auto I = Map.find(Node); |
98 | 0 | if (I == Map.end()) { |
99 | 0 | return llvm::ArrayRef<DynTypedNode>(); |
100 | 0 | } |
101 | 0 | if (const auto *V = I->second.template dyn_cast<ParentVector *>()) { |
102 | 0 | return llvm::ArrayRef(*V); |
103 | 0 | } |
104 | 0 | return getSingleDynTypedNodeFromParentMap(I->second); |
105 | 0 | } Unexecuted instantiation: clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<void const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(void const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&) Unexecuted instantiation: clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::Stmt const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::Stmt const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&) Unexecuted instantiation: clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::DeclStmt const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::DeclStmt const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&) Unexecuted instantiation: clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::CXXForRangeStmt const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::CXXForRangeStmt const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&) Unexecuted instantiation: clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::VarDecl const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::VarDecl const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&) Unexecuted instantiation: clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::CXXMethodDecl const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::CXXMethodDecl const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&) Unexecuted instantiation: clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::CXXRecordDecl const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::CXXRecordDecl const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&) Unexecuted instantiation: clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::LambdaExpr const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::LambdaExpr const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&) Unexecuted instantiation: clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::FunctionTemplateDecl const*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::FunctionTemplateDecl const* const&, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&) Unexecuted instantiation: clang::DynTypedNodeList clang::ParentMapContext::ParentMap::getDynNodeFromMap<clang::DynTypedNode, llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::DynTypedNode const&, llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > const&) |
106 | | |
107 | | public: |
108 | | ParentMap(ASTContext &Ctx); |
109 | 0 | ~ParentMap() { |
110 | 0 | for (const auto &Entry : PointerParents) { |
111 | 0 | if (Entry.second.is<DynTypedNode *>()) { |
112 | 0 | delete Entry.second.get<DynTypedNode *>(); |
113 | 0 | } else if (Entry.second.is<ParentVector *>()) { |
114 | 0 | delete Entry.second.get<ParentVector *>(); |
115 | 0 | } |
116 | 0 | } |
117 | 0 | for (const auto &Entry : OtherParents) { |
118 | 0 | if (Entry.second.is<DynTypedNode *>()) { |
119 | 0 | delete Entry.second.get<DynTypedNode *>(); |
120 | 0 | } else if (Entry.second.is<ParentVector *>()) { |
121 | 0 | delete Entry.second.get<ParentVector *>(); |
122 | 0 | } |
123 | 0 | } |
124 | 0 | } |
125 | | |
126 | 0 | DynTypedNodeList getParents(TraversalKind TK, const DynTypedNode &Node) { |
127 | 0 | if (Node.getNodeKind().hasPointerIdentity()) { |
128 | 0 | auto ParentList = |
129 | 0 | getDynNodeFromMap(Node.getMemoizationData(), PointerParents); |
130 | 0 | if (ParentList.size() > 0 && TK == TK_IgnoreUnlessSpelledInSource) { |
131 | |
|
132 | 0 | const auto *ChildExpr = Node.get<Expr>(); |
133 | |
|
134 | 0 | { |
135 | | // Don't match explicit node types because different stdlib |
136 | | // implementations implement this in different ways and have |
137 | | // different intermediate nodes. |
138 | | // Look up 4 levels for a cxxRewrittenBinaryOperator as that is |
139 | | // enough for the major stdlib implementations. |
140 | 0 | auto RewrittenBinOpParentsList = ParentList; |
141 | 0 | int I = 0; |
142 | 0 | while (ChildExpr && RewrittenBinOpParentsList.size() == 1 && |
143 | 0 | I++ < 4) { |
144 | 0 | const auto *S = RewrittenBinOpParentsList[0].get<Stmt>(); |
145 | 0 | if (!S) |
146 | 0 | break; |
147 | | |
148 | 0 | const auto *RWBO = dyn_cast<CXXRewrittenBinaryOperator>(S); |
149 | 0 | if (!RWBO) { |
150 | 0 | RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents); |
151 | 0 | continue; |
152 | 0 | } |
153 | 0 | if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr && |
154 | 0 | RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr) |
155 | 0 | break; |
156 | 0 | return DynTypedNode::create(*RWBO); |
157 | 0 | } |
158 | 0 | } |
159 | | |
160 | 0 | const auto *ParentExpr = ParentList[0].get<Expr>(); |
161 | 0 | if (ParentExpr && ChildExpr) |
162 | 0 | return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr); |
163 | | |
164 | 0 | { |
165 | 0 | auto AncestorNodes = |
166 | 0 | matchParents<DeclStmt, CXXForRangeStmt>(ParentList, this); |
167 | 0 | if (std::get<bool>(AncestorNodes) && |
168 | 0 | std::get<const CXXForRangeStmt *>(AncestorNodes) |
169 | 0 | ->getLoopVarStmt() == |
170 | 0 | std::get<const DeclStmt *>(AncestorNodes)) |
171 | 0 | return std::get<DynTypedNodeList>(AncestorNodes); |
172 | 0 | } |
173 | 0 | { |
174 | 0 | auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>( |
175 | 0 | ParentList, this); |
176 | 0 | if (std::get<bool>(AncestorNodes) && |
177 | 0 | std::get<const CXXForRangeStmt *>(AncestorNodes) |
178 | 0 | ->getRangeStmt() == |
179 | 0 | std::get<const DeclStmt *>(AncestorNodes)) |
180 | 0 | return std::get<DynTypedNodeList>(AncestorNodes); |
181 | 0 | } |
182 | 0 | { |
183 | 0 | auto AncestorNodes = |
184 | 0 | matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList, |
185 | 0 | this); |
186 | 0 | if (std::get<bool>(AncestorNodes)) |
187 | 0 | return std::get<DynTypedNodeList>(AncestorNodes); |
188 | 0 | } |
189 | 0 | { |
190 | 0 | auto AncestorNodes = |
191 | 0 | matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>( |
192 | 0 | ParentList, this); |
193 | 0 | if (std::get<bool>(AncestorNodes)) |
194 | 0 | return std::get<DynTypedNodeList>(AncestorNodes); |
195 | 0 | } |
196 | 0 | } |
197 | 0 | return ParentList; |
198 | 0 | } |
199 | 0 | return getDynNodeFromMap(Node, OtherParents); |
200 | 0 | } |
201 | | |
202 | | DynTypedNodeList AscendIgnoreUnlessSpelledInSource(const Expr *E, |
203 | 0 | const Expr *Child) { |
204 | |
|
205 | 0 | auto ShouldSkip = [](const Expr *E, const Expr *Child) { |
206 | 0 | if (isa<ImplicitCastExpr>(E)) |
207 | 0 | return true; |
208 | | |
209 | 0 | if (isa<FullExpr>(E)) |
210 | 0 | return true; |
211 | | |
212 | 0 | if (isa<MaterializeTemporaryExpr>(E)) |
213 | 0 | return true; |
214 | | |
215 | 0 | if (isa<CXXBindTemporaryExpr>(E)) |
216 | 0 | return true; |
217 | | |
218 | 0 | if (isa<ParenExpr>(E)) |
219 | 0 | return true; |
220 | | |
221 | 0 | if (isa<ExprWithCleanups>(E)) |
222 | 0 | return true; |
223 | | |
224 | 0 | auto SR = Child->getSourceRange(); |
225 | |
|
226 | 0 | if (const auto *C = dyn_cast<CXXFunctionalCastExpr>(E)) { |
227 | 0 | if (C->getSourceRange() == SR) |
228 | 0 | return true; |
229 | 0 | } |
230 | | |
231 | 0 | if (const auto *C = dyn_cast<CXXConstructExpr>(E)) { |
232 | 0 | if (C->getSourceRange() == SR || C->isElidable()) |
233 | 0 | return true; |
234 | 0 | } |
235 | | |
236 | 0 | if (const auto *C = dyn_cast<CXXMemberCallExpr>(E)) { |
237 | 0 | if (C->getSourceRange() == SR) |
238 | 0 | return true; |
239 | 0 | } |
240 | | |
241 | 0 | if (const auto *C = dyn_cast<MemberExpr>(E)) { |
242 | 0 | if (C->getSourceRange() == SR) |
243 | 0 | return true; |
244 | 0 | } |
245 | 0 | return false; |
246 | 0 | }; |
247 | |
|
248 | 0 | while (ShouldSkip(E, Child)) { |
249 | 0 | auto It = PointerParents.find(E); |
250 | 0 | if (It == PointerParents.end()) |
251 | 0 | break; |
252 | 0 | const auto *S = It->second.dyn_cast<const Stmt *>(); |
253 | 0 | if (!S) { |
254 | 0 | if (auto *Vec = It->second.dyn_cast<ParentVector *>()) |
255 | 0 | return llvm::ArrayRef(*Vec); |
256 | 0 | return getSingleDynTypedNodeFromParentMap(It->second); |
257 | 0 | } |
258 | 0 | const auto *P = dyn_cast<Expr>(S); |
259 | 0 | if (!P) |
260 | 0 | return DynTypedNode::create(*S); |
261 | 0 | Child = E; |
262 | 0 | E = P; |
263 | 0 | } |
264 | 0 | return DynTypedNode::create(*E); |
265 | 0 | } |
266 | | }; |
267 | | |
268 | | template <typename T, typename... U> struct MatchParents { |
269 | | static std::tuple<bool, DynTypedNodeList, const T *, const U *...> |
270 | | match(const DynTypedNodeList &NodeList, |
271 | 0 | ParentMapContext::ParentMap *ParentMap) { |
272 | 0 | if (const auto *TypedNode = NodeList[0].get<T>()) { |
273 | 0 | auto NextParentList = |
274 | 0 | ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents); |
275 | 0 | if (NextParentList.size() == 1) { |
276 | 0 | auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap); |
277 | 0 | if (std::get<bool>(TailTuple)) { |
278 | 0 | return std::apply( |
279 | 0 | [TypedNode](bool, DynTypedNodeList NodeList, auto... TupleTail) { |
280 | 0 | return std::make_tuple(true, NodeList, TypedNode, TupleTail...); |
281 | 0 | }, Unexecuted instantiation: _ZZN12MatchParentsIN5clang8DeclStmtEJNS0_15CXXForRangeStmtEEE5matchERKNS0_16DynTypedNodeListEPNS0_16ParentMapContext9ParentMapEENKUlbS4_DpT_E_clIJPKS2_EEEDabS4_SB_ Unexecuted instantiation: _ZZN12MatchParentsIN5clang7VarDeclEJNS0_8DeclStmtENS0_15CXXForRangeStmtEEE5matchERKNS0_16DynTypedNodeListEPNS0_16ParentMapContext9ParentMapEENKUlbS5_DpT_E_clIJPKS2_PKS3_EEEDabS5_SC_ Unexecuted instantiation: _ZZN12MatchParentsIN5clang13CXXRecordDeclEJNS0_10LambdaExprEEE5matchERKNS0_16DynTypedNodeListEPNS0_16ParentMapContext9ParentMapEENKUlbS4_DpT_E_clIJPKS2_EEEDabS4_SB_ Unexecuted instantiation: _ZZN12MatchParentsIN5clang13CXXMethodDeclEJNS0_13CXXRecordDeclENS0_10LambdaExprEEE5matchERKNS0_16DynTypedNodeListEPNS0_16ParentMapContext9ParentMapEENKUlbS5_DpT_E_clIJPKS2_PKS3_EEEDabS5_SC_ Unexecuted instantiation: _ZZN12MatchParentsIN5clang20FunctionTemplateDeclEJNS0_13CXXRecordDeclENS0_10LambdaExprEEE5matchERKNS0_16DynTypedNodeListEPNS0_16ParentMapContext9ParentMapEENKUlbS5_DpT_E_clIJPKS2_PKS3_EEEDabS5_SC_ |
282 | 0 | TailTuple); |
283 | 0 | } |
284 | 0 | } |
285 | 0 | } |
286 | 0 | return std::tuple_cat(std::make_tuple(false, NodeList), |
287 | 0 | std::tuple<const T *, const U *...>()); |
288 | 0 | } Unexecuted instantiation: MatchParents<clang::DeclStmt, clang::CXXForRangeStmt>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) Unexecuted instantiation: MatchParents<clang::VarDecl, clang::DeclStmt, clang::CXXForRangeStmt>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) Unexecuted instantiation: MatchParents<clang::CXXMethodDecl, clang::CXXRecordDecl, clang::LambdaExpr>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) Unexecuted instantiation: MatchParents<clang::CXXRecordDecl, clang::LambdaExpr>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) Unexecuted instantiation: MatchParents<clang::FunctionTemplateDecl, clang::CXXRecordDecl, clang::LambdaExpr>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) |
289 | | }; |
290 | | |
291 | | template <typename T> struct MatchParents<T> { |
292 | | static std::tuple<bool, DynTypedNodeList, const T *> |
293 | | match(const DynTypedNodeList &NodeList, |
294 | 0 | ParentMapContext::ParentMap *ParentMap) { |
295 | 0 | if (const auto *TypedNode = NodeList[0].get<T>()) { |
296 | 0 | auto NextParentList = |
297 | 0 | ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents); |
298 | 0 | if (NextParentList.size() == 1) |
299 | 0 | return std::make_tuple(true, NodeList, TypedNode); |
300 | 0 | } |
301 | 0 | return std::make_tuple(false, NodeList, nullptr); |
302 | 0 | } Unexecuted instantiation: MatchParents<clang::CXXForRangeStmt>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) Unexecuted instantiation: MatchParents<clang::LambdaExpr>::match(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) |
303 | | }; |
304 | | |
305 | | template <typename T, typename... U> |
306 | | std::tuple<bool, DynTypedNodeList, const T *, const U *...> |
307 | | matchParents(const DynTypedNodeList &NodeList, |
308 | 0 | ParentMapContext::ParentMap *ParentMap) { |
309 | 0 | return MatchParents<T, U...>::match(NodeList, ParentMap); |
310 | 0 | } Unexecuted instantiation: std::__1::tuple<bool, clang::DynTypedNodeList, clang::DeclStmt const*, clang::CXXForRangeStmt const*> matchParents<clang::DeclStmt, clang::CXXForRangeStmt>(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) Unexecuted instantiation: std::__1::tuple<bool, clang::DynTypedNodeList, clang::VarDecl const*, clang::DeclStmt const*, clang::CXXForRangeStmt const*> matchParents<clang::VarDecl, clang::DeclStmt, clang::CXXForRangeStmt>(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) Unexecuted instantiation: std::__1::tuple<bool, clang::DynTypedNodeList, clang::CXXMethodDecl const*, clang::CXXRecordDecl const*, clang::LambdaExpr const*> matchParents<clang::CXXMethodDecl, clang::CXXRecordDecl, clang::LambdaExpr>(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) Unexecuted instantiation: std::__1::tuple<bool, clang::DynTypedNodeList, clang::FunctionTemplateDecl const*, clang::CXXRecordDecl const*, clang::LambdaExpr const*> matchParents<clang::FunctionTemplateDecl, clang::CXXRecordDecl, clang::LambdaExpr>(clang::DynTypedNodeList const&, clang::ParentMapContext::ParentMap*) |
311 | | |
312 | | /// Template specializations to abstract away from pointers and TypeLocs. |
313 | | /// @{ |
314 | 0 | template <typename T> static DynTypedNode createDynTypedNode(const T &Node) { |
315 | 0 | return DynTypedNode::create(*Node); |
316 | 0 | } Unexecuted instantiation: ParentMapContext.cpp:clang::DynTypedNode createDynTypedNode<clang::Decl*>(clang::Decl* const&) Unexecuted instantiation: ParentMapContext.cpp:clang::DynTypedNode createDynTypedNode<clang::Attr*>(clang::Attr* const&) |
317 | 0 | template <> DynTypedNode createDynTypedNode(const TypeLoc &Node) { |
318 | 0 | return DynTypedNode::create(Node); |
319 | 0 | } |
320 | | template <> |
321 | 0 | DynTypedNode createDynTypedNode(const NestedNameSpecifierLoc &Node) { |
322 | 0 | return DynTypedNode::create(Node); |
323 | 0 | } |
324 | 0 | template <> DynTypedNode createDynTypedNode(const ObjCProtocolLoc &Node) { |
325 | 0 | return DynTypedNode::create(Node); |
326 | 0 | } |
327 | | /// @} |
328 | | |
329 | | /// A \c RecursiveASTVisitor that builds a map from nodes to their |
330 | | /// parents as defined by the \c RecursiveASTVisitor. |
331 | | /// |
332 | | /// Note that the relationship described here is purely in terms of AST |
333 | | /// traversal - there are other relationships (for example declaration context) |
334 | | /// in the AST that are better modeled by special matchers. |
335 | | class ParentMapContext::ParentMap::ASTVisitor |
336 | | : public RecursiveASTVisitor<ASTVisitor> { |
337 | | public: |
338 | 0 | ASTVisitor(ParentMap &Map) : Map(Map) {} |
339 | | |
340 | | private: |
341 | | friend class RecursiveASTVisitor<ASTVisitor>; |
342 | | |
343 | | using VisitorBase = RecursiveASTVisitor<ASTVisitor>; |
344 | | |
345 | 0 | bool shouldVisitTemplateInstantiations() const { return true; } |
346 | | |
347 | 0 | bool shouldVisitImplicitCode() const { return true; } |
348 | | |
349 | | /// Record the parent of the node we're visiting. |
350 | | /// MapNode is the child, the parent is on top of ParentStack. |
351 | | /// Parents is the parent storage (either PointerParents or OtherParents). |
352 | | template <typename MapNodeTy, typename MapTy> |
353 | 0 | void addParent(MapNodeTy MapNode, MapTy *Parents) { |
354 | 0 | if (ParentStack.empty()) |
355 | 0 | return; |
356 | | |
357 | | // FIXME: Currently we add the same parent multiple times, but only |
358 | | // when no memoization data is available for the type. |
359 | | // For example when we visit all subexpressions of template |
360 | | // instantiations; this is suboptimal, but benign: the only way to |
361 | | // visit those is with hasAncestor / hasParent, and those do not create |
362 | | // new matches. |
363 | | // The plan is to enable DynTypedNode to be storable in a map or hash |
364 | | // map. The main problem there is to implement hash functions / |
365 | | // comparison operators for all types that DynTypedNode supports that |
366 | | // do not have pointer identity. |
367 | 0 | auto &NodeOrVector = (*Parents)[MapNode]; |
368 | 0 | if (NodeOrVector.isNull()) { |
369 | 0 | if (const auto *D = ParentStack.back().get<Decl>()) |
370 | 0 | NodeOrVector = D; |
371 | 0 | else if (const auto *S = ParentStack.back().get<Stmt>()) |
372 | 0 | NodeOrVector = S; |
373 | 0 | else |
374 | 0 | NodeOrVector = new DynTypedNode(ParentStack.back()); |
375 | 0 | } else { |
376 | 0 | if (!NodeOrVector.template is<ParentVector *>()) { |
377 | 0 | auto *Vector = new ParentVector( |
378 | 0 | 1, getSingleDynTypedNodeFromParentMap(NodeOrVector)); |
379 | 0 | delete NodeOrVector.template dyn_cast<DynTypedNode *>(); |
380 | 0 | NodeOrVector = Vector; |
381 | 0 | } |
382 | |
|
383 | 0 | auto *Vector = NodeOrVector.template get<ParentVector *>(); |
384 | | // Skip duplicates for types that have memoization data. |
385 | | // We must check that the type has memoization data before calling |
386 | | // llvm::is_contained() because DynTypedNode::operator== can't compare all |
387 | | // types. |
388 | 0 | bool Found = ParentStack.back().getMemoizationData() && |
389 | 0 | llvm::is_contained(*Vector, ParentStack.back()); |
390 | 0 | if (!Found) |
391 | 0 | Vector->push_back(ParentStack.back()); |
392 | 0 | } |
393 | 0 | } Unexecuted instantiation: void clang::ParentMapContext::ParentMap::ASTVisitor::addParent<clang::Decl*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::Decl*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*) Unexecuted instantiation: void clang::ParentMapContext::ParentMap::ASTVisitor::addParent<clang::DynTypedNode, llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::DynTypedNode, llvm::DenseMap<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<clang::DynTypedNode, void>, llvm::detail::DenseMapPair<clang::DynTypedNode, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*) Unexecuted instantiation: void clang::ParentMapContext::ParentMap::ASTVisitor::addParent<clang::Stmt*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::Stmt*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*) Unexecuted instantiation: void clang::ParentMapContext::ParentMap::ASTVisitor::addParent<clang::Attr*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > > >(clang::Attr*, llvm::DenseMap<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*>, llvm::DenseMapInfo<void const*, void>, llvm::detail::DenseMapPair<void const*, llvm::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, llvm::SmallVector<clang::DynTypedNode, 2u>*> > >*) |
394 | | |
395 | 0 | template <typename T> static bool isNull(T Node) { return !Node; } Unexecuted instantiation: bool clang::ParentMapContext::ParentMap::ASTVisitor::isNull<clang::Decl*>(clang::Decl*) Unexecuted instantiation: bool clang::ParentMapContext::ParentMap::ASTVisitor::isNull<clang::NestedNameSpecifierLoc>(clang::NestedNameSpecifierLoc) Unexecuted instantiation: bool clang::ParentMapContext::ParentMap::ASTVisitor::isNull<clang::TypeLoc>(clang::TypeLoc) Unexecuted instantiation: bool clang::ParentMapContext::ParentMap::ASTVisitor::isNull<clang::Attr*>(clang::Attr*) |
396 | 0 | static bool isNull(ObjCProtocolLoc Node) { return false; } |
397 | | |
398 | | template <typename T, typename MapNodeTy, typename BaseTraverseFn, |
399 | | typename MapTy> |
400 | | bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse, |
401 | 0 | MapTy *Parents) { |
402 | 0 | if (isNull(Node)) |
403 | 0 | return true; |
404 | 0 | addParent(MapNode, Parents); |
405 | 0 | ParentStack.push_back(createDynTypedNode(Node)); |
406 | 0 | bool Result = BaseTraverse(); |
407 | 0 | ParentStack.pop_back(); |
408 | 0 | return Result; |
409 | 0 | } Unexecuted instantiation: bool clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNode<clang::Decl*, clang::Decl*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}, llvm::DenseMap<void const*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}::SmallVector<clang::Stmt const*, 2u>*>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}::DenseMapInfo<void const, void>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}::detail::DenseMapPair<void const, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}::SmallVector<clang::Stmt const*, 2u>*> > >(clang::Decl*, clang::Decl*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}, llvm::DenseMap<void const*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}::SmallVector<clang::Stmt const*, 2u>*>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}::DenseMapInfo<void const, void>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}::detail::DenseMapPair<void const, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseDecl(clang::Decl*)::{lambda()#1}::SmallVector<clang::Stmt const*, 2u>*> >*) Unexecuted instantiation: bool clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNode<clang::NestedNameSpecifierLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}, llvm::DenseMap<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}::DenseMapInfo<clang::DynTypedNode, void>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}::detail::DenseMapPair<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*> > >(clang::NestedNameSpecifierLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}, llvm::DenseMap<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}::DenseMapInfo<clang::DynTypedNode, void>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}::detail::DenseMapPair<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*> >*) Unexecuted instantiation: bool clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNode<clang::TypeLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}, llvm::DenseMap<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}::DenseMapInfo<clang::DynTypedNode, void>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}::detail::DenseMapPair<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*> > >(clang::TypeLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}, llvm::DenseMap<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}::DenseMapInfo<clang::DynTypedNode, void>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}::detail::DenseMapPair<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseTypeLoc(clang::TypeLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*> >*) Unexecuted instantiation: bool clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNode<clang::ObjCProtocolLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}, llvm::DenseMap<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}::DenseMapInfo<clang::DynTypedNode, void>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}::detail::DenseMapPair<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*> > >(clang::ObjCProtocolLoc, clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}, llvm::DenseMap<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}::DenseMapInfo<clang::DynTypedNode, void>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}::detail::DenseMapPair<clang::DynTypedNode, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseObjCProtocolLoc(clang::ObjCProtocolLoc)::{lambda()#1}::SmallVector<clang::DynTypedNode, 2u>*> >*) Unexecuted instantiation: bool clang::ParentMapContext::ParentMap::ASTVisitor::TraverseNode<clang::Attr*, clang::Attr*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}, llvm::DenseMap<void const*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}::SmallVector<clang::Stmt const*, 2u>*>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}::DenseMapInfo<void const, void>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}::detail::DenseMapPair<void const, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}::SmallVector<clang::Stmt const*, 2u>*> > >(clang::Attr*, clang::Attr*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}, llvm::DenseMap<void const*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}::PointerUnion<clang::Decl const*, clang::Stmt const*, clang::DynTypedNode*, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}::SmallVector<clang::Stmt const*, 2u>*>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}::DenseMapInfo<void const, void>, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}::detail::DenseMapPair<void const, clang::ParentMapContext::ParentMap::ASTVisitor::TraverseAttr(clang::Attr*)::{lambda()#1}::SmallVector<clang::Stmt const*, 2u>*> >*) |
410 | | |
411 | 0 | bool TraverseDecl(Decl *DeclNode) { |
412 | 0 | return TraverseNode( |
413 | 0 | DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); }, |
414 | 0 | &Map.PointerParents); |
415 | 0 | } |
416 | 0 | bool TraverseTypeLoc(TypeLoc TypeLocNode) { |
417 | 0 | return TraverseNode( |
418 | 0 | TypeLocNode, DynTypedNode::create(TypeLocNode), |
419 | 0 | [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); }, |
420 | 0 | &Map.OtherParents); |
421 | 0 | } |
422 | 0 | bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) { |
423 | 0 | return TraverseNode( |
424 | 0 | NNSLocNode, DynTypedNode::create(NNSLocNode), |
425 | 0 | [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); }, |
426 | 0 | &Map.OtherParents); |
427 | 0 | } |
428 | 0 | bool TraverseAttr(Attr *AttrNode) { |
429 | 0 | return TraverseNode( |
430 | 0 | AttrNode, AttrNode, [&] { return VisitorBase::TraverseAttr(AttrNode); }, |
431 | 0 | &Map.PointerParents); |
432 | 0 | } |
433 | 0 | bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) { |
434 | 0 | return TraverseNode( |
435 | 0 | ProtocolLocNode, DynTypedNode::create(ProtocolLocNode), |
436 | 0 | [&] { return VisitorBase::TraverseObjCProtocolLoc(ProtocolLocNode); }, |
437 | 0 | &Map.OtherParents); |
438 | 0 | } |
439 | | |
440 | | // Using generic TraverseNode for Stmt would prevent data-recursion. |
441 | 0 | bool dataTraverseStmtPre(Stmt *StmtNode) { |
442 | 0 | addParent(StmtNode, &Map.PointerParents); |
443 | 0 | ParentStack.push_back(DynTypedNode::create(*StmtNode)); |
444 | 0 | return true; |
445 | 0 | } |
446 | 0 | bool dataTraverseStmtPost(Stmt *StmtNode) { |
447 | 0 | ParentStack.pop_back(); |
448 | 0 | return true; |
449 | 0 | } |
450 | | |
451 | | ParentMap ⤅ |
452 | | llvm::SmallVector<DynTypedNode, 16> ParentStack; |
453 | | }; |
454 | | |
455 | 0 | ParentMapContext::ParentMap::ParentMap(ASTContext &Ctx) { |
456 | 0 | ASTVisitor(*this).TraverseAST(Ctx); |
457 | 0 | } |
458 | | |
459 | 0 | DynTypedNodeList ParentMapContext::getParents(const DynTypedNode &Node) { |
460 | 0 | if (!Parents) |
461 | | // We build the parent map for the traversal scope (usually whole TU), as |
462 | | // hasAncestor can escape any subtree. |
463 | 0 | Parents = std::make_unique<ParentMap>(ASTCtx); |
464 | 0 | return Parents->getParents(getTraversalKind(), Node); |
465 | 0 | } |