Index: cfe/trunk/include/clang/AST/ASTContext.h =================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h +++ cfe/trunk/include/clang/AST/ASTContext.h @@ -453,8 +453,47 @@ /// \brief Maps from a node to its parents. typedef llvm::DenseMap> ParentMap; + llvm::PointerUnion4> 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> Storage; + bool IsSingleNode; + + public: + DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) { + new (Storage.buffer) DynTypedNode(N); + } + DynTypedNodeList(ArrayRef A) : IsSingleNode(false) { + new (Storage.buffer) ArrayRef(A); + } + + const ast_type_traits::DynTypedNode *begin() const { + if (!IsSingleNode) + return reinterpret_cast *>(Storage.buffer) + ->begin(); + return reinterpret_cast(Storage.buffer); + } + + const ast_type_traits::DynTypedNode *end() const { + if (!IsSingleNode) + return reinterpret_cast *>(Storage.buffer) + ->end(); + return reinterpret_cast(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. /// @@ -480,13 +519,11 @@ /// /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc, /// NestedNameSpecifier or NestedNameSpecifierLoc. - template - ArrayRef getParents(const NodeT &Node) { + template DynTypedNodeList getParents(const NodeT &Node) { return getParents(ast_type_traits::DynTypedNode::create(Node)); } - ArrayRef - getParents(const ast_type_traits::DynTypedNode &Node); + DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node); const clang::PrintingPolicy &getPrintingPolicy() const { return PrintingPolicy; Index: cfe/trunk/lib/AST/ASTContext.cpp =================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp +++ cfe/trunk/lib/AST/ASTContext.cpp @@ -797,8 +797,7 @@ for (const auto &Entry : *AllParents) { if (Entry.second.is()) { delete Entry.second.get(); - } else { - assert(Entry.second.is()); + } else if (Entry.second.is()) { delete Entry.second.get(); } } @@ -8673,6 +8672,15 @@ namespace { +ast_type_traits::DynTypedNode +getSingleDynTypedNodeFromParentMap(ASTContext::ParentMap::mapped_type U) { + if (const auto *D = U.template dyn_cast()) + return ast_type_traits::DynTypedNode::create(*D); + if (const auto *S = U.template dyn_cast()) + return ast_type_traits::DynTypedNode::create(*S); + return *U.template get(); +} + /// \brief A \c RecursiveASTVisitor that builds a map from nodes to their /// parents as defined by the \c RecursiveASTVisitor. /// @@ -8728,16 +8736,23 @@ // 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()) + NodeOrVector = D; + else if (const auto *S = ParentStack.back().get()) + NodeOrVector = S; + else + NodeOrVector = + new ast_type_traits::DynTypedNode(ParentStack.back()); } else { - if (NodeOrVector.template is()) { - auto *Node = - NodeOrVector.template get(); - auto *Vector = new ASTContext::ParentVector(1, *Node); + if (!NodeOrVector.template is()) { + auto *Vector = new ASTContext::ParentVector( + 1, getSingleDynTypedNodeFromParentMap(NodeOrVector)); NodeOrVector = Vector; - delete Node; + if (auto *Node = + NodeOrVector + .template dyn_cast()) + delete Node; } - assert(NodeOrVector.template is()); auto *Vector = NodeOrVector.template get(); @@ -8774,7 +8789,7 @@ } // end namespace -ArrayRef +ASTContext::DynTypedNodeList ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { assert(Node.getMemoizationData() && "Invariant broken: only nodes that support memoization may be " @@ -8787,12 +8802,12 @@ } ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData()); if (I == AllParents->end()) { - return None; + return llvm::ArrayRef(); } - if (auto *N = I->second.dyn_cast()) { - return llvm::makeArrayRef(N, 1); + if (auto *V = I->second.dyn_cast()) { + return llvm::makeArrayRef(*V); } - return *I->second.get(); + return getSingleDynTypedNodeFromParentMap(I->second); } bool