[PATCH] Do not store duplicate parents when memoization data is available.
Samuel Benzaquen
sbenza at google.com
Thu Jun 12 08:31:28 PDT 2014
Hi klimek,
Do not store duplicate parents when memoization data is available.
This does not solve the duplication problem, but ameliorates it.
http://reviews.llvm.org/D4124
Files:
lib/AST/ASTContext.cpp
unittests/ASTMatchers/ASTMatchersTest.cpp
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -8177,29 +8177,41 @@
if (!Node)
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.
+ // 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, 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.
auto &NodeOrVector = (*Parents)[Node];
if (NodeOrVector.isNull()) {
NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back());
- } else if (NodeOrVector
- .template is<ast_type_traits::DynTypedNode *>()) {
- auto *Node =
- NodeOrVector.template get<ast_type_traits::DynTypedNode *>();
- auto *Vector = new ASTContext::ParentVector(1, *Node);
- Vector->push_back(ParentStack.back());
- NodeOrVector = Vector;
- delete Node;
} else {
+ if (NodeOrVector.template is<ast_type_traits::DynTypedNode *>()) {
+ auto *Node =
+ NodeOrVector.template get<ast_type_traits::DynTypedNode *>();
+ auto *Vector = new ASTContext::ParentVector(1, *Node);
+ NodeOrVector = Vector;
+ delete Node;
+ }
assert(NodeOrVector.template is<ASTContext::ParentVector *>());
- NodeOrVector.template get<ASTContext::ParentVector *>()->push_back(
- ParentStack.back());
+
+ auto *Vector =
+ NodeOrVector.template get<ASTContext::ParentVector *>();
+ const void* ParentMemo = ParentStack.back().getMemoizationData();
+ // Skip duplicates for types that have memoization data.
+ bool Found =
+ ParentMemo &&
+ std::any_of(Vector->begin(), Vector->end(),
+ [=](const ast_type_traits::DynTypedNode &Node) {
+ return Node.getMemoizationData() == ParentMemo;
+ });
+ if (!Found)
+ Vector->push_back(ParentStack.back());
}
}
ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node));
Index: unittests/ASTMatchers/ASTMatchersTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -3621,6 +3621,27 @@
compoundStmt(hasParent(recordDecl()))));
}
+TEST(HasParent, NoDuplicateParents) {
+ class HasDuplicateParents : public BoundNodesCallback {
+ public:
+ bool run(const BoundNodes *Nodes) override { return false; }
+ bool run(const BoundNodes *Nodes, ASTContext *Context) override {
+ const Stmt *Node = Nodes->getNodeAs<Stmt>("node");
+ std::set<const void *> Parents;
+ for (const auto &Parent : Context->getParents(*Node)) {
+ if (!Parents.insert(Parent.getMemoizationData()).second) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ EXPECT_FALSE(matchAndVerifyResultTrue(
+ "template <typename T> int Foo() { return 1 + 2; }\n"
+ "int x = Foo<int>() + Foo<unsigned>();",
+ stmt().bind("node"), new HasDuplicateParents()));
+}
+
TEST(TypeMatching, MatchesTypes) {
EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4124.10363.patch
Type: text/x-patch
Size: 4162 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140612/bc4491cc/attachment.bin>
More information about the cfe-commits
mailing list