xref: /llvm-project/clang/test/SemaTemplate/concepts-recursive-inst.cpp (revision 42667563721e139a93ab886119ea2780ebc3fecc)
12cee2663SErich Keane // RUN: %clang_cc1 -std=c++20 -verify %s
22cee2663SErich Keane namespace GH53213 {
32cee2663SErich Keane template<typename T>
42cee2663SErich Keane concept c = requires(T t) { f(t); }; // #CDEF
52cee2663SErich Keane 
62cee2663SErich Keane auto f(c auto); // #FDEF
72cee2663SErich Keane 
g()82cee2663SErich Keane void g() {
92cee2663SErich Keane   f(0);
102cee2663SErich Keane   // expected-error@-1{{no matching function for call to 'f'}}
112cee2663SErich Keane   // expected-note@#FDEF{{constraints not satisfied}}
122cee2663SErich Keane   // expected-note@#FDEF{{because 'int' does not satisfy 'c'}}
132cee2663SErich Keane   // expected-note@#CDEF{{because 'f(t)' would be invalid: no matching function for call to 'f'}}
142cee2663SErich Keane }
152cee2663SErich Keane } // namespace GH53213
162cee2663SErich Keane 
172cee2663SErich Keane namespace GH45736 {
182cee2663SErich Keane struct constrained;
192cee2663SErich Keane 
202cee2663SErich Keane template<typename T>
212cee2663SErich Keane   struct type {
222cee2663SErich Keane   };
232cee2663SErich Keane template<typename T>
f(type<T>)242cee2663SErich Keane   constexpr bool f(type<T>) {
252cee2663SErich Keane       return true;
262cee2663SErich Keane   }
272cee2663SErich Keane 
282cee2663SErich Keane template<typename T>
292cee2663SErich Keane   concept matches = f(type<T>());
302cee2663SErich Keane 
312cee2663SErich Keane 
322cee2663SErich Keane struct constrained {
332cee2663SErich Keane     template<typename U> requires matches<U>
constrainedGH45736::constrained342cee2663SErich Keane         explicit constrained(U value) {
352cee2663SErich Keane             }
362cee2663SErich Keane };
372cee2663SErich Keane 
f(constrained const &)382cee2663SErich Keane bool f(constrained const &) {
392cee2663SErich Keane     return true;
402cee2663SErich Keane }
412cee2663SErich Keane 
422cee2663SErich Keane struct outer {
432cee2663SErich Keane     constrained state;
442cee2663SErich Keane };
452cee2663SErich Keane 
f(outer const & x)462cee2663SErich Keane bool f(outer const & x) {
472cee2663SErich Keane     return f(x.state);
482cee2663SErich Keane }
492cee2663SErich Keane } // namespace GH45736
502cee2663SErich Keane 
512cee2663SErich Keane namespace DirectRecursiveCheck {
522cee2663SErich Keane template<class T>
532cee2663SErich Keane concept NotInf = true;
542cee2663SErich Keane template<class T>
552cee2663SErich Keane concept Inf = requires(T& v){ // #INF_REQ
562cee2663SErich Keane   {begin(v)}; // #INF_BEGIN_EXPR
572cee2663SErich Keane };
582cee2663SErich Keane 
begin(NotInf auto & v)592cee2663SErich Keane void begin(NotInf auto& v){ } // #NOTINF_BEGIN
602cee2663SErich Keane // This lookup should fail, since it results in a recursive check.
612cee2663SErich Keane // However, this is a 'hard failure'(not a SFINAE failure or constraints
622cee2663SErich Keane // violation), so it needs to cause the entire lookup to fail.
begin(Inf auto & v)632cee2663SErich Keane void begin(Inf auto& v){ } // #INF_BEGIN
642cee2663SErich Keane 
652cee2663SErich Keane struct my_range{
662cee2663SErich Keane } rng;
672cee2663SErich Keane 
baz()682cee2663SErich Keane void baz() {
692cee2663SErich Keane auto it = begin(rng); // #BEGIN_CALL
702cee2663SErich Keane // expected-error@#INF_BEGIN {{satisfaction of constraint 'Inf<Inf auto>' depends on itself}}
712cee2663SErich Keane // expected-note@#INF_BEGIN {{while substituting template arguments into constraint expression here}}
722cee2663SErich Keane // expected-note@#INF_BEGIN_EXPR {{while checking constraint satisfaction for template 'begin<DirectRecursiveCheck::my_range>' required here}}
732cee2663SErich Keane // expected-note@#INF_BEGIN_EXPR {{while substituting deduced template arguments into function template 'begin'}}
742cee2663SErich Keane // expected-note@#INF_BEGIN_EXPR {{in instantiation of requirement here}}
752cee2663SErich Keane // expected-note@#INF_REQ {{while substituting template arguments into constraint expression here}}
762cee2663SErich Keane // expected-note@#INF_BEGIN {{while checking the satisfaction of concept 'Inf<DirectRecursiveCheck::my_range>' requested here}}
772cee2663SErich Keane // expected-note@#INF_BEGIN {{while substituting template arguments into constraint expression here}}
782cee2663SErich Keane // expected-note@#BEGIN_CALL {{while checking constraint satisfaction for template 'begin<DirectRecursiveCheck::my_range>' required here}}
792cee2663SErich Keane // expected-note@#BEGIN_CALL {{in instantiation of function template specialization}}
802cee2663SErich Keane 
812cee2663SErich Keane // Fallout of the failure is failed lookup, which is necessary to stop odd
822cee2663SErich Keane // cascading errors.
832cee2663SErich Keane // expected-error@#BEGIN_CALL {{no matching function for call to 'begin'}}
842cee2663SErich Keane // expected-note@#NOTINF_BEGIN {{candidate function}}
852cee2663SErich Keane // expected-note@#INF_BEGIN{{candidate template ignored: constraints not satisfied}}
862cee2663SErich Keane }
872cee2663SErich Keane } // namespace DirectRecursiveCheck
882cee2663SErich Keane 
892cee2663SErich Keane namespace GH50891 {
902cee2663SErich Keane   template <typename T>
912cee2663SErich Keane   concept Numeric = requires(T a) { // #NUMERIC
922cee2663SErich Keane       foo(a); // #FOO_CALL
932cee2663SErich Keane     };
942cee2663SErich Keane 
952cee2663SErich Keane   struct Deferred {
962cee2663SErich Keane     friend void foo(Deferred);
972cee2663SErich Keane     template <Numeric TO> operator TO(); // #OP_TO
982cee2663SErich Keane   };
992cee2663SErich Keane 
1002cee2663SErich Keane   static_assert(Numeric<Deferred>); // #STATIC_ASSERT
10112cb1cb3SErich Keane   // expected-error@#NUMERIC{{satisfaction of constraint 'requires (T a) { foo(a); }' depends on itself}}
1022cee2663SErich Keane   // expected-note@#NUMERIC {{while substituting template arguments into constraint expression here}}
10312cb1cb3SErich Keane   // expected-note@#OP_TO {{while checking the satisfaction of concept 'Numeric<GH50891::Deferred>' requested here}}
10412cb1cb3SErich Keane   // expected-note@#OP_TO {{while substituting template arguments into constraint expression here}}
1052cee2663SErich Keane   // expected-note@#FOO_CALL {{while checking constraint satisfaction for template}}
1062cee2663SErich Keane   // expected-note@#FOO_CALL {{in instantiation of function template specialization}}
1072cee2663SErich Keane   // expected-note@#FOO_CALL {{in instantiation of requirement here}}
1082cee2663SErich Keane   // expected-note@#NUMERIC {{while substituting template arguments into constraint expression here}}
1092cee2663SErich Keane 
1102cee2663SErich Keane   // expected-error@#STATIC_ASSERT {{static assertion failed}}
11112cb1cb3SErich Keane   // expected-note@#STATIC_ASSERT{{while checking the satisfaction of concept 'Numeric<GH50891::Deferred>' requested here}}
11212cb1cb3SErich Keane   // expected-note@#STATIC_ASSERT{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
11312cb1cb3SErich Keane 
1142cee2663SErich Keane } // namespace GH50891
1152cee2663SErich Keane 
116*42667563SErich Keane 
117*42667563SErich Keane namespace GH60323 {
118*42667563SErich Keane   // This should not diagnose, as it does not depend on itself.
119*42667563SErich Keane   struct End {
120*42667563SErich Keane         template<class T>
goGH60323::End121*42667563SErich Keane               void go(T t) { }
122*42667563SErich Keane 
123*42667563SErich Keane             template<class T>
endparensGH60323::End124*42667563SErich Keane                   auto endparens(T t)
125*42667563SErich Keane                           requires requires { go(t); }
126*42667563SErich Keane                 { return go(t); }
127*42667563SErich Keane   };
128*42667563SErich Keane 
129*42667563SErich Keane   struct Size {
130*42667563SErich Keane         template<class T>
goGH60323::Size131*42667563SErich Keane               auto go(T t)
132*42667563SErich Keane                   { return End().endparens(t); }
133*42667563SErich Keane 
134*42667563SErich Keane             template<class T>
sizeparensGH60323::Size135*42667563SErich Keane                   auto sizeparens(T t)
136*42667563SErich Keane                           requires requires { go(t); }
137*42667563SErich Keane                 { return go(t); }
138*42667563SErich Keane   };
139*42667563SErich Keane 
f()140*42667563SErich Keane   int f()
141*42667563SErich Keane   {
142*42667563SErich Keane         int i = 42;
143*42667563SErich Keane             Size().sizeparens(i);
144*42667563SErich Keane   }
145*42667563SErich Keane }
146