123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- ParentMapContext.h - Map of parents using DynTypedNode -------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // Similar to ParentMap.h, but generalizes to non-Stmt nodes, which can have
- // multiple parents.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_CLANG_AST_PARENTMAPCONTEXT_H
- #define LLVM_CLANG_AST_PARENTMAPCONTEXT_H
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/ASTTypeTraits.h"
- namespace clang {
- class DynTypedNodeList;
- class ParentMapContext {
- public:
- ParentMapContext(ASTContext &Ctx);
- ~ParentMapContext();
- /// Returns the parents of the given node (within the traversal scope).
- ///
- /// Note that this will lazily compute the parents of all nodes
- /// and store them for later retrieval. Thus, the first call is O(n)
- /// in the number of AST nodes.
- ///
- /// Caveats and FIXMEs:
- /// Calculating the parent map over all AST nodes will need to load the
- /// full AST. This can be undesirable in the case where the full AST is
- /// expensive to create (for example, when using precompiled header
- /// preambles). Thus, there are good opportunities for optimization here.
- /// One idea is to walk the given node downwards, looking for references
- /// to declaration contexts - once a declaration context is found, compute
- /// the parent map for the declaration context; if that can satisfy the
- /// request, loading the whole AST can be avoided. Note that this is made
- /// more complex by statements in templates having multiple parents - those
- /// problems can be solved by building closure over the templated parts of
- /// the AST, which also avoids touching large parts of the AST.
- /// Additionally, we will want to add an interface to already give a hint
- /// where to search for the parents, for example when looking at a statement
- /// inside a certain function.
- ///
- /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
- /// NestedNameSpecifier or NestedNameSpecifierLoc.
- template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node);
- DynTypedNodeList getParents(const DynTypedNode &Node);
- /// Clear parent maps.
- void clear();
- TraversalKind getTraversalKind() const { return Traversal; }
- void setTraversalKind(TraversalKind TK) { Traversal = TK; }
- const Expr *traverseIgnored(const Expr *E) const;
- Expr *traverseIgnored(Expr *E) const;
- DynTypedNode traverseIgnored(const DynTypedNode &N) const;
- class ParentMap;
- private:
- ASTContext &ASTCtx;
- TraversalKind Traversal = TK_AsIs;
- std::unique_ptr<ParentMap> Parents;
- };
- class TraversalKindScope {
- ParentMapContext &Ctx;
- TraversalKind TK = TK_AsIs;
- public:
- TraversalKindScope(ASTContext &ASTCtx, std::optional<TraversalKind> ScopeTK)
- : Ctx(ASTCtx.getParentMapContext()) {
- TK = Ctx.getTraversalKind();
- if (ScopeTK)
- Ctx.setTraversalKind(*ScopeTK);
- }
- ~TraversalKindScope() { Ctx.setTraversalKind(TK); }
- };
- /// Container for either a single DynTypedNode or for an ArrayRef to
- /// DynTypedNode. For use with ParentMap.
- class DynTypedNodeList {
- union {
- DynTypedNode SingleNode;
- ArrayRef<DynTypedNode> Nodes;
- };
- bool IsSingleNode;
- public:
- DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
- new (&SingleNode) DynTypedNode(N);
- }
- DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
- new (&Nodes) ArrayRef<DynTypedNode>(A);
- }
- const DynTypedNode *begin() const {
- return !IsSingleNode ? Nodes.begin() : &SingleNode;
- }
- const DynTypedNode *end() const {
- return !IsSingleNode ? Nodes.end() : &SingleNode + 1;
- }
- size_t size() const { return end() - begin(); }
- bool empty() const { return begin() == end(); }
- const DynTypedNode &operator[](size_t N) const {
- assert(N < size() && "Out of bounds!");
- return *(begin() + N);
- }
- };
- template <typename NodeT>
- inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
- return getParents(DynTypedNode::create(Node));
- }
- template <typename NodeT>
- inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
- return getParentMapContext().getParents(Node);
- }
- template <>
- inline DynTypedNodeList ASTContext::getParents(const DynTypedNode &Node) {
- return getParentMapContext().getParents(Node);
- }
- } // namespace clang
- #endif
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|