/// \brief Maps from a node to its parents.
typedef llvm::DenseMap<const void *,
- llvm::PointerUnion<ast_type_traits::DynTypedNode *,
- ParentVector *>> ParentMap;
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *,
+ ParentVector *>> ParentMap;
+
+ /// Container for either a single DynTypedNode or for an ArrayRef to
+ /// DynTypedNode. For use with ParentMap.
+ class DynTypedNodeList {
+ typedef ast_type_traits::DynTypedNode DynTypedNode;
+ llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode,
+ ArrayRef<DynTypedNode>> Storage;
+ bool IsSingleNode;
+
+ public:
+ DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
+ new (Storage.buffer) DynTypedNode(N);
+ }
+ DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
+ new (Storage.buffer) ArrayRef<DynTypedNode>(A);
+ }
+
+ const ast_type_traits::DynTypedNode *begin() const {
+ if (!IsSingleNode)
+ return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
+ ->begin();
+ return reinterpret_cast<const DynTypedNode *>(Storage.buffer);
+ }
+
+ const ast_type_traits::DynTypedNode *end() const {
+ if (!IsSingleNode)
+ return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
+ ->end();
+ return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 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);
+ }
+ };
/// \brief Returns the parents of the given node.
///
///
/// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
/// NestedNameSpecifier or NestedNameSpecifierLoc.
- template <typename NodeT>
- ArrayRef<ast_type_traits::DynTypedNode> getParents(const NodeT &Node) {
+ template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node) {
return getParents(ast_type_traits::DynTypedNode::create(Node));
}
- ArrayRef<ast_type_traits::DynTypedNode>
- getParents(const ast_type_traits::DynTypedNode &Node);
+ DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node);
const clang::PrintingPolicy &getPrintingPolicy() const {
return PrintingPolicy;
for (const auto &Entry : *AllParents) {
if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
delete Entry.second.get<ast_type_traits::DynTypedNode *>();
- } else {
- assert(Entry.second.is<ParentVector *>());
+ } else if (Entry.second.is<ParentVector *>()) {
delete Entry.second.get<ParentVector *>();
}
}
namespace {
+ast_type_traits::DynTypedNode
+getSingleDynTypedNodeFromParentMap(ASTContext::ParentMap::mapped_type U) {
+ if (const auto *D = U.template dyn_cast<const Decl *>())
+ return ast_type_traits::DynTypedNode::create(*D);
+ if (const auto *S = U.template dyn_cast<const Stmt *>())
+ return ast_type_traits::DynTypedNode::create(*S);
+ return *U.template get<ast_type_traits::DynTypedNode *>();
+}
+
/// \brief A \c RecursiveASTVisitor that builds a map from nodes to their
/// parents as defined by the \c RecursiveASTVisitor.
///
// do not have pointer identity.
auto &NodeOrVector = (*Parents)[Node];
if (NodeOrVector.isNull()) {
- NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back());
+ if (const auto *D = ParentStack.back().get<Decl>())
+ NodeOrVector = D;
+ else if (const auto *S = ParentStack.back().get<Stmt>())
+ NodeOrVector = S;
+ else
+ NodeOrVector =
+ new ast_type_traits::DynTypedNode(ParentStack.back());
} else {
- if (NodeOrVector.template is<ast_type_traits::DynTypedNode *>()) {
- auto *Node =
- NodeOrVector.template get<ast_type_traits::DynTypedNode *>();
- auto *Vector = new ASTContext::ParentVector(1, *Node);
+ if (!NodeOrVector.template is<ASTContext::ParentVector *>()) {
+ auto *Vector = new ASTContext::ParentVector(
+ 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
NodeOrVector = Vector;
- delete Node;
+ if (auto *Node =
+ NodeOrVector
+ .template dyn_cast<ast_type_traits::DynTypedNode *>())
+ delete Node;
}
- assert(NodeOrVector.template is<ASTContext::ParentVector *>());
auto *Vector =
NodeOrVector.template get<ASTContext::ParentVector *>();
} // end namespace
-ArrayRef<ast_type_traits::DynTypedNode>
+ASTContext::DynTypedNodeList
ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) {
assert(Node.getMemoizationData() &&
"Invariant broken: only nodes that support memoization may be "
}
ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData());
if (I == AllParents->end()) {
- return None;
+ return llvm::ArrayRef<ast_type_traits::DynTypedNode>();
}
- if (auto *N = I->second.dyn_cast<ast_type_traits::DynTypedNode *>()) {
- return llvm::makeArrayRef(N, 1);
+ if (auto *V = I->second.dyn_cast<ParentVector *>()) {
+ return llvm::makeArrayRef(*V);
}
- return *I->second.get<ParentVector *>();
+ return getSingleDynTypedNodeFromParentMap(I->second);
}
bool