When throwing objects with deleted copy constructors, the copy ctor field of the catchable type should remain null and the mangle name changes. This already worked in simple cases, but in cases involving non-trivial subobjects, sometimes LookupCopyingConstructor could return a non-null but deleted constructor decl. Skip those and don't reference them. Fixes PR43680
168 lines
9.3 KiB
C++
168 lines
9.3 KiB
C++
// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions | FileCheck %s
|
|
// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions -DSTD | FileCheck %s
|
|
|
|
// CHECK-DAG: @"??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat
|
|
// 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
|
|
// CHECK-DAG: @"??_R0?AUZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUZ@@\00" }, comdat
|
|
// 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
|
|
// CHECK-DAG: @"??_R0?AUW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUW@@\00" }, comdat
|
|
// 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
|
|
// CHECK-DAG: @"??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }, comdat
|
|
// 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
|
|
// CHECK-DAG: @"??_R0?AUV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUV@@\00" }, comdat
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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
|
|
// 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"
|
|
|
|
|
|
struct N { ~N(); };
|
|
struct M : private N {};
|
|
struct X {};
|
|
struct Z {};
|
|
struct V : private X {};
|
|
struct W : M, virtual V {};
|
|
struct Y : Z, W, virtual V {};
|
|
|
|
void f(const Y &y) {
|
|
// CHECK-LABEL: @"?f@@YAXABUY@@@Z"
|
|
// CHECK: call x86_thiscallcc %struct.Y* @"??0Y@@QAE@ABU0@@Z"(%struct.Y* %[[mem:.*]], %struct.Y*
|
|
// CHECK: %[[cast:.*]] = bitcast %struct.Y* %[[mem]] to i8*
|
|
// CHECK: call void @_CxxThrowException(i8* %[[cast]], %eh.ThrowInfo* @"_TI5?AUY@@")
|
|
throw y;
|
|
}
|
|
|
|
void g(const int *const *y) {
|
|
// CHECK-LABEL: @"?g@@YAXPBQBH@Z"
|
|
// CHECK: call void @_CxxThrowException(i8* %{{.*}}, %eh.ThrowInfo* @_TIC2PAPBH)
|
|
throw y;
|
|
}
|
|
|
|
void h(__unaligned int * __unaligned *y) {
|
|
// CHECK-LABEL: @"?h@@YAXPFAPFAH@Z"
|
|
// CHECK: call void @_CxxThrowException(i8* %{{.*}}, %eh.ThrowInfo* @_TIU2PAPFAH)
|
|
throw y;
|
|
}
|
|
|
|
struct Default {
|
|
Default(Default &, int = 42);
|
|
};
|
|
|
|
// CHECK-LABEL: @"??_ODefault@@QAEXAAU0@@Z"
|
|
// CHECK: %[[src_addr:.*]] = alloca
|
|
// CHECK: %[[this_addr:.*]] = alloca
|
|
// CHECK: store {{.*}} %src, {{.*}} %[[src_addr]], align 4
|
|
// CHECK: store {{.*}} %this, {{.*}} %[[this_addr]], align 4
|
|
// CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]]
|
|
// CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]]
|
|
// CHECK: call x86_thiscallcc {{.*}} @"??0Default@@QAE@AAU0@H@Z"({{.*}} %[[this]], {{.*}} %[[src]], i32 42)
|
|
// CHECK: ret void
|
|
|
|
void h(Default &d) {
|
|
throw d;
|
|
}
|
|
|
|
struct DeletedCopy {
|
|
DeletedCopy();
|
|
DeletedCopy(DeletedCopy &&);
|
|
DeletedCopy(const DeletedCopy &) = delete;
|
|
};
|
|
void throwDeletedCopy() { throw DeletedCopy(); }
|
|
|
|
|
|
struct MoveOnly {
|
|
MoveOnly();
|
|
MoveOnly(MoveOnly &&);
|
|
~MoveOnly();
|
|
MoveOnly(const MoveOnly &) = delete;
|
|
|
|
// For some reason this subobject was important for reproducing PR43680
|
|
struct HasCopy {
|
|
HasCopy();
|
|
HasCopy(const HasCopy &o);
|
|
~HasCopy();
|
|
int x;
|
|
} sub;
|
|
};
|
|
|
|
void throwMoveOnly() { throw MoveOnly(); }
|
|
|
|
struct Variadic {
|
|
Variadic(Variadic &, ...);
|
|
};
|
|
|
|
void i(Variadic &v) {
|
|
throw v;
|
|
}
|
|
|
|
// CHECK-LABEL: @"??_OVariadic@@QAEXAAU0@@Z"
|
|
// CHECK: %[[src_addr:.*]] = alloca
|
|
// CHECK: %[[this_addr:.*]] = alloca
|
|
// CHECK: store {{.*}} %src, {{.*}} %[[src_addr:.*]], align
|
|
// CHECK: store {{.*}} %this, {{.*}} %[[this_addr:.*]], align
|
|
// CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]]
|
|
// CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]]
|
|
// CHECK: call {{.*}} @"??0Variadic@@QAA@AAU0@ZZ"({{.*}} %[[this]], {{.*}} %[[src]])
|
|
// CHECK: ret void
|
|
|
|
struct TemplateWithDefault {
|
|
template <typename T>
|
|
static int f() {
|
|
return 0;
|
|
}
|
|
template <typename T = int>
|
|
TemplateWithDefault(TemplateWithDefault &, T = f<T>());
|
|
};
|
|
|
|
void j(TemplateWithDefault &twd) {
|
|
throw twd;
|
|
}
|
|
|
|
|
|
void h() {
|
|
throw nullptr;
|
|
}
|
|
|
|
#ifdef STD
|
|
namespace std {
|
|
template <typename T>
|
|
void *__GetExceptionInfo(T);
|
|
}
|
|
#else
|
|
template <typename T>
|
|
void *__GetExceptionInfo(T);
|
|
#endif
|
|
using namespace std;
|
|
|
|
void *GetExceptionInfo_test0() {
|
|
// CHECK-LABEL: @"?GetExceptionInfo_test0@@YAPAXXZ"
|
|
// CHECK: ret i8* bitcast (%eh.ThrowInfo* @_TI1H to i8*)
|
|
return __GetExceptionInfo(0);
|
|
}
|
|
|
|
void *GetExceptionInfo_test1() {
|
|
// CHECK-LABEL: @"?GetExceptionInfo_test1@@YAPAXXZ"
|
|
// CHECK: ret i8* bitcast (%eh.ThrowInfo* @_TI1P6AXXZ to i8*)
|
|
return __GetExceptionInfo<void (*)()>(&h);
|
|
}
|
|
|
|
// PR36327: Try an exception type with no linkage.
|
|
namespace { struct Foo { } foo_exc; }
|
|
|
|
void *GetExceptionInfo_test2() {
|
|
// CHECK-LABEL: @"?GetExceptionInfo_test2@@YAPAXXZ"
|
|
// CHECK: ret i8* bitcast (%eh.ThrowInfo* @"_TI1?AUFoo@?A0x{{[^@]*}}@@" to i8*)
|
|
return __GetExceptionInfo(foo_exc);
|
|
}
|