diff options
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 50 |
1 files changed, 18 insertions, 32 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index c26d772139a..848158877aa 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -8678,23 +8678,6 @@ bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { namespace { -/// Template specializations to abstract away from pointers and TypeLocs. -/// @{ -template <typename T> -ast_type_traits::DynTypedNode createDynTypedNode(const T &Node) { - return ast_type_traits::DynTypedNode::create(*Node); -} -template <> -ast_type_traits::DynTypedNode createDynTypedNode(const TypeLoc &Node) { - return ast_type_traits::DynTypedNode::create(Node); -} -template <> -ast_type_traits::DynTypedNode -createDynTypedNode(const NestedNameSpecifierLoc &Node) { - return ast_type_traits::DynTypedNode::create(Node); -} -/// @} - /// \brief A \c RecursiveASTVisitor that builds a map from nodes to their /// parents as defined by the \c RecursiveASTVisitor. /// @@ -8702,8 +8685,7 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { /// traversal - there are other relationships (for example declaration context) /// in the AST that are better modeled by special matchers. /// -/// FIXME: Currently only builds up the map using \c Stmt, \c Decl, -/// \c NestedNameSpecifierLoc and \c TypeLoc nodes. + /// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes. class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> { public: @@ -8735,11 +8717,21 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { } template <typename T> - bool TraverseNode(T Node, bool (VisitorBase::*traverse)(T)) { + bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) { if (!Node) return true; if (ParentStack.size() > 0) { - auto &NodeOrVector = (*Parents)[createDynTypedNode(Node)]; + // FIXME: Currently we add the same parent multiple times, but only + // when no memoization data is available for the type. + // For example when we visit all subexpressions of template + // instantiations; this is suboptimal, but benign: the only way to + // visit those is with hasAncestor / hasParent, and those do not create + // new matches. + // The plan is to enable DynTypedNode to be storable in a map or hash + // map. The main problem there is to implement hash functions / + // comparison operators for all types that DynTypedNode supports that + // do not have pointer identity. + auto &NodeOrVector = (*Parents)[Node]; if (NodeOrVector.isNull()) { NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back()); } else { @@ -8765,7 +8757,7 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { Vector->push_back(ParentStack.back()); } } - ParentStack.push_back(createDynTypedNode(Node)); + ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node)); bool Result = (this ->* traverse) (Node); ParentStack.pop_back(); return Result; @@ -8779,15 +8771,6 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { return TraverseNode(StmtNode, &VisitorBase::TraverseStmt); } - bool TraverseTypeLoc(TypeLoc TypeLocNode) { - return TraverseNode(TypeLocNode, &VisitorBase::TraverseTypeLoc); - } - - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) { - return TraverseNode(NNSLocNode, - &VisitorBase::TraverseNestedNameSpecifierLoc); - } - ASTContext::ParentMap *Parents; llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack; @@ -8798,13 +8781,16 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { ArrayRef<ast_type_traits::DynTypedNode> ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { + assert(Node.getMemoizationData() && + "Invariant broken: only nodes that support memoization may be " + "used in the parent map."); if (!AllParents) { // We always need to run over the whole translation unit, as // hasAncestor can escape any subtree. AllParents.reset( ParentMapASTVisitor::buildMap(*getTranslationUnitDecl())); } - ParentMap::const_iterator I = AllParents->find(Node); + ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData()); if (I == AllParents->end()) { return None; } |