clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
143 lines
4.5 KiB
C++
143 lines
4.5 KiB
C++
//===- 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
|