diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8bd06fadfdc98..553856f3060bc 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -712,6 +712,7 @@ Bug Fixes to C++ Support - Name independent data members were not correctly initialized from default member initializers. (#GH114069) - Fixed expression transformation for ``[[assume(...)]]``, allowing using pack indexing expressions within the assumption if they also occur inside of a dependent lambda. (#GH114787) +- Lambdas now capture function types without considering top-level const qualifiers. (#GH84961) - Clang now uses valid deduced type locations when diagnosing functions with trailing return type missing placeholder return type. (#GH78694) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 6c7472ce92703..47612ef2effb9 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -18479,7 +18479,11 @@ static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, // are mutable in the sense that user can change their value - they are // private instances of the captured declarations. const Capture &Cap = CSI->getCapture(Var); - if (Cap.isCopyCapture() && + // C++ [expr.prim.lambda]p10: + // The type of such a data member is [...] an lvalue reference to the + // referenced function type if the entity is a reference to a function. + // [...] + if (Cap.isCopyCapture() && !DeclRefType->isFunctionType() && !(isa(CSI) && !cast(CSI)->lambdaCaptureShouldBeConst()) && !(isa(CSI) && @@ -18789,7 +18793,12 @@ static bool captureInLambda(LambdaScopeInfo *LSI, ValueDecl *Var, // parameter-declaration-clause is not followed by mutable. DeclRefType = CaptureType.getNonReferenceType(); bool Const = LSI->lambdaCaptureShouldBeConst(); - if (Const && !CaptureType->isReferenceType()) + // C++ [expr.prim.lambda]p10: + // The type of such a data member is [...] an lvalue reference to the + // referenced function type if the entity is a reference to a function. + // [...] + if (Const && !CaptureType->isReferenceType() && + !DeclRefType->isFunctionType()) DeclRefType.addConst(); } diff --git a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp index a86f301898992..ba7ab34f943be 100644 --- a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp +++ b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp @@ -319,3 +319,17 @@ constexpr void foo() { } } // namespace GH47400 + +namespace GH84961 { + +template void g(const T &t) {} + +template void f(const T &t) { + [t] { g(t); }(); +} + +void h() { + f(h); +} + +} // namespace GH84961