| // 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 { // #defined-here-A |
| void spam(decltype([] {})); |
| }; |
| |
| template <class T> |
| void A<T>::spam(decltype([] {})) // expected-error{{out-of-line definition of 'spam' does not match}} |
| // expected-note@#defined-here-A{{defined here}} |
| {} |
| |
| struct B { // #defined-here-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}} |
| // expected-note@#defined-here-B{{defined here}} |
| |
| } // 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(); }; // expected-error{{type 'int' cannot be used prior to '::'}} |
| // expected-note@-1{{while substituting into a lambda expression here}} |
| // expected-note@-2{{in instantiation of requirement here}} |
| // expected-note@-4{{while substituting template arguments into constraint expression here}} |
| }; |
| |
| static_assert(!lambda_works<int>); // expected-note {{while checking the satisfaction of concept 'lambda_works<int>' requested here}} |
| static_assert(lambda_works<WithFoo>); |
| |
| template <class T> |
| int* func(T) requires requires { []() { T::foo(); }; }; // expected-error{{type 'int' cannot be used prior to '::'}} |
| // expected-note@-1{{while substituting into a lambda expression here}} |
| // expected-note@-2{{in instantiation of requirement here}} |
| // expected-note@-3{{while substituting template arguments into constraint expression here}} |
| double* func(...); |
| |
| static_assert(__is_same(decltype(func(0)), double*)); // expected-note {{while checking constraint satisfaction for template 'func<int>' required here}} |
| // expected-note@-1 {{in instantiation of function template specialization 'lambda_in_constraints::func<int>'}} |
| 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}} |
| |
| } |
| } |
| |
| // GH63845: Test if we have skipped past RequiresExprBodyDecls in tryCaptureVariable(). |
| namespace GH63845 { |
| |
| template <bool> struct A {}; |
| |
| struct true_type { |
| constexpr operator bool() noexcept { return true; } |
| }; |
| |
| constexpr bool foo() { |
| true_type x{}; |
| return requires { typename A<x>; }; |
| } |
| |
| static_assert(foo()); |
| |
| } // namespace GH63845 |
| |
| // GH69307: Test if we can correctly handle param decls that have yet to get into the function scope. |
| namespace GH69307 { |
| |
| constexpr auto ICE() { |
| constexpr auto b = 1; |
| return [=](auto c) -> int |
| requires requires { b + c; } |
| { return 1; }; |
| }; |
| |
| constexpr auto Ret = ICE()(1); |
| |
| } // namespace GH69307 |
| |
| // GH88081: Test if we evaluate the requires expression with lambda captures properly. |
| namespace GH88081 { |
| |
| // Test that ActOnLambdaClosureQualifiers() is called only once. |
| void foo(auto value) |
| requires requires { [&] -> decltype(value) {}; } |
| // expected-error@-1 {{non-local lambda expression cannot have a capture-default}} |
| {} |
| |
| struct S { //#S |
| S(auto value) //#S-ctor |
| requires requires { [&] -> decltype(value) { return 2; }; } {} // #S-requires |
| |
| static auto foo(auto value) -> decltype([&]() -> decltype(value) {}()) { return {}; } // #S-foo |
| |
| // FIXME: 'value' does not constitute an ODR use here. Add a diagnostic for it. |
| static auto bar(auto value) -> decltype([&] { return value; }()) { |
| return "a"; // #bar-body |
| } |
| }; |
| |
| S s("a"); // #use |
| // expected-error@#S-requires {{cannot initialize return object of type 'decltype(value)' (aka 'const char *') with an rvalue of type 'int'}} |
| // expected-error@#use {{no matching constructor}} |
| // expected-note@#S-requires {{substituting into a lambda expression here}} |
| // expected-note@#S-requires {{substituting template arguments into constraint expression here}} |
| // expected-note@#S-requires {{in instantiation of requirement here}} |
| // expected-note@#use {{checking constraint satisfaction for template 'S<const char *>' required here}} |
| // expected-note@#use {{requested here}} |
| // expected-note-re@#S 2{{candidate constructor {{.*}} not viable}} |
| // expected-note@#S-ctor {{constraints not satisfied}} |
| // expected-note-re@#S-requires {{because {{.*}} would be invalid}} |
| |
| void func() { |
| S::foo(42); |
| S::bar("str"); |
| S::bar(0.618); |
| // expected-error-re@#bar-body {{cannot initialize return object of type {{.*}} (aka 'double') with an lvalue of type 'const char[2]'}} |
| // expected-note@-2 {{requested here}} |
| } |
| |
| } // namespace GH88081 |