|  | // RUN: %clang_cc1 -std=c++20 -verify %s | 
|  | namespace GH53213 { | 
|  | template<typename T> | 
|  | concept c = requires(T t) { f(t); }; // #CDEF | 
|  |  | 
|  | auto f(c auto); // #FDEF | 
|  |  | 
|  | void g() { | 
|  | f(0); | 
|  | // expected-error@-1{{no matching function for call to 'f'}} | 
|  | // expected-note@#FDEF{{constraints not satisfied}} | 
|  | // expected-note@#FDEF{{because 'int' does not satisfy 'c'}} | 
|  | // expected-note@#CDEF{{because 'f(t)' would be invalid: no matching function for call to 'f'}} | 
|  | } | 
|  | } // namespace GH53213 | 
|  |  | 
|  | namespace GH45736 { | 
|  | struct constrained; | 
|  |  | 
|  | template<typename T> | 
|  | struct type { | 
|  | }; | 
|  | template<typename T> | 
|  | constexpr bool f(type<T>) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | template<typename T> | 
|  | concept matches = f(type<T>()); | 
|  |  | 
|  |  | 
|  | struct constrained { | 
|  | template<typename U> requires matches<U> | 
|  | explicit constrained(U value) { | 
|  | } | 
|  | }; | 
|  |  | 
|  | bool f(constrained const &) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | struct outer { | 
|  | constrained state; | 
|  | }; | 
|  |  | 
|  | bool f(outer const & x) { | 
|  | return f(x.state); | 
|  | } | 
|  | } // namespace GH45736 | 
|  |  | 
|  | namespace DirectRecursiveCheck { | 
|  | template<class T> | 
|  | concept NotInf = true; | 
|  | template<class T> | 
|  | concept Inf = requires(T& v){ // #INF_REQ | 
|  | {begin(v)}; // #INF_BEGIN_EXPR | 
|  | }; | 
|  |  | 
|  | void begin(NotInf auto& v){ } // #NOTINF_BEGIN | 
|  | // This lookup should fail, since it results in a recursive check. | 
|  | // However, this is a 'hard failure'(not a SFINAE failure or constraints | 
|  | // violation), so it needs to cause the entire lookup to fail. | 
|  | void begin(Inf auto& v){ } // #INF_BEGIN | 
|  |  | 
|  | struct my_range{ | 
|  | } rng; | 
|  |  | 
|  | void baz() { | 
|  | auto it = begin(rng); // #BEGIN_CALL | 
|  | // expected-error@#INF_BEGIN {{satisfaction of constraint 'Inf<Inf auto>' depends on itself}} | 
|  | // expected-note@#INF_BEGIN {{while substituting template arguments into constraint expression here}} | 
|  | // expected-note@#INF_BEGIN_EXPR {{while checking constraint satisfaction for template 'begin<DirectRecursiveCheck::my_range>' required here}} | 
|  | // expected-note@#INF_BEGIN_EXPR {{while substituting deduced template arguments into function template 'begin'}} | 
|  | // expected-note@#INF_BEGIN_EXPR {{in instantiation of requirement here}} | 
|  | // expected-note@#INF_REQ {{while substituting template arguments into constraint expression here}} | 
|  | // expected-note@#INF_BEGIN {{while checking the satisfaction of concept 'Inf<DirectRecursiveCheck::my_range>' requested here}} | 
|  | // expected-note@#INF_BEGIN {{while substituting template arguments into constraint expression here}} | 
|  | // expected-note@#BEGIN_CALL {{while checking constraint satisfaction for template 'begin<DirectRecursiveCheck::my_range>' required here}} | 
|  | // expected-note@#BEGIN_CALL {{while substituting deduced template arguments into function template}} | 
|  |  | 
|  | // Fallout of the failure is failed lookup, which is necessary to stop odd | 
|  | // cascading errors. | 
|  | // expected-error@#BEGIN_CALL {{no matching function for call to 'begin'}} | 
|  | // expected-note@#NOTINF_BEGIN {{candidate function}} | 
|  | // expected-note@#INF_BEGIN{{candidate template ignored: constraints not satisfied}} | 
|  | } | 
|  | } // namespace DirectRecursiveCheck | 
|  |  | 
|  | namespace GH50891 { | 
|  | template <typename T> | 
|  | concept Numeric = requires(T a) { // #NUMERIC | 
|  | foo(a); // #FOO_CALL | 
|  | }; | 
|  |  | 
|  | struct Deferred { | 
|  | friend void foo(Deferred); | 
|  | template <Numeric TO> operator TO(); // #OP_TO | 
|  | }; | 
|  |  | 
|  | static_assert(Numeric<Deferred>); // #STATIC_ASSERT | 
|  | // expected-error@#NUMERIC{{satisfaction of constraint 'requires (T a) { foo(a); }' depends on itself}} | 
|  | // expected-note@#NUMERIC {{while substituting template arguments into constraint expression here}} | 
|  | // expected-note@#OP_TO {{while checking the satisfaction of concept 'Numeric<GH50891::Deferred>' requested here}} | 
|  | // expected-note@#OP_TO {{while substituting template arguments into constraint expression here}} | 
|  | // expected-note@#FOO_CALL {{while checking constraint satisfaction for template}} | 
|  | // expected-note@#FOO_CALL {{while substituting deduced template arguments into function template}} | 
|  | // expected-note@#FOO_CALL {{in instantiation of requirement here}} | 
|  | // expected-note@#NUMERIC {{while substituting template arguments into constraint expression here}} | 
|  |  | 
|  | // expected-error@#STATIC_ASSERT {{static assertion failed}} | 
|  | // expected-note@#STATIC_ASSERT{{while checking the satisfaction of concept 'Numeric<GH50891::Deferred>' requested here}} | 
|  | // expected-note@#STATIC_ASSERT{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}} | 
|  |  | 
|  | } // namespace GH50891 | 
|  |  | 
|  |  | 
|  | namespace GH60323 { | 
|  | // This should not diagnose, as it does not depend on itself. | 
|  | struct End { | 
|  | template<class T> | 
|  | void go(T t) { } | 
|  |  | 
|  | template<class T> | 
|  | auto endparens(T t) | 
|  | requires requires { go(t); } | 
|  | { return go(t); } | 
|  | }; | 
|  |  | 
|  | struct Size { | 
|  | template<class T> | 
|  | auto go(T t) | 
|  | { return End().endparens(t); } | 
|  |  | 
|  | template<class T> | 
|  | auto sizeparens(T t) | 
|  | requires requires { go(t); } | 
|  | { return go(t); } | 
|  | }; | 
|  |  | 
|  | int f() | 
|  | { | 
|  | int i = 42; | 
|  | Size().sizeparens(i); | 
|  | } | 
|  | } | 
|  |  | 
|  | namespace CWG2369_Regressions { | 
|  |  | 
|  | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109397 | 
|  | namespace GCC_103997 { | 
|  |  | 
|  | template<typename _type, typename _stream> | 
|  | concept streamable = requires(_stream &s, _type &&v) { | 
|  | s << static_cast<_type &&>(v); | 
|  | }; | 
|  |  | 
|  | struct type_a { | 
|  | template<typename _arg> | 
|  | type_a &operator<<(_arg &&) { | 
|  | // std::clog << "type_a" << std::endl; | 
|  | return *this; | 
|  | } | 
|  | }; | 
|  |  | 
|  | struct type_b { | 
|  | type_b &operator<<(type_a const &) { | 
|  | // std::clog << "type_b" << std::endl; | 
|  | return *this; | 
|  | } | 
|  | }; | 
|  |  | 
|  | struct type_c { | 
|  | type_b b; | 
|  | template<typename _arg> | 
|  | requires streamable<_arg, type_b> | 
|  | friend type_c &operator<<(type_c &c, _arg &&a) { | 
|  | // std::clog << "type_c" << std::endl; | 
|  | c.b << static_cast<_arg &&>(a); | 
|  | return c; | 
|  | } | 
|  | }; | 
|  |  | 
|  | void foo() { | 
|  | type_a a; | 
|  | type_c c; | 
|  | a << c; // "type_a\n" (gcc gives error here) | 
|  | c << a; // "type_c\ntype_b\n" | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108393 | 
|  | namespace GCC_108393 { | 
|  |  | 
|  | template<class> | 
|  | struct iterator_traits | 
|  | {}; | 
|  |  | 
|  | template<class T> | 
|  | requires requires(T __t, T __u) { __t == __u; } | 
|  | struct iterator_traits<T> | 
|  | {}; | 
|  |  | 
|  | template<class T> | 
|  | concept C = requires { typename iterator_traits<T>::A; }; | 
|  |  | 
|  | struct unreachable_sentinel_t | 
|  | { | 
|  | template<C _Iter> | 
|  | friend constexpr bool operator==(unreachable_sentinel_t, const _Iter&) noexcept; | 
|  | }; | 
|  |  | 
|  | template<class T> | 
|  | struct S | 
|  | {}; | 
|  |  | 
|  | static_assert(!C<S<unreachable_sentinel_t>>); | 
|  |  | 
|  | } | 
|  |  | 
|  | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107429 | 
|  | namespace GCC_107429 { | 
|  |  | 
|  | struct tag_foo { } inline constexpr foo; | 
|  | struct tag_bar { } inline constexpr bar; | 
|  |  | 
|  | template<typename... T> | 
|  | auto f(tag_foo, T... x) | 
|  | { | 
|  | return (x + ...); | 
|  | } | 
|  |  | 
|  | template<typename... T> | 
|  | concept fooable = requires (T... x) { f(foo, x...); }; | 
|  |  | 
|  | template<typename... T> requires (fooable<T...>) | 
|  | auto f(tag_bar, T... x) | 
|  | { | 
|  | return f(foo, x...); | 
|  | } | 
|  |  | 
|  | auto test() | 
|  | { | 
|  | return f(bar, 1, 2, 3); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | namespace GCC_99599 { | 
|  |  | 
|  | struct foo_tag {}; | 
|  | struct bar_tag {}; | 
|  |  | 
|  | template <class T> | 
|  | concept fooable = requires(T it) { | 
|  | invoke_tag(foo_tag{}, it); // <-- here | 
|  | }; | 
|  |  | 
|  | template <class T> auto invoke_tag(foo_tag, T in) { return in; } | 
|  |  | 
|  | template <fooable T> auto invoke_tag(bar_tag, T it) { return it; } | 
|  |  | 
|  | int main() { | 
|  | // Neither line below compiles in GCC 11, independently of the other | 
|  | return invoke_tag(foo_tag{}, 2) + invoke_tag(bar_tag{}, 2); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99599#c22 | 
|  | namespace GCC_99599_2 { | 
|  |  | 
|  | template<typename T> class indirect { | 
|  | public: | 
|  | template<typename U> requires | 
|  | requires (const T& t, const U& u) { t == u; } | 
|  | friend constexpr bool operator==(const indirect&, const U&) { return false; } | 
|  |  | 
|  | private: | 
|  | T* _M_ptr{}; | 
|  | }; | 
|  |  | 
|  | indirect<int> i; | 
|  | bool b = i == 1; | 
|  |  | 
|  | } | 
|  |  | 
|  | namespace GCC_99599_3 { | 
|  |  | 
|  | template<typename T> | 
|  | struct S { T t; }; | 
|  |  | 
|  | template<typename T> | 
|  | concept C = sizeof(S<T>) > 0; | 
|  |  | 
|  | struct I; | 
|  |  | 
|  | struct from_range_t { | 
|  | explicit from_range_t() = default; | 
|  | }; | 
|  | inline constexpr from_range_t from_range; | 
|  |  | 
|  | template<typename T> | 
|  | concept FromRange = __is_same_as (T, from_range_t); | 
|  |  | 
|  | //#define WORKAROUND | 
|  | #ifdef WORKAROUND | 
|  | template<FromRange U, C T> | 
|  | void f(U, T*); | 
|  | #else | 
|  | template<C T> | 
|  | void f(from_range_t, T*); | 
|  | #endif | 
|  |  | 
|  | void f(...); | 
|  |  | 
|  | void g(I* p) { | 
|  | f(0, p); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | namespace GCC_99599_4 { | 
|  |  | 
|  | struct A { | 
|  | A(...); | 
|  | }; | 
|  |  | 
|  | template <class T> void f(A, T) { } | 
|  |  | 
|  | int main() | 
|  | { | 
|  | f(42, 24); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | namespace FAILED_GCC_110160 { | 
|  | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110160 | 
|  | // Current heuristic FAILED; GCC trunk also failed | 
|  | // https://godbolt.org/z/r3Pz9Tehz | 
|  | #if 0 | 
|  | #include <sstream> | 
|  | #include <string> | 
|  |  | 
|  | template <class T> | 
|  | concept StreamCanReceiveString = requires(T& t, std::string s) { | 
|  | { t << s }; | 
|  | }; | 
|  |  | 
|  | struct NotAStream {}; | 
|  | struct UnrelatedType {}; | 
|  |  | 
|  | template <StreamCanReceiveString S> | 
|  | S& operator<<(S& s, UnrelatedType) { | 
|  | return s; | 
|  | } | 
|  |  | 
|  | static_assert(!StreamCanReceiveString<NotAStream>); | 
|  |  | 
|  | static_assert(StreamCanReceiveString<std::stringstream>); | 
|  | #endif | 
|  | } | 
|  | } |