[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.
This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG9809c6c61ceb: Add `isInitCapture` and `forEachLambdaCapture` matchers. (authored by jcking1034, committed by ymandel). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D113575/new/ https://reviews.llvm.org/D113575 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -4769,6 +4769,66 @@ cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer(); } +TEST(ForEachLambdaCapture, MatchesCaptures) { + EXPECT_TRUE(matches( + "int main() { int x, y; auto f = [x, y]() { return x + y; }; }", + lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater())); + auto matcher = lambdaExpr(forEachLambdaCapture( + lambdaCapture(capturesVar(varDecl(hasType(isInteger().bind("LC"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + " + "z; }; }", + matcher, std::make_unique>("LC", 2))); +} + +TEST(ForEachLambdaCapture, IgnoreUnlessSpelledInSource) { + auto matcher = + traverse(TK_IgnoreUnlessSpelledInSource, + lambdaExpr(forEachLambdaCapture( + lambdaCapture(capturesVar(varDecl(hasType(isInteger() + .bind("LC"; + EXPECT_TRUE( + notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }", + matcher, langCxx11OrLater())); + EXPECT_TRUE( + notMatches("int main() { int x, y; auto f = [&]() { return x + y; }; }", + matcher, langCxx11OrLater())); + EXPECT_TRUE(matchAndVerifyResultTrue( + R"cc( + int main() { +int x, y; +float z; +auto f = [=, ]() { return x + y + z; }; + } + )cc", + matcher, std::make_unique>("LC", 1))); +} + +TEST(ForEachLambdaCapture, MatchImplicitCapturesOnly) { + auto matcher = + lambdaExpr(forEachLambdaCapture(lambdaCapture(isImplicit()).bind("LC"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y, z; auto f = [=, ]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 2))); +} + +TEST(ForEachLambdaCapture, MatchExplicitCapturesOnly) { + auto matcher = lambdaExpr( + forEachLambdaCapture(lambdaCapture(unless(isImplicit())).bind("LC"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y, z; auto f = [=, ]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 1))); +} + TEST(HasConditionVariableStatement, DoesNotMatchCondition) { EXPECT_TRUE(notMatches( "void x() { if(true) {} }", Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1439,6 +1439,22 @@ EXPECT_TRUE(notMatches("int X;", M)); } +TEST_P(ASTMatchersTest, IsInitCapture) { + if (!GetParam().isCXX11OrLater()) { +return; + } + auto M = varDecl(hasName("vd"), isInitCapture()); + EXPECT_TRUE(notMatches( + "int main() { int vd = 3; auto f = [vd]() { return vd; }; }", M)); + + if (!GetParam().isCXX14OrLater()) { +return; + } + EXPECT_TRUE(matches("int main() { auto f = [vd=3]() { return vd; }; }", M)); + EXPECT_TRUE(matches( + "int main() { int x = 3; auto f = [vd=x]() { return vd; }; }", M)); +} + TEST_P(ASTMatchersTest, StorageDuration) { StringRef T = "void f() { int x; static int y; } int a;static int b;extern int c;"; Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp === --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -246,6 +246,7 @@ REGISTER_MATCHER(forEachArgumentWithParamType); REGISTER_MATCHER(forEachConstructorInitializer);
[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.
aaron.ballman accepted this revision. aaron.ballman added a comment. LGTM! Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D113575/new/ https://reviews.llvm.org/D113575 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.
ymandel accepted this revision. ymandel added inline comments. This revision is now accepted and ready to land. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4235 + for (const auto : Node.captures()) { +if (Finder->isTraversalIgnoringImplicitNodes() && Capture.isImplicit()) + continue; nice catch! i would have overlooked that detail. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D113575/new/ https://reviews.llvm.org/D113575 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.
fowles added a comment. That is awesome! Thanks for much for the examples. Everything here LGTM. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D113575/new/ https://reviews.llvm.org/D113575 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.
jcking1034 marked an inline comment as done. jcking1034 added inline comments. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4224 +/// float z; +/// auto f = [=]() { return x + y + z; }; +/// } fowles wrote: > it would be nice to be able to do something like > > ``` > int main() { > int x, y; > float z; > auto f = [=, z]() { return x+ y + z; }; > } > ``` > > `lambdaExpr(forEachLambdaCapture(isImplicit())` matches `x` and `y` but not > `z` I believe that this should be possible, I've gone ahead and added some unit tests to demonstrate (see the tests named `MatchImplicitCapturesOnly` and `MatchExplicitCapturesOnly`). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D113575/new/ https://reviews.llvm.org/D113575 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.
jcking1034 updated this revision to Diff 386577. jcking1034 added a comment. Add additional unit tests. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D113575/new/ https://reviews.llvm.org/D113575 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -4769,6 +4769,66 @@ cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer(); } +TEST(ForEachLambdaCapture, MatchesCaptures) { + EXPECT_TRUE(matches( + "int main() { int x, y; auto f = [x, y]() { return x + y; }; }", + lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater())); + auto matcher = lambdaExpr(forEachLambdaCapture( + lambdaCapture(capturesVar(varDecl(hasType(isInteger().bind("LC"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + " + "z; }; }", + matcher, std::make_unique>("LC", 2))); +} + +TEST(ForEachLambdaCapture, IgnoreUnlessSpelledInSource) { + auto matcher = + traverse(TK_IgnoreUnlessSpelledInSource, + lambdaExpr(forEachLambdaCapture( + lambdaCapture(capturesVar(varDecl(hasType(isInteger() + .bind("LC"; + EXPECT_TRUE( + notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }", + matcher, langCxx11OrLater())); + EXPECT_TRUE( + notMatches("int main() { int x, y; auto f = [&]() { return x + y; }; }", + matcher, langCxx11OrLater())); + EXPECT_TRUE(matchAndVerifyResultTrue( + R"cc( + int main() { +int x, y; +float z; +auto f = [=, ]() { return x + y + z; }; + } + )cc", + matcher, std::make_unique>("LC", 1))); +} + +TEST(ForEachLambdaCapture, MatchImplicitCapturesOnly) { + auto matcher = + lambdaExpr(forEachLambdaCapture(lambdaCapture(isImplicit()).bind("LC"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y, z; auto f = [=, ]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 2))); +} + +TEST(ForEachLambdaCapture, MatchExplicitCapturesOnly) { + auto matcher = lambdaExpr( + forEachLambdaCapture(lambdaCapture(unless(isImplicit())).bind("LC"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y, z; auto f = [=, ]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 1))); +} + TEST(HasConditionVariableStatement, DoesNotMatchCondition) { EXPECT_TRUE(notMatches( "void x() { if(true) {} }", Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1439,6 +1439,22 @@ EXPECT_TRUE(notMatches("int X;", M)); } +TEST_P(ASTMatchersTest, IsInitCapture) { + if (!GetParam().isCXX11OrLater()) { +return; + } + auto M = varDecl(hasName("vd"), isInitCapture()); + EXPECT_TRUE(notMatches( + "int main() { int vd = 3; auto f = [vd]() { return vd; }; }", M)); + + if (!GetParam().isCXX14OrLater()) { +return; + } + EXPECT_TRUE(matches("int main() { auto f = [vd=3]() { return vd; }; }", M)); + EXPECT_TRUE(matches( + "int main() { int x = 3; auto f = [vd=x]() { return vd; }; }", M)); +} + TEST_P(ASTMatchersTest, StorageDuration) { StringRef T = "void f() { int x; static int y; } int a;static int b;extern int c;"; Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp === --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -246,6 +246,7 @@ REGISTER_MATCHER(forEachArgumentWithParamType); REGISTER_MATCHER(forEachConstructorInitializer); REGISTER_MATCHER(forEachDescendant); + REGISTER_MATCHER(forEachLambdaCapture); REGISTER_MATCHER(forEachOverridden); REGISTER_MATCHER(forEachSwitchCase); REGISTER_MATCHER(forField);
[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.
fowles added inline comments. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4224 +/// float z; +/// auto f = [=]() { return x + y + z; }; +/// } it would be nice to be able to do something like ``` int main() { int x, y; float z; auto f = [=, z]() { return x+ y + z; }; } ``` `lambdaExpr(forEachLambdaCapture(isImplicit())` matches `x` and `y` but not `z` Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D113575/new/ https://reviews.llvm.org/D113575 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.
jcking1034 created this revision. jcking1034 added reviewers: ymandel, tdl-g, aaron.ballman, fowles. jcking1034 requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits. This contributes follow-up work from https://reviews.llvm.org/D112491, which allows for increased control over the matching of lambda captures. This also updates the documentation for the `lambdaCapture` matcher. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D113575 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -4769,6 +4769,36 @@ cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer(); } +TEST(ForEachLambdaCapture, MatchesCaptures) { + EXPECT_TRUE(matches( + "int main() { int x, y; auto f = [x, y]() { return x + y; }; }", + lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater())); + auto matcher = lambdaExpr(forEachLambdaCapture( + lambdaCapture(capturesVar(varDecl(hasType(isInteger().bind("LC"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }", + matcher, std::make_unique>("LC", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + " + "z; }; }", + matcher, std::make_unique>("LC", 2))); +} + +TEST(ForEachLambdaCapture, IgnoreUnlessSpelledInSource) { + auto matcher = + traverse(TK_IgnoreUnlessSpelledInSource, + lambdaExpr(forEachLambdaCapture( + lambdaCapture(capturesVar(varDecl(hasType(isInteger() + .bind("LC"; + EXPECT_TRUE( + notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }", + matcher, langCxx11OrLater())); + EXPECT_TRUE(matchAndVerifyResultTrue( + "int main() { int x, y; float z; auto f = [=, ]() { return x + y + z; " + "}; }", + matcher, std::make_unique>("LC", 1))); +} + TEST(HasConditionVariableStatement, DoesNotMatchCondition) { EXPECT_TRUE(notMatches( "void x() { if(true) {} }", Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1439,6 +1439,22 @@ EXPECT_TRUE(notMatches("int X;", M)); } +TEST_P(ASTMatchersTest, IsInitCapture) { + if (!GetParam().isCXX11OrLater()) { +return; + } + auto M = varDecl(hasName("vd"), isInitCapture()); + EXPECT_TRUE(notMatches( + "int main() { int vd = 3; auto f = [vd]() { return vd; }; }", M)); + + if (!GetParam().isCXX14OrLater()) { +return; + } + EXPECT_TRUE(matches("int main() { auto f = [vd=3]() { return vd; }; }", M)); + EXPECT_TRUE(matches( + "int main() { int x = 3; auto f = [vd=x]() { return vd; }; }", M)); +} + TEST_P(ASTMatchersTest, StorageDuration) { StringRef T = "void f() { int x; static int y; } int a;static int b;extern int c;"; Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp === --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -246,6 +246,7 @@ REGISTER_MATCHER(forEachArgumentWithParamType); REGISTER_MATCHER(forEachConstructorInitializer); REGISTER_MATCHER(forEachDescendant); + REGISTER_MATCHER(forEachLambdaCapture); REGISTER_MATCHER(forEachOverridden); REGISTER_MATCHER(forEachSwitchCase); REGISTER_MATCHER(forField); @@ -424,6 +425,7 @@ REGISTER_MATCHER(isImplicit); REGISTER_MATCHER(isInStdNamespace); REGISTER_MATCHER(isInTemplateInstantiation); + REGISTER_MATCHER(isInitCapture); REGISTER_MATCHER(isInline); REGISTER_MATCHER(isInstanceMessage); REGISTER_MATCHER(isInstanceMethod); Index: clang/include/clang/ASTMatchers/ASTMatchers.h === --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -4205,6 +4205,45 @@ InnerMatcher.matches(*Initializer, Finder, Builder)); } +/// Matches a variable serving as the implicit variable for a lambda init- +/// capture. +/// +/// Example matches x (matcher = varDecl(isInitCapture())) +/// \code +/// auto f = [x=3]() { return x; }; +/// \endcode +AST_MATCHER(VarDecl, isInitCapture) { return Node.isInitCapture(); } + +/// Matches each lambda capture in