90 lines
2.5 KiB
C++
90 lines
2.5 KiB
C++
// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
|
|
|
|
template<typename Signature>
|
|
class C;
|
|
|
|
template<typename Ret>
|
|
class C<Ret(void)> {};
|
|
typedef C<void(void)> C0;
|
|
|
|
template<typename Ret, typename Arg1>
|
|
class C<Ret(Arg1)> {};
|
|
|
|
template<typename Ret, typename Arg1, typename Arg2>
|
|
class C<Ret(Arg1, Arg2)> {};
|
|
|
|
C0 callback_void;
|
|
// CHECK: "?callback_void@@3V?$C@$$A6AXXZ@@A"
|
|
|
|
volatile C0 callback_void_volatile;
|
|
// CHECK: "?callback_void_volatile@@3V?$C@$$A6AXXZ@@C"
|
|
|
|
class Type {};
|
|
|
|
C<int(void)> callback_int;
|
|
// CHECK: "?callback_int@@3V?$C@$$A6AHXZ@@A"
|
|
C<Type(void)> callback_Type;
|
|
// CHECK: "?callback_Type@@3V?$C@$$A6A?AVType@@XZ@@A"
|
|
|
|
C<void(int)> callback_void_int;
|
|
// CHECK: "?callback_void_int@@3V?$C@$$A6AXH@Z@@A"
|
|
C<int(int)> callback_int_int;
|
|
// CHECK: "?callback_int_int@@3V?$C@$$A6AHH@Z@@A"
|
|
C<void(Type)> callback_void_Type;
|
|
// CHECK: "?callback_void_Type@@3V?$C@$$A6AXVType@@@Z@@A"
|
|
|
|
void foo(C0 c) {}
|
|
// CHECK: "?foo@@YAXV?$C@$$A6AXXZ@@@Z"
|
|
|
|
// Here be dragons!
|
|
// Let's face the magic of template partial specialization...
|
|
|
|
void function(C<void(void)>) {}
|
|
// CHECK: "?function@@YAXV?$C@$$A6AXXZ@@@Z"
|
|
|
|
template<typename Ret> class C<Ret(*)(void)> {};
|
|
void function_pointer(C<void(*)(void)>) {}
|
|
// CHECK: "?function_pointer@@YAXV?$C@P6AXXZ@@@Z"
|
|
|
|
// Block equivalent to the previous definitions.
|
|
template<typename Ret> class C<Ret(^)(void)> {};
|
|
void block(C<void(^)(void)>) {}
|
|
// CHECK: "?block@@YAXV?$C@P_EAXXZ@@@Z"
|
|
// FYI blocks are not present in MSVS, so we're free to choose the spec.
|
|
|
|
template<typename T> class C<void (T::*)(void)> {};
|
|
class Z {
|
|
public:
|
|
void method() {}
|
|
};
|
|
void member_pointer(C<void (Z::*)(void)>) {}
|
|
// CHECK: "?member_pointer@@YAXV?$C@P8Z@@AEXXZ@@@Z"
|
|
|
|
template<typename T> void bar(T) {}
|
|
|
|
void call_bar() {
|
|
bar<int (*)(int)>(0);
|
|
// CHECK: "??$bar@P6AHH@Z@@YAXP6AHH@Z@Z"
|
|
|
|
bar<int (^)(int)>(0);
|
|
// CHECK: "??$bar@P_EAHH@Z@@YAXP_EAHH@Z@Z"
|
|
// FYI blocks are not present in MSVS, so we're free to choose the spec.
|
|
}
|
|
|
|
template <void (*Fn)()> void WrapFnPtr() { Fn(); }
|
|
template <void (&Fn)()> void WrapFnRef() { Fn(); }
|
|
struct Thing {
|
|
static void VoidStaticMethod();
|
|
};
|
|
void VoidFn();
|
|
void CallWrapper() {
|
|
WrapFnPtr<VoidFn>();
|
|
WrapFnRef<VoidFn>();
|
|
WrapFnPtr<Thing::VoidStaticMethod>();
|
|
WrapFnRef<Thing::VoidStaticMethod>();
|
|
}
|
|
// CHECK: call {{.*}} @"??$WrapFnPtr@$1?VoidFn@@YAXXZ@@YAXXZ"
|
|
// CHECK: call {{.*}} @"??$WrapFnRef@$1?VoidFn@@YAXXZ@@YAXXZ"
|
|
// CHECK: call {{.*}} @"??$WrapFnPtr@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
|
|
// CHECK: call {{.*}} @"??$WrapFnRef@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
|