xref: /llvm-project/clang/test/SemaCXX/cxx2c-pack-indexing.cpp (revision b311ab0f89980105a11f7bff5c6e7dd95d5c86fa)
1 // RUN: %clang_cc1 -std=c++2c -verify %s
2 
3 struct NotAPack;
4 template <typename T, auto V, template<typename> typename Tp>
5 void not_pack() {
6     int i = 0;
7     i...[0]; // expected-error {{i does not refer to the name of a parameter pack}}
8     V...[0]; // expected-error {{V does not refer to the name of a parameter pack}}
9     NotAPack...[0] a; // expected-error{{'NotAPack' does not refer to the name of a parameter pack}}
10     T...[0] b;   // expected-error{{'T' does not refer to the name of a parameter pack}}
11     Tp...[0] c; // expected-error{{'Tp' does not refer to the name of a parameter pack}}
12 }
13 
14 template <typename T, auto V, template<typename> typename Tp>
15 void not_pack_arrays() {
16     NotAPack...[0] a[1]; // expected-error{{'NotAPack' does not refer to the name of a parameter pack}}
17     T...[0] b[1];   // expected-error{{'T' does not refer to the name of a parameter pack}}
18     Tp...[0] c[1]; // expected-error{{'Tp' does not refer to the name of a parameter pack}}
19 }
20 
21 template <typename T>
22 struct TTP;
23 
24 void test_errors() {
25     not_pack<int, 0, TTP>();
26     not_pack_arrays<int, 0, TTP>();
27 }
28 
29 namespace invalid_indexes {
30 
31 int non_constant_index(); // expected-note 2{{declared here}}
32 
33 template <int idx>
34 int params(auto... p) {
35     return p...[idx]; // #error-param-size
36 }
37 
38 template <auto N, typename...T>
39 int test_types() {
40     T...[N] a; // #error-type-size
41 }
42 
43 void test() {
44     params<0>();   // expected-note{{here}} \
45                    // expected-error@#error-param-size {{invalid index 0 for pack p of size 0}}
46     params<1>(0);  // expected-note{{here}} \
47                    // expected-error@#error-param-size {{invalid index 1 for pack p of size 1}}
48     params<-1>(0); // expected-note{{here}} \
49                    // expected-error@#error-param-size {{invalid index -1 for pack p of size 1}}
50 
51     test_types<-1>(); //expected-note {{in instantiation}} \
52                       // expected-error@#error-type-size {{invalid index -1 for pack 'T' of size 0}}
53     test_types<-1, int>(); //expected-note {{in instantiation}} \
54                       // expected-error@#error-type-size {{invalid index -1 for pack 'T' of size 1}}
55     test_types<0>(); //expected-note {{in instantiation}} \
56                     // expected-error@#error-type-size {{invalid index 0 for pack 'T' of size 0}}
57     test_types<1, int>(); //expected-note {{in instantiation}}  \
58                          // expected-error@#error-type-size {{invalid index 1 for pack 'T' of size 1}}
59 }
60 
61 void invalid_indexes(auto... p) {
62     p...[non_constant_index()]; // expected-error {{array size is not a constant expression}}\
63                                 // expected-note {{cannot be used in a constant expression}}
64 
65     const char* no_index = "";
66     p...[no_index]; // expected-error {{value of type 'const char *' is not implicitly convertible}}
67 }
68 
69 void invalid_index_types() {
70     []<typename... T> {
71         T...[non_constant_index()] a;  // expected-error {{array size is not a constant expression}}\
72                                        // expected-note {{cannot be used in a constant expression}}
73     }(); //expected-note {{in instantiation}}
74 }
75 
76 }
77 
78 template <typename T, typename U>
79 constexpr bool is_same = false;
80 
81 template <typename T>
82 constexpr bool is_same<T, T> = true;
83 
84 template <typename T>
85 constexpr bool f(auto&&... p) {
86     return is_same<T, decltype(p...[0])>;
87 }
88 
89 void g() {
90     int a = 0;
91     const int b = 0;
92     static_assert(f<int&&>(0));
93     static_assert(f<int&>(a));
94     static_assert(f<const int&>(b));
95 }
96 
97 template <auto... p>
98 struct check_ice {
99     enum e {
100         x = p...[0]
101     };
102 };
103 
104 static_assert(check_ice<42>::x == 42);
105 
106 struct S{};
107 template <auto... p>
108 constexpr auto constant_initializer = p...[0];
109 constexpr auto InitOk = constant_initializer<S{}>;
110 
111 consteval int evaluate(auto... p) {
112     return p...[0];
113 }
114 constexpr int x = evaluate(42, S{});
115 static_assert(x == 42);
116 
117 
118 namespace splice {
119 template <auto ... Is>
120 struct IL{};
121 
122 template <typename ... Ts>
123 struct TL{};
124 
125 template <typename Tl, typename Il>
126 struct SpliceImpl;
127 
128 template <typename ... Ts, auto ...Is>
129 struct SpliceImpl<TL<Ts...>, IL<Is...>>{
130     using type = TL<Ts...[Is]...>;
131 };
132 
133 template <typename Tl, typename Il>
134 using Splice = typename SpliceImpl<Tl, Il>::type;
135 using type = Splice<TL<char, short, long, double>, IL<1, 2>>;
136 static_assert(is_same<type, TL<short, long>>);
137 }
138 
139 
140 namespace GH81697 {
141 
142 template<class... Ts> struct tuple {
143     int __x0;
144 };
145 
146 template<auto I, class... Ts>
147 Ts...[I]& get(tuple<Ts...>& t) {
148   return t.__x0;
149 }
150 
151 void f() {
152   tuple<int> x;
153   get<0>(x);
154 }
155 
156 }
157 
158 namespace GH88929 {
159     bool b = a...[0];  // expected-error {{use of undeclared identifier 'a'}}
160     using E = P...[0]; // expected-error {{unknown type name 'P'}} \
161                        // expected-error {{expected ';' after alias declaration}}
162 }
163 
164 namespace GH88925 {
165 template <typename...> struct S {};
166 
167 template <auto...> struct W {};
168 
169 template <int...> struct sequence {};
170 
171 template <typename... args, int... indices> auto f(sequence<indices...>) {
172   return S<args...[indices]...>(); // #use
173 }
174 
175 template <auto... args, int... indices> auto g(sequence<indices...>) {
176   return W<args...[indices]...>(); // #nttp-use
177 }
178 
179 void h() {
180   static_assert(__is_same(decltype(f<int>(sequence<0, 0>())), S<int, int>));
181   static_assert(__is_same(decltype(f<int, long>(sequence<0, 0>())), S<int, int>));
182   static_assert(__is_same(decltype(f<int, long>(sequence<0, 1>())), S<int, long>));
183   f<int, long>(sequence<3>());
184   // expected-error@#use {{invalid index 3 for pack 'args' of size 2}}}
185   // expected-note-re@-2 {{function template specialization '{{.*}}' requested here}}
186 
187   struct foo {};
188   struct bar {};
189   struct baz {};
190 
191   static_assert(__is_same(decltype(g<foo{}, bar{}, baz{}>(sequence<0, 2, 1>())), W<foo{}, baz{}, bar{}>));
192   g<foo{}>(sequence<4>());
193   // expected-error@#nttp-use {{invalid index 4 for pack args of size 1}}
194   // expected-note-re@-2 {{function template specialization '{{.*}}' requested here}}
195 }
196 }
197 
198 namespace GH91885 {
199 
200 void test(auto...args){
201     [&]<int idx>(){
202         using R = decltype( args...[idx] ) ;
203     }.template operator()<0>();
204 }
205 
206 template<int... args>
207 void test2(){
208   [&]<int idx>(){
209     using R = decltype( args...[idx] ) ; // #test2-R
210   }.template operator()<0>(); // #test2-call
211 }
212 
213 void f( ) {
214   test(1);
215   test2<1>();
216   test2();
217   // expected-error@#test2-R {{invalid index 0 for pack args of size 0}}
218   // expected-note@#test2-call {{requested here}}
219   // expected-note@-3 {{requested here}}
220 }
221 
222 
223 }
224 
225 namespace std {
226 struct type_info {
227   const char *name;
228 };
229 } // namespace std
230 
231 namespace GH93650 {
232 auto func(auto... inputArgs) { return typeid(inputArgs...[0]); }
233 } // namespace GH93650
234 
235 
236 namespace GH105900 {
237 
238 template <typename... opts>
239 struct types  {
240     template <unsigned idx>
241     static constexpr __SIZE_TYPE__ get_index() { return idx; }
242 
243     template <unsigned s>
244     static auto x() -> opts...[get_index<s>()] {}
245 };
246 
247 template <auto... opts>
248 struct vars  {
249     template <unsigned idx>
250     static constexpr __SIZE_TYPE__ get_index() { return idx; }
251 
252     template <unsigned s>
253     static auto x() -> decltype(opts...[get_index<s>()]) {return 0;}
254 };
255 
256 void f() {
257     types<void>::x<0>();
258     vars<0>::x<0>();
259 }
260 
261 } // namespace GH105900
262 
263 namespace GH105903 {
264 
265 template <typename... opts> struct temp {
266   template <unsigned s> static auto x() -> opts... [s] {} // expected-note {{invalid index 0 for pack 'opts' of size 0}}
267 };
268 
269 void f() {
270   temp<>::x<0>(); // expected-error {{no matching}}
271 }
272 
273 } // namespace GH105903
274 
275 namespace GH116105 {
276 
277 template <unsigned long Np, class... Ts> using pack_type = Ts...[Np];
278 
279 template <unsigned long Np, auto... Ts> using pack_expr = decltype(Ts...[Np]);
280 
281 template <class...> struct types;
282 
283 template <class, long... Is> struct indices;
284 
285 template <class> struct repack;
286 
287 template <long... Idx> struct repack<indices<long, Idx...>> {
288   template <class... Ts>
289   using pack_type_alias = types<pack_type<Idx, Ts...>...>;
290 
291   template <class... Ts>
292   using pack_expr_alias = types<pack_expr<Idx, Ts{}...>...>;
293 };
294 
295 template <class... Args> struct mdispatch_ {
296   using Idx = __make_integer_seq<indices, long, sizeof...(Args)>;
297 
298   static_assert(__is_same(
299       typename repack<Idx>::template pack_type_alias<Args...>, types<Args...>));
300 
301   static_assert(__is_same(
302       typename repack<Idx>::template pack_expr_alias<Args...>, types<Args...>));
303 };
304 
305 mdispatch_<int, int> d;
306 
307 } // namespace GH116105
308 
309 namespace GH121242 {
310     // Non-dependent type pack access
311     template <int...x>
312     int y = x...[0];
313 
314     struct X {};
315 
316     template <X...x>
317     X z = x...[0];
318 
319     void foo() {
320         (void)y<0>;
321         (void)z<X{}>;
322     }
323 } // namespace GH121242
324 
325 namespace GH123033 {
326   template <class... Types>
327   requires __is_same_as(Types...[0], int)
328   void print(double d);
329 
330   template <class... Types>
331   requires  __is_same_as(Types...[0], int)
332   void print(double d);
333 
334   template <class... Types>
335   Types...[0] convert(double d);
336 
337   template <class... Types>
338   Types...[0] convert(double d) {
339       return static_cast<Types...[0]>(d);
340   }
341 
342   void f() {
343       print<int, int>(12.34);
344       convert<int, int>(12.34);
345   }
346 }
347