xref: /llvm-project/clang/test/CodeGenCXX/microsoft-abi-throw.cpp (revision 1b9a6e58a8b831193c9e5e733f881aabe0d2d06b)
1 // RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions | FileCheck %s
2 
3 // CHECK-DAG: @"??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { ptr @"??_7type_info@@6B@", ptr null, [8 x i8] c".?AUY@@\00" }, comdat
4 // CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, ptr @"??_R0?AUY@@@8", i32 0, i32 -1, i32 0, i32 8, ptr @"??0Y@@QAE@ABU0@@Z" }, section ".xdata", comdat
5 // CHECK-DAG: @"??_R0?AUZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { ptr @"??_7type_info@@6B@", ptr null, [8 x i8] c".?AUZ@@\00" }, comdat
6 // CHECK-DAG: @"_CT??_R0?AUZ@@@81" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, ptr @"??_R0?AUZ@@@8", i32 0, i32 -1, i32 0, i32 1, ptr null }, section ".xdata", comdat
7 // CHECK-DAG: @"??_R0?AUW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { ptr @"??_7type_info@@6B@", ptr null, [8 x i8] c".?AUW@@\00" }, comdat
8 // CHECK-DAG: @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z44" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, ptr @"??_R0?AUW@@@8", i32 4, i32 -1, i32 0, i32 4, ptr @"??0W@@QAE@ABU0@@Z" }, section ".xdata", comdat
9 // CHECK-DAG: @"??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { ptr @"??_7type_info@@6B@", ptr null, [8 x i8] c".?AUM@@\00" }, comdat
10 // CHECK-DAG: @"_CT??_R0?AUM@@@818" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, ptr @"??_R0?AUM@@@8", i32 8, i32 -1, i32 0, i32 1, ptr null }, section ".xdata", comdat
11 // CHECK-DAG: @"??_R0?AUV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { ptr @"??_7type_info@@6B@", ptr null, [8 x i8] c".?AUV@@\00" }, comdat
12 // CHECK-DAG: @"_CT??_R0?AUV@@@81044" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, ptr @"??_R0?AUV@@@8", i32 0, i32 4, i32 4, i32 1, ptr null }, section ".xdata", comdat
13 // CHECK-DAG: @"_CTA5?AUY@@" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.5 { i32 5, [5 x ptr] [ptr @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8", ptr @"_CT??_R0?AUZ@@@81", ptr @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z44", ptr @"_CT??_R0?AUM@@@818", ptr @"_CT??_R0?AUV@@@81044"] }, section ".xdata", comdat
14 // CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, ptr @"??_DY@@QAEXXZ", ptr null, ptr @"_CTA5?AUY@@" }, section ".xdata", comdat
15 // CHECK-DAG: @"_CT??_R0?AUDefault@@@8??_ODefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, ptr @"??_R0?AUDefault@@@8", i32 0, i32 -1, i32 0, i32 1, ptr @"??_ODefault@@QAEXAAU0@@Z" }, section ".xdata", comdat
16 // CHECK-DAG: @"_CT??_R0?AUDeletedCopy@@@81" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, ptr @"??_R0?AUDeletedCopy@@@8", i32 0, i32 -1, i32 0, i32 1, ptr null }, section ".xdata", comdat
17 // CHECk-DAG: @"_CT??_R0?AUMoveOnly@@@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, ptr @"??_R0?AUMoveOnly@@@8", i32 0, i321-1, i32 0, i32 4, ptr null }, section ".xdata", comda
18 // CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, ptr @"??_R0?AUVariadic@@@8", i32 0, i32 -1, i32 0, i32 1, ptr @"??_OVariadic@@QAEXAAU0@@Z" }, section ".xdata", comdat
19 // CHECK-DAG: @"_CT??_R0?AUTemplateWithDefault@@@8??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, ptr @"??_R0?AUTemplateWithDefault@@@8", i32 0, i32 -1, i32 0, i32 1, ptr @"??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z" }, section ".xdata", comdat
20 // CHECK-DAG: @"_CTA2$$T" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.2 { i32 2, [2 x ptr] [ptr @"_CT??_R0$$T@84", ptr @"_CT??_R0PAX@84"] }, section ".xdata", comdat
21 // CHECK-DAG: @"_CT??_R0P6AXXZ@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, ptr @"??_R0P6AXXZ@8", i32 0, i32 -1, i32 0, i32 4, ptr null }, section ".xdata", comdat
22 // CHECK-DAG: @_CTA1P6AXXZ = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x ptr] [ptr @"_CT??_R0P6AXXZ@84"] }, section ".xdata", comdat
23 // CHECK-DAG: @_TI1P6AXXZ = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, ptr null, ptr null, ptr @_CTA1P6AXXZ }, section ".xdata", comdat
24 // CHECK-DAG: @_TIU2PAPFAH = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 4, ptr null, ptr null, ptr @_CTA2PAPFAH }, section ".xdata", comdat
25 // CHECK-DAG: @_CTA2PAPFAH = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.2 { i32 2, [2 x ptr] [ptr @"_CT??_R0PAPFAH@84", ptr @"_CT??_R0PAX@84"] }, section ".xdata", comdat
26 // CHECK-DAG: @"_TI1?AUFoo@?A0x{{[^@]*}}@@" = internal unnamed_addr constant %eh.ThrowInfo { i32 0, ptr null, ptr null, ptr @"_CTA1?AUFoo@?A0x{{[^@]*}}@@" }, section ".xdata"
27 
28 
29 struct N { ~N(); };
30 struct M : private N {};
31 struct X {};
32 struct Z {};
33 struct V : private X {};
34 struct W : M, virtual V {};
35 struct Y : Z, W, virtual V {};
36 
f(const Y & y)37 void f(const Y &y) {
38   // CHECK-LABEL: @"?f@@YAXABUY@@@Z"
39   // CHECK: call x86_thiscallcc noundef ptr @"??0Y@@QAE@ABU0@@Z"(ptr {{[^,]*}} %[[mem:.*]], ptr
40   // CHECK: call void @_CxxThrowException(ptr %[[mem]], ptr @"_TI5?AUY@@")
41   throw y;
42 }
43 
g(const int * const * y)44 void g(const int *const *y) {
45   // CHECK-LABEL: @"?g@@YAXPBQBH@Z"
46   // CHECK: call void @_CxxThrowException(ptr %{{.*}}, ptr @_TIC2PAPBH)
47   throw y;
48 }
49 
h(__unaligned int * __unaligned * y)50 void h(__unaligned int * __unaligned *y) {
51   // CHECK-LABEL: @"?h@@YAXPFAPFAH@Z"
52   // CHECK: call void @_CxxThrowException(ptr %{{.*}}, ptr @_TIU2PAPFAH)
53   throw y;
54 }
55 
56 struct Default {
57   Default(Default &, int = 42);
58 };
59 
60 // CHECK-LABEL: @"??_ODefault@@QAEXAAU0@@Z"
61 // CHECK: %[[src_addr:.*]] = alloca
62 // CHECK: %[[this_addr:.*]] = alloca
63 // CHECK: store {{.*}} %src, {{.*}} %[[src_addr]], align 4
64 // CHECK: store {{.*}} %this, {{.*}} %[[this_addr]], align 4
65 // CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]]
66 // CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]]
67 // CHECK: call x86_thiscallcc {{.*}} @"??0Default@@QAE@AAU0@H@Z"({{.*}} %[[this]], {{.*}} %[[src]], i32 noundef 42)
68 // CHECK: ret void
69 
h(Default & d)70 void h(Default &d) {
71   throw d;
72 }
73 
74 struct DeletedCopy {
75   DeletedCopy();
76   DeletedCopy(DeletedCopy &&);
77   DeletedCopy(const DeletedCopy &) = delete;
78 };
throwDeletedCopy()79 void throwDeletedCopy() { throw DeletedCopy(); }
80 
81 
82 struct MoveOnly {
83   MoveOnly();
84   MoveOnly(MoveOnly &&);
85   ~MoveOnly();
86   MoveOnly(const MoveOnly &) = delete;
87 
88   // For some reason this subobject was important for reproducing PR43680
89   struct HasCopy {
90     HasCopy();
91     HasCopy(const HasCopy &o);
92     ~HasCopy();
93     int x;
94   } sub;
95 };
96 
throwMoveOnly()97 void throwMoveOnly() { throw MoveOnly(); }
98 
99 struct Variadic {
100   Variadic(Variadic &, ...);
101 };
102 
i(Variadic & v)103 void i(Variadic &v) {
104   throw v;
105 }
106 
107 // CHECK-LABEL: @"??_OVariadic@@QAEXAAU0@@Z"
108 // CHECK:  %[[src_addr:.*]] = alloca
109 // CHECK:  %[[this_addr:.*]] = alloca
110 // CHECK:  store {{.*}} %src, {{.*}} %[[src_addr:.*]], align
111 // CHECK:  store {{.*}} %this, {{.*}} %[[this_addr:.*]], align
112 // CHECK:  %[[this:.*]] = load {{.*}} %[[this_addr]]
113 // CHECK:  %[[src:.*]] = load {{.*}} %[[src_addr]]
114 // CHECK:  call {{.*}} @"??0Variadic@@QAA@AAU0@ZZ"({{.*}} %[[this]], {{.*}} %[[src]])
115 // CHECK:  ret void
116 
117 struct TemplateWithDefault {
118   template <typename T>
fTemplateWithDefault119   static int f() {
120     return 0;
121   }
122   template <typename T = int>
123   TemplateWithDefault(TemplateWithDefault &, T = f<T>());
124 };
125 
j(TemplateWithDefault & twd)126 void j(TemplateWithDefault &twd) {
127   throw twd;
128 }
129 
130 
h()131 void h() {
132   throw nullptr;
133 }
134 
135 namespace std {
136 template <typename T>
137 void *__GetExceptionInfo(T);
138 }
139 using namespace std;
140 
GetExceptionInfo_test0()141 void *GetExceptionInfo_test0() {
142 // CHECK-LABEL: @"?GetExceptionInfo_test0@@YAPAXXZ"
143 // CHECK:  ret ptr @_TI1H
144   return __GetExceptionInfo(0);
145 }
146 
GetExceptionInfo_test1()147 void *GetExceptionInfo_test1() {
148 // CHECK-LABEL: @"?GetExceptionInfo_test1@@YAPAXXZ"
149 // CHECK:  ret ptr @_TI1P6AXXZ
150   return __GetExceptionInfo<void (*)()>(&h);
151 }
152 
153 // PR36327: Try an exception type with no linkage.
154 namespace { struct Foo { } foo_exc; }
155 
GetExceptionInfo_test2()156 void *GetExceptionInfo_test2() {
157 // CHECK-LABEL: @"?GetExceptionInfo_test2@@YAPAXXZ"
158 // CHECK:  ret ptr @"_TI1?AUFoo@?A0x{{[^@]*}}@@"
159   return __GetExceptionInfo(foo_exc);
160 }
161