diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2062,7 +2062,7 @@ if (const auto *MD = dyn_cast(D)) { if (const CXXRecordDecl *RD = MD->getParent()) { - if (RD->isLambda()) { + if (RD->isLambda() && RD->getLambdaCallOperator() == MD) { VisitBody = VisitBody && getDerived().shouldVisitLambdaBody(); } } diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -474,6 +474,42 @@ EXPECT_TRUE(notMatches("void f() { int z = 3; [&z](){}; }", HasCaptureThis)); } +TEST(Matcher, MatchesMethodsOnLambda) { + StringRef Code = R"cpp( +struct A { + ~A() {} +}; +void foo() +{ + A a; + auto l = [a] { }; + auto lCopy = l; + auto lPtrDecay = +[] { }; + (void)lPtrDecay; +} +)cpp"; + + EXPECT_TRUE(matches( + Code, cxxConstructorDecl( + hasBody(compoundStmt()), + hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))), + isCopyConstructor()))); + EXPECT_TRUE(matches( + Code, cxxConstructorDecl( + hasBody(compoundStmt()), + hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))), + isMoveConstructor()))); + EXPECT_TRUE(matches( + Code, cxxDestructorDecl( + hasBody(compoundStmt()), + hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l")))))))); + EXPECT_TRUE(matches( + Code, cxxConversionDecl(hasBody(compoundStmt(has(returnStmt( + hasReturnValue(implicitCastExpr()))))), + hasAncestor(lambdaExpr(hasAncestor( + varDecl(hasName("lPtrDecay")))))))); +} + TEST(Matcher, isClassMessage) { EXPECT_TRUE(matchesObjC( "@interface NSString +(NSString *) stringWithFormat; @end "