diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1900,6 +1900,12 @@ ValueDecl *Var = From.getVariable(); LambdaCaptureKind Kind = From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef; + if (isa(Var->getType()) && + cast(Var->getType()) + ->getPattern() + ->isReferenceType()) { + Kind = LCK_ByRef; + } return LambdaCapture(From.getLocation(), IsImplicit, Kind, Var, From.getEllipsisLoc()); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13147,9 +13147,10 @@ } Expr *NewExprInit = NewExprInitResult.get(); + bool isReferenceType = (C->getCaptureKind() == LCK_ByRef); QualType NewInitCaptureType = getSema().buildLambdaInitCaptureInitialization( - C->getLocation(), OldVD->getType()->isReferenceType(), + C->getLocation(), isReferenceType, EllipsisLoc, NumExpansions, OldVD->getIdentifier(), cast(C->getCapturedVar())->getInitStyle() != VarDecl::CInit, diff --git a/clang/test/SemaCXX/lambda-pack-expansion.cpp b/clang/test/SemaCXX/lambda-pack-expansion.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/lambda-pack-expansion.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++20 -Wno-unused-value -fsyntax-only -verify %s + +namespace GH49266 { +struct X { + X() = default; + X(X const&) = delete; // expected-note {{'X' has been explicitly marked deleted here}} +}; + +void take_by_copy(auto &...args) { + [...args = args] {}(); // expected-error {{call to deleted constructor}} +} + +void take_by_ref(auto &...args) { + [&...args = args] {}(); // args is passed by reference and not copied. +} + +void foo() { + X x; + take_by_copy(x); // expected-note {{in instantiation of function template specialization}} + take_by_ref(x); +} +} diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -2306,6 +2306,30 @@ hasName("cc"), hasInitializer(integerLiteral(equals(1)))))))))); } +TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfReferenceType) { + if (!GetParam().isCXX20OrLater()) { + return; + } + auto matcher = lambdaExpr(hasAnyCapture( + lambdaCapture(capturesVar(varDecl(hasType(referenceType())))))); + EXPECT_TRUE(matches("template void f(T &...args) {" + " [&...args = args] () mutable {" + " }();" + "}" + "int main() {" + " int a;" + " f(a);" + "}", matcher)); + EXPECT_FALSE(matches("template void f(T &...args) {" + " [...args = args] () mutable {" + " }();" + "}" + "int main() {" + " int a;" + " f(a);" + "}", matcher)); +} + TEST(ASTMatchersTestObjC, ObjCMessageCalees) { StatementMatcher MessagingFoo = objcMessageExpr(callee(objcMethodDecl(hasName("foo"))));