summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Jasper <djasper@google.com>2014-07-23 13:17:47 +0000
committerDaniel Jasper <djasper@google.com>2014-07-23 13:17:47 +0000
commit3dfa09bbbc07134da15cdf57928a67f85dc966ab (patch)
tree1970c8e12836cd5407da82118e9a28af3648d5e5
parent2727279117eac8671597fe457ac7ef3c5d82abe6 (diff)
downloadbcm5719-llvm-3dfa09bbbc07134da15cdf57928a67f85dc966ab.tar.gz
bcm5719-llvm-3dfa09bbbc07134da15cdf57928a67f85dc966ab.zip
Prevent assert in ASTMatchFinder.
If nodes without memoization data (e.g. TypeLocs) are bound to specific names, that effectively prevents memoization as those elements cannot be compared effectively. If it is tried anyway, this can lead to an assert as demonstrated in the new test. In the long term, the better solution will be to enable DynTypedNodes without memoization data. For now, simply skip memoization instead. llvm-svn: 213751
-rw-r--r--clang/include/clang/ASTMatchers/ASTMatchersInternal.h20
-rw-r--r--clang/lib/ASTMatchers/ASTMatchFinder.cpp2
-rw-r--r--clang/unittests/ASTMatchers/ASTMatchersTest.cpp6
3 files changed, 27 insertions, 1 deletions
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 94435fd274e..68b18164c23 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -103,6 +103,16 @@ public:
return NodeMap;
}
+ /// \brief Returns \c true if this \c BoundNodesMap can be compared, i.e. all
+ /// stored nodes have memoization data.
+ bool isComparable() const {
+ for (const auto &IDAndNode : NodeMap) {
+ if (!IDAndNode.second.getMemoizationData())
+ return false;
+ }
+ return true;
+ }
+
private:
IDToNodeMap NodeMap;
};
@@ -153,6 +163,16 @@ public:
return Bindings < Other.Bindings;
}
+ /// \brief Returns \c true if this \c BoundNodesTreeBuilder can be compared,
+ /// i.e. all stored node maps have memoization data.
+ bool isComparable() const {
+ for (const BoundNodesMap &NodesMap : Bindings) {
+ if (!NodesMap.isComparable())
+ return false;
+ }
+ return true;
+ }
+
private:
SmallVector<BoundNodesMap, 16> Bindings;
};
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 23708e2ff0c..b8ac68aad72 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -372,7 +372,7 @@ public:
BoundNodesTreeBuilder *Builder, int MaxDepth,
TraversalKind Traversal, BindKind Bind) {
// For AST-nodes that don't have an identity, we can't memoize.
- if (!Node.getMemoizationData())
+ if (!Node.getMemoizationData() || !Builder->isComparable())
return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal,
Bind);
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTest.cpp
index d4f867114e9..e769e887bd1 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -643,6 +643,12 @@ TEST(DeclarationMatcher, HasDescendant) {
"};", ZDescendantClassXDescendantClassY));
}
+TEST(DeclarationMatcher, HasDescendantMemoization) {
+ DeclarationMatcher CannotMemoize =
+ decl(hasDescendant(typeLoc().bind("x")), has(decl()));
+ EXPECT_TRUE(matches("void f() { int i; }", CannotMemoize));
+}
+
// Implements a run method that returns whether BoundNodes contains a
// Decl bound to Id that can be dynamically cast to T.
// Optionally checks that the check succeeded a specific number of times.
OpenPOWER on IntegriCloud