| // 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 {{in instantiation of function template specialization}} |
| |
| // 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 {{in instantiation of function template specialization}} |
| // 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); |
| } |
| } |