From 4d50d252990b201fb9ee02afee37a70d7ad6a507 Mon Sep 17 00:00:00 2001
From: Manuel Klimek <klimek@google.com>
Date: Mon, 8 Jul 2013 14:16:30 +0000
Subject: [PATCH] Fix use of invalidated iterator bug in AST match finder.

Pulled out the cache clearing in the case of descendant matching, too,
for consistency, also it is not technically needed there.

FIXME: Make cache size configurable and add unit test.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185820 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/ASTMatchers/ASTMatchFinder.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp
index a68c7fdffe1..e1e5f44c07b 100644
--- a/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -384,8 +384,6 @@ public:
       return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal,
                                 Bind);
 
-    if (ResultCache.size() > MaxMemoizationEntries)
-      ResultCache.clear();
     std::pair<MemoizationMap::iterator, bool> InsertResult =
         ResultCache.insert(std::make_pair(Key, MemoizedMatchResult()));
     if (InsertResult.second) {
@@ -426,6 +424,8 @@ public:
                                    const DynTypedMatcher &Matcher,
                                    BoundNodesTreeBuilder *Builder,
                                    BindKind Bind) {
+    if (ResultCache.size() > MaxMemoizationEntries)
+      ResultCache.clear();
     return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX,
                                       TK_AsIs, Bind);
   }
@@ -434,6 +434,10 @@ public:
                                  const DynTypedMatcher &Matcher,
                                  BoundNodesTreeBuilder *Builder,
                                  AncestorMatchMode MatchMode) {
+    // Reset the cache outside of the recursive call to make sure we
+    // don't invalidate any iterators.
+    if (ResultCache.size() > MaxMemoizationEntries)
+      ResultCache.clear();
     return memoizedMatchesAncestorOfRecursively(Node, Matcher, Builder,
                                                 MatchMode);
   }
@@ -498,8 +502,6 @@ private:
     Key.MatcherID = Matcher.getID();
     Key.Node = Node;
     Key.BoundNodes = *Builder;
-    if (ResultCache.size() > MaxMemoizationEntries)
-      ResultCache.clear();
     std::pair<MemoizationMap::iterator, bool> InsertResult =
         ResultCache.insert(std::make_pair(Key, MemoizedMatchResult()));
     if (InsertResult.second) {
-- 
GitLab