// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-windows -emit-llvm -o - | FileCheck %s --check-prefix=MSABI
#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
struct A { int a; const int b; };
template void f() {}
// CHECK: define weak_odr void @_Z1fIXtl1ALi1ELi2EEEEvv(
// MSABI: define {{.*}} @"??$f@$2UA@@H00$$CBH01@@@YAXXZ"
template void f();
struct B { const int *p; int k; };
template void f() {}
int n = 0;
// CHECK: define weak_odr void @_Z1fIXtl1BadL_Z1nEEEEvv(
// MSABI: define {{.*}} @"??$f@$2UB@@PEBHE?n@@3HAH0A@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1BLPKi0ELi1EEEEvv(
// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0A@H00@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1BEEEvv(
// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0A@H0A@@@@YAXXZ"
template void f();
// These are extensions, but they seem like the obvious manglings.
// CHECK: define weak_odr void @_Z1fIXtl1BLPKi32EEEEvv(
// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0CA@H0A@@@@YAXXZ"
template void f();
#ifndef _WIN32
// FIXME: On MS ABI, we mangle this the same as nullptr, despite considering a
// null pointer and zero bitcast to a pointer to be distinct pointer values.
// CHECK: define weak_odr void @_Z1fIXtl1BrcPKiLi0EEEEvv(
template void f(0))}>();
#endif
// Pointers to subobjects.
struct Nested { union { int k; int arr[2]; }; } nested[2];
struct Derived : A, Nested { int z; A a_field; } extern derived;
// CHECK: define weak_odr void @_Z1fIXtl1BadsoKiL_Z7derivedE16EEEEvv
// MSABI: define {{.*}} void @"??$f@$2UB@@PEBH56E?derived@@3UDerived@@Az@@@H0A@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1BadsoKiL_Z7derivedE20EEEEvv
// MSABI: define {{.*}} void @"??$f@$2UB@@PEBH566E?derived@@3UDerived@@Aa_field@@a@@@H0A@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1BadsoKiL_Z6nestedE_EEEEvv
// MSABI: define {{.*}} void @"??$f@$2UB@@PEBH56CE?nested@@3PAUNested@@A0A@@k@@@H0A@@@@YAXXZ"
template void f();
// Mangling of pointers to nested array elements and past-the-end pointers
// is still incorrect in MSVC.
#ifndef _WIN32
// CHECK: define weak_odr void @_Z1fIXtl1BadsoKiL_Z6nestedE16_0pEEEEvv
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1BadsoKiL_Z7derivedE8pEEEEvv
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1BcvPKiplcvPcadL_Z7derivedELl16EEEEvv
template void f();
#endif
// References to subobjects.
struct BR { const int &r; };
template
void f() {}
// CHECK: define weak_odr void @_Z1fIXtl2BRsoKiL_Z7derivedE16EEEEvv
// MSABI: define {{.*}} void @"??$f@$2UBR@@AEBH6E?derived@@3UDerived@@Az@@@@@YAXXZ"
template void f
();
// CHECK: define weak_odr void @_Z1fIXtl2BRsoKiL_Z6nestedE_EEEEvv
// MSABI: define {{.*}} void @"??$f@$2UBR@@AEBH6CE?nested@@3PAUNested@@A0A@@k@@@@@YAXXZ"
template void f
();
// CHECK: define weak_odr void @_Z1fIXtl2BRsoKiL_Z6nestedE12_0EEEEvv
// MSABI: define {{.*}} void @"??$f@$2UBR@@AEBHC6CE?nested@@3PAUNested@@A00@arr@@00@@@@YAXXZ"
template void f
();
// CHECK: define weak_odr void @_Z1fIXtl2BRsoKiL_Z7derivedE4EEEEvv
// MSABI: define {{.*}} void @"??$f@$2UBR@@AEBH66E?derived@@3UDerived@@AA@@b@@@@@YAXXZ"
template void f
();
#ifndef _WIN32
// CHECK: define weak_odr void @_Z1fIXtl2BRdecvPKiplcvPcadL_Z7derivedELl16EEEEvv
template void f
();
#endif
// Qualification conversions.
struct C { const int *p; };
template void f() {}
// CHECK: define weak_odr void @_Z1fIXtl1CadsoKiL_Z7derivedE16EEEEvv
// MSABI: define {{.*}} void @"??$f@$2UC@@PEBH56E?derived@@3UDerived@@Az@@@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1CadsoKiL_Z7derivedE4EEEEvv
// MSABI: define {{.*}} void @"??$f@$2UC@@PEBH566E?derived@@3UDerived@@AA@@b@@@@@@YAXXZ"
template void f();
// Pointers to members.
struct D { const int Derived::*p; int k; };
template void f() {}
// CHECK: define weak_odr void @_Z1fIXtl1DLM7DerivedKi0ELi1EEEEvv
// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@HNH00@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1DEEEvv
// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@HNH0A@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1DadL_ZN7Derived1zEEEEEvv
// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H82@z@@H0A@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1DmcM7DerivedKiadL_ZN1A1aEEEEEEvv
// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H8A@@a@@H0A@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1DmcM7DerivedKiadL_ZN1A1bEEEEEEvv
// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H8A@@b@@H0A@@@@YAXXZ"
template void f();
// FIXME: Is the Ut_1 mangling here correct?
// CHECK: define weak_odr void @_Z1fIXtl1DmcM7DerivedKiadL_ZN6NestedUt_1kEE8ELi2EEEEvv
// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H8@Nested@@k@@H01@@@YAXXZ"
template void f();
struct MoreDerived : A, Derived { int z; };
// CHECK: define weak_odr void @_Z1fIXtl1DmcM7DerivedKiadL_ZN11MoreDerived1zEEn8EEEEvv
// MSABI: define {{.*}} @"??$f@$2UD@@PERDerived@@H8MoreDerived@@z@@H0A@@@@YAXXZ"
template void f();
struct DerivedVirtually : virtual A, Nested { int z; };
struct D2 { const int DerivedVirtually::*p; int k; };
template void f() {}
// CHECK: define weak_odr void @_Z1fIXtl2D2LM16DerivedVirtuallyKi0ELi1EEEEvv
// MSABI: define {{.*}} @"??$f@$2UD2@@PERDerivedVirtually@@HFA@?0H00@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl2D2EEEvv
// MSABI: define {{.*}} @"??$f@$2UD2@@PERDerivedVirtually@@HFA@?0H0A@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl2D2adL_ZN16DerivedVirtually1zEEEEEvv
// MSABI: define {{.*}} @"??$f@$2UD2@@PERDerivedVirtually@@HFBA@A@H0A@@@@YAXXZ"
template void f();
// Forward-decl without MS inheritance keyword means unspecified inheritance
// which is different from e. g. single inheritance.
struct UnspecInherStruct;
struct D3 { const int UnspecInherStruct::*p; };
template void f() {}
struct UnspecInherStruct { int i; };
// CHECK: define weak_odr void @_Z1fIXtl2D3adL_ZN17UnspecInherStruct1iEEEEEvv
// MSABI: define {{.*}} @"??$f@$2UD3@@PERUnspecInherStruct@@HGA@A@A@@@@YAXXZ"
template void f();
// Pointers to member functions.
// Test struct templates instead of function templates so as to cover
// the separate code which handles nullptr in their pointer-to-member arguments.
struct Derived2 : A, Nested { void f(); virtual void g(); };
struct D4 { void (Derived2::*p)(); };
template struct S1 { static void fn() {} };
// CHECK: define weak_odr void @_ZN2S1IXtl2D4adL_ZN8Derived21fEvEEEE2fnEv
// MSABI: define {{.*}} @"?fn@?$S1@$2UD4@@P8Derived2@@EAAXXZE?f@2@QEAAXXZ@@@SAXXZ"
template void S1::fn();
// CHECK: define weak_odr void @_ZN2S1IXtl2D4adL_ZN8Derived21gEvEEEE2fnEv
// MSABI: define {{.*}} @"?fn@?$S1@$2UD4@@P8Derived2@@EAAXXZE??_92@$BA@AA@@@SAXXZ"
template void S1::fn();
// CHECK: define weak_odr void @_ZN2S1IXtl2D4EEE2fnEv
// MSABI: define {{.*}} @"?fn@?$S1@$2UD4@@P8Derived2@@EAAXXZHA@@@@SAXXZ"
template void S1::fn();
struct NoInheritance { void f(); };
struct D5 { void (NoInheritance::*p)(); };
template struct S2 { static void fn() {} };
// CHECK: define weak_odr void @_ZN2S2IXtl2D5adL_ZN13NoInheritance1fEvEEEE2fnEv
// MSABI: define {{.*}} @"?fn@?$S2@$2UD5@@P8NoInheritance@@EAAXXZE?f@2@QEAAXXZ@@@SAXXZ"
template void S2::fn();
// CHECK: define weak_odr void @_ZN2S2IXtl2D5EEE2fnEv
// MSABI: define {{.*}} @"?fn@?$S2@$2UD5@@P8NoInheritance@@EAAXXZN@@@SAXXZ"
template void S2::fn();
struct NoInheritanceButUnspecified;
struct D6 { void (NoInheritanceButUnspecified::*p)(); };
template struct S3 { static void fn() {} };
// CHECK: define weak_odr void @_ZN2S3IXtl2D6EEE2fnEv
// MSABI: define {{.*}} @"?fn@?$S3@$2UD6@@P8NoInheritanceButUnspecified@@EAAXXZJA@A@?0@@@SAXXZ"
template void S3::fn();
union E {
int n;
float f;
constexpr E() {}
constexpr E(int n) : n(n) {}
constexpr E(float f) : f(f) {}
};
template void f() {}
// Union members.
// CHECK: define weak_odr void @_Z1fIL1EEEvv(
// MSABI: define {{.*}} @"??$f@$7TE@@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1EEEEvv(
// MSABI: define {{.*}} @"??$f@$7TE@@n@0A@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1Edi1nLi42EEEEvv(
// MSABI: define {{.*}} @"??$f@$7TE@@n@0CK@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1Edi1fLf00000000EEEEvv(
// MSABI: define {{.*}} @"??$f@$7TE@@0AA@@@@YAXXZ"
template void f();
// immintrin.h vector types.
typedef float __m128 __attribute__((__vector_size__(16)));
typedef double __m128d __attribute__((__vector_size__(16)));
typedef long long __m128i __attribute__((__vector_size__(16)));
struct M128 { __m128 a; };
struct M128D { __m128d b; };
struct M128I { __m128i c; };
template void f() {}
template void f() {}
template void f() {}
// MSABI: define {{.*}} @"??$f@$2UM128@@2T__m128@@3MADPIAAAAA@@AEAAAAAAA@@AEAEAAAAA@@AEAIAAAAA@@@@@@@YAXXZ"
template void f();
// MSABI: define {{.*}} @"??$f@$2UM128D@@2U__m128d@@3NBDPPAAAAAAAAAAAAA@@BEAAAAAAAAAAAAAAA@@@@@@@YAXXZ"
template void f();
// FIXME: We define __m128i as a vector of long long, whereas MSVC appears to
// mangle it as if it were a vector of char.
// MSABI-FIXME: define {{.*}} @"??$f@$2UM128I@@2T__m128i@@3D00@01@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@@@@@@YAXXZ"
// MSABI: define {{.*}} @"??$f@$2UM128I@@2T__m128i@@3_J00@01@@@@@@YAXXZ"
template void f();
// Extensions, and dropping trailing zero-initialized elements of 'tl'
// manglings.
typedef int __attribute__((ext_vector_type(3))) VI3;
struct F { VI3 v; _Complex int ci; _Complex float cf; };
template void f() {}
// CHECK: define weak_odr void @_Z1fIXtl1FtlDv3_iLi1ELi2ELi3EEtlCiLi4ELi5EEtlCfLf40c00000ELf40e00000EEEEEvv
// MSABI: define {{.*}} @"??$f@$2UF@@2T?$__vector@H$02@__clang@@3H00@01@02@@@2U?$_Complex@H@3@0304@2U?$_Complex@M@3@AEAMAAAAA@AEAOAAAAA@@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1FtlDv3_iLi1ELi2ELi3EEtlCiLi4ELi5EEtlCfLf40c00000EEEEEvv
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1FtlDv3_iLi1ELi2ELi3EEtlCiLi4ELi5EEEEEvv
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1FtlDv3_iLi1ELi2ELi3EEtlCiLi4EEEEEvv
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1FtlDv3_iLi1ELi2ELi3EEEEEvv
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1FtlDv3_iLi1ELi2EEEEEvv
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1FtlDv3_iLi1EEEEEvv
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1FEEEvv
// MSABI: define {{.*}} @"??$f@$2UF@@2T?$__vector@H$02@__clang@@3H0A@@0A@@0A@@@@2U?$_Complex@H@3@0A@0A@@2U?$_Complex@M@3@AA@AA@@@@@YAXXZ"
template void f();
// Unnamed bit-fields.
struct G {
int : 3;
int a : 4;
int : 5;
int b : 6;
int : 7;
};
template void f() {}
// CHECK: define weak_odr void @_Z1fIXtl1GEEEvv
// MSABI: define {{.*}} @"??$f@$2UG@@H0A@H0A@@@@YAXXZ"
template void f<(G())>();
// CHECK: define weak_odr void @_Z1fIXtl1GLi1EEEEvv
// MSABI: define {{.*}} @"??$f@$2UG@@H00H0A@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1GLi1ELi2EEEEvv
// MSABI: define {{.*}} @"??$f@$2UG@@H00H01@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl1GLin8ELin32EEEEvv
// MSABI: define {{.*}} @"??$f@$2UG@@H0?7H0?CA@@@@YAXXZ"
template void f();
// Empty and nearly-empty unions.
union H1 {};
union H2 { int : 1, : 2, : 3; };
union H3 { int : 1, a, : 2, b, : 3; };
struct H4 { H2 h2; };
template void f() {}
template void f() {}
template void f() {}
template void f() {}
// CHECK: define weak_odr void @_Z1fIL2H1EEvv
// MSABI: define {{.*}} @"??$f@$7TH1@@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIL2H2EEvv
// MSABI: define {{.*}} @"??$f@$7TH2@@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl2H3EEEvv
// MSABI: define {{.*}} @"??$f@$7TH3@@a@0A@@@@YAXXZ"
template void f();
// CHECK: define weak_odr void @_Z1fIXtl2H3di1aLi1EEEEvv
// MSABI: define {{.*}} @"??$f@$7TH3@@a@00@@@YAXXZ"
template void f