typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 1> ParentVector;
/// \brief Maps from a node to its parents.
- typedef llvm::DenseMap<const void *, ParentVector> ParentMap;
+ typedef llvm::DenseMap<const void *,
+ llvm::PointerUnion<ast_type_traits::DynTypedNode *,
+ ParentVector *>> ParentMap;
/// \brief Returns the parents of the given node.
///
friend class DeclContext;
friend class DeclarationNameTable;
void ReleaseDeclContextMaps();
+ void ReleaseParentMapEntries();
std::unique_ptr<ParentMap> AllParents;
}
ASTContext::~ASTContext() {
+ ReleaseParentMapEntries();
+
// Release the DenseMaps associated with DeclContext objects.
// FIXME: Is this the ideal solution?
ReleaseDeclContextMaps();
llvm::DeleteContainerSeconds(MangleNumberingContexts);
}
+void ASTContext::ReleaseParentMapEntries() {
+ if (!AllParents) return;
+ 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 *>());
+ delete Entry.second.get<ParentVector *>();
+ }
+ }
+}
+
void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
Deallocations[Callback].push_back(Data);
}
bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) {
if (!Node)
return true;
- if (ParentStack.size() > 0)
+ if (ParentStack.size() > 0) {
// FIXME: Currently we add the same parent multiple times, for example
// when we visit all subexpressions of template instantiations; this is
// suboptimal, bug benign: the only way to visit those is with
// map. The main problem there is to implement hash functions /
// comparison operators for all types that DynTypedNode supports that
// do not have pointer identity.
- (*Parents)[Node].push_back(ParentStack.back());
+ auto &NodeOrVector = (*Parents)[Node];
+ if (NodeOrVector.isNull()) {
+ 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);
+ Vector->push_back(ParentStack.back());
+ NodeOrVector = Vector;
+ delete Node;
+ } else {
+ assert(NodeOrVector.template is<ASTContext::ParentVector *>());
+ NodeOrVector.template get<ASTContext::ParentVector *>()->push_back(
+ ParentStack.back());
+ }
+ }
ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node));
bool Result = (this ->* traverse) (Node);
ParentStack.pop_back();
if (I == AllParents->end()) {
return ParentVector();
}
- return I->second;
+ if (I->second.is<ast_type_traits::DynTypedNode *>()) {
+ return ParentVector(1, *I->second.get<ast_type_traits::DynTypedNode *>());
+ }
+ const auto &Parents = *I->second.get<ParentVector *>();
+ return ParentVector(Parents.begin(), Parents.end());
}
bool