xref: /llvm-project/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp (revision 12cb1cb3720de8d164196010123ce1a8901d8122)
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 Raz struct 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 Raz template<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 Saxena constexpr 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 Saxena constexpr 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 Saxena constexpr 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 Saxena constexpr 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 Saxena constexpr 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 Saxena constexpr 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 Saxena void 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