diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ASTMatchers/ASTMatchFinder.cpp | 91 |
1 files changed, 6 insertions, 85 deletions
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp index 3a3c1fb6e1..1af2f09c3e 100644 --- a/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/lib/ASTMatchers/ASTMatchFinder.cpp @@ -29,76 +29,6 @@ namespace { typedef MatchFinder::MatchCallback MatchCallback; -/// \brief A \c RecursiveASTVisitor that builds a map from nodes to their -/// parents as defined by the \c RecursiveASTVisitor. -/// -/// Note that the relationship described here is purely in terms of AST -/// 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 and \c Decl nodes. -class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> { -public: - /// \brief Contains parents of a node. - typedef SmallVector<ast_type_traits::DynTypedNode, 1> ParentVector; - - /// \brief Maps from a node to its parents. - typedef llvm::DenseMap<const void *, ParentVector> ParentMap; - - /// \brief Builds and returns the translation unit's parent map. - /// - /// The caller takes ownership of the returned \c ParentMap. - static ParentMap *buildMap(TranslationUnitDecl &TU) { - ParentMapASTVisitor Visitor(new ParentMap); - Visitor.TraverseDecl(&TU); - return Visitor.Parents; - } - -private: - typedef RecursiveASTVisitor<ParentMapASTVisitor> VisitorBase; - - ParentMapASTVisitor(ParentMap *Parents) : Parents(Parents) {} - - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return true; } - // Disables data recursion. We intercept Traverse* methods in the RAV, which - // are not triggered during data recursion. - bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; } - - template <typename T> - bool TraverseNode(T *Node, bool (VisitorBase::*traverse)(T*)) { - if (Node == NULL) - return true; - 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 - // 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. - (*Parents)[Node].push_back(ParentStack.back()); - ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node)); - bool Result = (this->*traverse)(Node); - ParentStack.pop_back(); - return Result; - } - - bool TraverseDecl(Decl *DeclNode) { - return TraverseNode(DeclNode, &VisitorBase::TraverseDecl); - } - - bool TraverseStmt(Stmt *StmtNode) { - return TraverseNode(StmtNode, &VisitorBase::TraverseStmt); - } - - ParentMap *Parents; - SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack; - - friend class RecursiveASTVisitor<ParentMapASTVisitor>; -}; - // We use memoization to avoid running the same matcher on the same // AST node twice. This pair is the key for looking up match // result. It consists of an ID of the MatcherInterface (for @@ -458,12 +388,6 @@ public: const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) { - if (!Parents) { - // We always need to run over the whole translation unit, as - // \c hasAncestor can escape any subtree. - Parents.reset(ParentMapASTVisitor::buildMap( - *ActiveASTContext->getTranslationUnitDecl())); - } return matchesAncestorOfRecursively(Node, Matcher, Builder, MatchMode); } @@ -506,22 +430,21 @@ private: assert(Node.getMemoizationData() && "Invariant broken: only nodes that support memoization may be " "used in the parent map."); - ParentMapASTVisitor::ParentMap::const_iterator I = - Parents->find(Node.getMemoizationData()); - if (I == Parents->end()) { + ASTContext::ParentVector Parents = ActiveASTContext->getParents(Node); + if (Parents.empty()) { assert(false && "Found node that is not in the parent map."); return false; } - for (ParentMapASTVisitor::ParentVector::const_iterator AncestorI = - I->second.begin(), AncestorE = I->second.end(); + for (ASTContext::ParentVector::const_iterator AncestorI = Parents.begin(), + AncestorE = Parents.end(); AncestorI != AncestorE; ++AncestorI) { if (Matcher.matches(*AncestorI, this, Builder)) return true; } if (MatchMode == ASTMatchFinder::AMM_ParentOnly) return false; - for (ParentMapASTVisitor::ParentVector::const_iterator AncestorI = - I->second.begin(), AncestorE = I->second.end(); + for (ASTContext::ParentVector::const_iterator AncestorI = Parents.begin(), + AncestorE = Parents.end(); AncestorI != AncestorE; ++AncestorI) { if (matchesAncestorOfRecursively(*AncestorI, Matcher, Builder, MatchMode)) return true; @@ -574,8 +497,6 @@ private: // Maps (matcher, node) -> the match result for memoization. typedef llvm::DenseMap<UntypedMatchInput, MemoizedMatchResult> MemoizationMap; MemoizationMap ResultCache; - - OwningPtr<ParentMapASTVisitor::ParentMap> Parents; }; // Returns true if the given class is directly or indirectly derived |