clang: lib/AST/ParentMapContext.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
19
20using namespace clang;
21
23
25
27
30}
31
33 if ()
34 return nullptr;
35
36 switch (Traversal) {
38 return E;
41 }
42 llvm_unreachable("Invalid Traversal type!");
43}
44
46 if (const auto *E = N.get<Expr>()) {
48 }
49 return N;
50}
51
52template <typename T, typename... U>
56
57template <typename, typename...> struct MatchParents;
58
60
61 template <typename, typename...> friend struct ::MatchParents;
62
63
64 class ParentVector {
65 public:
66 ParentVector() = default;
68 Items.reserve(N);
69 for (; N > 0; --N)
71 }
73 return Seen.contains(Value);
74 }
76 if (.getMemoizationData() || Seen.insert(Value).second)
77 Items.push_back(Value);
78 }
80 private:
82 llvm::SmallDenseSet<DynTypedNode, 2> Seen;
83 };
84
85
86
87
88 using ParentMapPointers =
89 llvm::DenseMap<const void *,
90 llvm::PointerUnion<const Decl *, const Stmt *,
92
93
94
95 using ParentMapOtherNodes =
97 llvm::PointerUnion<const Decl *, const Stmt *,
99
100 ParentMapPointers PointerParents;
101 ParentMapOtherNodes OtherParents;
102 class ASTVisitor;
103
105 getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) {
106 if (const auto *D = U.dyn_cast<const Decl *>())
108 if (const auto *S = U.dyn_cast<const Stmt *>())
110 return *cast<DynTypedNode *>(U);
111 }
112
113 template <typename NodeTy, typename MapTy>
115 const MapTy &Map) {
116 auto I = Map.find(Node);
117 if (I == Map.end()) {
119 }
120 if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
121 return V->view();
122 }
123 return getSingleDynTypedNodeFromParentMap(I->second);
124 }
125
126public:
129 for (const auto &Entry : PointerParents) {
130 if (auto *DTN = dyn_cast<DynTypedNode *>(Entry.second)) {
131 delete DTN;
132 } else if (auto *PV = dyn_cast<ParentVector *>(Entry.second)) {
133 delete PV;
134 }
135 }
136 for (const auto &Entry : OtherParents) {
137 if (auto *DTN = dyn_cast<DynTypedNode *>(Entry.second)) {
138 delete DTN;
139 } else if (auto *PV = dyn_cast<ParentVector *>(Entry.second)) {
140 delete PV;
141 }
142 }
143 }
144
147 auto ParentList =
150
151 const auto *ChildExpr = Node.get<Expr>();
152
153 {
154
155
156
157
158
159 auto RewrittenBinOpParentsList = ParentList;
160 int I = 0;
161 while (ChildExpr && RewrittenBinOpParentsList.size() == 1 &&
162 I++ < 4) {
163 const auto *S = RewrittenBinOpParentsList[0].get<Stmt>();
164 if (!S)
165 break;
166
167 const auto *RWBO = dyn_cast(S);
168 if (!RWBO) {
169 RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents);
170 continue;
171 }
172 if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr &&
173 RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr)
174 break;
176 }
177 }
178
179 const auto *ParentExpr = ParentList[0].get<Expr>();
180 if (ParentExpr && ChildExpr)
181 return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr);
182
183 {
184 auto AncestorNodes =
185 matchParents<DeclStmt, CXXForRangeStmt>(ParentList, this);
186 if (std::get(AncestorNodes) &&
187 std::get<const CXXForRangeStmt *>(AncestorNodes)
188 ->getLoopVarStmt() ==
189 std::get<const DeclStmt *>(AncestorNodes))
190 return std::get(AncestorNodes);
191 }
192 {
193 auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>(
194 ParentList, this);
195 if (std::get(AncestorNodes) &&
196 std::get<const CXXForRangeStmt *>(AncestorNodes)
197 ->getRangeStmt() ==
198 std::get<const DeclStmt *>(AncestorNodes))
199 return std::get(AncestorNodes);
200 }
201 {
202 auto AncestorNodes =
203 matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList,
204 this);
205 if (std::get(AncestorNodes))
206 return std::get(AncestorNodes);
207 }
208 {
209 auto AncestorNodes =
210 matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>(
211 ParentList, this);
212 if (std::get(AncestorNodes))
213 return std::get(AncestorNodes);
214 }
215 }
216 return ParentList;
217 }
218 return getDynNodeFromMap(Node, OtherParents);
219 }
220
222 const Expr *Child) {
223
224 auto ShouldSkip = [](const Expr *E, const Expr *Child) {
225 if (isa(E))
226 return true;
227
228 if (isa(E))
229 return true;
230
231 if (isa(E))
232 return true;
233
234 if (isa(E))
235 return true;
236
237 if (isa(E))
238 return true;
239
240 if (isa(E))
241 return true;
242
243 auto SR = Child->getSourceRange();
244
245 if (const auto *C = dyn_cast(E)) {
246 if (C->getSourceRange() == SR)
247 return true;
248 }
249
250 if (const auto *C = dyn_cast(E)) {
251 if (C->getSourceRange() == SR || C->isElidable())
252 return true;
253 }
254
255 if (const auto *C = dyn_cast(E)) {
256 if (C->getSourceRange() == SR)
257 return true;
258 }
259
260 if (const auto *C = dyn_cast(E)) {
261 if (C->getSourceRange() == SR)
262 return true;
263 }
264 return false;
265 };
266
267 while (ShouldSkip(E, Child)) {
268 auto It = PointerParents.find(E);
269 if (It == PointerParents.end())
270 break;
271 const auto *S = It->second.dyn_cast<const Stmt *>();
272 if (!S) {
273 if (auto *Vec = It->second.dyn_cast<ParentVector *>())
274 return Vec->view();
275 return getSingleDynTypedNodeFromParentMap(It->second);
276 }
277 const auto *P = dyn_cast(S);
278 if ()
280 Child = E;
282 }
284 }
285};
286
291 if (const auto *TypedNode = NodeList[0].get()) {
292 auto NextParentList =
294 if (NextParentList.size() == 1) {
296 if (std::get(TailTuple)) {
297 return std::apply(
298 [TypedNode](bool, DynTypedNodeList NodeList, auto... TupleTail) {
299 return std::make_tuple(true, NodeList, TypedNode, TupleTail...);
300 },
301 TailTuple);
302 }
303 }
304 }
305 return std::tuple_cat(std::make_tuple(false, NodeList),
306 std::tuple<const T *, const U *...>());
307 }
308};
309
311 static std::tuple<bool, DynTypedNodeList, const T *>
314 if (const auto *TypedNode = NodeList[0].get()) {
315 auto NextParentList =
317 if (NextParentList.size() == 1)
318 return std::make_tuple(true, NodeList, TypedNode);
319 }
320 return std::make_tuple(false, NodeList, nullptr);
321 }
322};
323
324template <typename T, typename... U>
329}
330
331
332
335}
338}
339template <>
342}
345}
346
347
348
349
350
351
352
353
356public:
358
359private:
361
363
364 bool shouldVisitTemplateInstantiations() const { return true; }
365
366 bool shouldVisitImplicitCode() const { return true; }
367
368
369
370
371 template <typename MapNodeTy, typename MapTy>
372 void addParent(MapNodeTy MapNode, MapTy *Parents) {
373 if (ParentStack.empty())
374 return;
375
376
377
378
379
380
381
382
383
384
385
386 auto &NodeOrVector = (*Parents)[MapNode];
387 if (NodeOrVector.isNull()) {
388 if (const auto *D = ParentStack.back().get<Decl>())
389 NodeOrVector = D;
390 else if (const auto *S = ParentStack.back().get<Stmt>())
391 NodeOrVector = S;
392 else
393 NodeOrVector = new DynTypedNode(ParentStack.back());
394 } else {
395 if (!isa<ParentVector *>(NodeOrVector)) {
396 auto *Vector = new ParentVector(
397 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
398 delete NodeOrVector.template dyn_cast<DynTypedNode *>();
399 NodeOrVector = Vector;
400 }
401
402 auto *Vector = cast<ParentVector *>(NodeOrVector);
403
404
405
406
407 bool Found = ParentStack.back().getMemoizationData() &&
408 llvm::is_contained(*Vector, ParentStack.back());
410 Vector->push_back(ParentStack.back());
411 }
412 }
413
414 template static bool isNull(T Node) { return ; }
416
417 template <typename T, typename MapNodeTy, typename BaseTraverseFn,
419 bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse,
420 MapTy *Parents) {
421 if (isNull(Node))
422 return true;
423 addParent(MapNode, Parents);
425 bool Result = BaseTraverse();
426 ParentStack.pop_back();
428 }
429
430 bool TraverseDecl(Decl *DeclNode) {
431 return TraverseNode(
433 &Map.PointerParents);
434 }
435 bool TraverseTypeLoc(TypeLoc TypeLocNode) {
436 return TraverseNode(
439 &Map.OtherParents);
440 }
442 return TraverseNode(
445 &Map.OtherParents);
446 }
447 bool TraverseAttr(Attr *AttrNode) {
448 return TraverseNode(
450 &Map.PointerParents);
451 }
452 bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLocNode) {
453 return TraverseNode(
456 &Map.OtherParents);
457 }
458
459
460 bool dataTraverseStmtPre(Stmt *StmtNode) {
461 addParent(StmtNode, &Map.PointerParents);
463 return true;
464 }
465 bool dataTraverseStmtPost(Stmt *StmtNode) {
466 ParentStack.pop_back();
467 return true;
468 }
469
472};
473
476}
477
479 if (!Parents)
480
481
482 Parents = std::make_unique(ASTCtx);
484}
static DynTypedNode createDynTypedNode(const T &Node)
Template specializations to abstract away from pointers and TypeLocs.
static std::tuple< bool, DynTypedNodeList, const T *, const U *... > matchParents(const DynTypedNodeList &NodeList, ParentMapContext::ParentMap *ParentMap)
llvm::DenseMap< Stmt *, Stmt * > MapTy
static bool contains(const std::set< tok::TokenKind > &Terminators, const Token &Tok)
A RecursiveASTVisitor that builds a map from nodes to their parents as defined by the RecursiveASTVis...
ASTVisitor(ParentMap &Map)
DynTypedNodeList getParents(TraversalKind TK, const DynTypedNode &Node)
DynTypedNodeList AscendIgnoreUnlessSpelledInSource(const Expr *E, const Expr *Child)
ParentMap(ASTContext &Ctx)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
constexpr bool hasPointerIdentity() const
Check if the given ASTNodeKind identifies a type that offers pointer identity.
Attr - This represents one attribute.
Decl - This represents one declaration (or definition), e.g.
Container for either a single DynTypedNode or for an ArrayRef to DynTypedNode.
A dynamically typed AST node container.
ASTNodeKind getNodeKind() const
const T * get() const
Retrieve the stored node as type T.
static DynTypedNode create(const T &Node)
Creates a DynTypedNode from Node.
const void * getMemoizationData() const
Returns a pointer that identifies the stored AST node.
This represents one expression.
Expr * IgnoreUnlessSpelledInSource()
Skip past any invisible AST nodes which might surround this statement, such as ExprWithCleanups or Im...
A C++ nested-name-specifier augmented with source location information.
const Expr * traverseIgnored(const Expr *E) const
void clear()
Clear parent maps.
TraversalKind getTraversalKind() const
DynTypedNodeList getParents(const NodeT &Node)
Returns the parents of the given node (within the traversal scope).
ParentMapContext(ASTContext &Ctx)
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc)
Recursively visit an Objective-C protocol reference with location information.
bool TraverseAST(ASTContext &AST)
Recursively visits an entire AST, starting from the TranslationUnitDecl.
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)
Recursively visit a C++ nested-name-specifier with location information.
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
bool TraverseTypeLoc(TypeLoc TL)
Recursively visit a type with location, by dispatching to Traverse*TypeLoc() based on the argument ty...
bool TraverseAttr(Attr *At)
Recursively visit an attribute, by dispatching to Traverse*Attr() based on the argument's dynamic typ...
Stmt - This represents one statement.
Base wrapper for a particular "section" of type source info.
The JSON file list parser is used to communicate input to InstallAPI.
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
TraversalKind
Defines how we descend a level in the AST when we pass through expressions.
@ TK_AsIs
Will traverse all child nodes.
@ TK_IgnoreUnlessSpelledInSource
Ignore AST nodes not written in the source.
@ Result
The result type of a method or function.
const FunctionProtoType * T
static std::tuple< bool, DynTypedNodeList, const T * > match(const DynTypedNodeList &NodeList, ParentMapContext::ParentMap *ParentMap)
static std::tuple< bool, DynTypedNodeList, const T *, const U *... > match(const DynTypedNodeList &NodeList, ParentMapContext::ParentMap *ParentMap)