Index: cfe/trunk/lib/AST/ItaniumMangle.cpp =================================================================== --- cfe/trunk/lib/AST/ItaniumMangle.cpp +++ cfe/trunk/lib/AST/ItaniumMangle.cpp @@ -2648,13 +2648,8 @@ case CC_C: return ""; - case CC_X86StdCall: - case CC_X86FastCall: - case CC_X86ThisCall: case CC_X86VectorCall: case CC_X86Pascal: - case CC_Win64: - case CC_X86_64SysV: case CC_X86RegCall: case CC_AAPCS: case CC_AAPCS_VFP: @@ -2667,6 +2662,16 @@ // FIXME: we should be mangling all of the above. return ""; + case CC_X86StdCall: + return "stdcall"; + case CC_X86FastCall: + return "fastcall"; + case CC_X86ThisCall: + return "thiscall"; + case CC_X86_64SysV: + return "sysv_abi"; + case CC_Win64: + return "ms_abi"; case CC_Swift: return "swiftcall"; } Index: cfe/trunk/test/CodeGenCXX/mangle-win-ccs.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/mangle-win-ccs.cpp +++ cfe/trunk/test/CodeGenCXX/mangle-win-ccs.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 %s -emit-llvm -triple i686-windows-gnu -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple i686-windows-itanium -o - | FileCheck %s + +// GCC 5.1 began mangling these Windows calling conventions into function +// types, since they can be used for overloading. They've always been mangled +// in the MS ABI, but they are new to the Itanium mangler. Note that the main +// function definition does not use a calling convention. Only function types +// that appear later use it. + +template static int func_as_ptr(Fn fn) { return int(fn); } + +void f_cdecl(int, int); +void __attribute__((stdcall)) f_stdcall(int, int); +void __attribute__((fastcall)) f_fastcall(int, int); +void __attribute__((thiscall)) f_thiscall(int, int); + +int as_cdecl() { return func_as_ptr(f_cdecl); } +int as_stdcall() { return func_as_ptr(f_stdcall); } +int as_fastcall() { return func_as_ptr(f_fastcall); } +int as_thiscall() { return func_as_ptr(f_thiscall); } + +// CHECK: define dso_local i32 @_Z8as_cdeclv() +// CHECK: call i32 @_ZL11func_as_ptrIPFviiEEiT_(void (i32, i32)* @_Z7f_cdeclii) + +// CHECK: define dso_local i32 @_Z10as_stdcallv() +// CHECK: call i32 @_ZL11func_as_ptrIPU7stdcallFviiEEiT_(void (i32, i32)* @"\01__Z9f_stdcallii@8") + +// CHECK: define dso_local i32 @_Z11as_fastcallv() +// CHECK: call i32 @_ZL11func_as_ptrIPU8fastcallFviiEEiT_(void (i32, i32)* @"\01@_Z10f_fastcallii@8") + +// CHECK: define dso_local i32 @_Z11as_thiscallv() +// CHECK: call i32 @_ZL11func_as_ptrIPU8thiscallFviiEEiT_(void (i32, i32)* @_Z10f_thiscallii) + +// CHECK: define dso_local void @_Z11funcRefTypeRU8fastcallFviiE(void (i32, i32)* %fr) +void funcRefType(void(__attribute__((fastcall)) & fr)(int, int)) { + fr(1, 2); +} + +// CHECK: define dso_local void @_Z12memptrCCTypeR3FooMS_U8fastcallFviiE(%struct.Foo* {{.*}}, { i32, i32 }* byval{{.*}}) +struct Foo { void bar(int, int); }; +void memptrCCType(Foo &o, void (__attribute__((fastcall)) Foo::*mp)(int, int)) { + (o.*mp)(1, 2); +} + +// CHECK: define dso_local i32 @_Z17useTemplateFnTypev() +// CHECK: call i32 @_ZL14templateFnTypeIU8fastcallFviiEElPT_(void (i32, i32)* @"\01@_Z10f_fastcallii@8") +template static long templateFnType(Fn *fn) { return long(fn); } +long useTemplateFnType() { return templateFnType(f_fastcall); } + +// CHECK: define weak_odr dso_local x86_fastcallcc void @"\01@_Z10fnTemplateIsEvv@0"() +// CHECK: define dso_local x86_fastcallcc void @"\01@_Z10fnTemplateIiEvv@0"() +template void __attribute__((fastcall)) fnTemplate() {} +template void __attribute__((fastcall)) fnTemplate(); +template <> void __attribute__((fastcall)) fnTemplate() {} + +// CHECK: define weak_odr dso_local x86_fastcallcc void (i32, i32)* @"\01@_Z12fnTempReturnIsEPU8fastcallFviiEv@0"() +// CHECK: define dso_local x86_fastcallcc void (i32, i32)* @"\01@_Z12fnTempReturnIiEPU8fastcallFviiEv@0"() +typedef void (__attribute__((fastcall)) *fp_cc_t)(int, int); +template fp_cc_t __attribute__((fastcall)) fnTempReturn() { return nullptr; } +template fp_cc_t __attribute__((fastcall)) fnTempReturn(); +template <> fp_cc_t __attribute__((fastcall)) fnTempReturn() { return nullptr; } Index: cfe/trunk/test/CodeGenCXX/mangle-win64-ccs.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/mangle-win64-ccs.cpp +++ cfe/trunk/test/CodeGenCXX/mangle-win64-ccs.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-windows-gnu -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-WIN +// RUN: %clang_cc1 -triple x86_64-linux-gnu -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-LIN + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +template ptrdiff_t func_as_int(FTy *fp) { return ptrdiff_t(fp); } + +int f_plain(int); +int __attribute__((sysv_abi)) f_sysvabi(int); +int __attribute__((ms_abi)) f_msabi(int); +ptrdiff_t useThem() { + ptrdiff_t rv = 0; + rv += func_as_int(f_plain); + rv += func_as_int(f_sysvabi); + rv += func_as_int(f_msabi); + return rv; +} + +// CHECK-WIN: define dso_local i64 @_Z7useThemv() +// CHECK-WIN: call i64 @_Z11func_as_intIFiiEExPT_(i32 (i32)* @_Z7f_plaini) +// CHECK-WIN: call i64 @_Z11func_as_intIU8sysv_abiFiiEExPT_(i32 (i32)* @_Z9f_sysvabii) +// CHECK-WIN: call i64 @_Z11func_as_intIFiiEExPT_(i32 (i32)* @_Z7f_msabii) + +// CHECK-LIN: define i64 @_Z7useThemv() +// CHECK-LIN: call i64 @_Z11func_as_intIFiiEElPT_(i32 (i32)* @_Z7f_plaini) +// CHECK-LIN: call i64 @_Z11func_as_intIFiiEElPT_(i32 (i32)* @_Z9f_sysvabii) +// CHECK-LIN: call i64 @_Z11func_as_intIU6ms_abiFiiEElPT_(i32 (i32)* @_Z7f_msabii)