[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.

2021-11-15 Thread Yitzhak Mandelbaum via Phabricator via cfe-commits
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.

2021-11-15 Thread Aaron Ballman via Phabricator via cfe-commits
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.

2021-11-12 Thread Yitzhak Mandelbaum via Phabricator via cfe-commits
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.

2021-11-11 Thread Matt Kulukundis via Phabricator via cfe-commits
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.

2021-11-11 Thread James King via Phabricator via cfe-commits
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.

2021-11-11 Thread James King via Phabricator via cfe-commits
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.

2021-11-10 Thread Matt Kulukundis via Phabricator via cfe-commits
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.

2021-11-10 Thread James King via Phabricator via cfe-commits
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