123 lines
4.7 KiB
C++
123 lines
4.7 KiB
C++
// 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@#OP_TO {{satisfaction of constraint 'Numeric<TO>' depends on itself}}
|
|
// expected-note@#OP_TO {{while substituting template arguments into constraint expression here}}
|
|
// FIXME: The following two refer to type-parameter-0-0, it would be nice to
|
|
// see if we could instead diagnose with the sugared name.
|
|
// 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-note@#OP_TO {{skipping 2 contexts in backtrace}}
|
|
// 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-note@#STATIC_ASSERT{{while checking the satisfaction of concept 'Numeric<Deferred>' requested here}}
|
|
|
|
// Fallout of that failure is that deferred does not satisfy numeric,
|
|
// which is unfortunate, but about what we can accomplish here.
|
|
// expected-error@#STATIC_ASSERT {{static assertion failed}}
|
|
// expected-note@#STATIC_ASSERT{{because 'Deferred' does not satisfy 'Numeric'}}
|
|
// expected-note@#FOO_CALL {{because 'foo(a)' would be invalid}}
|
|
} // namespace GH50891
|
|
|