Author: Stephen Kelly Date: 2021-02-02T13:31:05Z New Revision: d6a06365cf12bebe20a7d65cf3894608efc089b4
URL: https://github.com/llvm/llvm-project/commit/d6a06365cf12bebe20a7d65cf3894608efc089b4 DIFF: https://github.com/llvm/llvm-project/commit/d6a06365cf12bebe20a7d65cf3894608efc089b4.diff LOG: [ASTMatchers] Fix matching after generic top-level matcher With a matcher like expr(anyOf(integerLiteral(equals(42)), unless(expr()))) and code such as struct B { B(int); }; B func1() { return 42; } the top-level expr() would match each of the nodes which are not spelled in the source and then ignore-traverse to match the integerLiteral node. This would result in multiple results reported for the integerLiteral. Fix that by only running matching logic on nodes which are not skipped with the top-level matcher. Differential Revision: https://reviews.llvm.org/D95735 Added: Modified: clang/lib/ASTMatchers/ASTMatchFinder.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Removed: ################################################################################ diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 41be3738e707..69957a952d17 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -837,6 +837,14 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>, if (EnableCheckProfiling) Timer.setBucket(&TimeByBucket[MP.second->getID()]); BoundNodesTreeBuilder Builder; + + { + TraversalKindScope RAII(getASTContext(), MP.first.getTraversalKind()); + if (getASTContext().getParentMapContext().traverseIgnored(DynNode) != + DynNode) + continue; + } + if (MP.first.matches(DynNode, this, &Builder)) { MatchVisitor Visitor(ActiveASTContext, MP.second); Builder.visitMatches(&Visitor); diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index c67c40ed960a..06c2bbc29e5c 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -2519,6 +2519,78 @@ template<> bool timesTwo<bool>(bool){ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); } + + Code = R"cpp( +struct B { + B(int); +}; + +B func1() { return 42; } + )cpp"; + { + auto M = expr(ignoringImplicit(integerLiteral(equals(42)).bind("intLit"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + } + { + auto M = expr(unless(integerLiteral(equals(24)))).bind("intLit"); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 7))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + } + { + auto M = + expr(anyOf(integerLiteral(equals(42)).bind("intLit"), unless(expr()))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + } + { + auto M = expr(allOf(integerLiteral(equals(42)).bind("intLit"), expr())); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + } + { + auto M = expr(integerLiteral(equals(42)).bind("intLit"), expr()); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + } + { + auto M = expr(optionally(integerLiteral(equals(42)).bind("intLit"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1))); + } + { + auto M = expr().bind("allExprs"); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("allExprs", 7))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique<VerifyIdIsBoundTo<Expr>>("allExprs", 1))); + } } TEST(Traversal, traverseNoImplicit) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits