xref: /llvm-project/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp (revision 2579b411a13799534c8b8a22246134b88ba7785d)
143b88851SMax Winkler // 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
243b88851SMax Winkler 
343b88851SMax Winkler struct StructA {};
443b88851SMax Winkler 
543b88851SMax Winkler template<class T>
643b88851SMax Winkler auto AutoT() { return T(); }
743b88851SMax Winkler 
843b88851SMax Winkler template<class T>
943b88851SMax Winkler const auto AutoConstT() { return T(); }
1043b88851SMax Winkler 
1143b88851SMax Winkler template<class T>
1243b88851SMax Winkler volatile auto AutoVolatileT() { return T(); }
1343b88851SMax Winkler 
1443b88851SMax Winkler template<class T>
1543b88851SMax Winkler const volatile auto AutoConstVolatileT() { return T(); }
1643b88851SMax Winkler 
1743b88851SMax Winkler // The qualifiers of the return type should always be emitted even for void types.
1843b88851SMax Winkler // Void types usually have their qualifers stripped in the mangled name for MSVC ABI.
1943b88851SMax Winkler void test_template_auto_void() {
2043b88851SMax Winkler   AutoT<void>();
2143b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@X@@YA?A_PXZ"
2243b88851SMax Winkler 
2343b88851SMax Winkler   AutoT<const void>();
2443b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@$$CBX@@YA?A_PXZ"
2543b88851SMax Winkler 
2643b88851SMax Winkler   AutoT<volatile void>();
2743b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@$$CCX@@YA?A_PXZ"
2843b88851SMax Winkler 
2943b88851SMax Winkler   AutoT<const volatile void>();
3043b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@$$CDX@@YA?A_PXZ"
3143b88851SMax Winkler 
3243b88851SMax Winkler   AutoConstT<void>();
3343b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoConstT@X@@YA?B_PXZ"
3443b88851SMax Winkler 
3543b88851SMax Winkler   AutoVolatileT<void>();
3643b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoVolatileT@X@@YA?C_PXZ"
3743b88851SMax Winkler 
3843b88851SMax Winkler   AutoConstVolatileT<void>();
3943b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoConstVolatileT@X@@YA?D_PXZ"
4043b88851SMax Winkler }
4143b88851SMax Winkler 
4243b88851SMax Winkler void test_template_auto_int() {
4343b88851SMax Winkler   AutoT<int>();
4443b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@H@@YA?A_PXZ"
4543b88851SMax Winkler 
4643b88851SMax Winkler   AutoT<const int>();
4743b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@$$CBH@@YA?A_PXZ"
4843b88851SMax Winkler 
4943b88851SMax Winkler   AutoT<volatile int>();
5043b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@$$CCH@@YA?A_PXZ"
5143b88851SMax Winkler 
5243b88851SMax Winkler   AutoT<const volatile int>();
5343b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@$$CDH@@YA?A_PXZ"
5443b88851SMax Winkler 
5543b88851SMax Winkler   AutoConstT<int>();
5643b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoConstT@H@@YA?B_PXZ"
5743b88851SMax Winkler 
5843b88851SMax Winkler   AutoVolatileT<int>();
5943b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoVolatileT@H@@YA?C_PXZ"
6043b88851SMax Winkler 
6143b88851SMax Winkler   AutoConstVolatileT<int>();
6243b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoConstVolatileT@H@@YA?D_PXZ"
6343b88851SMax Winkler }
6443b88851SMax Winkler 
6543b88851SMax Winkler void test_template_auto_struct() {
6643b88851SMax Winkler   AutoT<StructA>();
6743b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@UStructA@@@@YA?A_PXZ"
6843b88851SMax Winkler 
6943b88851SMax Winkler   AutoT<const StructA>();
7043b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@$$CBUStructA@@@@YA?A_PXZ"
7143b88851SMax Winkler 
7243b88851SMax Winkler   AutoConstT<StructA>();
7343b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoConstT@UStructA@@@@YA?B_PXZ"
7443b88851SMax Winkler 
7543b88851SMax Winkler   AutoVolatileT<StructA>();
7643b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoVolatileT@UStructA@@@@YA?C_PXZ"
7743b88851SMax Winkler 
7843b88851SMax Winkler   AutoConstVolatileT<StructA>();
7943b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoConstVolatileT@UStructA@@@@YA?D_PXZ"
8043b88851SMax Winkler }
8143b88851SMax Winkler 
8243b88851SMax Winkler void test_template_auto_ptr() {
8343b88851SMax Winkler   AutoT<int*>();
8443b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@PEAH@@YA?A_PXZ"
8543b88851SMax Winkler 
8643b88851SMax Winkler   AutoT<const int*>();
8743b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@PEBH@@YA?A_PXZ"
8843b88851SMax Winkler 
8943b88851SMax Winkler   AutoT<const int* const>();
9043b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoT@QEBH@@YA?A_PXZ"
9143b88851SMax Winkler 
9243b88851SMax Winkler   AutoConstT<int*>();
9343b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoConstT@PEAH@@YA?B_PXZ"
9443b88851SMax Winkler 
9543b88851SMax Winkler   AutoVolatileT<int*>();
9643b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoVolatileT@PEAH@@YA?C_PXZ"
9743b88851SMax Winkler 
9843b88851SMax Winkler   AutoConstVolatileT<int*>();
9943b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoConstVolatileT@PEAH@@YA?D_PXZ"
10043b88851SMax Winkler }
10143b88851SMax Winkler 
10243b88851SMax Winkler template<class T>
10343b88851SMax Winkler auto* PtrAutoT() { return T(); }
10443b88851SMax Winkler 
10543b88851SMax Winkler template<class T>
10643b88851SMax Winkler const auto* PtrAutoConstT() { return T(); }
10743b88851SMax Winkler 
10843b88851SMax Winkler template<class T>
10943b88851SMax Winkler volatile auto* PtrAutoVolatileT() { return T(); }
11043b88851SMax Winkler 
11143b88851SMax Winkler template<class T>
11243b88851SMax Winkler const volatile auto* PtrAutoConstVolatileT() { return T(); }
11343b88851SMax Winkler 
11443b88851SMax Winkler void test_template_ptr_auto() {
11543b88851SMax Winkler   PtrAutoT<int*>();
11643b88851SMax Winkler   // CHECK: call {{.*}} @"??$PtrAutoT@PEAH@@YAPEA_PXZ"
11743b88851SMax Winkler 
11843b88851SMax Winkler   PtrAutoT<const int*>();
11943b88851SMax Winkler   // CHECK: call {{.*}} @"??$PtrAutoT@PEBH@@YAPEA_PXZ"
12043b88851SMax Winkler 
12143b88851SMax Winkler   PtrAutoT<const int* const>();
12243b88851SMax Winkler   // CHECK: call {{.*}} @"??$PtrAutoT@QEBH@@YAPEA_PXZ"
12343b88851SMax Winkler 
12443b88851SMax Winkler   PtrAutoConstT<int*>();
12543b88851SMax Winkler   // CHECK: call {{.*}} @"??$PtrAutoConstT@PEAH@@YAPEB_PXZ"
12643b88851SMax Winkler 
12743b88851SMax Winkler   PtrAutoVolatileT<int*>();
12843b88851SMax Winkler   // CHECK: call {{.*}} @"??$PtrAutoVolatileT@PEAH@@YAPEC_PXZ"
12943b88851SMax Winkler 
13043b88851SMax Winkler   PtrAutoConstVolatileT<int*>();
13143b88851SMax Winkler   // CHECK: call {{.*}} @"??$PtrAutoConstVolatileT@PEAH@@YAPED_PXZ"
13243b88851SMax Winkler }
13343b88851SMax Winkler 
13443b88851SMax Winkler int func_int();
13543b88851SMax Winkler const int func_constint();
13643b88851SMax Winkler void func_void();
13743b88851SMax Winkler int* func_intptr();
13843b88851SMax Winkler 
13943b88851SMax Winkler template<class T, T v>
14043b88851SMax Winkler auto (*FuncPtrAutoT())() { return v; }
14143b88851SMax Winkler 
14243b88851SMax Winkler void test_template_func_ptr_auto() {
14343b88851SMax Winkler   FuncPtrAutoT<int (*)(), &func_int>();
14443b88851SMax Winkler   // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6AHXZ$1?func_int@@YAHXZ@@YAP6A?A_PXZXZ"
14543b88851SMax Winkler 
14643b88851SMax Winkler   FuncPtrAutoT<const int (*)(), &func_constint>();
14743b88851SMax Winkler   // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6A?BHXZ$1?func_constint@@YA?BHXZ@@YAP6A?A_PXZXZ"
14843b88851SMax Winkler 
14943b88851SMax Winkler   FuncPtrAutoT<void (*)(), &func_void>();
15043b88851SMax Winkler   // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6AXXZ$1?func_void@@YAXXZ@@YAP6A?A_PXZXZ"
15143b88851SMax Winkler 
15243b88851SMax Winkler   FuncPtrAutoT<int * (*)(), &func_intptr>();
15343b88851SMax Winkler   // CHECK: call {{.*}} @"??$FuncPtrAutoT@P6APEAHXZ$1?func_intptr@@YAPEAHXZ@@YAP6A?A_PXZXZ"
15443b88851SMax Winkler }
15543b88851SMax Winkler 
15643b88851SMax Winkler template<class T>
15743b88851SMax Winkler auto& RefAutoT(T& x) { return x; }
15843b88851SMax Winkler 
15943b88851SMax Winkler template<class T>
16043b88851SMax Winkler const auto& ConstRefAutoT(T& x) { return x; }
16143b88851SMax Winkler 
16243b88851SMax Winkler template<class T>
16343b88851SMax Winkler auto&& RRefAutoT(T& x) { return static_cast<int&&>(x); }
16443b88851SMax Winkler 
16543b88851SMax Winkler void test_template_ref_auto() {
16643b88851SMax Winkler   int x;
16743b88851SMax Winkler 
16843b88851SMax Winkler   RefAutoT(x);
16943b88851SMax Winkler   // CHECK: call {{.*}} @"??$RefAutoT@H@@YAAEA_PAEAH@Z"
17043b88851SMax Winkler 
17143b88851SMax Winkler   ConstRefAutoT(x);
17243b88851SMax Winkler   // CHECK: call {{.*}} @"??$ConstRefAutoT@H@@YAAEB_PAEAH@Z"
17343b88851SMax Winkler 
17443b88851SMax Winkler   RRefAutoT(x);
17543b88851SMax Winkler   // CHECK: call {{.*}} @"??$RRefAutoT@H@@YA$$QEA_PAEAH@Z"
17643b88851SMax Winkler }
17743b88851SMax Winkler 
17843b88851SMax Winkler template<class T>
17943b88851SMax Winkler decltype(auto) DecltypeAutoT() { return T(); }
18043b88851SMax Winkler 
18143b88851SMax Winkler template<class T>
18243b88851SMax Winkler decltype(auto) DecltypeAutoT2(T& x) { return static_cast<T&&>(x); }
18343b88851SMax Winkler 
18443b88851SMax Winkler void test_template_decltypeauto() {
18543b88851SMax Winkler   DecltypeAutoT<void>();
18643b88851SMax Winkler   // CHECK: call {{.*}} @"??$DecltypeAutoT@X@@YA?A_TXZ"
18743b88851SMax Winkler 
18843b88851SMax Winkler   DecltypeAutoT<const void>();
18943b88851SMax Winkler   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBX@@YA?A_TXZ"
19043b88851SMax Winkler 
19143b88851SMax Winkler   DecltypeAutoT<volatile void>();
19243b88851SMax Winkler   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCX@@YA?A_TXZ"
19343b88851SMax Winkler 
19443b88851SMax Winkler   DecltypeAutoT<const volatile void>();
19543b88851SMax Winkler   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDX@@YA?A_TXZ"
19643b88851SMax Winkler 
19743b88851SMax Winkler   DecltypeAutoT<int>();
19843b88851SMax Winkler   // CHECK: call {{.*}} @"??$DecltypeAutoT@H@@YA?A_TXZ"
19943b88851SMax Winkler 
20043b88851SMax Winkler   DecltypeAutoT<const int>();
20143b88851SMax Winkler   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBH@@YA?A_TXZ"
20243b88851SMax Winkler 
20343b88851SMax Winkler   DecltypeAutoT<volatile int>();
20443b88851SMax Winkler   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCH@@YA?A_TXZ"
20543b88851SMax Winkler 
20643b88851SMax Winkler   DecltypeAutoT<const volatile int>();
20743b88851SMax Winkler   // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDH@@YA?A_TXZ"
20843b88851SMax Winkler 
20943b88851SMax Winkler   int x;
21043b88851SMax Winkler 
21143b88851SMax Winkler   DecltypeAutoT2(x);
21243b88851SMax Winkler   // CHECK: call {{.*}} @"??$DecltypeAutoT2@H@@YA?A_TAEAH@Z"
21343b88851SMax Winkler }
21443b88851SMax Winkler 
21543b88851SMax Winkler // Still want to use clang's custom mangling for lambdas to keep backwards compatibility until
21643b88851SMax Winkler // MSVC lambda name mangling has been deciphered.
21743b88851SMax Winkler void test_lambda() {
218*2579b411SMax Winkler   int i = 0;
219*2579b411SMax Winkler 
22043b88851SMax Winkler   auto lambdaIntRetAuto = []() { return 0; };
22143b88851SMax Winkler   lambdaIntRetAuto();
22243b88851SMax Winkler   // CHECK: call {{.*}} @"??R<lambda_1>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@XZ"
22343b88851SMax Winkler 
22443b88851SMax Winkler   auto lambdaIntRet = []() -> int { return 0; };
22543b88851SMax Winkler   lambdaIntRet();
22643b88851SMax Winkler   // CHECK: call {{.*}} @"??R<lambda_2>@?0??test_lambda@@YAXXZ@QEBA@XZ"
22743b88851SMax Winkler 
22843b88851SMax Winkler   auto lambdaGenericIntIntRetAuto = [](auto a) { return a; };
22943b88851SMax Winkler   lambdaGenericIntIntRetAuto(0);
23043b88851SMax Winkler   // CHECK: call {{.*}} @"??$?RH@<lambda_0>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@H@Z"
231*2579b411SMax Winkler 
232*2579b411SMax Winkler   auto lambdaRetTrailingAuto = []() -> auto { return 0; };
233*2579b411SMax Winkler   lambdaRetTrailingAuto();
234*2579b411SMax Winkler   // CHECK: call {{.*}} @"??R<lambda_3>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@XZ"
235*2579b411SMax Winkler 
236*2579b411SMax Winkler   auto lambdaRetTrailingDecltypeAuto = []() -> decltype(auto) { return 0; };
237*2579b411SMax Winkler   lambdaRetTrailingDecltypeAuto();
238*2579b411SMax Winkler   // CHECK: call {{.*}} @"??R<lambda_4>@?0??test_lambda@@YAXXZ@QEBA?A?<decltype-auto>@@XZ"
239*2579b411SMax Winkler 
240*2579b411SMax Winkler   auto lambdaRetTrailingRefCollapse = [](int x) -> auto&& { return x; };
241*2579b411SMax Winkler   lambdaRetTrailingRefCollapse(i);
242*2579b411SMax Winkler   // CHECK: call {{.*}} @"??R<lambda_5>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@H@Z"
24343b88851SMax Winkler }
24443b88851SMax Winkler 
24543b88851SMax Winkler auto TestTrailingInt() -> int {
24643b88851SMax Winkler   return 0;
24743b88851SMax Winkler }
24843b88851SMax Winkler 
24943b88851SMax Winkler auto TestTrailingConstVolatileVoid() -> const volatile void {
25043b88851SMax Winkler }
25143b88851SMax Winkler 
25243b88851SMax Winkler auto TestTrailingStructA() -> StructA {
25343b88851SMax Winkler   return StructA{};
25443b88851SMax Winkler }
25543b88851SMax Winkler 
25643b88851SMax Winkler void test_trailing_return() {
25743b88851SMax Winkler   TestTrailingInt();
25843b88851SMax Winkler   // CHECK: call {{.*}} @"?TestTrailingInt@@YAHXZ"
25943b88851SMax Winkler 
26043b88851SMax Winkler   TestTrailingConstVolatileVoid();
26143b88851SMax Winkler   // CHECK: call {{.*}} @"?TestTrailingConstVolatileVoid@@YAXXZ"
26243b88851SMax Winkler 
26343b88851SMax Winkler   TestTrailingStructA();
26443b88851SMax Winkler   // CHECK: call {{.*}} @"?TestTrailingStructA@@YA?AUStructA@@XZ"
26543b88851SMax Winkler }
26643b88851SMax Winkler 
26743b88851SMax Winkler auto TestNonTemplateAutoInt() {
26843b88851SMax Winkler   return 0;
26943b88851SMax Winkler }
27043b88851SMax Winkler 
27143b88851SMax Winkler auto TestNonTemplateAutoVoid() {
27243b88851SMax Winkler   return;
27343b88851SMax Winkler }
27443b88851SMax Winkler 
27543b88851SMax Winkler auto TestNonTemplateAutoStructA() {
27643b88851SMax Winkler   return StructA{};
27743b88851SMax Winkler }
27843b88851SMax Winkler 
27943b88851SMax Winkler const auto TestNonTemplateConstAutoInt() {
28043b88851SMax Winkler   return 0;
28143b88851SMax Winkler }
28243b88851SMax Winkler 
28343b88851SMax Winkler const auto TestNonTemplateConstAutoVoid() {
28443b88851SMax Winkler   return;
28543b88851SMax Winkler }
28643b88851SMax Winkler 
28743b88851SMax Winkler const auto TestNonTemplateConstAutoStructA() {
28843b88851SMax Winkler   return StructA{};
28943b88851SMax Winkler }
29043b88851SMax Winkler 
29143b88851SMax Winkler void test_nontemplate_auto() {
29243b88851SMax Winkler   TestNonTemplateAutoInt();
29343b88851SMax Winkler   // CHECK: call {{.*}} @"?TestNonTemplateAutoInt@@YA@XZ"
29443b88851SMax Winkler 
29543b88851SMax Winkler   TestNonTemplateAutoVoid();
29643b88851SMax Winkler   // CHECK: call {{.*}} @"?TestNonTemplateAutoVoid@@YA@XZ"
29743b88851SMax Winkler 
29843b88851SMax Winkler   TestNonTemplateAutoStructA();
29943b88851SMax Winkler   // CHECK: call {{.*}} @"?TestNonTemplateAutoStructA@@YA@XZ"
30043b88851SMax Winkler 
30143b88851SMax Winkler   TestNonTemplateConstAutoInt();
30243b88851SMax Winkler   // CHECK: call {{.*}} @"?TestNonTemplateConstAutoInt@@YA@XZ"
30343b88851SMax Winkler 
30443b88851SMax Winkler   TestNonTemplateConstAutoVoid();
30543b88851SMax Winkler   // CHECK: call {{.*}} @"?TestNonTemplateConstAutoVoid@@YA@XZ"
30643b88851SMax Winkler 
30743b88851SMax Winkler   TestNonTemplateConstAutoStructA();
30843b88851SMax Winkler   // CHECK: call {{.*}} @"?TestNonTemplateConstAutoStructA@@YA@XZ"
30943b88851SMax Winkler }
31043b88851SMax Winkler 
31143b88851SMax Winkler decltype(auto) TestNonTemplateDecltypeAutoInt() {
31243b88851SMax Winkler     return 0;
31343b88851SMax Winkler }
31443b88851SMax Winkler 
31543b88851SMax Winkler decltype(auto) TestNonTemplateDecltypeAutoVoid() {
31643b88851SMax Winkler     return;
31743b88851SMax Winkler }
31843b88851SMax Winkler 
31943b88851SMax Winkler decltype(auto) TestNonTemplateDecltypeAutoStructA() {
32043b88851SMax Winkler     return StructA{};
32143b88851SMax Winkler }
32243b88851SMax Winkler 
32343b88851SMax Winkler void test_nontemplate_decltypeauto() {
32443b88851SMax Winkler   TestNonTemplateDecltypeAutoInt();
32543b88851SMax Winkler   // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoInt@@YA@XZ"
32643b88851SMax Winkler 
32743b88851SMax Winkler   TestNonTemplateDecltypeAutoVoid();
32843b88851SMax Winkler   // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoVoid@@YA@XZ"
32943b88851SMax Winkler 
33043b88851SMax Winkler   TestNonTemplateDecltypeAutoStructA();
33143b88851SMax Winkler   // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoStructA@@YA@XZ"
33243b88851SMax Winkler }
33343b88851SMax Winkler 
33443b88851SMax Winkler struct StructB {
33543b88851SMax Winkler   int x;
33643b88851SMax Winkler };
33743b88851SMax Winkler 
33843b88851SMax Winkler template<class T>
33943b88851SMax Winkler auto StructB::* AutoMemberDataPtrT(T x) { return x; }
34043b88851SMax Winkler 
34143b88851SMax Winkler template<class T>
34243b88851SMax Winkler const auto StructB::* AutoConstMemberDataPtrT(T x) { return x; }
34343b88851SMax Winkler 
34443b88851SMax Winkler void test_template_auto_member_data_ptr() {
34543b88851SMax Winkler   AutoMemberDataPtrT(&StructB::x);
34643b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoMemberDataPtrT@PEQStructB@@H@@YAPEQStructB@@_PPEQ0@H@Z"
34743b88851SMax Winkler 
34843b88851SMax Winkler   AutoConstMemberDataPtrT(&StructB::x);
34943b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoConstMemberDataPtrT@PEQStructB@@H@@YAPERStructB@@_PPEQ0@H@Z"
35043b88851SMax Winkler }
35143b88851SMax Winkler 
35243b88851SMax Winkler struct StructC {
35343b88851SMax Winkler   void test() {}
35443b88851SMax Winkler };
35543b88851SMax Winkler 
35643b88851SMax Winkler struct StructD {
35743b88851SMax Winkler   const int test() { return 0; }
35843b88851SMax Winkler };
35943b88851SMax Winkler 
36043b88851SMax Winkler template<class T>
36143b88851SMax Winkler auto (StructC::*AutoMemberFuncPtrT(T x))() { return x; }
36243b88851SMax Winkler 
36343b88851SMax Winkler template<class T>
36443b88851SMax Winkler const auto (StructD::*AutoConstMemberFuncPtrT(T x))() { return x; }
36543b88851SMax Winkler 
36643b88851SMax Winkler void test_template_auto_member_func_ptr() {
36743b88851SMax Winkler   AutoMemberFuncPtrT(&StructC::test);
36843b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoMemberFuncPtrT@P8StructC@@EAAXXZ@@YAP8StructC@@EAA?A_PXZP80@EAAXXZ@Z"
36943b88851SMax Winkler 
37043b88851SMax Winkler   AutoConstMemberFuncPtrT(&StructD::test);
37143b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoConstMemberFuncPtrT@P8StructD@@EAA?BHXZ@@YAP8StructD@@EAA?B_PXZP80@EAA?BHXZ@Z"
37243b88851SMax Winkler }
37343b88851SMax Winkler 
37443b88851SMax Winkler template<class T>
37543b88851SMax Winkler auto * __attribute__((address_space(1))) * AutoPtrAddressSpaceT() {
37643b88851SMax Winkler   T * __attribute__((address_space(1))) * p = nullptr;
37743b88851SMax Winkler   return p;
37843b88851SMax Winkler }
37943b88851SMax Winkler 
38043b88851SMax Winkler void test_template_auto_address_space_ptr() {
38143b88851SMax Winkler   AutoPtrAddressSpaceT<int>();
38243b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoPtrAddressSpaceT@H@@YA?A?<auto>@@XZ"
38343b88851SMax Winkler }
38443b88851SMax Winkler 
38543b88851SMax Winkler template<class T>
38643b88851SMax Winkler auto&& AutoReferenceCollapseT(T& x) { return static_cast<T&>(x); }
38743b88851SMax Winkler 
38843b88851SMax Winkler auto&& AutoReferenceCollapse(int& x) { return static_cast<int&>(x); }
38943b88851SMax Winkler 
39043b88851SMax Winkler void test2() {
39143b88851SMax Winkler   int x = 1;
39243b88851SMax Winkler   auto&& rref0 = AutoReferenceCollapseT(x);
39343b88851SMax Winkler   // CHECK: call {{.*}} @"??$AutoReferenceCollapseT@H@@YA$$QEA_PAEAH@Z"
39443b88851SMax Winkler 
39543b88851SMax Winkler   auto&& rref1 = AutoReferenceCollapse(x);
39643b88851SMax Winkler   // CHECK: call {{.*}} @"?AutoReferenceCollapse@@YA@AEAH@Z"
39743b88851SMax Winkler }
398