blob: 7bf36a6a9cab732c4d53a420f5385467a9ff1dfd [file] [log] [blame]
// RUN: %clang_cc1 -std=c++23 -verify -fsyntax-only %s
template <typename T, typename U>
constexpr bool is_same = false;
template <typename T>
constexpr bool is_same<T, T> = true;
void f() {
int y;
static_assert(is_same<const int &,
decltype([x = 1] -> decltype((x)) { return x; }())>);
static_assert(is_same<int &,
decltype([x = 1] mutable -> decltype((x)) { return x; }())>);
static_assert(is_same<const int &,
decltype([=] -> decltype((y)) { return y; }())>);
static_assert(is_same<int &,
decltype([=] mutable -> decltype((y)) { return y; }())>);
static_assert(is_same<const int &,
decltype([=] -> decltype((y)) { return y; }())>);
static_assert(is_same<int &,
decltype([=] mutable -> decltype((y)) { return y; }())>);
auto ref = [&x = y](
decltype([&](decltype(x)) { return 0; }) y) {
return x;
};
}
void test_noexcept() {
int y;
static_assert(noexcept([x = 1] noexcept(is_same<const int &, decltype((x))>) {}()));
static_assert(noexcept([x = 1] mutable noexcept(is_same<int &, decltype((x))>) {}()));
static_assert(noexcept([y] noexcept(is_same<const int &, decltype((y))>) {}()));
static_assert(noexcept([y] mutable noexcept(is_same<int &, decltype((y))>) {}()));
static_assert(noexcept([=] noexcept(is_same<const int &, decltype((y))>) {}()));
static_assert(noexcept([=] mutable noexcept(is_same<int &, decltype((y))>) {}()));
static_assert(noexcept([&] noexcept(is_same<int &, decltype((y))>) {}()));
static_assert(noexcept([&] mutable noexcept(is_same<int &, decltype((y))>) {}()));
}
template<typename T>
void test_requires() {
int x;
[x = 1]() requires is_same<const int &, decltype((x))> {}
();
[x = 1]() mutable requires is_same<int &, decltype((x))> {}
();
[x]() requires is_same<const int &, decltype((x))> {}
();
[x]() mutable requires is_same<int &, decltype((x))> {}
();
[=]() requires is_same<const int &, decltype((x))> {}
();
[=]() mutable requires is_same<int &, decltype((x))> {}
();
[&]() requires is_same<int &, decltype((x))> {}
();
[&]() mutable requires is_same<int &, decltype((x))> {}
();
[&x]() requires is_same<int &, decltype((x))> {}
();
[&x]() mutable requires is_same<int &, decltype((x))> {}
();
[x = 1]() requires is_same<const int &, decltype((x))> {} ();
[x = 1]() mutable requires is_same<int &, decltype((x))> {} ();
}
void use() {
test_requires<int>();
}
void err() {
int y, z;
(void)[x = 1]<typename T>
requires(is_same<const int &, decltype((x))>) {};
(void)[x = 1]<typename T = decltype((x))>{};
(void)[=]<typename T = decltype((y))>{};
(void)[z]<typename T = decltype((z))>{};
}
void gnu_attributes() {
int y;
(void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), const int &>, "wrong type", "warning"))){}();
// expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
(void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), int &>, "wrong type", "warning"))){}();
(void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), int &>, "wrong type", "warning"))) mutable {}();
(void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), const int &>, "wrong type", "warning"))) mutable {}();
// expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
(void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), const int &>, "wrong type", "warning"))){}();
// expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
(void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), int &>, "wrong type", "warning"))){}();
(void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), int &>, "wrong type", "warning"))) mutable {}();
(void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), const int &>, "wrong type", "warning"))) mutable {}();
// expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
}
void nested() {
int x, y, z;
(void)[&](
decltype([&](
decltype([=](
decltype([&](
decltype([&](decltype(x)) {})) {})) {})) {})){};
(void)[&](
decltype([&](
decltype([&](
decltype([&](
decltype([&](decltype(y)) {})) {})) {})) {})){};
(void)[=](
decltype([=](
decltype([=](
decltype([=](
decltype([&]<decltype(z)> {})) {})) {})) {})){};
}
template <typename T, typename U>
void dependent(U&& u) {
[&]() requires is_same<decltype(u), T> {}();
}
template <typename T>
void dependent_init_capture(T x = 0) {
[ y = x + 1, x ]() mutable -> decltype(y + x)
requires(is_same<decltype((y)), int &>
&& is_same<decltype((x)), int &>) {
return y;
}
();
[ y = x + 1, x ]() -> decltype(y + x)
requires(is_same<decltype((y)), const int &>
&& is_same<decltype((x)), const int &>) {
return y;
}
();
}
template <typename T, typename...>
struct extract_type {
using type = T;
};
template <typename... T>
void dependent_variadic_capture(T... x) {
[... y = x, x... ](auto...) mutable -> typename extract_type<decltype(y)...>::type requires((is_same<decltype((y)), int &> && ...) && (is_same<decltype((x)), int &> && ...)) {
return 0;
}
(x...);
[... y = x, x... ](auto...) -> typename extract_type<decltype(y)...>::type requires((is_same<decltype((y)), const int &> && ...) && (is_same<decltype((x)), const int &> && ...)) {
return 0;
}
(x...);
}
void test_dependent() {
int v = 0;
int & r = v;
const int & cr = v;
dependent<int&>(v);
dependent<int&>(r);
dependent<const int&>(cr);
dependent_init_capture(0);
dependent_variadic_capture(1, 2, 3, 4);
}
void check_params() {
int i = 0;
int &j = i;
(void)[=](decltype((j)) jp, decltype((i)) ip) {
static_assert(is_same<const int&, decltype((j))>);
static_assert(is_same<const int &, decltype((i))>);
static_assert(is_same<int &, decltype((jp))>);
static_assert(is_same<int &, decltype((ip))>);
};
(void)[=](decltype((j)) jp, decltype((i)) ip) mutable {
static_assert(is_same<int &, decltype((j))>);
static_assert(is_same<int &, decltype((i))>);
static_assert(is_same<int &, decltype((jp))>);
static_assert(is_same<int &, decltype((ip))>);
static_assert(is_same<int &, decltype(jp)>);
static_assert(is_same<int &, decltype(ip)>);
};
(void)[a = 0](decltype((a)) ap) mutable {
static_assert(is_same<int &, decltype((a))>);
static_assert(is_same<int, decltype(a)>);
static_assert(is_same<int &, decltype(ap)>);
};
(void)[a = 0](decltype((a)) ap) {
static_assert(is_same<const int &, decltype((a))>);
static_assert(is_same<int, decltype(a)>);
static_assert(is_same<int&, decltype((ap))>);
};
}
template <typename T>
void check_params_tpl() {
T i = 0;
T &j = i;
(void)[=](decltype((j)) jp, decltype((i)) ip) {
static_assert(is_same<const int&, decltype((j))>);
static_assert(is_same<const int &, decltype((i))>);
static_assert(is_same<const int &, decltype((jp))>);
static_assert(is_same<const int &, decltype((ip))>);
};
(void)[=](decltype((j)) jp, decltype((i)) ip) mutable {
static_assert(is_same<int &, decltype((j))>);
static_assert(is_same<int &, decltype((i))>);
static_assert(is_same<int &, decltype((jp))>);
static_assert(is_same<int &, decltype((ip))>);
static_assert(is_same<int &, decltype(jp)>);
static_assert(is_same<int &, decltype(ip)>);
};
(void)[a = 0](decltype((a)) ap) mutable {
static_assert(is_same<int &, decltype((a))>);
static_assert(is_same<int, decltype(a)>);
static_assert(is_same<int &, decltype(ap)>);
};
(void)[a = 0](decltype((a)) ap) {
static_assert(is_same<const int &, decltype((a))>);
static_assert(is_same<int, decltype(a)>);
static_assert(is_same<int&, decltype((ap))>);
};
}
namespace GH61267 {
template <typename> concept C = true;
template<typename>
void f(int) {
int i;
[i]<C P>(P) {}(0);
i = 4;
}
void test() { f<int>(0); }
}
namespace GH65067 {
template <typename> class a {
public:
template <typename b> void c(b f) { d<int>(f)(0); }
template <typename, typename b> auto d(b f) {
return [f = f](auto arg) -> a<decltype(f(arg))> { return {}; };
}
};
a<void> e;
auto fn1() {
e.c([](int) {});
}
}
namespace GH63675 {
template <class _Tp> _Tp __declval();
struct __get_tag {
template <class _Tag> void operator()(_Tag);
};
template <class _ImplFn> struct __basic_sender {
using __tag_t = decltype(__declval<_ImplFn>()(__declval<__get_tag>()));
_ImplFn __impl_;
};
auto __make_basic_sender = []<class... _Children>(
_Children... __children) {
return __basic_sender{[... __children = __children]<class _Fun>(
_Fun __fun) -> decltype(__fun(__children...)) {}};
};
void __trans_tmp_1() {
__make_basic_sender(__trans_tmp_1);
}
}