summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp175
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.req/equivalence.cpp125
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp46
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.req/p3.cpp37
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp68
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp106
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp194
-rw-r--r--clang/test/PCH/cxx2a-requires-expr.cpp20
-rw-r--r--clang/test/Parser/cxx2a-concepts-requires-expr.cpp141
-rw-r--r--clang/test/SemaTemplate/instantiate-requires-expr.cpp216
10 files changed, 1128 insertions, 0 deletions
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp
new file mode 100644
index 00000000000..578efb5b24e
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp
@@ -0,0 +1,175 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify
+
+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}}
+
+void foo() {}
+static_assert(requires { { foo() }; });
+
+// Substitution failure in expression
+
+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{{because 'a + b' would be invalid: invalid operands to binary expression ('A' and 'const A')}} expected-note{{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{{because 'a.foo()' would be invalid: no member named 'foo' in 'A'}} expected-note{{because 'a.foo()' would be invalid: member reference base type 'int' is not a structure or union}} expected-note{{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{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} expected-note{{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]}}
+
+// Non-dependent expressions
+
+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)>;
+
+// Noexcept requirement
+void maythrow() { }
+static_assert(!requires { { maythrow() } noexcept; });
+static_assert(requires { { 1 } noexcept; });
+
+struct E { void operator++(int) noexcept; };
+struct F { void operator++(int); };
+
+template<typename T> requires requires (T t) { { t++ } noexcept; } // expected-note{{because 't ++' may throw an exception}}
+struct r5 {};
+
+using r5i1 = r5<int>;
+using r5i2 = r5<E>;
+using r5i2 = r5<F>; // expected-error{{constraints not satisfied for class template 'r5' [with T = F]}}
+
+template<typename T> requires requires (T t) { { t.foo() } noexcept; } // expected-note{{because 't.foo()' would be invalid: no member named 'foo' in 'E'}}
+struct r6 {};
+
+using r6i = r6<E>; // expected-error{{constraints not satisfied for class template 'r6' [with T = E]}}
+
+template<typename T, typename U>
+constexpr bool is_same_v = false;
+
+template<typename T>
+constexpr bool is_same_v<T, T> = true;
+
+template<typename T, typename U>
+concept Same = is_same_v<T, U>;
+
+template<typename T>
+concept Large = sizeof(T) >= 4; // expected-note{{because 'sizeof(short) >= 4' (2 >= 4) evaluated to false}}
+
+template<typename T> requires requires (T t) { { t } -> Large; } // expected-note{{because 'decltype(t)' (aka 'short') does not satisfy 'Large':}}
+struct r7 {};
+
+using r7i1 = r7<int>;
+using r7i2 = r7<short>; // expected-error{{constraints not satisfied for class template 'r7' [with T = short]}}
+
+template<typename T> requires requires (T t) { { t } -> Same<T>; }
+struct r8 {};
+
+using r8i1 = r8<int>;
+using r8i2 = r8<short*>;
+
+// Substitution failure in type constraint
+
+template<typename T> requires requires (T t) { { t } -> Same<typename T::type>; } // expected-note{{because 'Same<expr-type, typename T::type>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}}
+struct r9 {};
+
+struct M { using type = M; };
+
+using r9i1 = r9<M>;
+using r9i2 = r9<int>; // expected-error{{constraints not satisfied for class template 'r9' [with T = int]}}
+
+// Substitution failure in both expression and return type requirement
+
+template<typename T> requires requires (T t) { { t.foo() } -> Same<typename T::type>; } // expected-note{{because 't.foo()' would be invalid: member reference base type 'int' is not a structure or union}}
+struct r10 {};
+
+using r10i = r10<int>; // expected-error{{constraints not satisfied for class template 'r10' [with T = int]}}
+
+// Non-type concept in type constraint
+
+template<int T>
+concept IsEven = (T % 2) == 0;
+
+template<typename T> requires requires (T t) { { t } -> IsEven; } // expected-error{{concept named in type constraint is not a type concept}}
+struct r11 {};
+
+// C++ [expr.prim.req.compound] Example
+namespace std_example {
+ template<typename T> concept C1 =
+ requires(T x) {
+ {x++};
+ };
+
+ template<typename T, typename U> constexpr bool is_same_v = false;
+ template<typename T> constexpr bool is_same_v<T, T> = true;
+
+ template<typename T, typename U> concept same_as = is_same_v<T, U>;
+ // expected-note@-1 {{because 'is_same_v<int, int *>' evaluated to false}}
+
+ static_assert(C1<int>);
+ static_assert(C1<int*>);
+ template<C1 T> struct C1_check {};
+ using c1c1 = C1_check<int>;
+ using c1c2 = C1_check<int[10]>;
+
+ template<typename T> concept C2 =
+ requires(T x) {
+ {*x} -> same_as<typename T::inner>;
+ // expected-note@-1{{because type constraint 'same_as<int, typename T2::inner>' was not satisfied:}}
+ // expected-note@-2{{because '*x' would be invalid: indirection requires pointer operand ('int' invalid)}}
+ };
+
+ struct T1 {
+ using inner = int;
+ inner operator *() { return 0; }
+ };
+ struct T2 {
+ using inner = int *;
+ int operator *() { return 0; }
+ };
+ static_assert(C2<T1>);
+ template<C2 T> struct C2_check {}; // expected-note{{because 'int' does not satisfy 'C2'}} expected-note{{because 'std_example::T2' does not satisfy 'C2'}}
+ using c2c1 = C2_check<int>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = int]}}
+ using c2c2 = C2_check<T2>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::T2]}}
+
+ template<typename T>
+ void g(T t) noexcept(sizeof(T) == 1) {}
+
+ template<typename T> concept C5 =
+ requires(T x) {
+ {g(x)} noexcept; // expected-note{{because 'g(x)' may throw an exception}}
+ };
+
+ static_assert(C5<char>);
+ template<C5 T> struct C5_check {}; // expected-note{{because 'short' does not satisfy 'C5'}}
+ using c5 = C5_check<short>; // expected-error{{constraints not satisfied for class template 'C5_check' [with T = short]}}
+} \ No newline at end of file
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/equivalence.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/equivalence.cpp
new file mode 100644
index 00000000000..ea345320190
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/equivalence.cpp
@@ -0,0 +1,125 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify
+
+template<typename T, typename U> constexpr bool is_same_v = false;
+template<typename T> constexpr bool is_same_v<T, T> = true;
+
+template<typename T> struct identity { using type = T; };
+template<typename T> using identity_t = T;
+
+// Type requirements
+template<typename T> requires requires { typename identity_t<T>; }
+struct r1;
+template<typename U> requires requires { typename identity_t<U>; } // expected-note{{previous template declaration is here}}
+struct r1;
+template<typename T> requires requires { typename identity_t<T*>; } // expected-error{{requires clause differs in template redeclaration}}
+struct r1;
+template<typename T> requires requires { typename ::identity_t<T>; }
+struct r1;
+
+template<typename Y> requires requires { typename identity<Y>::type; }
+struct r2;
+template<typename U> requires requires { typename identity<U>::type; }
+struct r2;
+template<typename T> requires requires { typename ::identity<T>::type; } // expected-note 2{{previous template declaration is here}}
+struct r2;
+template<typename T> requires requires { typename identity<T>::typr; } // expected-error{{requires clause differs in template redeclaration}}
+struct r2;
+namespace ns {
+ template<typename T> struct identity { using type = T; };
+}
+template<typename T> requires requires { typename ns::identity<T>::type; } // expected-error{{requires clause differs in template redeclaration}}
+struct r2;
+
+template<typename T> requires requires { typename T::template identity<T>::type; }
+struct r3;
+template<typename U> requires requires { typename U::template identity<U>::type; } // expected-note{{previous template declaration is here}}
+struct r3;
+template<typename T> requires requires { typename T::template identitr<T>::type; } // expected-error{{requires clause differs in template redeclaration}}
+struct r3;
+
+template<typename T> requires requires { typename T::template temp<>; }
+struct r4;
+template<typename U> requires requires { typename U::template temp<>; }
+struct r4;
+
+// Expr requirements
+template<typename T> requires requires { 0; } // expected-note{{previous template declaration is here}}
+struct r5;
+template<typename T> requires requires { 1; } // expected-error{{requires clause differs in template redeclaration}}
+struct r5;
+
+template<typename T>
+concept C1 = true;
+
+template<typename T> requires requires { sizeof(T); }
+struct r6;
+template<typename U> requires requires { sizeof(U); } // expected-note{{previous template declaration is here}}
+struct r6;
+template<typename U> requires requires { sizeof(U) - 1; } // expected-error{{requires clause differs in template redeclaration}}
+struct r6;
+template<typename T> requires requires { { sizeof(T) }; } // expected-note 2{{previous template declaration is here}}
+struct r6;
+template<typename T> requires requires { { sizeof(T) } noexcept; } // expected-error{{requires clause differs in template redeclaration}}
+struct r6;
+template<typename T> requires requires { { sizeof(T) } -> C1; } // expected-error{{requires clause differs in template redeclaration}}
+struct r6;
+
+template<typename T> requires requires { { sizeof(T) } -> C1; }
+struct r7;
+template<typename U> requires requires { { sizeof(U) } -> C1; }
+struct r7;
+template<typename T> requires requires { { sizeof(T) } -> C1<>; } // expected-note {{previous template declaration is here}}
+struct r7;
+template<typename U> requires requires { { sizeof(U) }; } // expected-error{{requires clause differs in template redeclaration}}
+struct r7;
+
+template<typename T, typename U>
+concept C2 = true;
+
+template<typename T> requires requires { { sizeof(T) } -> C2<T>; }
+struct r8;
+template<typename U> requires requires { { sizeof(U) } -> C2<U>; } // expected-note{{previous template declaration is here}}
+struct r8;
+template<typename T> requires requires { { sizeof(T) } -> C2<T*>; } // expected-error{{requires clause differs in template redeclaration}}
+struct r8;
+
+// Nested requirements
+template<typename T> requires requires { requires sizeof(T) == 0; }
+struct r9;
+template<typename U> requires requires { requires sizeof(U) == 0; } // expected-note{{previous template declaration is here}}
+struct r9;
+template<typename T> requires requires { requires sizeof(T) == 1; } // expected-error{{requires clause differs in template redeclaration}}
+struct r9;
+
+// Parameter list
+template<typename T> requires requires { requires true; }
+struct r10;
+template<typename T> requires requires() { requires true; } // expected-note{{previous template declaration is here}}
+struct r10;
+template<typename T> requires requires(T i) { requires true; } // expected-error{{requires clause differs in template redeclaration}}
+struct r10;
+
+template<typename T> requires requires(T i, T *j) { requires true; } // expected-note 2{{previous template declaration is here}}
+struct r11;
+template<typename T> requires requires(T i) { requires true; } // expected-error{{requires clause differs in template redeclaration}}
+struct r11;
+template<typename T> requires requires(T i, T *j, T &k) { requires true; } // expected-error{{requires clause differs in template redeclaration}}
+struct r11;
+
+// Parameter names
+template<typename T> requires requires(int i) { requires sizeof(i) == 1; }
+struct r12;
+template<typename T> requires requires(int j) { requires sizeof(j) == 1; } // expected-note 2{{previous template declaration is here}}
+struct r12;
+template<typename T> requires requires(int k) { requires sizeof(k) == 2; } // expected-error{{requires clause differs in template redeclaration}}
+struct r12;
+template<typename T> requires requires(const int k) { requires sizeof(k) == 1; } // expected-error{{requires clause differs in template redeclaration}}
+struct r12;
+
+// Order of requirements
+template<typename T> requires requires { requires true; 0; }
+struct r13;
+template<typename T> requires requires { requires true; 0; } // expected-note{{previous template declaration is here}}
+struct r13;
+template<typename T> requires requires { 0; requires true; } // expected-error{{requires clause differs in template redeclaration}}
+struct r13;
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
new file mode 100644
index 00000000000..f8776832d33
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify
+
+static_assert(requires { requires true; });
+
+template<typename T> requires requires { requires false; } // expected-note{{because 'false' evaluated to false}}
+struct r1 {};
+
+using r1i = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}
+
+template<typename T> requires requires { requires sizeof(T) == 0; } // expected-note{{because 'sizeof(int) == 0' (4 == 0) evaluated to false}}
+struct r2 {};
+
+using r2i = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}}
+
+template<typename T> requires requires (T t) { requires sizeof(t) == 0; } // expected-note{{because 'sizeof (t) == 0' (4 == 0) evaluated to false}}
+struct r3 {};
+
+using r3i = r3<int>; // expected-error{{constraints not satisfied for class template 'r3' [with T = int]}}
+
+template<typename T>
+struct X {
+ template<typename U> requires requires (U u) { requires sizeof(u) == sizeof(T); } // expected-note{{because 'sizeof (u) == sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}}
+ struct r4 {};
+};
+
+using r4i = X<void>::r4<int>; // expected-error{{constraints not satisfied for class template 'r4' [with U = int]}}
+
+// C++ [expr.prim.req.nested] Examples
+namespace std_example {
+ template<typename U> concept C1 = sizeof(U) == 1; // expected-note{{because 'sizeof(int) == 1' (4 == 1) evaluated to false}}
+ template<typename T> concept D =
+ requires (T t) {
+ requires C1<decltype (+t)>; // expected-note{{because 'decltype(+t)' (aka 'int') does not satisfy 'C1'}}
+ };
+
+ struct T1 { char operator+() { return 'a'; } };
+ static_assert(D<T1>);
+ template<D T> struct D_check {}; // expected-note{{because 'short' does not satisfy 'D'}}
+ using dc1 = D_check<short>; // expected-error{{constraints not satisfied for class template 'D_check' [with T = short]}}
+
+ template<typename T>
+ concept C2 = requires (T a) { // expected-note{{'a' declared here}}
+ requires sizeof(a) == 4; // OK
+ requires a == 0; // expected-error{{constraint variable 'a' cannot be used in an evaluated context}}
+ };
+} \ No newline at end of file
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/p3.cpp
new file mode 100644
index 00000000000..a1a745253dd
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/p3.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify
+
+// Examples from standard
+
+template<typename T, typename U>
+concept convertible_to = requires(T t) { U(t); };
+
+template<typename T>
+concept R = requires (T i) {
+ typename T::type;
+ {*i} -> convertible_to<const typename T::type&>;
+};
+
+template<typename T> requires R<T> struct S {};
+
+struct T {
+ using type = int;
+ type i;
+ const type &operator*() { return i; }
+};
+
+using si = S<T>;
+
+template<typename T>
+requires requires (T x) { x + x; } // expected-note{{because 'x + x' would be invalid: invalid operands to binary expression ('T' and 'T')}}
+T add(T a, T b) { return a + b; } // expected-note{{candidate template ignored: constraints not satisfied [with T = T]}}
+
+int x = add(1, 2);
+int y = add(T{}, T{}); // expected-error{{no matching function for call to 'add'}}
+
+template<typename T>
+concept C = requires (T x) { x + x; }; // expected-note{{because 'x + x' would be invalid: invalid operands to binary expression ('T' and 'T')}}
+template<typename T> requires C<T> // expected-note{{because 'T' does not satisfy 'C'}}
+T add2(T a, T b) { return a + b; } // expected-note{{candidate template ignored: constraints not satisfied [with T = T]}}
+
+int z = add2(1, 2);
+int w = add2(T{}, T{}); // expected-error{{no matching function for call to 'add2'}} \ No newline at end of file
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp
new file mode 100644
index 00000000000..f9d8c3eed11
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify
+
+using A = int;
+
+template<typename T, typename U>
+constexpr bool is_same_v = false;
+
+template<typename T>
+constexpr bool is_same_v<T, T> = true;
+
+template<typename T, typename U>
+concept same_as = is_same_v<T, U>;
+
+static_assert(requires { requires true; 0; typename A;
+ { 0 } -> same_as<int>; });
+static_assert(is_same_v<bool, decltype(requires { requires false; })>);
+
+// Check that requires expr is an unevaluated context.
+struct Y {
+ int i;
+ static constexpr bool r = requires { i; };
+};
+
+template<typename T> requires requires (T t) {
+ requires false; // expected-note{{because 'false' evaluated to false}}
+ requires false;
+ requires requires {
+ requires false;
+ };
+}
+struct r1 { };
+
+using r1i = r1<int>;
+// expected-error@-1 {{constraints not satisfied for class template 'r1' [with T = int]}}
+
+template<typename T> requires requires (T t) {
+ requires requires {
+ requires false; // expected-note{{because 'false' evaluated to false}}
+ };
+}
+struct r2 { };
+
+using r2i = r2<int>;
+// expected-error@-1 {{constraints not satisfied for class template 'r2' [with T = int]}}
+
+template<typename T> requires requires (T t) {
+ requires requires {
+ requires true;
+ };
+ requires true;
+ requires requires {
+ requires false; // expected-note{{because 'false' evaluated to false}}
+ };
+}
+struct r3 { };
+
+using r3i = r3<int>;
+// expected-error@-1 {{constraints not satisfied for class template 'r3' [with T = int]}}
+
+template<typename T>
+struct S { static const int s = T::value; };
+
+template<typename T> requires requires { T::value; S<T>::s; }
+// expected-note@-1 {{because 'T::value' would be invalid: type 'int' cannot be used prior to '::' because it has no members}}
+struct r4 { };
+
+using r4i = r4<int>;
+// expected-error@-1 {{constraints not satisfied for class template 'r4' [with T = int]}} \ No newline at end of file
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
new file mode 100644
index 00000000000..a5e6c3057fe
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp
@@ -0,0 +1,106 @@
+// RUN: %clang_cc1 %s -I%S -std=c++2a -fconcepts-ts -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 substituted constraint expression is ill-formed: 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}}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
new file mode 100644
index 00000000000..8e402a88c40
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
@@ -0,0 +1,194 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify
+
+using A = int;
+
+template<typename T> using identity_t = T; // expected-note 4{{template is declared here}}}
+
+template<typename T> struct identity { using type = T; };
+// expected-note@-1 2{{template is declared here}}
+
+struct C {};
+
+struct D { static int type; }; // expected-note{{referenced member 'type' is declared here}}
+
+// Basic unqualified and global-qualified lookups
+
+static_assert(requires { typename A; typename ::A; });
+static_assert(requires { typename identity_t<A>; typename ::identity_t<A>; });
+static_assert(!requires { typename identity_t<A, A>; }); // expected-error{{too many template arguments for alias template 'identity_t'}}
+static_assert(!requires { typename ::identity_t<A, A>; }); // expected-error{{too many template arguments for alias template 'identity_t'}}
+static_assert(requires { typename identity<A>; });
+static_assert(!requires { typename identity; });
+// expected-error@-1 {{typename specifier refers to class template; argument deduction not allowed here}}
+static_assert(!requires { typename ::identity; });
+// expected-error@-1 {{typename specifier refers to class template; argument deduction not allowed here}}
+static_assert(!requires { typename identity_t; });
+// expected-error@-1 {{typename specifier refers to alias template; argument deduction not allowed here}}
+static_assert(!requires { typename ::identity_t; });
+// expected-error@-1 {{typename specifier refers to alias template; argument deduction not allowed here}}
+
+namespace ns {
+ using B = int;
+ int C = 0;
+ // expected-note@-1 {{referenced 'C' is declared here}}
+ static_assert(requires { typename A; typename B; typename ::A; });
+ static_assert(!requires { typename ns::A; }); // expected-error{{no type named 'A' in namespace 'ns'}}
+ static_assert(!requires { typename ::B; }); // expected-error{{no type named 'B' in the global namespace}}
+ static_assert(requires { typename C; });
+ // expected-error@-1 {{typename specifier refers to non-type 'C'}}
+}
+
+// member type lookups
+
+static_assert(requires { typename identity<int>::type; typename ::identity<int>::type; });
+static_assert(!requires { typename identity<int>::typr; }); // expected-error{{no type named 'typr' in 'identity<int>'}}
+static_assert(!requires { typename ::identity<int>::typr; }); // expected-error{{no type named 'typr' in 'identity<int>'}}
+
+template<typename T> requires requires { typename T::type; }
+// expected-note@-1 {{because 'typename T::type' would be invalid: type 'int' cannot be used prior to '::' because it has no members}}
+// expected-note@-2 {{because 'typename T::type' would be invalid: no type named 'type' in 'C'}}
+// expected-note@-3 {{because 'typename T::type' would be invalid: typename specifier refers to non-type member 'type' in 'D'}}
+// expected-note@-4 {{in instantiation of template class 'invalid<D>' requested here}}
+// expected-note@-5 {{in instantiation of requirement here}}
+// expected-note@-6 {{while substituting template arguments into constraint expression here}}
+// expected-note@-7 {{because 'typename T::type' would be invalid}}
+struct r1 {};
+
+using r1i1 = r1<identity<int>>;
+using r1i2 = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}
+using r1i3 = r1<C>; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}}
+using r1i4 = r1<D>; // expected-error{{constraints not satisfied for class template 'r1' [with T = D]}}
+
+template<typename T> struct invalid { typename T::type x; };
+// expected-error@-1 {{typename specifier refers to non-type member 'type' in 'D'}}
+using r1i5 = r1<invalid<D>>;
+// expected-error@-1 {{constraints not satisfied for class template 'r1' [with T = invalid<D>]}}
+// expected-note@-2 {{while checking constraint satisfaction for template 'r1<invalid<D> >' required here}}
+
+// mismatching template arguments
+
+template<typename... Ts> requires requires { typename identity<Ts...>; } // expected-note{{because 'typename identity<Ts...>' would be invalid: too many template arguments for class template 'identity'}}
+struct r2 {};
+
+using r2i1 = r2<int>;
+using r2i2 = r2<void>;
+using r2i3 = r2<int, int>; // expected-error{{constraints not satisfied for class template 'r2' [with Ts = <int, int>]}}
+
+namespace ns2 {
+ template<typename T, typename U> struct identity {};
+
+ template<typename... Ts> requires requires { typename identity<Ts...>; } // expected-note 2{{because 'typename identity<Ts...>' would be invalid: too few template arguments for class template 'identity'}}
+ struct r4 {};
+
+ using r4i1 = r4<int>; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = <int>]}}
+}
+
+using r4i2 = ns2::r4<int>; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = <int>]}}
+
+using E = int;
+template<typename T> requires requires { typename E<T>; } // expected-error{{expected ';' at end of requirement}}
+struct r5v1 {};
+template<typename T> requires requires { typename ::E<T>; } // expected-error{{expected ';' at end of requirement}}
+struct r5v2 {};
+
+template<typename T> requires (sizeof(T) == 1)
+struct chars_only {};
+
+template<typename T> requires requires { typename chars_only<T>; } // expected-note{{because 'typename chars_only<T>' would be invalid: constraints not satisfied for class template 'chars_only' [with T = int]}}
+struct r6 {};
+
+using r6i = r6<int>; // expected-error{{constraints not satisfied for class template 'r6' [with T = int]}}
+
+template<typename T> int F = 0; // expected-note 2{{variable template 'F' declared here}}
+
+static_assert(!requires { typename F<int>; });
+// expected-error@-1{{template name refers to non-type template 'F'}}
+static_assert(!requires { typename ::F<int>; });
+// expected-error@-1{{template name refers to non-type template '::F'}}
+
+struct G { template<typename T> static T temp; };
+
+template<typename T> requires requires { typename T::template temp<int>; }
+// expected-note@-1{{because 'typename T::temp<int>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}}
+// expected-note@-2{{because 'typename T::temp<int>' would be invalid: no member named 'temp' in 'D'}}
+// expected-note@-3{{because 'typename T::temp<int>' would be invalid: template name refers to non-type template 'G::template temp'}}
+struct r7 {};
+
+using r7i1 = r7<int>; // expected-error{{constraints not satisfied for class template 'r7' [with T = int]}}
+using r7i2 = r7<D>; // expected-error{{constraints not satisfied for class template 'r7' [with T = D]}}
+using r7i3 = r7<G>; // expected-error{{constraints not satisfied for class template 'r7' [with T = G]}}
+
+template<typename T> struct H;
+
+template<typename T> requires requires { typename H<T>; }
+struct r8 {};
+
+using r8i = r8<int>;
+
+template<typename T> struct I { struct incomplete; }; // expected-note{{member is declared here}}
+
+static_assert(!requires { I<int>::incomplete::inner; }); // expected-error{{implicit instantiation of undefined member 'I<int>::incomplete'}}
+
+template<typename T> requires requires { typename I<T>::incomplete::inner; } // expected-note{{because 'typename I<T>::incomplete::inner' would be invalid: implicit instantiation of undefined member 'I<int>::incomplete'}}
+struct r9 {};
+
+using r9i = r9<int>; // expected-error{{constraints not satisfied for class template 'r9' [with T = int]}}
+
+namespace ns3 {
+ struct X { }; // expected-note 2{{candidate found by name lookup is 'ns3::X'}}
+}
+
+struct X { using inner = int; }; // expected-note 2{{candidate found by name lookup is 'X'}}
+
+using namespace ns3;
+static_assert(requires { typename X; }); // expected-error{{reference to 'X' is ambiguous}}
+static_assert(requires { typename X::inner; }); // expected-error{{reference to 'X' is ambiguous}}
+// expected-error@-1{{unknown type name 'inner'}}
+
+// naming a type template specialization in a type requirement does not require
+// it to be complete and should not care about partial specializations.
+
+template<typename T>
+struct Z;
+
+template<typename T> requires (sizeof(T) >= 1)
+struct Z<T> {}; // expected-note{{partial specialization matches [with T = int]}}
+
+template<typename T> requires (sizeof(T) <= 4)
+struct Z<T> {}; // expected-note{{partial specialization matches [with T = int]}}
+
+Z<int> x; // expected-error{{ambiguous partial specializations of 'Z<int>'}}
+
+static_assert(requires { typename Z<int>; });
+
+// C++ [expr.prim.req.type] Example
+namespace std_example {
+ template<typename T, typename T::type = 0> struct S;
+ // expected-note@-1 {{because 'typename S<T>' would be invalid: no type named 'type' in 'std_example::has_inner}}
+ template<typename T> using Ref = T&; // expected-note{{because 'typename Ref<T>' would be invalid: cannot form a reference to 'void'}}
+ template<typename T> concept C1 =
+ requires {
+ typename T::inner;
+ // expected-note@-1 {{because 'typename T::inner' would be invalid: type 'int' cannot be used prior to '::' because it has no members}}
+ // expected-note@-2 {{because 'typename T::inner' would be invalid: no type named 'inner' in 'std_example::has_type'}}
+ };
+ template<typename T> concept C2 = requires { typename S<T>; };
+ template<typename T> concept C3 = requires { typename Ref<T>; };
+
+ struct has_inner { using inner = int;};
+ struct has_type { using type = int; };
+ struct has_inner_and_type { using inner = int; using type = int; };
+
+ static_assert(C1<has_inner_and_type> && C2<has_inner_and_type> && C3<has_inner_and_type>);
+ template<C1 T> struct C1_check {};
+ // expected-note@-1 {{because 'int' does not satisfy 'C1'}}
+ // expected-note@-2 {{because 'std_example::has_type' does not satisfy 'C1'}}
+ template<C2 T> struct C2_check {};
+ // expected-note@-1 {{because 'std_example::has_inner' does not satisfy 'C2'}}
+ template<C3 T> struct C3_check {};
+ // expected-note@-1 {{because 'void' does not satisfy 'C3'}}
+ using c1 = C1_check<int>; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = int]}}
+ using c2 = C1_check<has_type>; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = std_example::has_type]}}
+ using c3 = C2_check<has_inner>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::has_inner]}}
+ using c4 = C3_check<void>; // expected-error{{constraints not satisfied for class template 'C3_check' [with T = void]}}
+} \ No newline at end of file
diff --git a/clang/test/PCH/cxx2a-requires-expr.cpp b/clang/test/PCH/cxx2a-requires-expr.cpp
new file mode 100644
index 00000000000..d52d451c2d6
--- /dev/null
+++ b/clang/test/PCH/cxx2a-requires-expr.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -emit-pch -std=c++2a -fconcepts-ts -o %t %s
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x ast -ast-print %t | FileCheck %s
+
+template<typename T>
+concept C = true;
+
+template<typename T, typename U>
+concept C2 = true;
+
+template<typename T>
+bool f() {
+ // CHECK: requires (T t) { t++; { t++ } noexcept -> C; { t++ } -> C2<int>; typename T::a; requires T::val; };
+ return requires (T t) {
+ t++;
+ { t++ } noexcept -> C;
+ { t++ } -> C2<int>;
+ typename T::a;
+ requires T::val;
+ };
+}
diff --git a/clang/test/Parser/cxx2a-concepts-requires-expr.cpp b/clang/test/Parser/cxx2a-concepts-requires-expr.cpp
new file mode 100644
index 00000000000..a53189caa5f
--- /dev/null
+++ b/clang/test/Parser/cxx2a-concepts-requires-expr.cpp
@@ -0,0 +1,141 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify
+
+bool r1 = requires () {};
+// expected-error@-1 {{a requires expression must contain at least one requirement}}
+
+bool r2 = requires { requires true; };
+
+bool r3 = requires (int a, ...) { requires true; };
+// expected-error@-1 {{varargs not allowed in requires expression}}
+
+template<typename... T>
+bool r4 = requires (T... ts) { requires true; };
+
+bool r5 = requires (bool c, int d) { c; d; };
+
+bool r6 = requires (bool c, int d) { c; d; } && decltype(d){};
+// expected-error@-1 {{use of undeclared identifier 'd'}}
+
+bool r7 = requires (bool c) { c; (requires (int d) { c; d; }); d; } && decltype(c){} && decltype(d){};
+// expected-error@-1 2{{use of undeclared identifier 'd'}}
+// expected-error@-2 {{use of undeclared identifier 'c'}}
+
+bool r8 = requires (bool, int) { requires true; };
+
+bool r9 = requires (bool a, int a) { requires true; };
+// expected-error@-1 {{redefinition of parameter 'a'}}
+// expected-note@-2 {{previous declaration is here}}
+
+bool r10 = requires (struct new_struct { int x; } s) { requires true; };
+// expected-error@-1 {{'new_struct' cannot be defined in a parameter type}}
+
+bool r11 = requires (int x(1)) { requires true; };
+// expected-error@-1 {{expected parameter declarator}}
+// expected-error@-2 {{expected ')'}}
+// expected-note@-3 {{to match this '('}}
+
+bool r12 = requires (int x = 10) { requires true; };
+// expected-error@-1 {{default arguments not allowed for parameters of a requires expression}}
+
+bool r13 = requires (int f(int)) { requires true; };
+
+bool r14 = requires (int (*f)(int)) { requires true; };
+
+bool r15 = requires (10) { requires true; };
+// expected-error@-1 {{expected parameter declarator}}
+
+bool r16 = requires (auto x) { requires true; };
+// expected-error@-1 {{'auto' not allowed in requires expression parameter}}
+
+bool r17 = requires (auto [x, y]) { requires true; };
+// expected-error@-1 {{'auto' not allowed in requires expression parameter}}
+// expected-error@-2 {{use of undeclared identifier 'x'}}
+
+using a = int;
+
+bool r18 = requires { typename a; };
+
+bool r19 = requires { typename ::a; };
+
+template<typename T> struct identity { using type = T; };
+
+template<typename T> using identity_t = T;
+
+bool r20 = requires {
+ typename identity<int>::type;
+ typename identity<int>;
+ typename ::identity_t<int>;
+};
+
+struct s { bool operator==(const s&); ~s(); };
+
+bool r21 = requires { typename s::operator==; };
+// expected-error@-1 {{expected an identifier or template-id after '::'}}
+
+bool r22 = requires { typename s::~s; };
+// expected-error@-1 {{expected an identifier or template-id after '::'}}
+
+template<typename T>
+bool r23 = requires { typename identity<T>::temp<T>; };
+// expected-error@-1 {{use 'template' keyword to treat 'temp' as a dependent template name}}
+
+template<typename T>
+bool r24 = requires {
+ typename identity<T>::template temp<T>;
+ typename identity<T>::template temp; // expected-error{{expected an identifier or template-id after '::'}}
+};
+
+bool r25 = requires { ; };
+// expected-error@-1 {{expected expression}}
+
+bool r26 = requires { {}; };
+// expected-error@-1 {{expected expression}}
+
+bool r27 = requires { { 0 } noexcept; };
+
+bool r28 = requires { { 0 } noexcept noexcept; };
+// expected-error@-1 {{expected '->' before expression type requirement}}
+// expected-error@-2 {{expected concept name with optional arguments}}
+
+template<typename T>
+concept C1 = true;
+
+template<typename T, typename U>
+concept C2 = true;
+
+bool r29 = requires { { 0 } noexcept C1; };
+// expected-error@-1 {{expected '->' before expression type requirement}}
+
+bool r30 = requires { { 0 } noexcept -> C2<int>; };
+
+template<typename T>
+T i1 = 0;
+
+bool r31 = requires { requires false, 1; };
+// expected-error@-1 {{expected ';' at end of requirement}}
+
+bool r32 = requires { 0 noexcept; };
+// expected-error@-1 {{'noexcept' can only be used in a compound requirement (with '{' '}' around the expression)}}
+
+bool r33 = requires { 0 int; };
+// expected-error@-1 {{expected ';' at end of requirement}}
+
+bool r34 = requires { requires true };
+// expected-error@-1 {{expected ';' at end of requirement}}
+
+bool r35 = requires (bool b) { requires sizeof(b) == 1; };
+
+void r36(bool b) requires requires { 1 } {}
+// expected-error@-1 {{expected ';' at end of requirement}}
+
+bool r37 = requires { requires { 1; }; };
+// expected-warning@-1 {{this requires expression will only be checked for syntactic validity; did you intend to place it in a nested requirement? (add another 'requires' before the expression)}}
+
+bool r38 = requires { requires () { 1; }; };
+// expected-warning@-1 {{this requires expression will only be checked for syntactic validity; did you intend to place it in a nested requirement? (add another 'requires' before the expression)}}
+
+bool r39 = requires { requires (int i) { i; }; };
+// expected-warning@-1 {{this requires expression will only be checked for syntactic validity; did you intend to place it in a nested requirement? (add another 'requires' before the expression)}}
+
+bool r40 = requires { requires (); };
+// expected-error@-1 {{expected expression}}
diff --git a/clang/test/SemaTemplate/instantiate-requires-expr.cpp b/clang/test/SemaTemplate/instantiate-requires-expr.cpp
new file mode 100644
index 00000000000..3304fd25cdc
--- /dev/null
+++ b/clang/test/SemaTemplate/instantiate-requires-expr.cpp
@@ -0,0 +1,216 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify -Wno-unused-value
+
+template<typename T, typename U>
+constexpr bool is_same_v = false;
+
+template<typename T>
+constexpr bool is_same_v<T, T> = true;
+
+// We use a hack in this file to make the compiler print out the requires
+// expression after it has been instantiated - we put false_v<requires {...}> as
+// the requires clause of a class template, then instantiate the template.
+// The requirement will not be satisfied, and the explaining diagnostic will
+// print out false_v<requires {...}> in its raw form (the false_v serves to
+// prevent the diagnostic from elaborating on why the requires expr wasn't
+// satisfied).
+
+template<bool v>
+constexpr bool false_v = false;
+
+template<typename... Ts>
+using void_t = void;
+
+// Check that requires parameters are instantiated correctly.
+
+template<typename T> requires
+false_v<requires (T t) { requires is_same_v<decltype(t), int>; }>
+// expected-note@-1 {{because 'false_v<requires (int t) { requires is_same_v<decltype(t), int>; }>' evaluated to false}}
+// expected-note@-2 {{because 'false_v<requires (char t) { requires is_same_v<decltype(t), int>; }>' evaluated to false}}
+struct r1 {};
+
+using r1i1 = r1<int>; // expected-error {{constraints not satisfied for class template 'r1' [with T = int]}}
+using r1i2 = r1<char>; // expected-error {{constraints not satisfied for class template 'r1' [with T = char]}}
+
+// Check that parameter packs work.
+
+template<typename... Ts> requires
+false_v<requires (Ts... ts) {requires ((sizeof(ts) == 2) && ...);}>
+// expected-note@-1 {{because 'false_v<requires (short ts, unsigned short ts) { requires (sizeof (ts) == 2) && (sizeof (ts) == 2); }>'}}
+// expected-note@-2 {{because 'false_v<requires (short ts) { requires (sizeof (ts) == 2); }>' evaluated to false}}
+struct r2 {};
+
+using r2i1 = r2<short, unsigned short>; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = <short, unsigned short>]}}
+using r2i2 = r2<short>; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = <short>]}}
+
+template<typename... Ts> requires
+false_v<(requires (Ts ts) {requires sizeof(ts) != 0;} && ...)>
+// expected-note@-1 {{because 'false_v<requires (short ts) { requires sizeof (ts) != 0; } && requires (unsigned short ts) { requires sizeof (ts) != 0; }>' evaluated to false}}
+// expected-note@-2 {{because 'false_v<requires (short ts) { requires sizeof (ts) != 0; }>' evaluated to false}}
+struct r3 {};
+
+using r3i1 = r3<short, unsigned short>; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = <short, unsigned short>]}}
+using r3i2 = r3<short>; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = <short>]}}
+
+template<typename T>
+struct identity { using type = T; };
+
+namespace type_requirement {
+ struct A {};
+
+ // check that nested name specifier is instantiated correctly.
+ template<typename T> requires false_v<requires { typename T::type; }> // expected-note{{because 'false_v<requires { typename identity<int>::type; }>' evaluated to false}}
+ struct r1 {};
+
+ using r1i = r1<identity<int>>; // expected-error{{constraints not satisfied for class template 'r1' [with T = identity<int>]}}
+
+ // check that template argument list is instantiated correctly.
+ template<typename T>
+ struct contains_template {
+ template<typename U> requires is_same_v<contains_template<T>, U>
+ using temp = int;
+ };
+
+ template<typename T> requires
+ false_v<requires { typename T::template temp<T>; }>
+ // expected-note@-1 {{because 'false_v<requires { typename contains_template<int>::temp<contains_template<int> >; }>' evaluated to false}}
+ // expected-note@-2 {{because 'false_v<requires { typename contains_template<short>::temp<contains_template<short> >; }>' evaluated to false}}
+ struct r2 {};
+
+ using r2i1 = r2<contains_template<int>>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template<int>]}}
+ using r2i2 = r2<contains_template<short>>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template<short>]}}
+
+ // substitution error occurs, then requires expr is instantiated again
+
+ template<typename T>
+ struct a {
+ template<typename U> requires (requires { typename T::a::a; }, false)
+ // expected-note@-1{{because 'requires { <<error-type>>; } , false' evaluated to false}}
+ struct r {};
+ };
+
+ using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
+
+ // Parameter pack inside expr
+ template<typename... Ts> requires
+ false_v<(requires { typename Ts::type; } && ...)>
+ // expected-note@-1 {{because 'false_v<requires { typename identity<short>::type; } && requires { typename identity<int>::type; } && requires { <<error-type>>; }>' evaluated to false}}
+ struct r5 {};
+
+ using r5i = r5<identity<short>, identity<int>, short>; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = <identity<short>, identity<int>, short>]}}
+ template<typename... Ts> requires
+ false_v<(requires { typename void_t<Ts>; } && ...)> // expected-note{{because 'false_v<requires { typename void_t<int>; } && requires { typename void_t<short>; }>' evaluated to false}}
+ struct r6 {};
+
+ using r6i = r6<int, short>; // expected-error{{constraints not satisfied for class template 'r6' [with Ts = <int, short>]}}
+
+ template<typename... Ts> requires
+ false_v<(requires { typename Ts::template aaa<Ts>; } && ...)>
+ // expected-note@-1 {{because 'false_v<requires { <<error-type>>; } && requires { <<error-type>>; }>' evaluated to false}}
+ struct r7 {};
+
+ using r7i = r7<int, A>; // expected-error{{constraints not satisfied for class template 'r7' [with Ts = <int, type_requirement::A>]}}
+}
+
+namespace expr_requirement {
+ // check that compound/simple requirements are instantiated correctly.
+
+ template<typename T> requires false_v<requires { sizeof(T); { sizeof(T) }; }>
+ // expected-note@-1 {{because 'false_v<requires { sizeof(int); { sizeof(int) }; }>' evaluated to false}}
+ // expected-note@-2 {{because 'false_v<requires { <<error-expression>>; { sizeof(T) }; }>' evaluated to false}}
+ struct r1 {};
+
+ using r1i1 = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}
+ using r1i2 = r1<void>; // expected-error{{constraints not satisfied for class template 'r1' [with T = void]}}
+
+ // substitution error occurs in expr, then expr is instantiated again.
+
+ template<typename T>
+ struct a {
+ template<typename U> requires (requires { sizeof(T::a); }, false) // expected-note{{because 'requires { <<error-expression>>; } , false' evaluated to false}}
+ struct r {};
+ };
+
+ using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
+
+ // check that the return-type-requirement is instantiated correctly.
+
+ template<typename T, typename U = int>
+ concept C1 = is_same_v<T, U>;
+
+ template<typename T> requires false_v<requires(T t) { { t } -> C1<T>; }>
+ // expected-note@-1 {{because 'false_v<requires (int t) { { t } -> C1<int>; }>' evaluated to false}}
+ // expected-note@-2 {{because 'false_v<requires (double t) { { t } -> C1<double>; }>' evaluated to false}}
+ struct r2 {};
+
+ using r2i1 = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}}
+ using r2i2 = r2<double>; // expected-error{{constraints not satisfied for class template 'r2' [with T = double]}}
+
+
+ // substitution error occurs in return type requirement, then requires expr is
+ // instantiated again.
+
+ template<typename T>
+ struct b {
+ template<typename U> requires (requires { { 0 } -> C1<typename T::a>; }, false) // expected-note{{because 'requires { { 0 } -> <<error-type>>; } , false' evaluated to false}}
+ struct r {};
+ };
+
+ using bri = b<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
+
+
+ template<typename... Ts> requires
+ false_v<(requires { { 0 } noexcept -> C1<Ts>; } && ...)>
+ // expected-note@-1 {{because 'false_v<requires { { 0 } noexcept -> C1<int>; } && requires { { 0 } noexcept -> C1<unsigned int>; }>' evaluated to false}}
+ struct r3 {};
+
+ using r3i = r3<int, unsigned int>; // expected-error{{constraints not satisfied for class template 'r3' [with Ts = <int, unsigned int>]}}
+}
+
+namespace nested_requirement {
+ // check that constraint expression is instantiated correctly
+ template<typename T> requires false_v<requires { requires sizeof(T) == 2; }> // expected-note{{because 'false_v<requires { requires sizeof(int) == 2; }>' evaluated to false}}
+ struct r1 {};
+
+ using r1i = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}
+
+ // substitution error occurs in expr, then expr is instantiated again.
+ template<typename T>
+ struct a {
+ template<typename U> requires
+ (requires { requires sizeof(T::a) == 0; }, false) // expected-note{{because 'requires { requires <<error-expression>>; } , false' evaluated to false}}
+ struct r {};
+ };
+
+ using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
+
+ // Parameter pack inside expr
+ template<typename... Ts> requires
+ false_v<(requires { requires sizeof(Ts) == 0; } && ...)>
+ // expected-note@-1 {{because 'false_v<requires { requires sizeof(int) == 0; } && requires { requires sizeof(short) == 0; }>' evaluated to false}}
+ struct r2 {};
+
+ using r2i = r2<int, short>; // expected-error{{constraints not satisfied for class template 'r2' [with Ts = <int, short>]}}
+}
+
+// Parameter pack inside multiple requirements
+template<typename... Ts> requires
+false_v<(requires { requires sizeof(Ts) == 0; sizeof(Ts); } && ...)>
+// expected-note@-1 {{because 'false_v<requires { requires sizeof(int) == 0; sizeof(Ts); } && requires { requires sizeof(short) == 0; sizeof(Ts); }>' evaluated to false}}
+struct r4 {};
+
+using r4i = r4<int, short>; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = <int, short>]}}
+
+template<typename... Ts> requires
+false_v<(requires(Ts t) { requires sizeof(t) == 0; t++; } && ...)>
+// expected-note@-1 {{because 'false_v<requires (int t) { requires sizeof (t) == 0; t++; } && requires (short t) { requires sizeof (t) == 0; t++; }>' evaluated to false}}
+struct r5 {};
+
+using r5i = r5<int, short>; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = <int, short>]}}
+
+template<typename T> requires
+false_v<(requires(T t) { T{t}; })> // T{t} creates an "UnevaluatedList" context.
+// expected-note@-1 {{because 'false_v<(requires (int t) { int{t}; })>' evaluated to false}}
+struct r6 {};
+
+using r6i = r6<int>;
+// expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}}
OpenPOWER on IntegriCloud