1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
// RUN: %clang_cc1 -std=c++20 %s -Wno-c++23-extensions -verify
// RUN: %clang_cc1 -std=c++23 %s -verify
template <auto> struct Nothing {};
Nothing<[]() { return 0; }()> nothing;
template <typename> struct NothingT {};
Nothing<[]() { return 0; }> nothingT;
template <typename T>
concept True = [] { return true; }();
static_assert(True<int>);
static_assert(sizeof([] { return 0; }));
static_assert(sizeof([] { return 0; }()));
void f() noexcept(noexcept([] { return 0; }()));
using a = decltype([] { return 0; });
using b = decltype([] { return 0; }());
using c = decltype([]() noexcept(noexcept([] { return 0; }())) { return 0; });
using d = decltype(sizeof([] { return 0; }));
template <auto T>
int unique_test1();
static_assert(&unique_test1<[](){}> != &unique_test1<[](){}>);
template <class T>
auto g(T) -> decltype([]() { T::invalid; } ());
auto e = g(0); // expected-error@-1{{type 'int' cannot be used prior to '::'}}
// expected-note@-1{{while substituting deduced template}}
// expected-note@-3{{while substituting into a lambda}}
// expected-error@-3 {{no matching function for call to 'g'}}
// expected-note@-5 {{substitution failure}}
template <typename T>
auto foo(decltype([] {
return [] { return T(); }();
})) {}
void test() {
foo<int>({});
}
template <typename T>
struct C {
template <typename U>
auto foo(decltype([] {
return [] { return T(); }();
})) {}
};
void test2() {
C<int>{}.foo<long>({});
}
namespace PR52073 {
// OK, these are distinct functions not redefinitions.
template<typename> void f(decltype([]{})) {} // expected-note {{candidate}}
template<typename> void f(decltype([]{})) {} // expected-note {{candidate}}
void use_f() { f<int>({}); } // expected-error {{ambiguous}}
// Same.
template<int N> void g(const char (*)[([]{ return N; })()]) {} // expected-note {{candidate}}
template<int N> void g(const char (*)[([]{ return N; })()]) {} // expected-note {{candidate}}
void use_g() { g<6>(&"hello"); } // expected-error {{ambiguous}}
}
namespace GH51416 {
template <class T>
struct A {
void spam(decltype([] {}));
};
template <class T>
void A<T>::spam(decltype([] {})) // expected-error{{out-of-line definition of 'spam' does not match}}
{}
struct B {
template <class T>
void spam(decltype([] {}));
};
template <class T>
void B::spam(decltype([] {})) {} // expected-error{{out-of-line definition of 'spam' does not match}}
} // namespace GH51416
namespace GH50376 {
template <typename T, typename Fn>
struct foo_t { // expected-note 2{{candidate constructor}}
foo_t(T ptr) {} // expected-note{{candidate constructor}}
};
template <typename T>
using alias = foo_t<T, decltype([](int) { return 0; })>;
template <typename T>
auto fun(T const &t) -> alias<T> {
return alias<T>{t}; // expected-error{{no viable conversion from returned value of type 'alias<...>'}}
}
void f() {
int i;
auto const error = fun(i); // expected-note{{in instantiation}}
}
} // namespace GH50376
namespace GH51414 {
template <class T> void spam(decltype([] {}) (*s)[sizeof(T)] = nullptr) {}
void foo() {
spam<int>();
}
} // namespace GH51414
namespace GH51641 {
template <class T>
void foo(decltype(+[](T) {}) lambda, T param);
static_assert(!__is_same(decltype(foo<int>), void));
} // namespace GH51641
namespace StaticLambdas {
template <auto> struct Nothing {};
Nothing<[]() static { return 0; }()> nothing;
template <typename> struct NothingT {};
Nothing<[]() static { return 0; }> nothingT;
template <typename T>
concept True = [] static { return true; }();
static_assert(True<int>);
static_assert(sizeof([] static { return 0; }));
static_assert(sizeof([] static { return 0; }()));
void f() noexcept(noexcept([] static { return 0; }()));
using a = decltype([] static { return 0; });
using b = decltype([] static { return 0; }());
using c = decltype([]() static noexcept(noexcept([] { return 0; }())) { return 0; });
using d = decltype(sizeof([] static { return 0; }));
}
namespace lambda_in_trailing_decltype {
auto x = ([](auto) -> decltype([] {}()) {}(0), 2);
}
namespace lambda_in_constraints {
struct WithFoo { static void foo(); };
template <class T>
concept lambda_works = requires {
[]() { T::foo(); };
};
static_assert(!lambda_works<int>);
static_assert(lambda_works<WithFoo>);
template <class T>
int* func(T) requires requires { []() { T::foo(); }; };
double* func(...);
static_assert(__is_same(decltype(func(0)), double*));
static_assert(__is_same(decltype(func(WithFoo())), int*));
template <class T>
auto direct_lambda(T) -> decltype([] { T::foo(); }) {}
void direct_lambda(...) {}
void recursive() {
direct_lambda(0); // expected-error@-4 {{type 'int' cannot be used prior to '::'}}
// expected-note@-1 {{while substituting deduced template arguments}}
// expected-note@-6 {{while substituting into a lambda}}
bool x = requires { direct_lambda(0); }; // expected-error@-7 {{type 'int' cannot be used prior to '::'}}
// expected-note@-1 {{while substituting deduced template arguments}}
// expected-note@-9 {{while substituting into a lambda}}
}
}
|