]> granicus.if.org Git - clang/commitdiff
Fix binding of nodes in case of forEach..() matchers.
authorDaniel Jasper <djasper@google.com>
Sun, 11 Nov 2012 22:14:55 +0000 (22:14 +0000)
committerDaniel Jasper <djasper@google.com>
Sun, 11 Nov 2012 22:14:55 +0000 (22:14 +0000)
When recursively visiting the generated matches, the aggregated bindings need
to be copied during the recursion. Otherwise, we they might not be properly
overwritten (which is shown by the test), or there might be bound nodes present
that were bound on a different matching branch.

Review: http://llvm-reviews.chandlerc.com/D112

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167695 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/ASTMatchers/ASTMatchersInternal.h
lib/ASTMatchers/ASTMatchersInternal.cpp
unittests/ASTMatchers/ASTMatchersTest.cpp
unittests/ASTMatchers/ASTMatchersTest.h

index 7bcf90fce7fec3478de31e41e23ef02c1a93ab4c..e5365ff89d7259bd0fe170631cb3c6995b88eae4 100644 (file)
@@ -141,7 +141,7 @@ public:
 private:
   void visitMatchesRecursively(
       Visitor* ResultVistior,
-      BoundNodesMap *AggregatedBindings);
+      const BoundNodesMap& AggregatedBindings);
 
   // FIXME: Find out whether we want to use different data structures here -
   // first benchmarks indicate that it doesn't matter though.
index e7ee8ee7ed378962082d47468f57bfd0e8840836..408195d36902b24cea5e0fc684e147acf93f01c2 100644 (file)
@@ -51,19 +51,20 @@ void BoundNodesTree::copyTo(BoundNodesTreeBuilder* Builder) const {
 
 void BoundNodesTree::visitMatches(Visitor* ResultVisitor) {
   BoundNodesMap AggregatedBindings;
-  visitMatchesRecursively(ResultVisitor, &AggregatedBindings);
+  visitMatchesRecursively(ResultVisitor, AggregatedBindings);
 }
 
 void BoundNodesTree::
 visitMatchesRecursively(Visitor* ResultVisitor,
-                        BoundNodesMap* AggregatedBindings) {
-  Bindings.copyTo(AggregatedBindings);
+                        const BoundNodesMap& AggregatedBindings) {
+  BoundNodesMap CombinedBindings(AggregatedBindings);
+  Bindings.copyTo(&CombinedBindings);
   if (RecursiveBindings.empty()) {
-    ResultVisitor->visitMatch(BoundNodes(*AggregatedBindings));
+    ResultVisitor->visitMatch(BoundNodes(CombinedBindings));
   } else {
     for (unsigned I = 0; I < RecursiveBindings.size(); ++I) {
       RecursiveBindings[I].visitMatchesRecursively(ResultVisitor,
-                                                   AggregatedBindings);
+                                                   CombinedBindings);
     }
   }
 }
index ad5469348d5dfd1fc9c25ed6be2772852b3fa634..e15940aea42747df4e709cd02897dd5b61e63ca5 100644 (file)
@@ -2775,6 +2775,17 @@ TEST(ForEachDescendant, BindsRecursiveCombinations) {
       new VerifyIdIsBoundTo<FieldDecl>("f", 8)));
 }
 
+TEST(ForEachDescendant, BindsCorrectNodes) {
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "class C { void f(); int i; };",
+      recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
+      new VerifyIdIsBoundTo<FieldDecl>("decl", 1)));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "class C { void f() {} int i; };",
+      recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
+      new VerifyIdIsBoundTo<FunctionDecl>("decl", 1)));
+}
+
 
 TEST(IsTemplateInstantiation, MatchesImplicitClassTemplateInstantiation) {
   // Make sure that we can both match the class by name (::X) and by the type
index 5e63b6bb1196ccf360e38a1b45479f015f175e22..3b23ada8da778cf51a6d54b4cde3e0babd5fa31b 100644 (file)
@@ -38,7 +38,7 @@ public:
 
   virtual void run(const MatchFinder::MatchResult &Result) {
     if (FindResultReviewer != NULL) {
-      *Verified = FindResultReviewer->run(&Result.Nodes, Result.Context);
+      *Verified |= FindResultReviewer->run(&Result.Nodes, Result.Context);
     } else {
       *Verified = true;
     }