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