diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index edc932efd9416..838cb69f647ee 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -973,6 +973,8 @@ Bug Fixes to C++ Support of the address of operator. (#GH97483). - Fixed an assertion failure about a constant expression which is a known integer but is not evaluated to an integer. (#GH96670). +- Fixed a bug where references to lambda capture inside a ``noexcept`` specifier were not correctly + instantiated. (#GH95735). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 64f6b01bed229..2e90f0c215b8d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4704,6 +4704,12 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, return; } + // The noexcept specification could reference any lambda captures. Ensure + // those are added to the LocalInstantiationScope. + LambdaScopeForCallOperatorInstantiationRAII PushLambdaCaptures( + *this, Decl, TemplateArgs, Scope, + /*ShouldAddDeclsFromParentScope=*/false); + SubstExceptionSpec(Decl, Template->getType()->castAs(), TemplateArgs); } diff --git a/clang/test/SemaTemplate/generic-lambda.cpp b/clang/test/SemaTemplate/generic-lambda.cpp index fb5fa09ebcc1f..804eeaa29d6a1 100644 --- a/clang/test/SemaTemplate/generic-lambda.cpp +++ b/clang/test/SemaTemplate/generic-lambda.cpp @@ -60,3 +60,26 @@ template C1>> auto t3() { template C1>> auto t3(); static_assert(is_same()), X>>>); #endif + +namespace GH95735 { + +int g(int fn) { + return [f = fn](auto tpl) noexcept(noexcept(f)) { return f; }(0); +} + +int foo(auto... fn) { + // FIXME: This one hits the assertion "if the exception specification is dependent, + // then the noexcept expression should be value-dependent" in the constructor of + // FunctionProtoType. + // One possible solution is to update Sema::canThrow() to consider expressions + // (e.g. DeclRefExpr/FunctionParmPackExpr) involving unexpanded parameters as Dependent. + // This would effectively add an extra value-dependent flag to the noexcept expression. + // However, I'm afraid that would also cause ABI breakage. + // [...f = fn](auto tpl) noexcept(noexcept(f)) { return 0; }(0); + [...f = fn](auto tpl) noexcept(noexcept(g(fn...))) { return 0; }(0); + return [...f = fn](auto tpl) noexcept(noexcept(g(f...))) { return 0; }(0); +} + +int v = foo(42); + +} // namespace GH95735