[clang] c0b298f - Add `LambdaCapture`-related matchers.
Yitzhak Mandelbaum via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 8 10:52:00 PST 2021
Author: James King
Date: 2021-11-08T18:50:54Z
New Revision: c0b298fc213c1b33e97ca72fba58597365375875
URL: https://github.com/llvm/llvm-project/commit/c0b298fc213c1b33e97ca72fba58597365375875
DIFF: https://github.com/llvm/llvm-project/commit/c0b298fc213c1b33e97ca72fba58597365375875.diff
LOG: Add `LambdaCapture`-related matchers.
This provides better support for `LambdaCapture`s by making them first-
class and allowing them to be bindable. In addition, this implements several
`LambdaCapture`-related matchers. This does not update how lambdas are
traversed. As a result, something like trying to match `lambdaCapture()` by
itself will not work - it must be used as an inner matcher.
Reviewed By: aaron.ballman, sammccall
Differential Revision: https://reviews.llvm.org/D112491
Added:
Modified:
clang/docs/LibASTMatchersReference.html
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/ASTTypeTraits.h
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/lib/AST/ASTTypeTraits.cpp
clang/lib/ASTMatchers/Dynamic/Registry.cpp
clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html
index 3977d26414521..9d2398effff10 100644
--- a/clang/docs/LibASTMatchersReference.html
+++ b/clang/docs/LibASTMatchersReference.html
@@ -1190,6 +1190,10 @@ <h2 id="decl-matchers">Node Matchers</h2>
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaCapture.html">LambdaCapture</a>></td><td class="name" onclick="toggle('lambdaCapture0')"><a name="lambdaCapture0Anchor">lambdaCapture</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaCapture.html">LambdaCapture</a>>...</td></tr>
+<tr><td colspan="4" class="doc" id="lambdaCapture0"><pre></pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>></td><td class="name" onclick="toggle('nestedNameSpecifierLoc0')"><a name="nestedNameSpecifierLoc0Anchor">nestedNameSpecifierLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="nestedNameSpecifierLoc0"><pre>Same as nestedNameSpecifier but matches NestedNameSpecifierLoc.
</pre></td></tr>
@@ -4514,6 +4518,42 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="equals9"><pre></pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaCapture.html">LambdaCapture</a>></td><td class="name" onclick="toggle('capturesThis0')"><a name="capturesThis0Anchor">capturesThis</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="capturesThis0"><pre>Matches a `LambdaCapture` that refers to 'this'.
+
+Given
+class C {
+ int cc;
+ int f() {
+ auto l = [this]() { return cc; };
+ return l();
+ }
+};
+lambdaExpr(hasAnyCapture(lambdaCapture(capturesThis())))
+ matches `[this]() { return cc; }`.
+</pre></td></tr>
+
+
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaCapture.html">LambdaCapture</a>></td><td class="name" onclick="toggle('isImplicit2')"><a name="isImplicit2Anchor">isImplicit</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isImplicit2"><pre>Matches an entity that has been implicitly added by the compiler (e.g.
+implicit default/copy constructors).
+</pre></td></tr>
+
+
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaExpr.html">LambdaExpr</a>></td><td class="name" onclick="toggle('hasAnyCapture0')"><a name="hasAnyCapture0Anchor">hasAnyCapture</a></td><td>LambdaCaptureMatcher InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyCapture0"><pre>Matches any capture in a lambda expression.
+
+Given
+ void foo() {
+ int t = 5;
+ auto f = [=](){ return t; };
+ }
+lambdaExpr(hasAnyCapture(lambdaCapture())) and
+lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("t")))))
+ both match `[=](){ return t; }`.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>></td><td class="name" onclick="toggle('isArrow0')"><a name="isArrow0Anchor">isArrow</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isArrow0"><pre>Matches member expressions that are called with '->' as opposed
to '.'.
@@ -8314,30 +8354,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaExpr.html">LambdaExpr</a>></td><td class="name" onclick="toggle('hasAnyCapture1')"><a name="hasAnyCapture1Anchor">hasAnyCapture</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXThisExpr.html">CXXThisExpr</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasAnyCapture1"><pre>Matches any capture of 'this' in a lambda expression.
-
-Given
- struct foo {
- void bar() {
- auto f = [this](){};
- }
- }
-lambdaExpr(hasAnyCapture(cxxThisExpr()))
- matches [this](){};
-</pre></td></tr>
-
-
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaExpr.html">LambdaExpr</a>></td><td class="name" onclick="toggle('hasAnyCapture0')"><a name="hasAnyCapture0Anchor">hasAnyCapture</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasAnyCapture0"><pre>Matches any capture of a lambda expression.
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaCapture.html">LambdaCapture</a>></td><td class="name" onclick="toggle('capturesVar0')"><a name="capturesVar0Anchor">capturesVar</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="capturesVar0"><pre>Matches a `LambdaCapture` that refers to the specified `VarDecl`. The
+`VarDecl` can be a separate variable that is captured by value or
+reference, or a synthesized variable if the capture has an initializer.
Given
void foo() {
int x;
auto f = [x](){};
+ auto g = [x = 1](){};
}
-lambdaExpr(hasAnyCapture(anything()))
- matches [x](){};
+In the matcher
+lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(hasName("x")))),
+capturesVar(hasName("x")) matches `x` and `x = 1`.
</pre></td></tr>
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ba15803e6f482..56ed6d28949f3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -220,6 +220,13 @@ AST Matchers
matcher or the ``hasReturnTypeLoc`` matcher. The addition of these matchers
was made possible by changes to the handling of ``TypeLoc`` nodes that
allows them to enjoy the same static type checking as other AST node kinds.
+- ``LambdaCapture`` AST Matchers are now available. These matchers allow for
+ the binding of ``LambdaCapture`` nodes. The ``LambdaCapture`` matchers added
+ include the ``lambdaCapture`` node matcher, the ``capturesVar`` traversal
+ matcher, and ``capturesThis`` narrowing matcher.
+- The ``hasAnyCapture`` matcher now only accepts an inner matcher of type
+ ``Matcher<LambdaCapture>``. The matcher originally accepted an inner matcher
+ of type ``Matcher<CXXThisExpr>`` or ``Matcher<VarDecl>``.
clang-format
------------
diff --git a/clang/include/clang/AST/ASTTypeTraits.h b/clang/include/clang/AST/ASTTypeTraits.h
index 144977b3cd219..6d96146a4d455 100644
--- a/clang/include/clang/AST/ASTTypeTraits.h
+++ b/clang/include/clang/AST/ASTTypeTraits.h
@@ -17,6 +17,7 @@
#include "clang/AST/ASTFwd.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TypeLoc.h"
@@ -64,6 +65,7 @@ class ASTNodeKind {
static ASTNodeKind getFromNode(const Stmt &S);
static ASTNodeKind getFromNode(const Type &T);
static ASTNodeKind getFromNode(const TypeLoc &T);
+ static ASTNodeKind getFromNode(const LambdaCapture &L);
static ASTNodeKind getFromNode(const OMPClause &C);
static ASTNodeKind getFromNode(const Attr &A);
/// \}
@@ -131,6 +133,7 @@ class ASTNodeKind {
NKI_None,
NKI_TemplateArgument,
NKI_TemplateArgumentLoc,
+ NKI_LambdaCapture,
NKI_TemplateName,
NKI_NestedNameSpecifierLoc,
NKI_QualType,
@@ -197,6 +200,7 @@ class ASTNodeKind {
KIND_TO_KIND_ID(CXXCtorInitializer)
KIND_TO_KIND_ID(TemplateArgument)
KIND_TO_KIND_ID(TemplateArgumentLoc)
+KIND_TO_KIND_ID(LambdaCapture)
KIND_TO_KIND_ID(TemplateName)
KIND_TO_KIND_ID(NestedNameSpecifier)
KIND_TO_KIND_ID(NestedNameSpecifierLoc)
@@ -540,6 +544,10 @@ template <>
struct DynTypedNode::BaseConverter<TemplateArgumentLoc, void>
: public ValueConverter<TemplateArgumentLoc> {};
+template <>
+struct DynTypedNode::BaseConverter<LambdaCapture, void>
+ : public ValueConverter<LambdaCapture> {};
+
template <>
struct DynTypedNode::BaseConverter<
TemplateName, void> : public ValueConverter<TemplateName> {};
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index dfd1d8bc56fc8..aa49d4cf5e962 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -148,6 +148,7 @@ using CXXBaseSpecifierMatcher = internal::Matcher<CXXBaseSpecifier>;
using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>;
using TemplateArgumentMatcher = internal::Matcher<TemplateArgument>;
using TemplateArgumentLocMatcher = internal::Matcher<TemplateArgumentLoc>;
+using LambdaCaptureMatcher = internal::Matcher<LambdaCapture>;
using AttrMatcher = internal::Matcher<Attr>;
/// @}
@@ -756,7 +757,8 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasSpecializedTemplate,
/// Matches an entity that has been implicitly added by the compiler (e.g.
/// implicit default/copy constructors).
AST_POLYMORPHIC_MATCHER(isImplicit,
- AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Attr)) {
+ AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Attr,
+ LambdaCapture)) {
return Node.isImplicit();
}
@@ -4588,50 +4590,68 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
return false;
}
-/// Matches any capture of a lambda expression.
+extern const internal::VariadicAllOfMatcher<LambdaCapture> lambdaCapture;
+
+/// Matches any capture in a lambda expression.
///
/// Given
/// \code
/// void foo() {
-/// int x;
-/// auto f = [x](){};
+/// int t = 5;
+/// auto f = [=](){ return t; };
/// }
/// \endcode
-/// lambdaExpr(hasAnyCapture(anything()))
-/// matches [x](){};
-AST_MATCHER_P_OVERLOAD(LambdaExpr, hasAnyCapture, internal::Matcher<VarDecl>,
- InnerMatcher, 0) {
+/// lambdaExpr(hasAnyCapture(lambdaCapture())) and
+/// lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("t")))))
+/// both match `[=](){ return t; }`.
+AST_MATCHER_P(LambdaExpr, hasAnyCapture, LambdaCaptureMatcher, InnerMatcher) {
for (const LambdaCapture &Capture : Node.captures()) {
- if (Capture.capturesVariable()) {
- BoundNodesTreeBuilder Result(*Builder);
- if (InnerMatcher.matches(*Capture.getCapturedVar(), Finder, &Result)) {
- *Builder = std::move(Result);
- return true;
- }
+ clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
+ if (InnerMatcher.matches(Capture, Finder, &Result)) {
+ *Builder = std::move(Result);
+ return true;
}
}
return false;
}
-/// Matches any capture of 'this' in a lambda expression.
+/// Matches a `LambdaCapture` that refers to the specified `VarDecl`. The
+/// `VarDecl` can be a separate variable that is captured by value or
+/// reference, or a synthesized variable if the capture has an initializer.
///
/// Given
/// \code
-/// struct foo {
-/// void bar() {
-/// auto f = [this](){};
-/// }
+/// void foo() {
+/// int x;
+/// auto f = [x](){};
+/// auto g = [x = 1](){};
/// }
/// \endcode
-/// lambdaExpr(hasAnyCapture(cxxThisExpr()))
-/// matches [this](){};
-AST_MATCHER_P_OVERLOAD(LambdaExpr, hasAnyCapture,
- internal::Matcher<CXXThisExpr>, InnerMatcher, 1) {
- return llvm::any_of(Node.captures(), [](const LambdaCapture &LC) {
- return LC.capturesThis();
- });
+/// In the matcher
+/// lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(hasName("x")))),
+/// capturesVar(hasName("x")) matches `x` and `x = 1`.
+AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher<VarDecl>,
+ InnerMatcher) {
+ auto *capturedVar = Node.getCapturedVar();
+ return capturedVar && InnerMatcher.matches(*capturedVar, Finder, Builder);
}
+/// Matches a `LambdaCapture` that refers to 'this'.
+///
+/// Given
+/// \code
+/// class C {
+/// int cc;
+/// int f() {
+/// auto l = [this]() { return cc; };
+/// return l();
+/// }
+/// };
+/// \endcode
+/// lambdaExpr(hasAnyCapture(lambdaCapture(capturesThis())))
+/// matches `[this]() { return cc; }`.
+AST_MATCHER(LambdaCapture, capturesThis) { return Node.capturesThis(); }
+
/// Matches a constructor call expression which uses list initialization.
AST_MATCHER(CXXConstructExpr, isListInitialization) {
return Node.isListInitialization();
diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp
index 88f86cbb367ac..b333f4618efb8 100644
--- a/clang/lib/AST/ASTTypeTraits.cpp
+++ b/clang/lib/AST/ASTTypeTraits.cpp
@@ -26,6 +26,7 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
{NKI_None, "<None>"},
{NKI_None, "TemplateArgument"},
{NKI_None, "TemplateArgumentLoc"},
+ {NKI_None, "LambdaCapture"},
{NKI_None, "TemplateName"},
{NKI_None, "NestedNameSpecifierLoc"},
{NKI_None, "QualType"},
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 7b52a083f54c9..395051e0dfae6 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -106,7 +106,6 @@ RegistryMaps::RegistryMaps() {
std::make_unique<internal::MapAnyOfBuilderDescriptor>());
REGISTER_OVERLOADED_2(callee);
- REGISTER_OVERLOADED_2(hasAnyCapture);
REGISTER_OVERLOADED_2(hasPrefix);
REGISTER_OVERLOADED_2(hasType);
REGISTER_OVERLOADED_2(ignoringParens);
@@ -157,6 +156,8 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(builtinType);
REGISTER_MATCHER(cStyleCastExpr);
REGISTER_MATCHER(callExpr);
+ REGISTER_MATCHER(capturesThis);
+ REGISTER_MATCHER(capturesVar);
REGISTER_MATCHER(caseStmt);
REGISTER_MATCHER(castExpr);
REGISTER_MATCHER(characterLiteral);
@@ -264,6 +265,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasAnyBase);
REGISTER_MATCHER(hasAnyBinding);
REGISTER_MATCHER(hasAnyBody);
+ REGISTER_MATCHER(hasAnyCapture);
REGISTER_MATCHER(hasAnyClause);
REGISTER_MATCHER(hasAnyConstructorInitializer);
REGISTER_MATCHER(hasAnyDeclaration);
@@ -465,6 +467,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(lValueReferenceType);
REGISTER_MATCHER(labelDecl);
REGISTER_MATCHER(labelStmt);
+ REGISTER_MATCHER(lambdaCapture);
REGISTER_MATCHER(lambdaExpr);
REGISTER_MATCHER(linkageSpecDecl);
REGISTER_MATCHER(materializeTemporaryExpr);
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 877cc6185a4b1..05a01f6735a8c 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -4445,5 +4445,42 @@ TEST_P(ASTMatchersTest, HasDirectBase) {
cxxRecordDecl(hasName("Derived"),
hasDirectBase(hasType(cxxRecordDecl(hasName("Base")))))));
}
+
+TEST_P(ASTMatchersTest, CapturesThis) {
+ if (!GetParam().isCXX11OrLater()) {
+ return;
+ }
+ auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(capturesThis())));
+ EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [this](){ return "
+ "cc; }; return l(); } };",
+ matcher));
+ EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [=](){ return cc; "
+ "}; return l(); } };",
+ matcher));
+ EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [&](){ return cc; "
+ "}; return l(); } };",
+ matcher));
+ EXPECT_FALSE(matches("class C { int cc; int f() { auto l = [cc](){ return "
+ "cc; }; return l(); } };",
+ matcher));
+ EXPECT_FALSE(matches("class C { int this; int f() { auto l = [this](){ "
+ "return this; }; return l(); } };",
+ matcher));
+}
+
+TEST_P(ASTMatchersTest, IsImplicit_LambdaCapture) {
+ if (!GetParam().isCXX11OrLater()) {
+ return;
+ }
+ auto matcher = lambdaExpr(hasAnyCapture(
+ lambdaCapture(isImplicit(), capturesVar(varDecl(hasName("cc"))))));
+ EXPECT_TRUE(
+ matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+ EXPECT_TRUE(
+ matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+ EXPECT_FALSE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+ matcher));
+}
+
} // namespace ast_matchers
} // namespace clang
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 022f6ef8e5772..ed222a1fdf877 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,65 @@ TEST_P(ASTMatchersTest,
varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc()))));
}
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+ if (!GetParam().isCXX11OrLater()) {
+ return;
+ }
+ EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+ lambdaExpr(hasAnyCapture(lambdaCapture()))));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfVarDecl) {
+ if (!GetParam().isCXX11OrLater()) {
+ return;
+ }
+ auto matcher = lambdaExpr(
+ hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"))))));
+ EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+ matcher));
+ EXPECT_TRUE(matches("int main() { int cc; auto f = [&cc](){ return cc; }; }",
+ matcher));
+ EXPECT_TRUE(
+ matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+ EXPECT_TRUE(
+ matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {
+ if (!GetParam().isCXX14OrLater()) {
+ return;
+ }
+ auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(
+ varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1))))))));
+ EXPECT_TRUE(
+ matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+ EXPECT_TRUE(
+ matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",
+ matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_DoesNotBindToCaptureOfVarDecl) {
+ if (!GetParam().isCXX11OrLater()) {
+ return;
+ }
+ auto matcher = lambdaExpr(
+ hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"))))));
+ EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+ EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+ matcher));
+}
+
+TEST_P(ASTMatchersTest,
+ LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {
+ if (!GetParam().isCXX14OrLater()) {
+ return;
+ }
+ EXPECT_FALSE(matches(
+ "int main() { auto lambda = [xx = 1] {return xx;}; }",
+ lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(varDecl(
+ hasName("cc"), hasInitializer(integerLiteral(equals(1))))))))));
+}
+
TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
// Don't find ObjCMessageExpr where none are present.
EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything())));
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index af15572a573b6..e1540e9096e63 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -563,26 +563,6 @@ TEST(Matcher, HasReceiver) {
objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
}
-TEST(Matcher, HasAnyCapture) {
- auto HasCaptureX = lambdaExpr(hasAnyCapture(varDecl(hasName("x"))));
- EXPECT_TRUE(matches("void f() { int x = 3; [x](){}; }", HasCaptureX));
- EXPECT_TRUE(matches("void f() { int x = 3; [&x](){}; }", HasCaptureX));
- EXPECT_TRUE(notMatches("void f() { [](){}; }", HasCaptureX));
- EXPECT_TRUE(notMatches("void f() { int z = 3; [&z](){}; }", HasCaptureX));
- EXPECT_TRUE(
- notMatches("struct a { void f() { [this](){}; }; };", HasCaptureX));
-}
-
-TEST(Matcher, CapturesThis) {
- auto HasCaptureThis = lambdaExpr(hasAnyCapture(cxxThisExpr()));
- EXPECT_TRUE(
- matches("struct a { void f() { [this](){}; }; };", HasCaptureThis));
- EXPECT_TRUE(notMatches("void f() { [](){}; }", HasCaptureThis));
- EXPECT_TRUE(notMatches("void f() { int x = 3; [x](){}; }", HasCaptureThis));
- EXPECT_TRUE(notMatches("void f() { int x = 3; [&x](){}; }", HasCaptureThis));
- EXPECT_TRUE(notMatches("void f() { int z = 3; [&z](){}; }", HasCaptureThis));
-}
-
TEST(Matcher, MatchesMethodsOnLambda) {
StringRef Code = R"cpp(
struct A {
More information about the cfe-commits
mailing list