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