
Fixes https://github.com/llvm/llvm-project/pull/104722. Missed handling `decltype(auto)` trailing return types for lambdas. This was a mistake and regression on my part with my PR, https://github.com/llvm/llvm-project/pull/104722. Added some missing unit tests to test for the various placeholder trailing return types in lambdas.
398 lines
11 KiB
C++
398 lines
11 KiB
C++
// 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
|
|
|
|
struct StructA {};
|
|
|
|
template<class T>
|
|
auto AutoT() { return T(); }
|
|
|
|
template<class T>
|
|
const auto AutoConstT() { return T(); }
|
|
|
|
template<class T>
|
|
volatile auto AutoVolatileT() { return T(); }
|
|
|
|
template<class T>
|
|
const volatile auto AutoConstVolatileT() { return T(); }
|
|
|
|
// The qualifiers of the return type should always be emitted even for void types.
|
|
// Void types usually have their qualifers stripped in the mangled name for MSVC ABI.
|
|
void test_template_auto_void() {
|
|
AutoT<void>();
|
|
// CHECK: call {{.*}} @"??$AutoT@X@@YA?A_PXZ"
|
|
|
|
AutoT<const void>();
|
|
// CHECK: call {{.*}} @"??$AutoT@$$CBX@@YA?A_PXZ"
|
|
|
|
AutoT<volatile void>();
|
|
// CHECK: call {{.*}} @"??$AutoT@$$CCX@@YA?A_PXZ"
|
|
|
|
AutoT<const volatile void>();
|
|
// CHECK: call {{.*}} @"??$AutoT@$$CDX@@YA?A_PXZ"
|
|
|
|
AutoConstT<void>();
|
|
// CHECK: call {{.*}} @"??$AutoConstT@X@@YA?B_PXZ"
|
|
|
|
AutoVolatileT<void>();
|
|
// CHECK: call {{.*}} @"??$AutoVolatileT@X@@YA?C_PXZ"
|
|
|
|
AutoConstVolatileT<void>();
|
|
// CHECK: call {{.*}} @"??$AutoConstVolatileT@X@@YA?D_PXZ"
|
|
}
|
|
|
|
void test_template_auto_int() {
|
|
AutoT<int>();
|
|
// CHECK: call {{.*}} @"??$AutoT@H@@YA?A_PXZ"
|
|
|
|
AutoT<const int>();
|
|
// CHECK: call {{.*}} @"??$AutoT@$$CBH@@YA?A_PXZ"
|
|
|
|
AutoT<volatile int>();
|
|
// CHECK: call {{.*}} @"??$AutoT@$$CCH@@YA?A_PXZ"
|
|
|
|
AutoT<const volatile int>();
|
|
// CHECK: call {{.*}} @"??$AutoT@$$CDH@@YA?A_PXZ"
|
|
|
|
AutoConstT<int>();
|
|
// CHECK: call {{.*}} @"??$AutoConstT@H@@YA?B_PXZ"
|
|
|
|
AutoVolatileT<int>();
|
|
// CHECK: call {{.*}} @"??$AutoVolatileT@H@@YA?C_PXZ"
|
|
|
|
AutoConstVolatileT<int>();
|
|
// CHECK: call {{.*}} @"??$AutoConstVolatileT@H@@YA?D_PXZ"
|
|
}
|
|
|
|
void test_template_auto_struct() {
|
|
AutoT<StructA>();
|
|
// CHECK: call {{.*}} @"??$AutoT@UStructA@@@@YA?A_PXZ"
|
|
|
|
AutoT<const StructA>();
|
|
// CHECK: call {{.*}} @"??$AutoT@$$CBUStructA@@@@YA?A_PXZ"
|
|
|
|
AutoConstT<StructA>();
|
|
// CHECK: call {{.*}} @"??$AutoConstT@UStructA@@@@YA?B_PXZ"
|
|
|
|
AutoVolatileT<StructA>();
|
|
// CHECK: call {{.*}} @"??$AutoVolatileT@UStructA@@@@YA?C_PXZ"
|
|
|
|
AutoConstVolatileT<StructA>();
|
|
// CHECK: call {{.*}} @"??$AutoConstVolatileT@UStructA@@@@YA?D_PXZ"
|
|
}
|
|
|
|
void test_template_auto_ptr() {
|
|
AutoT<int*>();
|
|
// CHECK: call {{.*}} @"??$AutoT@PEAH@@YA?A_PXZ"
|
|
|
|
AutoT<const int*>();
|
|
// CHECK: call {{.*}} @"??$AutoT@PEBH@@YA?A_PXZ"
|
|
|
|
AutoT<const int* const>();
|
|
// CHECK: call {{.*}} @"??$AutoT@QEBH@@YA?A_PXZ"
|
|
|
|
AutoConstT<int*>();
|
|
// CHECK: call {{.*}} @"??$AutoConstT@PEAH@@YA?B_PXZ"
|
|
|
|
AutoVolatileT<int*>();
|
|
// CHECK: call {{.*}} @"??$AutoVolatileT@PEAH@@YA?C_PXZ"
|
|
|
|
AutoConstVolatileT<int*>();
|
|
// CHECK: call {{.*}} @"??$AutoConstVolatileT@PEAH@@YA?D_PXZ"
|
|
}
|
|
|
|
template<class T>
|
|
auto* PtrAutoT() { return T(); }
|
|
|
|
template<class T>
|
|
const auto* PtrAutoConstT() { return T(); }
|
|
|
|
template<class T>
|
|
volatile auto* PtrAutoVolatileT() { return T(); }
|
|
|
|
template<class T>
|
|
const volatile auto* PtrAutoConstVolatileT() { return T(); }
|
|
|
|
void test_template_ptr_auto() {
|
|
PtrAutoT<int*>();
|
|
// CHECK: call {{.*}} @"??$PtrAutoT@PEAH@@YAPEA_PXZ"
|
|
|
|
PtrAutoT<const int*>();
|
|
// CHECK: call {{.*}} @"??$PtrAutoT@PEBH@@YAPEA_PXZ"
|
|
|
|
PtrAutoT<const int* const>();
|
|
// CHECK: call {{.*}} @"??$PtrAutoT@QEBH@@YAPEA_PXZ"
|
|
|
|
PtrAutoConstT<int*>();
|
|
// CHECK: call {{.*}} @"??$PtrAutoConstT@PEAH@@YAPEB_PXZ"
|
|
|
|
PtrAutoVolatileT<int*>();
|
|
// CHECK: call {{.*}} @"??$PtrAutoVolatileT@PEAH@@YAPEC_PXZ"
|
|
|
|
PtrAutoConstVolatileT<int*>();
|
|
// CHECK: call {{.*}} @"??$PtrAutoConstVolatileT@PEAH@@YAPED_PXZ"
|
|
}
|
|
|
|
int func_int();
|
|
const int func_constint();
|
|
void func_void();
|
|
int* func_intptr();
|
|
|
|
template<class T, T v>
|
|
auto (*FuncPtrAutoT())() { return v; }
|
|
|
|
void test_template_func_ptr_auto() {
|
|
FuncPtrAutoT<int (*)(), &func_int>();
|
|
// CHECK: call {{.*}} @"??$FuncPtrAutoT@P6AHXZ$1?func_int@@YAHXZ@@YAP6A?A_PXZXZ"
|
|
|
|
FuncPtrAutoT<const int (*)(), &func_constint>();
|
|
// CHECK: call {{.*}} @"??$FuncPtrAutoT@P6A?BHXZ$1?func_constint@@YA?BHXZ@@YAP6A?A_PXZXZ"
|
|
|
|
FuncPtrAutoT<void (*)(), &func_void>();
|
|
// CHECK: call {{.*}} @"??$FuncPtrAutoT@P6AXXZ$1?func_void@@YAXXZ@@YAP6A?A_PXZXZ"
|
|
|
|
FuncPtrAutoT<int * (*)(), &func_intptr>();
|
|
// CHECK: call {{.*}} @"??$FuncPtrAutoT@P6APEAHXZ$1?func_intptr@@YAPEAHXZ@@YAP6A?A_PXZXZ"
|
|
}
|
|
|
|
template<class T>
|
|
auto& RefAutoT(T& x) { return x; }
|
|
|
|
template<class T>
|
|
const auto& ConstRefAutoT(T& x) { return x; }
|
|
|
|
template<class T>
|
|
auto&& RRefAutoT(T& x) { return static_cast<int&&>(x); }
|
|
|
|
void test_template_ref_auto() {
|
|
int x;
|
|
|
|
RefAutoT(x);
|
|
// CHECK: call {{.*}} @"??$RefAutoT@H@@YAAEA_PAEAH@Z"
|
|
|
|
ConstRefAutoT(x);
|
|
// CHECK: call {{.*}} @"??$ConstRefAutoT@H@@YAAEB_PAEAH@Z"
|
|
|
|
RRefAutoT(x);
|
|
// CHECK: call {{.*}} @"??$RRefAutoT@H@@YA$$QEA_PAEAH@Z"
|
|
}
|
|
|
|
template<class T>
|
|
decltype(auto) DecltypeAutoT() { return T(); }
|
|
|
|
template<class T>
|
|
decltype(auto) DecltypeAutoT2(T& x) { return static_cast<T&&>(x); }
|
|
|
|
void test_template_decltypeauto() {
|
|
DecltypeAutoT<void>();
|
|
// CHECK: call {{.*}} @"??$DecltypeAutoT@X@@YA?A_TXZ"
|
|
|
|
DecltypeAutoT<const void>();
|
|
// CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBX@@YA?A_TXZ"
|
|
|
|
DecltypeAutoT<volatile void>();
|
|
// CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCX@@YA?A_TXZ"
|
|
|
|
DecltypeAutoT<const volatile void>();
|
|
// CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDX@@YA?A_TXZ"
|
|
|
|
DecltypeAutoT<int>();
|
|
// CHECK: call {{.*}} @"??$DecltypeAutoT@H@@YA?A_TXZ"
|
|
|
|
DecltypeAutoT<const int>();
|
|
// CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBH@@YA?A_TXZ"
|
|
|
|
DecltypeAutoT<volatile int>();
|
|
// CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCH@@YA?A_TXZ"
|
|
|
|
DecltypeAutoT<const volatile int>();
|
|
// CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDH@@YA?A_TXZ"
|
|
|
|
int x;
|
|
|
|
DecltypeAutoT2(x);
|
|
// CHECK: call {{.*}} @"??$DecltypeAutoT2@H@@YA?A_TAEAH@Z"
|
|
}
|
|
|
|
// Still want to use clang's custom mangling for lambdas to keep backwards compatibility until
|
|
// MSVC lambda name mangling has been deciphered.
|
|
void test_lambda() {
|
|
int i = 0;
|
|
|
|
auto lambdaIntRetAuto = []() { return 0; };
|
|
lambdaIntRetAuto();
|
|
// CHECK: call {{.*}} @"??R<lambda_1>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@XZ"
|
|
|
|
auto lambdaIntRet = []() -> int { return 0; };
|
|
lambdaIntRet();
|
|
// CHECK: call {{.*}} @"??R<lambda_2>@?0??test_lambda@@YAXXZ@QEBA@XZ"
|
|
|
|
auto lambdaGenericIntIntRetAuto = [](auto a) { return a; };
|
|
lambdaGenericIntIntRetAuto(0);
|
|
// CHECK: call {{.*}} @"??$?RH@<lambda_0>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@H@Z"
|
|
|
|
auto lambdaRetTrailingAuto = []() -> auto { return 0; };
|
|
lambdaRetTrailingAuto();
|
|
// CHECK: call {{.*}} @"??R<lambda_3>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@XZ"
|
|
|
|
auto lambdaRetTrailingDecltypeAuto = []() -> decltype(auto) { return 0; };
|
|
lambdaRetTrailingDecltypeAuto();
|
|
// CHECK: call {{.*}} @"??R<lambda_4>@?0??test_lambda@@YAXXZ@QEBA?A?<decltype-auto>@@XZ"
|
|
|
|
auto lambdaRetTrailingRefCollapse = [](int x) -> auto&& { return x; };
|
|
lambdaRetTrailingRefCollapse(i);
|
|
// CHECK: call {{.*}} @"??R<lambda_5>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@H@Z"
|
|
}
|
|
|
|
auto TestTrailingInt() -> int {
|
|
return 0;
|
|
}
|
|
|
|
auto TestTrailingConstVolatileVoid() -> const volatile void {
|
|
}
|
|
|
|
auto TestTrailingStructA() -> StructA {
|
|
return StructA{};
|
|
}
|
|
|
|
void test_trailing_return() {
|
|
TestTrailingInt();
|
|
// CHECK: call {{.*}} @"?TestTrailingInt@@YAHXZ"
|
|
|
|
TestTrailingConstVolatileVoid();
|
|
// CHECK: call {{.*}} @"?TestTrailingConstVolatileVoid@@YAXXZ"
|
|
|
|
TestTrailingStructA();
|
|
// CHECK: call {{.*}} @"?TestTrailingStructA@@YA?AUStructA@@XZ"
|
|
}
|
|
|
|
auto TestNonTemplateAutoInt() {
|
|
return 0;
|
|
}
|
|
|
|
auto TestNonTemplateAutoVoid() {
|
|
return;
|
|
}
|
|
|
|
auto TestNonTemplateAutoStructA() {
|
|
return StructA{};
|
|
}
|
|
|
|
const auto TestNonTemplateConstAutoInt() {
|
|
return 0;
|
|
}
|
|
|
|
const auto TestNonTemplateConstAutoVoid() {
|
|
return;
|
|
}
|
|
|
|
const auto TestNonTemplateConstAutoStructA() {
|
|
return StructA{};
|
|
}
|
|
|
|
void test_nontemplate_auto() {
|
|
TestNonTemplateAutoInt();
|
|
// CHECK: call {{.*}} @"?TestNonTemplateAutoInt@@YA@XZ"
|
|
|
|
TestNonTemplateAutoVoid();
|
|
// CHECK: call {{.*}} @"?TestNonTemplateAutoVoid@@YA@XZ"
|
|
|
|
TestNonTemplateAutoStructA();
|
|
// CHECK: call {{.*}} @"?TestNonTemplateAutoStructA@@YA@XZ"
|
|
|
|
TestNonTemplateConstAutoInt();
|
|
// CHECK: call {{.*}} @"?TestNonTemplateConstAutoInt@@YA@XZ"
|
|
|
|
TestNonTemplateConstAutoVoid();
|
|
// CHECK: call {{.*}} @"?TestNonTemplateConstAutoVoid@@YA@XZ"
|
|
|
|
TestNonTemplateConstAutoStructA();
|
|
// CHECK: call {{.*}} @"?TestNonTemplateConstAutoStructA@@YA@XZ"
|
|
}
|
|
|
|
decltype(auto) TestNonTemplateDecltypeAutoInt() {
|
|
return 0;
|
|
}
|
|
|
|
decltype(auto) TestNonTemplateDecltypeAutoVoid() {
|
|
return;
|
|
}
|
|
|
|
decltype(auto) TestNonTemplateDecltypeAutoStructA() {
|
|
return StructA{};
|
|
}
|
|
|
|
void test_nontemplate_decltypeauto() {
|
|
TestNonTemplateDecltypeAutoInt();
|
|
// CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoInt@@YA@XZ"
|
|
|
|
TestNonTemplateDecltypeAutoVoid();
|
|
// CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoVoid@@YA@XZ"
|
|
|
|
TestNonTemplateDecltypeAutoStructA();
|
|
// CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoStructA@@YA@XZ"
|
|
}
|
|
|
|
struct StructB {
|
|
int x;
|
|
};
|
|
|
|
template<class T>
|
|
auto StructB::* AutoMemberDataPtrT(T x) { return x; }
|
|
|
|
template<class T>
|
|
const auto StructB::* AutoConstMemberDataPtrT(T x) { return x; }
|
|
|
|
void test_template_auto_member_data_ptr() {
|
|
AutoMemberDataPtrT(&StructB::x);
|
|
// CHECK: call {{.*}} @"??$AutoMemberDataPtrT@PEQStructB@@H@@YAPEQStructB@@_PPEQ0@H@Z"
|
|
|
|
AutoConstMemberDataPtrT(&StructB::x);
|
|
// CHECK: call {{.*}} @"??$AutoConstMemberDataPtrT@PEQStructB@@H@@YAPERStructB@@_PPEQ0@H@Z"
|
|
}
|
|
|
|
struct StructC {
|
|
void test() {}
|
|
};
|
|
|
|
struct StructD {
|
|
const int test() { return 0; }
|
|
};
|
|
|
|
template<class T>
|
|
auto (StructC::*AutoMemberFuncPtrT(T x))() { return x; }
|
|
|
|
template<class T>
|
|
const auto (StructD::*AutoConstMemberFuncPtrT(T x))() { return x; }
|
|
|
|
void test_template_auto_member_func_ptr() {
|
|
AutoMemberFuncPtrT(&StructC::test);
|
|
// CHECK: call {{.*}} @"??$AutoMemberFuncPtrT@P8StructC@@EAAXXZ@@YAP8StructC@@EAA?A_PXZP80@EAAXXZ@Z"
|
|
|
|
AutoConstMemberFuncPtrT(&StructD::test);
|
|
// CHECK: call {{.*}} @"??$AutoConstMemberFuncPtrT@P8StructD@@EAA?BHXZ@@YAP8StructD@@EAA?B_PXZP80@EAA?BHXZ@Z"
|
|
}
|
|
|
|
template<class T>
|
|
auto * __attribute__((address_space(1))) * AutoPtrAddressSpaceT() {
|
|
T * __attribute__((address_space(1))) * p = nullptr;
|
|
return p;
|
|
}
|
|
|
|
void test_template_auto_address_space_ptr() {
|
|
AutoPtrAddressSpaceT<int>();
|
|
// CHECK: call {{.*}} @"??$AutoPtrAddressSpaceT@H@@YA?A?<auto>@@XZ"
|
|
}
|
|
|
|
template<class T>
|
|
auto&& AutoReferenceCollapseT(T& x) { return static_cast<T&>(x); }
|
|
|
|
auto&& AutoReferenceCollapse(int& x) { return static_cast<int&>(x); }
|
|
|
|
void test2() {
|
|
int x = 1;
|
|
auto&& rref0 = AutoReferenceCollapseT(x);
|
|
// CHECK: call {{.*}} @"??$AutoReferenceCollapseT@H@@YA$$QEA_PAEAH@Z"
|
|
|
|
auto&& rref1 = AutoReferenceCollapse(x);
|
|
// CHECK: call {{.*}} @"?AutoReferenceCollapse@@YA@AEAH@Z"
|
|
}
|