Skip to content

Commit f4c7811

Browse files
authored
[Clang] Add captures to the instantiation scope for noexcept specifiers (#97166)
The noexcept specifiers of dependent lambdas would be transformed and rebuilt, where the map of instantiation should also contain captured variables in case they are used from the noexcept specifier. I also uncovered another assertion failure while at it. However, I decided to leave it as-is because 1) that doesn't appear to be the case in the release version and 2) fixing that might lead to ABI breakage. Anyhow, the case has been added to the test comment. Fixes #95735
1 parent 1acb086 commit f4c7811

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,8 @@ Bug Fixes to C++ Support
973973
of the address of operator. (#GH97483).
974974
- Fixed an assertion failure about a constant expression which is a known integer but is not
975975
evaluated to an integer. (#GH96670).
976+
- Fixed a bug where references to lambda capture inside a ``noexcept`` specifier were not correctly
977+
instantiated. (#GH95735).
976978

977979
Bug Fixes to AST Handling
978980
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4704,6 +4704,12 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
47044704
return;
47054705
}
47064706

4707+
// The noexcept specification could reference any lambda captures. Ensure
4708+
// those are added to the LocalInstantiationScope.
4709+
LambdaScopeForCallOperatorInstantiationRAII PushLambdaCaptures(
4710+
*this, Decl, TemplateArgs, Scope,
4711+
/*ShouldAddDeclsFromParentScope=*/false);
4712+
47074713
SubstExceptionSpec(Decl, Template->getType()->castAs<FunctionProtoType>(),
47084714
TemplateArgs);
47094715
}

clang/test/SemaTemplate/generic-lambda.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,26 @@ template<class T1> C1<X<X<T1>>> auto t3() {
6060
template C1<X<X<int>>> auto t3<int>();
6161
static_assert(is_same<decltype(t3<int>()), X<X<X<int>>>>);
6262
#endif
63+
64+
namespace GH95735 {
65+
66+
int g(int fn) {
67+
return [f = fn](auto tpl) noexcept(noexcept(f)) { return f; }(0);
68+
}
69+
70+
int foo(auto... fn) {
71+
// FIXME: This one hits the assertion "if the exception specification is dependent,
72+
// then the noexcept expression should be value-dependent" in the constructor of
73+
// FunctionProtoType.
74+
// One possible solution is to update Sema::canThrow() to consider expressions
75+
// (e.g. DeclRefExpr/FunctionParmPackExpr) involving unexpanded parameters as Dependent.
76+
// This would effectively add an extra value-dependent flag to the noexcept expression.
77+
// However, I'm afraid that would also cause ABI breakage.
78+
// [...f = fn](auto tpl) noexcept(noexcept(f)) { return 0; }(0);
79+
[...f = fn](auto tpl) noexcept(noexcept(g(fn...))) { return 0; }(0);
80+
return [...f = fn](auto tpl) noexcept(noexcept(g(f...))) { return 0; }(0);
81+
}
82+
83+
int v = foo(42);
84+
85+
} // namespace GH95735

0 commit comments

Comments
 (0)