mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 11:46:40 +00:00

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
86 lines
2.4 KiB
C++
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
|