167c608a9SSaar Raz // RUN: %clang_cc1 %s -I%S -std=c++2a -verify 2a0f50d73SSaar Raz 3a0f50d73SSaar Raz namespace std { struct type_info; } 4a0f50d73SSaar Raz 5a0f50d73SSaar Raz static_assert(requires { 0; }); 6a0f50d73SSaar Raz static_assert(requires { "aaaa"; }); 7a0f50d73SSaar Raz static_assert(requires { (0).da; }); // expected-error{{member reference base type 'int' is not a structure or union}} 8a0f50d73SSaar Raz 9a0f50d73SSaar Raz struct A {}; 10a0f50d73SSaar Raz struct B { operator +B11a0f50d73SSaar Raz B operator+(const B &other) const { return other; } 12a0f50d73SSaar Raz }; 13a0f50d73SSaar Raz struct C { operator +C14a0f50d73SSaar Raz C operator+(C &other) const { return other; } 15a0f50d73SSaar Raz }; 16a0f50d73SSaar Raz 17a0f50d73SSaar Raz template<typename T> requires requires (T a, const T& b) { a + b; } 18a0f50d73SSaar Raz // expected-note@-1{{because 'a + b' would be invalid: invalid operands to binary expression ('A' and 'const A')}} 19a0f50d73SSaar Raz // expected-note@-2{{because 'a + b' would be invalid: invalid operands to binary expression ('C' and 'const C')}} 20a0f50d73SSaar Raz struct r1 {}; 21a0f50d73SSaar Raz 22a0f50d73SSaar Raz using r1i1 = r1<int>; 23a0f50d73SSaar Raz using r1i2 = r1<A>; // expected-error{{constraints not satisfied for class template 'r1' [with T = A]}} 24a0f50d73SSaar Raz using r1i3 = r1<B>; 25a0f50d73SSaar Raz using r1i4 = r1<C>; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}} 26a0f50d73SSaar Raz fooD27a0f50d73SSaar Razstruct D { void foo() {} }; 28a0f50d73SSaar Raz 29a0f50d73SSaar Raz template<typename T> requires requires (T a) { a.foo(); } 30a0f50d73SSaar Raz // expected-note@-1{{because 'a.foo()' would be invalid: no member named 'foo' in 'A'}} 31a0f50d73SSaar Raz // expected-note@-2{{because 'a.foo()' would be invalid: member reference base type 'int' is not a structure or union}} 32a0f50d73SSaar Raz // expected-note@-3{{because 'a.foo()' would be invalid: 'this' argument to member function 'foo' has type 'const D', but function is not marked const}} 33a0f50d73SSaar Raz struct r2 {}; 34a0f50d73SSaar Raz 35a0f50d73SSaar Raz using r2i1 = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}} 36a0f50d73SSaar Raz using r2i2 = r2<A>; // expected-error{{constraints not satisfied for class template 'r2' [with T = A]}} 37a0f50d73SSaar Raz using r2i3 = r2<D>; 38a0f50d73SSaar Raz using r2i4 = r2<const D>; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}} 39a0f50d73SSaar Raz 40a0f50d73SSaar Raz template<typename T> requires requires { sizeof(T); } 41a0f50d73SSaar Raz // expected-note@-1{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} 42*12cb1cb3SErich Keane // expected-note@-2{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}} 43a0f50d73SSaar Raz struct r3 {}; 44a0f50d73SSaar Raz 45a0f50d73SSaar Raz using r3i1 = r3<int>; 46a0f50d73SSaar Raz using r3i2 = r3<A>; 47a0f50d73SSaar Raz using r3i3 = r3<A &>; 48a0f50d73SSaar Raz using r3i4 = r3<void>; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}} 49*12cb1cb3SErich Keane using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}} 50a0f50d73SSaar Raz 51a0f50d73SSaar Raz template<typename T> requires requires (T t) { 0; "a"; (void)'a'; } 52a0f50d73SSaar Raz struct r4 {}; 53a0f50d73SSaar Raz 54a0f50d73SSaar Raz using r4i1 = r4<int>; 55a0f50d73SSaar Raz using r4i2 = r4<int[10]>; 56a0f50d73SSaar Raz using r4i3 = r4<int(int)>; 57a0f50d73SSaar Raz 58a0f50d73SSaar Raz template<class T> void f(T) = delete; f(T)59a0f50d73SSaar Raztemplate<class T> requires (sizeof(T) == 1) void f(T) { } 60a0f50d73SSaar Raz 61a0f50d73SSaar Raz template<typename T> requires requires(T t) { f(t); } 62a0f50d73SSaar Raz // expected-note@-1{{because 'f(t)' would be invalid: call to deleted function 'f'}} 63a0f50d73SSaar Raz struct r5 {}; 64a0f50d73SSaar Raz 65a0f50d73SSaar Raz using r5i1 = r5<int>; 66a0f50d73SSaar Raz // expected-error@-1 {{constraints not satisfied for class template 'r5' [with T = int]}} 67a0f50d73SSaar Raz using r5i2 = r5<char>; 68a0f50d73SSaar Raz 69a0f50d73SSaar Raz template<typename T> 70a0f50d73SSaar Raz struct E { non_default_constructibleE::non_default_constructible71a0f50d73SSaar Raz struct non_default_constructible { non_default_constructible(T t) { } }; 72a0f50d73SSaar Raz }; 73a0f50d73SSaar Raz 74a0f50d73SSaar Raz template<typename T> requires requires(T t) { typename E<T>::non_default_constructible{}; } 75d1a59eefSZhihao Yuan // expected-note@-1 {{because 'typename E<T>::non_default_constructible{}' would be invalid: no matching constructor for initialization of 'typename E<int>::non_default_constructible'}} 76a0f50d73SSaar Raz struct r6 {}; 77a0f50d73SSaar Raz 78a0f50d73SSaar Raz using r6i1 = r6<int>; 79a0f50d73SSaar Raz // expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}} 80a0f50d73SSaar Raz 81a0f50d73SSaar Raz template<typename T> requires requires(T t) { typename E<T>::non_default_constructible(); } 82a0f50d73SSaar Raz // expected-note@-1 {{because 'typename E<T>::non_default_constructible()' would be invalid: no matching constructor for initialization of 'typename E<int>::non_default_constructible'}} 83a0f50d73SSaar Raz struct r7 {}; 84a0f50d73SSaar Raz 85a0f50d73SSaar Raz using r7i1 = r7<int>; 86a0f50d73SSaar Raz // expected-error@-1 {{constraints not satisfied for class template 'r7' [with T = int]}} 87a0f50d73SSaar Raz 88a0f50d73SSaar Raz // C++ [expr.prim.req.simple] Example 89a0f50d73SSaar Raz namespace std_example { 90a0f50d73SSaar Raz template<typename T> concept C = 913d7946c5SErich Keane requires (T a, T b) { // expected-note{{because 'a' would be invalid: argument may not have 'void' type}} 92a0f50d73SSaar Raz a + b; // expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('int *' and 'int *')}} 93a0f50d73SSaar Raz }; 94a0f50d73SSaar Raz 95a0f50d73SSaar Raz static_assert(C<int>); 96a0f50d73SSaar Raz template<C T> struct C_check {}; // expected-note{{because 'void' does not satisfy 'C'}} expected-note{{because 'int *' does not satisfy 'C'}} 97a0f50d73SSaar Raz using c1c1 = C_check<void>; // expected-error{{constraints not satisfied for class template 'C_check' [with T = void]}} 98a0f50d73SSaar Raz using c1c2 = C_check<int *>; // expected-error{{constraints not satisfied for class template 'C_check' [with T = int *]}} 99a0f50d73SSaar Raz } 100a0f50d73SSaar Raz 101a0f50d73SSaar Raz // typeid() of an expression becomes potentially evaluated if the expression is 102a0f50d73SSaar Raz // of a polymorphic type. 103a0f50d73SSaar Raz class X { virtual ~X(); }; 104a0f50d73SSaar Raz constexpr bool b = requires (X &x) { static_cast<int(*)[(typeid(x), 0)]>(nullptr); }; 105a0f50d73SSaar Raz // expected-error@-1{{constraint variable 'x' cannot be used in an evaluated context}} 106a0f50d73SSaar Raz // expected-note@-2{{'x' declared here}} 1079e0474fbSUtkarsh Saxena 1089e0474fbSUtkarsh Saxena namespace access_checks { 1099e0474fbSUtkarsh Saxena namespace in_requires_expression { 1109e0474fbSUtkarsh Saxena template<auto> 1119e0474fbSUtkarsh Saxena struct A { 1129e0474fbSUtkarsh Saxena static constexpr bool foo(); 1139e0474fbSUtkarsh Saxena static constexpr bool bar(); 1149e0474fbSUtkarsh Saxena static constexpr bool baz(); 1159e0474fbSUtkarsh Saxena static constexpr bool faz(); 1169e0474fbSUtkarsh Saxena }; 1179e0474fbSUtkarsh Saxena 1189e0474fbSUtkarsh Saxena class C{}; 1199e0474fbSUtkarsh Saxena 1209e0474fbSUtkarsh Saxena class B { p()1219e0474fbSUtkarsh Saxena void p() {} 1229e0474fbSUtkarsh Saxena bool data_member = true; 1239e0474fbSUtkarsh Saxena static const bool static_member = true; 1249e0474fbSUtkarsh Saxena friend struct A<0>; 1259e0474fbSUtkarsh Saxena }; 1269e0474fbSUtkarsh Saxena 1279e0474fbSUtkarsh Saxena template<auto x> foo()1289e0474fbSUtkarsh Saxenaconstexpr bool A<x>::foo() { 1299e0474fbSUtkarsh Saxena return requires(B b) { b.p(); }; 1309e0474fbSUtkarsh Saxena } 1319e0474fbSUtkarsh Saxena static_assert(!A<1>::foo()); 1329e0474fbSUtkarsh Saxena static_assert(A<0>::foo()); 1339e0474fbSUtkarsh Saxena 1349e0474fbSUtkarsh Saxena template<auto x> bar()1359e0474fbSUtkarsh Saxenaconstexpr bool A<x>::bar() { 1369e0474fbSUtkarsh Saxena return requires() { B::static_member; }; 1379e0474fbSUtkarsh Saxena } 1389e0474fbSUtkarsh Saxena static_assert(!A<1>::bar()); 1399e0474fbSUtkarsh Saxena static_assert(A<0>::bar()); 1409e0474fbSUtkarsh Saxena 1419e0474fbSUtkarsh Saxena template<auto x> baz()1429e0474fbSUtkarsh Saxenaconstexpr bool A<x>::baz() { 1439e0474fbSUtkarsh Saxena return requires(B b) { b.data_member; }; 1449e0474fbSUtkarsh Saxena } 1459e0474fbSUtkarsh Saxena static_assert(!A<1>::baz()); 1469e0474fbSUtkarsh Saxena static_assert(A<0>::baz()); 1479e0474fbSUtkarsh Saxena 1489e0474fbSUtkarsh Saxena template<auto x> faz()1499e0474fbSUtkarsh Saxenaconstexpr bool A<x>::faz() { 1509e0474fbSUtkarsh Saxena return requires(B a, B b) { 1519e0474fbSUtkarsh Saxena a.p(); 1529e0474fbSUtkarsh Saxena b.data_member; 1539e0474fbSUtkarsh Saxena B::static_member; 1549e0474fbSUtkarsh Saxena }; 1559e0474fbSUtkarsh Saxena } 1569e0474fbSUtkarsh Saxena static_assert(!A<1>::faz()); 1579e0474fbSUtkarsh Saxena static_assert(A<0>::faz()); 1589e0474fbSUtkarsh Saxena } // namespace in_requires_expression 1599e0474fbSUtkarsh Saxena 1609e0474fbSUtkarsh Saxena namespace in_concepts { 1619e0474fbSUtkarsh Saxena // Dependent access does not cause hard errors. 1629e0474fbSUtkarsh Saxena template<int N> class A; 1639e0474fbSUtkarsh Saxena 1649e0474fbSUtkarsh Saxena template <> class A<0> { f()1659e0474fbSUtkarsh Saxena static void f() {} 1669e0474fbSUtkarsh Saxena }; 1679e0474fbSUtkarsh Saxena template<int N> 1689e0474fbSUtkarsh Saxena concept C1 = requires() { A<N>::f(); }; 1699e0474fbSUtkarsh Saxena static_assert(!C1<0>); 1709e0474fbSUtkarsh Saxena 1719e0474fbSUtkarsh Saxena template <> class A<1> { 1729e0474fbSUtkarsh Saxena public: f()1739e0474fbSUtkarsh Saxena static void f() {} 1749e0474fbSUtkarsh Saxena }; 1759e0474fbSUtkarsh Saxena static_assert(C1<1>); 1769e0474fbSUtkarsh Saxena 1779e0474fbSUtkarsh Saxena // Non-dependent access to private member is a hard error. 1789e0474fbSUtkarsh Saxena class B{ f()1799e0474fbSUtkarsh Saxena static void f() {} // expected-note 2{{implicitly declared private here}} 1809e0474fbSUtkarsh Saxena }; 1819e0474fbSUtkarsh Saxena template<class T> 1829e0474fbSUtkarsh Saxena concept C2 = requires() { B::f(); }; // expected-error {{'f' is a private member}} 1839e0474fbSUtkarsh Saxena non_template_func()1849e0474fbSUtkarsh Saxenaconstexpr bool non_template_func() { 1859e0474fbSUtkarsh Saxena return requires() { 1869e0474fbSUtkarsh Saxena B::f(); // expected-error {{'f' is a private member}} 1879e0474fbSUtkarsh Saxena }; 1889e0474fbSUtkarsh Saxena } 1899e0474fbSUtkarsh Saxena template<int x> template_func()1909e0474fbSUtkarsh Saxenaconstexpr bool template_func() { 1919e0474fbSUtkarsh Saxena return requires() { 1929e0474fbSUtkarsh Saxena A<x>::f(); 1939e0474fbSUtkarsh Saxena }; 1949e0474fbSUtkarsh Saxena } 1959e0474fbSUtkarsh Saxena static_assert(!template_func<0>()); 1969e0474fbSUtkarsh Saxena static_assert(template_func<1>()); 1979e0474fbSUtkarsh Saxena } // namespace in_concepts 1989e0474fbSUtkarsh Saxena 1999e0474fbSUtkarsh Saxena namespace in_trailing_requires { 2009e0474fbSUtkarsh Saxena template <class> struct B; 2019e0474fbSUtkarsh Saxena class A { 2029e0474fbSUtkarsh Saxena static void f(); 2039e0474fbSUtkarsh Saxena friend struct B<short>; 2049e0474fbSUtkarsh Saxena }; 2059e0474fbSUtkarsh Saxena 2069e0474fbSUtkarsh Saxena template <class T> struct B { indexaccess_checks::in_trailing_requires::B2079e0474fbSUtkarsh Saxena static constexpr int index() requires requires{ A::f(); } { 2089e0474fbSUtkarsh Saxena return 1; 2099e0474fbSUtkarsh Saxena } indexaccess_checks::in_trailing_requires::B2109e0474fbSUtkarsh Saxena static constexpr int index() { 2119e0474fbSUtkarsh Saxena return 2; 2129e0474fbSUtkarsh Saxena } 2139e0474fbSUtkarsh Saxena }; 2149e0474fbSUtkarsh Saxena 2159e0474fbSUtkarsh Saxena static_assert(B<short>::index() == 1); 2169e0474fbSUtkarsh Saxena static_assert(B<int>::index() == 2); 2179e0474fbSUtkarsh Saxena 2189e0474fbSUtkarsh Saxena namespace missing_member_function { 2199e0474fbSUtkarsh Saxena template <class T> struct Use; 2209e0474fbSUtkarsh Saxena class X { 2219e0474fbSUtkarsh Saxena int a; 2229e0474fbSUtkarsh Saxena static int B; 2239e0474fbSUtkarsh Saxena friend struct Use<short>; 2249e0474fbSUtkarsh Saxena }; 2259e0474fbSUtkarsh Saxena template <class T> struct Use { fooaccess_checks::in_trailing_requires::missing_member_function::Use2269e0474fbSUtkarsh Saxena constexpr static int foo() requires requires(X x) { x.a; } { 2279e0474fbSUtkarsh Saxena return 1; 2289e0474fbSUtkarsh Saxena } baraccess_checks::in_trailing_requires::missing_member_function::Use2299e0474fbSUtkarsh Saxena constexpr static int bar() requires requires { X::B; } { 2309e0474fbSUtkarsh Saxena return 1; 2319e0474fbSUtkarsh Saxena } 2329e0474fbSUtkarsh Saxena }; 2339e0474fbSUtkarsh Saxena test()2349e0474fbSUtkarsh Saxenavoid test() { 2359e0474fbSUtkarsh Saxena // FIXME: Propagate diagnostic. 2369e0474fbSUtkarsh Saxena Use<int>::foo(); //expected-error {{invalid reference to function 'foo': constraints not satisfied}} 2379e0474fbSUtkarsh Saxena static_assert(Use<short>::foo() == 1); 2389e0474fbSUtkarsh Saxena } 2399e0474fbSUtkarsh Saxena } // namespace missing_member_function 2409e0474fbSUtkarsh Saxena } // namespace in_trailing_requires 2419e0474fbSUtkarsh Saxena } // namespace access_check 242