llvm-project/clang/test/SemaTemplate/generic-lambda.cpp
Younan Zhang f4c781174b
[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 https://github.com/llvm/llvm-project/issues/95735
2024-07-07 09:46:38 +08:00

86 lines
2.4 KiB
C++

// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
// expected-no-diagnostics
template <class T, class U> constexpr bool is_same_v = false;
template <class T> constexpr bool is_same_v<T, T> = true;
template <class T, class U>
concept is_same = is_same_v<T, U>;
template <class T> struct X {};
template <class T, class U>
concept C1 = is_same<T, X<U>>;
template <class T1> X<X<X<T1>>> t1() {
return []<class T2>(T2) -> X<X<T2>> {
struct S {
static X<X<T2>> f() {
return []<class T3>(T3) -> X<T3> {
static_assert(is_same<T2, X<T1>>);
static_assert(is_same<T3, X<T2>>);
return X<T3>();
}(X<T2>());
}
};
return S::f();
}(X<T1>());
};
template X<X<X<int>>> t1<int>();
#if 0 // FIXME: crashes
template<class T1> auto t2() {
return []<class T2>(T2) {
struct S {
static auto f() {
return []<class T3>(T3) {
static_assert(is_same<T2, X<T1>>);
static_assert(is_same<T3, X<T2>>);
return X<T3>();
}(X<T2>());
}
};
return S::f();
}(X<T1>());
};
template auto t2<int>();
static_assert(is_same<decltype(t2<int>()), X<X<X<int>>>>);
template<class T1> C1<X<X<T1>>> auto t3() {
return []<C1<T1> T2>(T2) -> C1<X<T2>> auto {
struct S {
static auto f() {
return []<C1<T2> T3>(T3) -> C1<T3> auto {
return X<T3>();
}(X<T2>());
}
};
return S::f();
}(X<T1>());
};
template C1<X<X<int>>> auto t3<int>();
static_assert(is_same<decltype(t3<int>()), X<X<X<int>>>>);
#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