massberg updated this revision to Diff 480475. massberg added a comment. Moved check if we have a pack expansion with reference type to Sema::BuildLambdaExpr.
I'm still not sure if this is the right place, or if `From.isCopyCapture()` should be `false` for pack expansions with refernece types. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D139125/new/ https://reviews.llvm.org/D139125 Files: clang/lib/Sema/SemaLambda.cpp clang/lib/Sema/TreeTransform.h clang/test/SemaCXX/lambda-pack-expansion.cpp clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ 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 <class ...T> void f(T &...args) {" + " [&...args = args] () mutable {" + " }();" + "}" + "int main() {" + " int a;" + " f(a);" + "}", matcher)); + EXPECT_FALSE(matches("template <class ...T> void f(T &...args) {" + " [...args = args] () mutable {" + " }();" + "}" + "int main() {" + " int a;" + " f(a);" + "}", matcher)); +} + TEST(ASTMatchersTestObjC, ObjCMessageCalees) { StatementMatcher MessagingFoo = objcMessageExpr(callee(objcMethodDecl(hasName("foo")))); Index: clang/test/SemaCXX/lambda-pack-expansion.cpp =================================================================== --- /dev/null +++ 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); +} +} Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ 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<VarDecl>(C->getCapturedVar())->getInitStyle() != VarDecl::CInit, Index: clang/lib/Sema/SemaLambda.cpp =================================================================== --- clang/lib/Sema/SemaLambda.cpp +++ clang/lib/Sema/SemaLambda.cpp @@ -1900,6 +1900,12 @@ ValueDecl *Var = From.getVariable(); LambdaCaptureKind Kind = From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef; + if (isa<PackExpansionType>(Var->getType()) && + cast<PackExpansionType>(Var->getType()) + ->getPattern() + ->isReferenceType()) { + Kind = LCK_ByRef; + } return LambdaCapture(From.getLocation(), IsImplicit, Kind, Var, From.getEllipsisLoc()); }
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ 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 <class ...T> void f(T &...args) {" + " [&...args = args] () mutable {" + " }();" + "}" + "int main() {" + " int a;" + " f(a);" + "}", matcher)); + EXPECT_FALSE(matches("template <class ...T> void f(T &...args) {" + " [...args = args] () mutable {" + " }();" + "}" + "int main() {" + " int a;" + " f(a);" + "}", matcher)); +} + TEST(ASTMatchersTestObjC, ObjCMessageCalees) { StatementMatcher MessagingFoo = objcMessageExpr(callee(objcMethodDecl(hasName("foo")))); Index: clang/test/SemaCXX/lambda-pack-expansion.cpp =================================================================== --- /dev/null +++ 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); +} +} Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ 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<VarDecl>(C->getCapturedVar())->getInitStyle() != VarDecl::CInit, Index: clang/lib/Sema/SemaLambda.cpp =================================================================== --- clang/lib/Sema/SemaLambda.cpp +++ clang/lib/Sema/SemaLambda.cpp @@ -1900,6 +1900,12 @@ ValueDecl *Var = From.getVariable(); LambdaCaptureKind Kind = From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef; + if (isa<PackExpansionType>(Var->getType()) && + cast<PackExpansionType>(Var->getType()) + ->getPattern() + ->isReferenceType()) { + Kind = LCK_ByRef; + } return LambdaCapture(From.getLocation(), IsImplicit, Kind, Var, From.getEllipsisLoc()); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits