aboutsummaryrefslogtreecommitdiff
path: root/lib/ASTMatchers
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2013-02-28 13:21:39 +0000
committerManuel Klimek <klimek@google.com>2013-02-28 13:21:39 +0000
commitff9a01000ff74a994aa3da26ea2ec732c97291b7 (patch)
treeb979e136b99083c2f2e8e1a47e919b15c2cfd93b /lib/ASTMatchers
parenta4d4621b206f941cc58d9d0bc7c67a8e705c9d49 (diff)
First step towards adding a parent map to the ASTContext.
This does not yet implement the LimitNode approach discussed. The impact of this is an O(n) in the number of nodes in the AST reduction of complexity for certain kinds of matchers (as otherwise the parent map gets recreated for every new MatchFinder). See FIXMEs in the comments for the direction of future work. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176251 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ASTMatchers')
-rw-r--r--lib/ASTMatchers/ASTMatchFinder.cpp91
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