clang 24.0.0git
ParentMapContext.h
Go to the documentation of this file.
1//===- ParentMapContext.h - 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.h, but generalizes to non-Stmt nodes, which can have
10// multiple parents.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_PARENTMAPCONTEXT_H
15#define LLVM_CLANG_AST_PARENTMAPCONTEXT_H
16
19
20namespace clang {
22
24public:
26
28
29 /// Returns the parents of the given node (within the traversal scope).
30 ///
31 /// Note that this will lazily compute the parents of all nodes
32 /// and store them for later retrieval. Thus, the first call is O(n)
33 /// in the number of AST nodes.
34 ///
35 /// Caveats and FIXMEs:
36 /// Calculating the parent map over all AST nodes will need to load the
37 /// full AST. This can be undesirable in the case where the full AST is
38 /// expensive to create (for example, when using precompiled header
39 /// preambles). Thus, there are good opportunities for optimization here.
40 /// One idea is to walk the given node downwards, looking for references
41 /// to declaration contexts - once a declaration context is found, compute
42 /// the parent map for the declaration context; if that can satisfy the
43 /// request, loading the whole AST can be avoided. Note that this is made
44 /// more complex by statements in templates having multiple parents - those
45 /// problems can be solved by building closure over the templated parts of
46 /// the AST, which also avoids touching large parts of the AST.
47 /// Additionally, we will want to add an interface to already give a hint
48 /// where to search for the parents, for example when looking at a statement
49 /// inside a certain function.
50 ///
51 /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
52 /// NestedNameSpecifier or NestedNameSpecifierLoc.
53 template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node);
54
56
57 /// Clear parent maps.
58 void clear();
59
60 TraversalKind getTraversalKind() const { return Traversal; }
61 void setTraversalKind(TraversalKind TK) { Traversal = TK; }
62
63 const Expr *traverseIgnored(const Expr *E) const;
64 Expr *traverseIgnored(Expr *E) const;
66 // Fast path: Nothing is ignored in the default traversal mode TK_AsIs.
67 if (Traversal == TK_AsIs)
68 return N;
69 if (const auto *E = N.get<Expr>())
71 return N;
72 }
73
74 class ParentMap;
75
76private:
77 ASTContext &ASTCtx;
78 TraversalKind Traversal = TK_AsIs;
79 std::unique_ptr<ParentMap> Parents;
80};
81
85
86public:
87 TraversalKindScope(ASTContext &ASTCtx, std::optional<TraversalKind> ScopeTK)
88 : Ctx(ASTCtx.getParentMapContext()) {
89 TK = Ctx.getTraversalKind();
90 if (ScopeTK)
91 Ctx.setTraversalKind(*ScopeTK);
92 }
93
94 ~TraversalKindScope() { Ctx.setTraversalKind(TK); }
95};
96
97/// Container for either a single DynTypedNode or for an ArrayRef to
98/// DynTypedNode. For use with ParentMap.
100 union {
103 };
104 bool IsSingleNode;
105
106public:
107 DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
108 new (&SingleNode) DynTypedNode(N);
109 }
110
114
115 const DynTypedNode *begin() const {
116 return !IsSingleNode ? Nodes.begin() : &SingleNode;
117 }
118
119 const DynTypedNode *end() const {
120 return !IsSingleNode ? Nodes.end() : &SingleNode + 1;
121 }
122
123 size_t size() const { return end() - begin(); }
124 bool empty() const { return begin() == end(); }
125
126 const DynTypedNode &operator[](size_t N) const {
127 assert(N < size() && "Out of bounds!");
128 return *(begin() + N);
129 }
130};
131
132template <typename NodeT>
134 return getParents(DynTypedNode::create(Node));
135}
136
137template <typename NodeT>
138inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
139 return getParentMapContext().getParents(Node);
140}
141
142template <>
146
147} // namespace clang
148
149#endif
Defines the clang::ASTContext interface.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
DynTypedNodeList getParents(const NodeT &Node)
Forwards to get node parents from the ParentMapContext.
ParentMapContext & getParentMapContext()
Returns the dynamic AST node parent map context.
Definition ASTContext.h:882
Container for either a single DynTypedNode or for an ArrayRef to DynTypedNode.
DynTypedNodeList(const DynTypedNode &N)
DynTypedNodeList(ArrayRef< DynTypedNode > A)
const DynTypedNode * end() const
ArrayRef< DynTypedNode > Nodes
const DynTypedNode & operator[](size_t N) const
const DynTypedNode * begin() const
A dynamically typed AST node container.
const T * get() const
Retrieve the stored node as type T.
static DynTypedNode create(const T &Node)
Creates a DynTypedNode from Node.
This represents one expression.
Definition Expr.h:113
const Expr * traverseIgnored(const Expr *E) const
void clear()
Clear parent maps.
void setTraversalKind(TraversalKind TK)
DynTypedNode traverseIgnored(const DynTypedNode &N) const
TraversalKind getTraversalKind() const
DynTypedNodeList getParents(const NodeT &Node)
Returns the parents of the given node (within the traversal scope).
ParentMapContext(ASTContext &Ctx)
TraversalKindScope(ASTContext &ASTCtx, std::optional< TraversalKind > ScopeTK)
Top level wrappers for InstallAPI frontend operations.
TraversalKind
Defines how we descend a level in the AST when we pass through expressions.
@ TK_AsIs
Will traverse all child nodes.
#define false
Definition stdbool.h:26
#define true
Definition stdbool.h:25