1 // RUN: %clang_cc1 %s -I%S -std=c++2a -verify 2 3 namespace std { struct type_info; } 4 5 static_assert(requires { 0; }); 6 static_assert(requires { "aaaa"; }); 7 static_assert(requires { (0).da; }); // expected-error{{member reference base type 'int' is not a structure or union}} 8 9 struct A {}; 10 struct B { operator +B11 B operator+(const B &other) const { return other; } 12 }; 13 struct C { operator +C14 C operator+(C &other) const { return other; } 15 }; 16 17 template<typename T> requires requires (T a, const T& b) { a + b; } 18 // expected-note@-1{{because 'a + b' would be invalid: invalid operands to binary expression ('A' and 'const A')}} 19 // expected-note@-2{{because 'a + b' would be invalid: invalid operands to binary expression ('C' and 'const C')}} 20 struct r1 {}; 21 22 using r1i1 = r1<int>; 23 using r1i2 = r1<A>; // expected-error{{constraints not satisfied for class template 'r1' [with T = A]}} 24 using r1i3 = r1<B>; 25 using r1i4 = r1<C>; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}} 26 fooD27struct D { void foo() {} }; 28 29 template<typename T> requires requires (T a) { a.foo(); } 30 // expected-note@-1{{because 'a.foo()' would be invalid: no member named 'foo' in 'A'}} 31 // expected-note@-2{{because 'a.foo()' would be invalid: member reference base type 'int' is not a structure or union}} 32 // 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}} 33 struct r2 {}; 34 35 using r2i1 = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}} 36 using r2i2 = r2<A>; // expected-error{{constraints not satisfied for class template 'r2' [with T = A]}} 37 using r2i3 = r2<D>; 38 using r2i4 = r2<const D>; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}} 39 40 template<typename T> requires requires { sizeof(T); } 41 // expected-note@-1{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} 42 // expected-note@-2{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}} 43 struct r3 {}; 44 45 using r3i1 = r3<int>; 46 using r3i2 = r3<A>; 47 using r3i3 = r3<A &>; 48 using r3i4 = r3<void>; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}} 49 using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}} 50 51 template<typename T> requires requires (T t) { 0; "a"; (void)'a'; } 52 struct r4 {}; 53 54 using r4i1 = r4<int>; 55 using r4i2 = r4<int[10]>; 56 using r4i3 = r4<int(int)>; 57 58 template<class T> void f(T) = delete; f(T)59template<class T> requires (sizeof(T) == 1) void f(T) { } 60 61 template<typename T> requires requires(T t) { f(t); } 62 // expected-note@-1{{because 'f(t)' would be invalid: call to deleted function 'f'}} 63 struct r5 {}; 64 65 using r5i1 = r5<int>; 66 // expected-error@-1 {{constraints not satisfied for class template 'r5' [with T = int]}} 67 using r5i2 = r5<char>; 68 69 template<typename T> 70 struct E { non_default_constructibleE::non_default_constructible71 struct non_default_constructible { non_default_constructible(T t) { } }; 72 }; 73 74 template<typename T> requires requires(T t) { typename E<T>::non_default_constructible{}; } 75 // 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'}} 76 struct r6 {}; 77 78 using r6i1 = r6<int>; 79 // expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}} 80 81 template<typename T> requires requires(T t) { typename E<T>::non_default_constructible(); } 82 // 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'}} 83 struct r7 {}; 84 85 using r7i1 = r7<int>; 86 // expected-error@-1 {{constraints not satisfied for class template 'r7' [with T = int]}} 87 88 // C++ [expr.prim.req.simple] Example 89 namespace std_example { 90 template<typename T> concept C = 91 requires (T a, T b) { // expected-note{{because 'a' would be invalid: argument may not have 'void' type}} 92 a + b; // expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('int *' and 'int *')}} 93 }; 94 95 static_assert(C<int>); 96 template<C T> struct C_check {}; // expected-note{{because 'void' does not satisfy 'C'}} expected-note{{because 'int *' does not satisfy 'C'}} 97 using c1c1 = C_check<void>; // expected-error{{constraints not satisfied for class template 'C_check' [with T = void]}} 98 using c1c2 = C_check<int *>; // expected-error{{constraints not satisfied for class template 'C_check' [with T = int *]}} 99 } 100 101 // typeid() of an expression becomes potentially evaluated if the expression is 102 // of a polymorphic type. 103 class X { virtual ~X(); }; 104 constexpr bool b = requires (X &x) { static_cast<int(*)[(typeid(x), 0)]>(nullptr); }; 105 // expected-error@-1{{constraint variable 'x' cannot be used in an evaluated context}} 106 // expected-note@-2{{'x' declared here}} 107 108 namespace access_checks { 109 namespace in_requires_expression { 110 template<auto> 111 struct A { 112 static constexpr bool foo(); 113 static constexpr bool bar(); 114 static constexpr bool baz(); 115 static constexpr bool faz(); 116 }; 117 118 class C{}; 119 120 class B { p()121 void p() {} 122 bool data_member = true; 123 static const bool static_member = true; 124 friend struct A<0>; 125 }; 126 127 template<auto x> foo()128constexpr bool A<x>::foo() { 129 return requires(B b) { b.p(); }; 130 } 131 static_assert(!A<1>::foo()); 132 static_assert(A<0>::foo()); 133 134 template<auto x> bar()135constexpr bool A<x>::bar() { 136 return requires() { B::static_member; }; 137 } 138 static_assert(!A<1>::bar()); 139 static_assert(A<0>::bar()); 140 141 template<auto x> baz()142constexpr bool A<x>::baz() { 143 return requires(B b) { b.data_member; }; 144 } 145 static_assert(!A<1>::baz()); 146 static_assert(A<0>::baz()); 147 148 template<auto x> faz()149constexpr bool A<x>::faz() { 150 return requires(B a, B b) { 151 a.p(); 152 b.data_member; 153 B::static_member; 154 }; 155 } 156 static_assert(!A<1>::faz()); 157 static_assert(A<0>::faz()); 158 } // namespace in_requires_expression 159 160 namespace in_concepts { 161 // Dependent access does not cause hard errors. 162 template<int N> class A; 163 164 template <> class A<0> { f()165 static void f() {} 166 }; 167 template<int N> 168 concept C1 = requires() { A<N>::f(); }; 169 static_assert(!C1<0>); 170 171 template <> class A<1> { 172 public: f()173 static void f() {} 174 }; 175 static_assert(C1<1>); 176 177 // Non-dependent access to private member is a hard error. 178 class B{ f()179 static void f() {} // expected-note 2{{implicitly declared private here}} 180 }; 181 template<class T> 182 concept C2 = requires() { B::f(); }; // expected-error {{'f' is a private member}} 183 non_template_func()184constexpr bool non_template_func() { 185 return requires() { 186 B::f(); // expected-error {{'f' is a private member}} 187 }; 188 } 189 template<int x> template_func()190constexpr bool template_func() { 191 return requires() { 192 A<x>::f(); 193 }; 194 } 195 static_assert(!template_func<0>()); 196 static_assert(template_func<1>()); 197 } // namespace in_concepts 198 199 namespace in_trailing_requires { 200 template <class> struct B; 201 class A { 202 static void f(); 203 friend struct B<short>; 204 }; 205 206 template <class T> struct B { indexaccess_checks::in_trailing_requires::B207 static constexpr int index() requires requires{ A::f(); } { 208 return 1; 209 } indexaccess_checks::in_trailing_requires::B210 static constexpr int index() { 211 return 2; 212 } 213 }; 214 215 static_assert(B<short>::index() == 1); 216 static_assert(B<int>::index() == 2); 217 218 namespace missing_member_function { 219 template <class T> struct Use; 220 class X { 221 int a; 222 static int B; 223 friend struct Use<short>; 224 }; 225 template <class T> struct Use { fooaccess_checks::in_trailing_requires::missing_member_function::Use226 constexpr static int foo() requires requires(X x) { x.a; } { 227 return 1; 228 } baraccess_checks::in_trailing_requires::missing_member_function::Use229 constexpr static int bar() requires requires { X::B; } { 230 return 1; 231 } 232 }; 233 test()234void test() { 235 // FIXME: Propagate diagnostic. 236 Use<int>::foo(); //expected-error {{invalid reference to function 'foo': constraints not satisfied}} 237 static_assert(Use<short>::foo() == 1); 238 } 239 } // namespace missing_member_function 240 } // namespace in_trailing_requires 241 } // namespace access_check 242