xref: /llvm-project/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp (revision 2579b411a13799534c8b8a22246134b88ba7785d)
1 // RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19.20 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-windows-msvc | FileCheck %s
2 
3 struct StructA {};
4 
5 template<class T>
6 auto AutoT() { return T(); }
7 
8 template<class T>
9 const auto AutoConstT() { return T(); }
10 
11 template<class T>
12 volatile auto AutoVolatileT() { return T(); }
13 
14 template<class T>
15 const volatile auto AutoConstVolatileT() { return T(); }
16 
17 // The qualifiers of the return type should always be emitted even for void types.
18 // Void types usually have their qualifers stripped in the mangled name for MSVC ABI.
19 void test_template_auto_void() {
20   AutoT<void>();
21   // CHECK: call {{.*}} @"??$AutoT@X@@YA?A_PXZ"
22 
23   AutoT<const void>();
24   // CHECK: call {{.*}} @"??$AutoT@$$CBX@@YA?A_PXZ"
25 
26   AutoT<volatile void>();
27   // CHECK: call {{.*}} @"??$AutoT@$$CCX@@YA?A_PXZ"
28 
29   AutoT<const volatile void>();
30   // CHECK: call {{.*}} @"??$AutoT@$$CDX@@YA?A_PXZ"
31 
32   AutoConstT<void>();
33   // CHECK: call {{.*}} @"??$AutoConstT@X@@YA?B_PXZ"
34 
35   AutoVolatileT<void>();
36   // CHECK: call {{.*}} @"??$AutoVolatileT@X@@YA?C_PXZ"
37 
38   AutoConstVolatileT<void>();
39   // CHECK: call {{.*}} @"??$AutoConstVolatileT@X@@YA?D_PXZ"
40 }
41 
42 void test_template_auto_int() {
43   AutoT<int>();
44   // CHECK: call {{.*}} @"??$AutoT@H@@YA?A_PXZ"
45 
46   AutoT<const int>();
47   // CHECK: call {{.*}} @"??$AutoT@$$CBH@@YA?A_PXZ"
48 
49   AutoT<volatile int>();
50   // CHECK: call {{.*}} @"??$AutoT@$$CCH@@YA?A_PXZ"
51 
52   AutoT<const volatile int>();
53   // CHECK: call {{.*}} @"??$AutoT@$$CDH@@YA?A_PXZ"
54 
55   AutoConstT<int>();
56   // CHECK: call {{.*}} @"??$AutoConstT@H@@YA?B_PXZ"
57 
58   AutoVolatileT<int>();
59   // CHECK: call {{.*}} @"??$AutoVolatileT@H@@YA?C_PXZ"
60 
61   AutoConstVolatileT<int>();
62   // CHECK: call {{.*}} @"??$AutoConstVolatileT@H@@YA?D_PXZ"
63 }
64 
65 void test_template_auto_struct() {
66   AutoT<StructA>();
67   // CHECK: call {{.*}} @"??$AutoT@UStructA@@@@YA?A_PXZ"
68 
69   AutoT<const StructA>();
70   // CHECK: call {{.*}} @"??$AutoT@$$CBUStructA@@@@YA?A_PXZ"
71 
72   AutoConstT<StructA>();
73   // CHECK: call {{.*}} @"??$AutoConstT@UStructA@@@@YA?B_PXZ"
74 
75   AutoVolatileT<StructA>();
76   // CHECK: call {{.*}} @"??$AutoVolatileT@UStructA@@@@YA?C_PXZ"
77 
78   AutoConstVolatileT<StructA>();
79   // CHECK: call {{.*}} @"??$AutoConstVolatileT@UStructA@@@@YA?D_PXZ"
80 }
81 
82 void test_template_auto_ptr() {
83   AutoT<int*>();
84   // CHECK: call {{.*}} @"??$AutoT@PEAH@@YA?A_PXZ"
85 
86   AutoT<const int*>();
87   // CHECK: call {{.*}} @"??$AutoT@PEBH@@YA?A_PXZ"
88 
89   AutoT<const int* const>();
90   // CHECK: call {{.*}} @"??$AutoT@QEBH@@YA?A_PXZ"
91 
92   AutoConstT<int*>();
93   // CHECK: call {{.*}} @"??$AutoConstT@PEAH@@YA?B_PXZ"
94 
95   AutoVolatileT<int*>();
96   // CHECK: call {{.*}} @"??$AutoVolatileT@PEAH@@YA?C_PXZ"
97 
98   AutoConstVolatileT<int*>();
99   // CHECK: call {{.*}} @"??$AutoConstVolatileT@PEAH@@YA?D_PXZ"
100 }
101 
102 template<class T>
103 auto* PtrAutoT() { return T(); }
104 
105 template<class T>
106 const auto* PtrAutoConstT() { return T(); }
107 
108 template<class T>
109 volatile auto* PtrAutoVolatileT() { return T(); }
110 
111 template<class T>
112 const volatile auto* PtrAutoConstVolatileT() { return T(); }
113 
114 void test_template_ptr_auto() {
115   PtrAutoT<int*>();
116   // CHECK: call {{.*}} @"??$PtrAutoT@PEAH@@YAPEA_PXZ"
117 
118   PtrAutoT<const int*>();
119   // CHECK: call {{.*}} @"??$PtrAutoT@PEBH@@YAPEA_PXZ"
120 
121   PtrAutoT<const int* const>();
122   // CHECK: call {{.*}} @"??$PtrAutoT@QEBH@@YAPEA_PXZ"
123 
124   PtrAutoConstT<int*>();
125   // CHECK: call {{.*}} @"??$PtrAutoConstT@PEAH@@YAPEB_PXZ"
126 
127   PtrAutoVolatileT<int*>();
128   // CHECK: call {{.*}} @"??$PtrAutoVolatileT@PEAH@@YAPEC_PXZ"
129 
130   PtrAutoConstVolatileT<int*>();
131   // CHECK: call {{.*}} @"??$PtrAutoConstVolatileT@PEAH@@YAPED_PXZ"
132 }
133 
134 int func_int();
135 const int func_constint();
136 void func_void();
137 int* func_intptr();
138 
139 template<class T, T v>
140 auto (*FuncPtrAutoT())() { return v; }
141 
142 void test_template_func_ptr_auto() {
143   FuncPtrAutoT<int (*)(), &func_int>();
144   // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6AHXZ$1?func_int@@YAHXZ@@YAP6A?A_PXZXZ"
145 
146   FuncPtrAutoT<const int (*)(), &func_constint>();
147   // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6A?BHXZ$1?func_constint@@YA?BHXZ@@YAP6A?A_PXZXZ"
148 
149   FuncPtrAutoT<void (*)(), &func_void>();
150   // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6AXXZ$1?func_void@@YAXXZ@@YAP6A?A_PXZXZ"
151 
152   FuncPtrAutoT<int * (*)(), &func_intptr>();
153   // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6APEAHXZ$1?func_intptr@@YAPEAHXZ@@YAP6A?A_PXZXZ"
154 }
155 
156 template<class T>
157 auto& RefAutoT(T& x) { return x; }
158 
159 template<class T>
160 const auto& ConstRefAutoT(T& x) { return x; }
161 
162 template<class T>
163 auto&& RRefAutoT(T& x) { return static_cast<int&&>(x); }
164 
165 void test_template_ref_auto() {
166   int x;
167 
168   RefAutoT(x);
169   // CHECK: call {{.*}} @"??$RefAutoT@H@@YAAEA_PAEAH@Z"
170 
171   ConstRefAutoT(x);
172   // CHECK: call {{.*}} @"??$ConstRefAutoT@H@@YAAEB_PAEAH@Z"
173 
174   RRefAutoT(x);
175   // CHECK: call {{.*}} @"??$RRefAutoT@H@@YA$$QEA_PAEAH@Z"
176 }
177 
178 template<class T>
179 decltype(auto) DecltypeAutoT() { return T(); }
180 
181 template<class T>
182 decltype(auto) DecltypeAutoT2(T& x) { return static_cast<T&&>(x); }
183 
184 void test_template_decltypeauto() {
185   DecltypeAutoT<void>();
186   // CHECK: call {{.*}} @"??$DecltypeAutoT@X@@YA?A_TXZ"
187 
188   DecltypeAutoT<const void>();
189   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBX@@YA?A_TXZ"
190 
191   DecltypeAutoT<volatile void>();
192   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCX@@YA?A_TXZ"
193 
194   DecltypeAutoT<const volatile void>();
195   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDX@@YA?A_TXZ"
196 
197   DecltypeAutoT<int>();
198   // CHECK: call {{.*}} @"??$DecltypeAutoT@H@@YA?A_TXZ"
199 
200   DecltypeAutoT<const int>();
201   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBH@@YA?A_TXZ"
202 
203   DecltypeAutoT<volatile int>();
204   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCH@@YA?A_TXZ"
205 
206   DecltypeAutoT<const volatile int>();
207   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDH@@YA?A_TXZ"
208 
209   int x;
210 
211   DecltypeAutoT2(x);
212   // CHECK: call {{.*}} @"??$DecltypeAutoT2@H@@YA?A_TAEAH@Z"
213 }
214 
215 // Still want to use clang's custom mangling for lambdas to keep backwards compatibility until
216 // MSVC lambda name mangling has been deciphered.
217 void test_lambda() {
218   int i = 0;
219 
220   auto lambdaIntRetAuto = []() { return 0; };
221   lambdaIntRetAuto();
222   // CHECK: call {{.*}} @"??R<lambda_1>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@XZ"
223 
224   auto lambdaIntRet = []() -> int { return 0; };
225   lambdaIntRet();
226   // CHECK: call {{.*}} @"??R<lambda_2>@?0??test_lambda@@YAXXZ@QEBA@XZ"
227 
228   auto lambdaGenericIntIntRetAuto = [](auto a) { return a; };
229   lambdaGenericIntIntRetAuto(0);
230   // CHECK: call {{.*}} @"??$?RH@<lambda_0>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@H@Z"
231 
232   auto lambdaRetTrailingAuto = []() -> auto { return 0; };
233   lambdaRetTrailingAuto();
234   // CHECK: call {{.*}} @"??R<lambda_3>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@XZ"
235 
236   auto lambdaRetTrailingDecltypeAuto = []() -> decltype(auto) { return 0; };
237   lambdaRetTrailingDecltypeAuto();
238   // CHECK: call {{.*}} @"??R<lambda_4>@?0??test_lambda@@YAXXZ@QEBA?A?<decltype-auto>@@XZ"
239 
240   auto lambdaRetTrailingRefCollapse = [](int x) -> auto&& { return x; };
241   lambdaRetTrailingRefCollapse(i);
242   // CHECK: call {{.*}} @"??R<lambda_5>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@H@Z"
243 }
244 
245 auto TestTrailingInt() -> int {
246   return 0;
247 }
248 
249 auto TestTrailingConstVolatileVoid() -> const volatile void {
250 }
251 
252 auto TestTrailingStructA() -> StructA {
253   return StructA{};
254 }
255 
256 void test_trailing_return() {
257   TestTrailingInt();
258   // CHECK: call {{.*}} @"?TestTrailingInt@@YAHXZ"
259 
260   TestTrailingConstVolatileVoid();
261   // CHECK: call {{.*}} @"?TestTrailingConstVolatileVoid@@YAXXZ"
262 
263   TestTrailingStructA();
264   // CHECK: call {{.*}} @"?TestTrailingStructA@@YA?AUStructA@@XZ"
265 }
266 
267 auto TestNonTemplateAutoInt() {
268   return 0;
269 }
270 
271 auto TestNonTemplateAutoVoid() {
272   return;
273 }
274 
275 auto TestNonTemplateAutoStructA() {
276   return StructA{};
277 }
278 
279 const auto TestNonTemplateConstAutoInt() {
280   return 0;
281 }
282 
283 const auto TestNonTemplateConstAutoVoid() {
284   return;
285 }
286 
287 const auto TestNonTemplateConstAutoStructA() {
288   return StructA{};
289 }
290 
291 void test_nontemplate_auto() {
292   TestNonTemplateAutoInt();
293   // CHECK: call {{.*}} @"?TestNonTemplateAutoInt@@YA@XZ"
294 
295   TestNonTemplateAutoVoid();
296   // CHECK: call {{.*}} @"?TestNonTemplateAutoVoid@@YA@XZ"
297 
298   TestNonTemplateAutoStructA();
299   // CHECK: call {{.*}} @"?TestNonTemplateAutoStructA@@YA@XZ"
300 
301   TestNonTemplateConstAutoInt();
302   // CHECK: call {{.*}} @"?TestNonTemplateConstAutoInt@@YA@XZ"
303 
304   TestNonTemplateConstAutoVoid();
305   // CHECK: call {{.*}} @"?TestNonTemplateConstAutoVoid@@YA@XZ"
306 
307   TestNonTemplateConstAutoStructA();
308   // CHECK: call {{.*}} @"?TestNonTemplateConstAutoStructA@@YA@XZ"
309 }
310 
311 decltype(auto) TestNonTemplateDecltypeAutoInt() {
312     return 0;
313 }
314 
315 decltype(auto) TestNonTemplateDecltypeAutoVoid() {
316     return;
317 }
318 
319 decltype(auto) TestNonTemplateDecltypeAutoStructA() {
320     return StructA{};
321 }
322 
323 void test_nontemplate_decltypeauto() {
324   TestNonTemplateDecltypeAutoInt();
325   // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoInt@@YA@XZ"
326 
327   TestNonTemplateDecltypeAutoVoid();
328   // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoVoid@@YA@XZ"
329 
330   TestNonTemplateDecltypeAutoStructA();
331   // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoStructA@@YA@XZ"
332 }
333 
334 struct StructB {
335   int x;
336 };
337 
338 template<class T>
339 auto StructB::* AutoMemberDataPtrT(T x) { return x; }
340 
341 template<class T>
342 const auto StructB::* AutoConstMemberDataPtrT(T x) { return x; }
343 
344 void test_template_auto_member_data_ptr() {
345   AutoMemberDataPtrT(&StructB::x);
346   // CHECK: call {{.*}} @"??$AutoMemberDataPtrT@PEQStructB@@H@@YAPEQStructB@@_PPEQ0@H@Z"
347 
348   AutoConstMemberDataPtrT(&StructB::x);
349   // CHECK: call {{.*}} @"??$AutoConstMemberDataPtrT@PEQStructB@@H@@YAPERStructB@@_PPEQ0@H@Z"
350 }
351 
352 struct StructC {
353   void test() {}
354 };
355 
356 struct StructD {
357   const int test() { return 0; }
358 };
359 
360 template<class T>
361 auto (StructC::*AutoMemberFuncPtrT(T x))() { return x; }
362 
363 template<class T>
364 const auto (StructD::*AutoConstMemberFuncPtrT(T x))() { return x; }
365 
366 void test_template_auto_member_func_ptr() {
367   AutoMemberFuncPtrT(&StructC::test);
368   // CHECK: call {{.*}} @"??$AutoMemberFuncPtrT@P8StructC@@EAAXXZ@@YAP8StructC@@EAA?A_PXZP80@EAAXXZ@Z"
369 
370   AutoConstMemberFuncPtrT(&StructD::test);
371   // CHECK: call {{.*}} @"??$AutoConstMemberFuncPtrT@P8StructD@@EAA?BHXZ@@YAP8StructD@@EAA?B_PXZP80@EAA?BHXZ@Z"
372 }
373 
374 template<class T>
375 auto * __attribute__((address_space(1))) * AutoPtrAddressSpaceT() {
376   T * __attribute__((address_space(1))) * p = nullptr;
377   return p;
378 }
379 
380 void test_template_auto_address_space_ptr() {
381   AutoPtrAddressSpaceT<int>();
382   // CHECK: call {{.*}} @"??$AutoPtrAddressSpaceT@H@@YA?A?<auto>@@XZ"
383 }
384 
385 template<class T>
386 auto&& AutoReferenceCollapseT(T& x) { return static_cast<T&>(x); }
387 
388 auto&& AutoReferenceCollapse(int& x) { return static_cast<int&>(x); }
389 
390 void test2() {
391   int x = 1;
392   auto&& rref0 = AutoReferenceCollapseT(x);
393   // CHECK: call {{.*}} @"??$AutoReferenceCollapseT@H@@YA$$QEA_PAEAH@Z"
394 
395   auto&& rref1 = AutoReferenceCollapse(x);
396   // CHECK: call {{.*}} @"?AutoReferenceCollapse@@YA@AEAH@Z"
397 }
398