// 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
}
}
