From 16c6e9c58e9ae50a775945e6b407f1891f353d2f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 26 Dec 2020 21:07:14 +0000 Subject: [PATCH] [ASTMatchers] Fix child traversal over range-for loops Differential Revision: https://reviews.llvm.org/D94031 --- clang/lib/ASTMatchers/ASTMatchFinder.cpp | 16 +++++++- .../ASTMatchers/ASTMatchersTraversalTest.cpp | 47 +++++++++++++++++++++- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 99d9583..39bdb94 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -236,6 +236,20 @@ public: ScopedIncrement ScopedDepth(&CurrentDepth); return traverse(TAL); } + bool TraverseCXXForRangeStmt(CXXForRangeStmt *Node) { + if (!Finder->isTraversalIgnoringImplicitNodes()) + return VisitorBase::TraverseCXXForRangeStmt(Node); + if (!Node) + return true; + ScopedIncrement ScopedDepth(&CurrentDepth); + if (auto *Init = Node->getInit()) + if (!match(*Init)) + return false; + if (!match(*Node->getLoopVariable()) || !match(*Node->getRangeInit()) || + !match(*Node->getBody())) + return false; + return VisitorBase::TraverseStmt(Node->getBody()); + } bool TraverseLambdaExpr(LambdaExpr *Node) { if (!Finder->isTraversalIgnoringImplicitNodes()) return VisitorBase::TraverseLambdaExpr(Node); @@ -575,8 +589,6 @@ public: if (isTraversalIgnoringImplicitNodes()) { IgnoreImplicitChildren = true; - if (Node.get()) - ScopedTraversal = true; } ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal); diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index e706ea4..19ab618 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -2553,7 +2553,9 @@ struct CtorInitsNonTrivial : NonTrivial int arr[2]; for (auto i : arr) { - + if (true) + { + } } } )cpp"; @@ -2597,6 +2599,33 @@ struct CtorInitsNonTrivial : NonTrivial EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); } { + auto M = cxxForRangeStmt(hasDescendant(ifStmt())); + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); + } + { + EXPECT_TRUE(matches( + Code, traverse(TK_AsIs, cxxForRangeStmt(has(declStmt( + hasSingleDecl(varDecl(hasName("i"))))))))); + EXPECT_TRUE( + matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, + cxxForRangeStmt(has(varDecl(hasName("i"))))))); + } + { + EXPECT_TRUE(matches( + Code, traverse(TK_AsIs, cxxForRangeStmt(has(declStmt(hasSingleDecl( + varDecl(hasInitializer(declRefExpr( + to(varDecl(hasName("arr"))))))))))))); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, + cxxForRangeStmt(has(declRefExpr( + to(varDecl(hasName("arr"))))))))); + } + { + auto M = cxxForRangeStmt(has(compoundStmt())); + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); + } + { auto M = binaryOperator(hasOperatorName("!=")); EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); @@ -2659,7 +2688,8 @@ struct CtorInitsNonTrivial : NonTrivial true, {"-std=c++20"})); } { - auto M = cxxForRangeStmt(has(declStmt())); + auto M = + cxxForRangeStmt(has(declStmt(hasSingleDecl(varDecl(hasName("i")))))); EXPECT_TRUE( matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"})); EXPECT_FALSE( @@ -2679,6 +2709,19 @@ struct CtorInitsNonTrivial : NonTrivial matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M), true, {"-std=c++20"})); } + { + auto M = cxxForRangeStmt( + has(declStmt(hasSingleDecl(varDecl( + hasName("a"), + hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))), + hasLoopVariable(varDecl(hasName("i"))), + hasRangeInit(declRefExpr(to(varDecl(hasName("a")))))); + EXPECT_TRUE( + matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"})); + EXPECT_TRUE( + matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + true, {"-std=c++20"})); + } Code = R"cpp( void hasDefaultArg(int i, int j = 0) { -- 2.7.4