forked from OSchip/llvm-project
Fix binding of nodes in case of forEach..() matchers.
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 llvm-svn: 167695
This commit is contained in:
parent
07351f8e78
commit
33806cdefc
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue