reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
// 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"