1 // RUN: %clang_cc1 -std=c++2a -x c++ %s -verify 2 3 using A = int; 4 5 template<typename T> using identity_t = T; // expected-note 4{{template is declared here}}} 6 7 template<typename T> struct identity { using type = T; }; 8 // expected-note@-1 2{{template is declared here}} 9 10 struct C {}; 11 12 struct D { static int type; }; // expected-note{{referenced member 'type' is declared here}} 13 14 // Basic unqualified and global-qualified lookups 15 16 static_assert(requires { typename A; typename ::A; }); 17 static_assert(requires { typename identity_t<A>; typename ::identity_t<A>; }); 18 static_assert(!requires { typename identity_t<A, A>; }); // expected-error{{too many template arguments for alias template 'identity_t'}} 19 static_assert(!requires { typename ::identity_t<A, A>; }); // expected-error{{too many template arguments for alias template 'identity_t'}} 20 static_assert(requires { typename identity<A>; }); 21 static_assert(!requires { typename identity; }); 22 // expected-error@-1 {{typename specifier refers to class template; argument deduction not allowed here}} 23 static_assert(!requires { typename ::identity; }); 24 // expected-error@-1 {{typename specifier refers to class template; argument deduction not allowed here}} 25 static_assert(!requires { typename identity_t; }); 26 // expected-error@-1 {{typename specifier refers to alias template; argument deduction not allowed here}} 27 static_assert(!requires { typename ::identity_t; }); 28 // expected-error@-1 {{typename specifier refers to alias template; argument deduction not allowed here}} 29 30 namespace ns { 31 using B = int; 32 int C = 0; 33 // expected-note@-1 {{referenced 'C' is declared here}} 34 static_assert(requires { typename A; typename B; typename ::A; }); 35 static_assert(!requires { typename ns::A; }); // expected-error{{no type named 'A' in namespace 'ns'}} 36 static_assert(!requires { typename ::B; }); // expected-error{{no type named 'B' in the global namespace}} 37 static_assert(requires { typename C; }); 38 // expected-error@-1 {{typename specifier refers to non-type 'C'}} 39 } 40 41 // member type lookups 42 43 static_assert(requires { typename identity<int>::type; typename ::identity<int>::type; }); 44 static_assert(!requires { typename identity<int>::typr; }); // expected-error{{no type named 'typr' in 'identity<int>'}} 45 static_assert(!requires { typename ::identity<int>::typr; }); // expected-error{{no type named 'typr' in 'identity<int>'}} 46 47 template<typename T> requires requires { typename T::type; } 48 // expected-note@-1 {{because 'typename T::type' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} 49 // expected-note@-2 {{because 'typename T::type' would be invalid: no type named 'type' in 'C'}} 50 // expected-note@-3 {{because 'typename T::type' would be invalid: typename specifier refers to non-type member 'type' in 'D'}} 51 // expected-note@-4 {{in instantiation of template class 'invalid<D>' requested here}} 52 // expected-note@-5 {{in instantiation of requirement here}} 53 // expected-note@-6 {{while substituting template arguments into constraint expression here}} 54 // expected-note@-7 {{because 'typename T::type' would be invalid}} 55 struct r1 {}; 56 57 using r1i1 = r1<identity<int>>; 58 using r1i2 = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}} 59 using r1i3 = r1<C>; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}} 60 using r1i4 = r1<D>; // expected-error{{constraints not satisfied for class template 'r1' [with T = D]}} 61 62 template<typename T> struct invalid { typename T::type x; }; 63 // expected-error@-1 {{typename specifier refers to non-type member 'type' in 'D'}} 64 using r1i5 = r1<invalid<D>>; 65 // expected-error@-1 {{constraints not satisfied for class template 'r1' [with T = invalid<D>]}} 66 // expected-note@-2 {{while checking constraint satisfaction for template 'r1<invalid<D>>' required here}} 67 68 // mismatching template arguments 69 70 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'}} 71 struct r2 {}; 72 73 using r2i1 = r2<int>; 74 using r2i2 = r2<void>; 75 using r2i3 = r2<int, int>; // expected-error{{constraints not satisfied for class template 'r2' [with Ts = <int, int>]}} 76 77 namespace ns2 { 78 template<typename T, typename U> struct identity {}; 79 80 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'}} 81 struct r4 {}; 82 83 using r4i1 = r4<int>; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = <int>]}} 84 } 85 86 using r4i2 = ns2::r4<int>; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = <int>]}} 87 88 using E = int; 89 template<typename T> requires requires { typename E<T>; } // expected-error{{expected ';' at end of requirement}} 90 struct r5v1 {}; 91 template<typename T> requires requires { typename ::E<T>; } // expected-error{{expected ';' at end of requirement}} 92 struct r5v2 {}; 93 94 template<typename T> requires (sizeof(T) == 1) 95 struct chars_only {}; 96 97 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]}} 98 struct r6 {}; 99 100 using r6i = r6<int>; // expected-error{{constraints not satisfied for class template 'r6' [with T = int]}} 101 102 template<typename T> int F = 0; // expected-note 2{{variable template 'F' declared here}} 103 104 static_assert(!requires { typename F<int>; }); 105 // expected-error@-1{{template name refers to non-type template 'F'}} 106 static_assert(!requires { typename ::F<int>; }); 107 // expected-error@-1{{template name refers to non-type template '::F'}} 108 109 struct G { template<typename T> static T temp; }; 110 111 template<typename T> requires requires { typename T::template temp<int>; } 112 // expected-note@-1{{because 'typename T::template temp<int>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} 113 // expected-note@-2{{because 'typename T::template temp<int>' would be invalid: no member named 'temp' in 'D'}} 114 // expected-note@-3{{because 'typename T::template temp<int>' would be invalid: template name refers to non-type template 'G::template temp'}} 115 struct r7 {}; 116 117 using r7i1 = r7<int>; // expected-error{{constraints not satisfied for class template 'r7' [with T = int]}} 118 using r7i2 = r7<D>; // expected-error{{constraints not satisfied for class template 'r7' [with T = D]}} 119 using r7i3 = r7<G>; // expected-error{{constraints not satisfied for class template 'r7' [with T = G]}} 120 121 template<typename T> struct H; 122 123 template<typename T> requires requires { typename H<T>; } 124 struct r8 {}; 125 126 using r8i = r8<int>; 127 128 template<typename T> struct I { struct incomplete; }; // expected-note{{member is declared here}} 129 130 static_assert(!requires { I<int>::incomplete::inner; }); // expected-error{{implicit instantiation of undefined member 'I<int>::incomplete'}} 131 132 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'}} 133 struct r9 {}; 134 135 using r9i = r9<int>; // expected-error{{constraints not satisfied for class template 'r9' [with T = int]}} 136 137 namespace ns3 { 138 struct X { }; // expected-note 2{{candidate found by name lookup is 'ns3::X'}} 139 } 140 141 struct X { using inner = int; }; // expected-note 2{{candidate found by name lookup is 'X'}} 142 143 using namespace ns3; 144 static_assert(requires { typename X; }); // expected-error{{reference to 'X' is ambiguous}} 145 static_assert(requires { typename X::inner; }); // expected-error{{reference to 'X' is ambiguous}} 146 // expected-error@-1{{unknown type name 'inner'}} 147 148 // naming a type template specialization in a type requirement does not require 149 // it to be complete and should not care about partial specializations. 150 151 template<typename T> 152 struct Z; 153 154 template<typename T> requires (sizeof(T) >= 1) 155 struct Z<T> {}; // expected-note{{partial specialization matches [with T = int]}} 156 157 template<typename T> requires (sizeof(T) <= 4) 158 struct Z<T> {}; // expected-note{{partial specialization matches [with T = int]}} 159 160 Z<int> x; // expected-error{{ambiguous partial specializations of 'Z<int>'}} 161 162 static_assert(requires { typename Z<int>; }); 163 164 // C++ [expr.prim.req.type] Example 165 namespace std_example { 166 template<typename T, typename T::type = 0> struct S; 167 // expected-note@-1 {{because 'typename S<T>' would be invalid: no type named 'type' in 'std_example::has_inner}} 168 template<typename T> using Ref = T&; // expected-note{{because 'typename Ref<T>' would be invalid: cannot form a reference to 'void'}} 169 template<typename T> concept C1 = 170 requires { 171 typename T::inner; 172 // expected-note@-1 {{because 'typename T::inner' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} 173 // expected-note@-2 {{because 'typename T::inner' would be invalid: no type named 'inner' in 'std_example::has_type'}} 174 }; 175 template<typename T> concept C2 = requires { typename S<T>; }; 176 template<typename T> concept C3 = requires { typename Ref<T>; }; 177 178 struct has_inner { using inner = int;}; 179 struct has_type { using type = int; }; 180 struct has_inner_and_type { using inner = int; using type = int; }; 181 182 static_assert(C1<has_inner_and_type> && C2<has_inner_and_type> && C3<has_inner_and_type>); 183 template<C1 T> struct C1_check {}; 184 // expected-note@-1 {{because 'int' does not satisfy 'C1'}} 185 // expected-note@-2 {{because 'std_example::has_type' does not satisfy 'C1'}} 186 template<C2 T> struct C2_check {}; 187 // expected-note@-1 {{because 'std_example::has_inner' does not satisfy 'C2'}} 188 template<C3 T> struct C3_check {}; 189 // expected-note@-1 {{because 'void' does not satisfy 'C3'}} 190 using c1 = C1_check<int>; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = int]}} 191 using c2 = C1_check<has_type>; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = std_example::has_type]}} 192 using c3 = C2_check<has_inner>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::has_inner]}} 193 using c4 = C3_check<void>; // expected-error{{constraints not satisfied for class template 'C3_check' [with T = void]}} 194 } 195