| 1 | // RUN: %clang_cc1 %s -emit-llvm -triple i686-windows-gnu -o - | FileCheck %s |
| 2 | // RUN: %clang_cc1 %s -emit-llvm -triple i686-windows-itanium -o - | FileCheck %s |
| 3 | |
| 4 | // GCC 5.1 began mangling these Windows calling conventions into function |
| 5 | // types, since they can be used for overloading. They've always been mangled |
| 6 | // in the MS ABI, but they are new to the Itanium mangler. Note that the main |
| 7 | // function definition does not use a calling convention. Only function types |
| 8 | // that appear later use it. |
| 9 | |
| 10 | template <typename Fn> static int func_as_ptr(Fn fn) { return int(fn); } |
| 11 | |
| 12 | void f_cdecl(int, int); |
| 13 | void __attribute__((stdcall)) f_stdcall(int, int); |
| 14 | void __attribute__((fastcall)) f_fastcall(int, int); |
| 15 | void __attribute__((thiscall)) f_thiscall(int, int); |
| 16 | |
| 17 | int as_cdecl() { return func_as_ptr(f_cdecl); } |
| 18 | int as_stdcall() { return func_as_ptr(f_stdcall); } |
| 19 | int as_fastcall() { return func_as_ptr(f_fastcall); } |
| 20 | |
| 21 | // CHECK: define dso_local i32 @_Z8as_cdeclv() |
| 22 | // CHECK: call i32 @_ZL11func_as_ptrIPFviiEEiT_(void (i32, i32)* @_Z7f_cdeclii) |
| 23 | |
| 24 | // CHECK: define dso_local i32 @_Z10as_stdcallv() |
| 25 | // CHECK: call i32 @_ZL11func_as_ptrIPU7stdcallFviiEEiT_(void (i32, i32)* @"\01__Z9f_stdcallii@8") |
| 26 | |
| 27 | // CHECK: define dso_local i32 @_Z11as_fastcallv() |
| 28 | // CHECK: call i32 @_ZL11func_as_ptrIPU8fastcallFviiEEiT_(void (i32, i32)* @"\01@_Z10f_fastcallii@8") |
| 29 | |
| 30 | // PR40107: We should mangle thiscall here but we don't because we can't |
| 31 | // disambiguate it from the member pointer case below where it shouldn't be |
| 32 | // mangled. |
| 33 | //int as_thiscall() { return func_as_ptr(f_thiscall); } |
| 34 | // CHECKX: define dso_local i32 @_Z11as_thiscallv() |
| 35 | // CHECKX: call i32 @_ZL11func_as_ptrIPU8thiscallFviiEEiT_(void (i32, i32)* @_Z10f_thiscallii) |
| 36 | |
| 37 | // CHECK: define dso_local void @_Z11funcRefTypeRU8fastcallFviiE(void (i32, i32)* %fr) |
| 38 | void funcRefType(void(__attribute__((fastcall)) & fr)(int, int)) { |
| 39 | fr(1, 2); |
| 40 | } |
| 41 | |
| 42 | struct Foo { void bar(int, int); }; |
| 43 | |
| 44 | // PR40107: In this case, the member function pointer uses the thiscall |
| 45 | // convention, but GCC doesn't mangle it, so we don't either. |
| 46 | // CHECK: define dso_local void @_Z15memptr_thiscallP3FooMS_FvvE(%struct.Foo* {{.*}}) |
| 47 | void memptr_thiscall(Foo *o, void (Foo::*mp)()) { (o->*mp)(); } |
| 48 | |
| 49 | // CHECK: define dso_local void @_Z12memptrCCTypeR3FooMS_U8fastcallFviiE(%struct.Foo* {{.*}}, { i32, i32 }* byval{{.*}}) |
| 50 | void memptrCCType(Foo &o, void (__attribute__((fastcall)) Foo::*mp)(int, int)) { |
| 51 | (o.*mp)(1, 2); |
| 52 | } |
| 53 | |
| 54 | // CHECK: define dso_local i32 @_Z17useTemplateFnTypev() |
| 55 | // CHECK: call i32 @_ZL14templateFnTypeIU8fastcallFviiEElPT_(void (i32, i32)* @"\01@_Z10f_fastcallii@8") |
| 56 | template <typename Fn> static long templateFnType(Fn *fn) { return long(fn); } |
| 57 | long useTemplateFnType() { return templateFnType(f_fastcall); } |
| 58 | |
| 59 | // CHECK: define weak_odr dso_local x86_fastcallcc void @"\01@_Z10fnTemplateIsEvv@0"() |
| 60 | // CHECK: define dso_local x86_fastcallcc void @"\01@_Z10fnTemplateIiEvv@0"() |
| 61 | template <typename T> void __attribute__((fastcall)) fnTemplate() {} |
| 62 | template void __attribute__((fastcall)) fnTemplate<short>(); |
| 63 | template <> void __attribute__((fastcall)) fnTemplate<int>() {} |
| 64 | |
| 65 | // CHECK: define weak_odr dso_local x86_fastcallcc void (i32, i32)* @"\01@_Z12fnTempReturnIsEPU8fastcallFviiEv@0"() |
| 66 | // CHECK: define dso_local x86_fastcallcc void (i32, i32)* @"\01@_Z12fnTempReturnIiEPU8fastcallFviiEv@0"() |
| 67 | typedef void (__attribute__((fastcall)) *fp_cc_t)(int, int); |
| 68 | template <typename T> fp_cc_t __attribute__((fastcall)) fnTempReturn() { return nullptr; } |
| 69 | template fp_cc_t __attribute__((fastcall)) fnTempReturn<short>(); |
| 70 | template <> fp_cc_t __attribute__((fastcall)) fnTempReturn<int>() { return nullptr; } |
| 71 | |