summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/microsoft-abi-thunks.cpp
blob: 091ef3274b9828de2ca298a74d6437ba86c7ea35 (plain)
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 >%t 2>&1
// RUN: FileCheck --check-prefix=MANGLING %s < %t
// RUN: FileCheck --check-prefix=XMANGLING %s < %t
// RUN: FileCheck --check-prefix=CODEGEN %s < %t
// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s

void foo(void *);

struct A {
  virtual ~A();
  virtual void public_f();
  // Make sure we don't emit unneeded thunks:
  // XMANGLING-NOT: @"\01?public_f@A@@QAEXXZ"
 protected:
  virtual void protected_f();
 private:
  virtual void private_f();
};

struct B {
  virtual ~B();
  virtual void public_f();
 protected:
  virtual void protected_f();
 private:
  virtual void private_f();
};


struct C : A, B {
  C();

  virtual ~C();
  // MANGLING-DAG: @"\01??1C@@UAE@XZ"
  // MANGLING-DAG: @"\01??_GC@@UAEPAXI@Z"
  // MANGLING-DAG: @"\01??_EC@@W3AEPAXI@Z"
  // MANGLING-X64-DAG: @"\01??1C@@UEAA@XZ"
  // MANGLING-X64-DAG: @"\01??_GC@@UEAAPEAXI@Z"
  // MANGLING-X64-DAG: @"\01??_EC@@W7EAAPEAXI@Z"

  // Overrides public_f() of two subobjects with distinct vfptrs, thus needs a thunk.
  virtual void public_f();
  // MANGLING-DAG: @"\01?public_f@C@@UAEXXZ"
  // MANGLING-DAG: @"\01?public_f@C@@W3AEXXZ"
  // MANGLING-X64-DAG: @"\01?public_f@C@@UEAAXXZ"
  // MANGLING-X64-DAG: @"\01?public_f@C@@W7EAAXXZ"
 protected:
  virtual void protected_f();
  // MANGLING-DAG: @"\01?protected_f@C@@MAEXXZ"
  // MANGLING-DAG: @"\01?protected_f@C@@O3AEXXZ"
  // MANGLING-X64-DAG: @"\01?protected_f@C@@MEAAXXZ"
  // MANGLING-X64-DAG: @"\01?protected_f@C@@O7EAAXXZ"

 private:
  virtual void private_f();
  // MANGLING-DAG: @"\01?private_f@C@@EAEXXZ"
  // MANGLING-DAG: @"\01?private_f@C@@G3AEXXZ"
  // MANGLING-X64-DAG: @"\01?private_f@C@@EEAAXXZ"
  // MANGLING-X64-DAG: @"\01?private_f@C@@G7EAAXXZ"
};

C::C() {}  // Emits vftable and forces thunk generation.

// CODEGEN: define weak x86_thiscallcc void @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete)
// CODEGEN:   getelementptr inbounds i8* {{.*}}, i64 -4
// FIXME: should actually call _EC, not _GC.
// CODEGEN:   call x86_thiscallcc void @"\01??_GC@@UAEPAXI@Z"
// CODEGEN: ret

// CODEGEN: define weak x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C*
// CODEGEN:   getelementptr inbounds i8* {{.*}}, i64 -4
// CODEGEN:   call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C*
// CODEGEN: ret

void zoo(C* obj) {
  delete obj;
}

struct D {
  virtual B* goo();
};

struct E : D {
  virtual C* goo();
  // MANGLING-DAG: @"\01?goo@E@@UAEPAUC@@XZ"
  // MANGLING-DAG: @"\01?goo@E@@QAEPAUB@@XZ"
  // MANGLING-X64-DAG: @"\01?goo@E@@UEAAPEAUC@@XZ"
  // MANGLING-X64-DAG: @"\01?goo@E@@QEAAPEAUB@@XZ"
};

E e;  // Emits vftable and forces thunk generation.

// CODEGEN: define weak x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ"
// CODEGEN:   call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ"
// CODEGEN:   getelementptr inbounds i8* {{.*}}, i64 4
// CODEGEN: ret

struct F : virtual A, virtual B {
  virtual ~F();
};

F f;  // Just make sure we don't crash, e.g. mangling the complete dtor.

struct G : C { };

struct H : E {
  virtual G* goo();
  // MANGLING-DAG: @"\01?goo@H@@UAEPAUG@@XZ"
  // MANGLING-DAG: @"\01?goo@H@@QAEPAUB@@XZ"
  // MANGLING-DAG: @"\01?goo@H@@QAEPAUC@@XZ"
  // MANGLING-X64-DAG: @"\01?goo@H@@UEAAPEAUG@@XZ"
  // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUB@@XZ"
  // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUC@@XZ"
};

H h;

// FIXME: Write vtordisp adjusting thunk tests