Viewing file: ParentMapContext.h (4.46 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//===- 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
|