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