forked from OSchip/llvm-project
[MS ABI] Correctly mangling vbase destructors
They are a little bit of a special case in the mangling. They are always mangled without taking into account their virtual-ness of the destructor. They are also mangled to return void, unlike the actual destructor. This fixes PR31931. Differential Revision: https://reviews.llvm.org/D29912 llvm-svn: 295010
This commit is contained in:
parent
d96089b248
commit
dc169759ca
|
@ -1890,15 +1890,19 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
|
||||||
// <return-type> ::= <type>
|
// <return-type> ::= <type>
|
||||||
// ::= @ # structors (they have no declared return type)
|
// ::= @ # structors (they have no declared return type)
|
||||||
if (IsStructor) {
|
if (IsStructor) {
|
||||||
if (isa<CXXDestructorDecl>(D) && isStructorDecl(D) &&
|
if (isa<CXXDestructorDecl>(D) && isStructorDecl(D)) {
|
||||||
StructorType == Dtor_Deleting) {
|
// The scalar deleting destructor takes an extra int argument which is not
|
||||||
// The scalar deleting destructor takes an extra int argument.
|
// reflected in the AST.
|
||||||
// However, the FunctionType generated has 0 arguments.
|
if (StructorType == Dtor_Deleting) {
|
||||||
// FIXME: This is a temporary hack.
|
|
||||||
// Maybe should fix the FunctionType creation instead?
|
|
||||||
Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z");
|
Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// The vbase destructor returns void which is not reflected in the AST.
|
||||||
|
if (StructorType == Dtor_Complete) {
|
||||||
|
Out << "XXZ";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (IsCtorClosure) {
|
if (IsCtorClosure) {
|
||||||
// Default constructor closure and copy constructor closure both return
|
// Default constructor closure and copy constructor closure both return
|
||||||
// void.
|
// void.
|
||||||
|
@ -2005,13 +2009,20 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
|
||||||
// <global-function> ::= Y # global near
|
// <global-function> ::= Y # global near
|
||||||
// ::= Z # global far
|
// ::= Z # global far
|
||||||
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
|
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
|
||||||
|
bool IsVirtual = MD->isVirtual();
|
||||||
|
// When mangling vbase destructor variants, ignore whether or not the
|
||||||
|
// underlying destructor was defined to be virtual.
|
||||||
|
if (isa<CXXDestructorDecl>(MD) && isStructorDecl(MD) &&
|
||||||
|
StructorType == Dtor_Complete) {
|
||||||
|
IsVirtual = false;
|
||||||
|
}
|
||||||
switch (MD->getAccess()) {
|
switch (MD->getAccess()) {
|
||||||
case AS_none:
|
case AS_none:
|
||||||
llvm_unreachable("Unsupported access specifier");
|
llvm_unreachable("Unsupported access specifier");
|
||||||
case AS_private:
|
case AS_private:
|
||||||
if (MD->isStatic())
|
if (MD->isStatic())
|
||||||
Out << 'C';
|
Out << 'C';
|
||||||
else if (MD->isVirtual())
|
else if (IsVirtual)
|
||||||
Out << 'E';
|
Out << 'E';
|
||||||
else
|
else
|
||||||
Out << 'A';
|
Out << 'A';
|
||||||
|
@ -2019,7 +2030,7 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
|
||||||
case AS_protected:
|
case AS_protected:
|
||||||
if (MD->isStatic())
|
if (MD->isStatic())
|
||||||
Out << 'K';
|
Out << 'K';
|
||||||
else if (MD->isVirtual())
|
else if (IsVirtual)
|
||||||
Out << 'M';
|
Out << 'M';
|
||||||
else
|
else
|
||||||
Out << 'I';
|
Out << 'I';
|
||||||
|
@ -2027,7 +2038,7 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
|
||||||
case AS_public:
|
case AS_public:
|
||||||
if (MD->isStatic())
|
if (MD->isStatic())
|
||||||
Out << 'S';
|
Out << 'S';
|
||||||
else if (MD->isVirtual())
|
else if (IsVirtual)
|
||||||
Out << 'U';
|
Out << 'U';
|
||||||
else
|
else
|
||||||
Out << 'Q';
|
Out << 'Q';
|
||||||
|
|
|
@ -5,10 +5,10 @@ struct __declspec(dllexport) T { virtual ~T(); };
|
||||||
struct __declspec(dllexport) U : S, T { virtual ~U(); };
|
struct __declspec(dllexport) U : S, T { virtual ~U(); };
|
||||||
|
|
||||||
// CHECK-LABEL: define {{.*}} @"\01??_GS@@UAEPAXI@Z"
|
// CHECK-LABEL: define {{.*}} @"\01??_GS@@UAEPAXI@Z"
|
||||||
// CHECK: call x86_thiscallcc void @"\01??_DS@@UAE@XZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}}
|
// CHECK: call x86_thiscallcc void @"\01??_DS@@QAEXXZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}}
|
||||||
|
|
||||||
// CHECK-LABEL: define {{.*}} @"\01??_GT@@UAEPAXI@Z"
|
// CHECK-LABEL: define {{.*}} @"\01??_GT@@UAEPAXI@Z"
|
||||||
// CHECK: call x86_thiscallcc void @"\01??_DT@@UAE@XZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}}
|
// CHECK: call x86_thiscallcc void @"\01??_DT@@QAEXXZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}}
|
||||||
|
|
||||||
// CHECK-LABEL: define {{.*}} @"\01??_GU@@UAEPAXI@Z"
|
// CHECK-LABEL: define {{.*}} @"\01??_GU@@UAEPAXI@Z"
|
||||||
// CHECK: call x86_thiscallcc void @"\01??_DU@@UAE@XZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}}
|
// CHECK: call x86_thiscallcc void @"\01??_DU@@QAEXXZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}}
|
||||||
|
|
|
@ -55,12 +55,12 @@ void test_cleanup() {
|
||||||
// CHECK: to label %[[LEAVE_FUNC:.*]] unwind label %[[CLEANUP:.*]]
|
// CHECK: to label %[[LEAVE_FUNC:.*]] unwind label %[[CLEANUP:.*]]
|
||||||
|
|
||||||
// CHECK: [[LEAVE_FUNC]]
|
// CHECK: [[LEAVE_FUNC]]
|
||||||
// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"(
|
// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAEXXZ"(
|
||||||
// CHECK: ret void
|
// CHECK: ret void
|
||||||
|
|
||||||
// CHECK: [[CLEANUP]]
|
// CHECK: [[CLEANUP]]
|
||||||
// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none []
|
// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none []
|
||||||
// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"(
|
// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAEXXZ"(
|
||||||
// CHECK: cleanupret from %[[CLEANUPPAD]] unwind to caller
|
// CHECK: cleanupret from %[[CLEANUPPAD]] unwind to caller
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ namespace inalloca_nonvirt {
|
||||||
// WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
|
// WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
|
||||||
// WIN32: call void @llvm.stackrestore(
|
// WIN32: call void @llvm.stackrestore(
|
||||||
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
||||||
// WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"(
|
// WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
|
||||||
|
|
||||||
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
|
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
|
||||||
// support that in the non-inlined case, so we force inlining.
|
// support that in the non-inlined case, so we force inlining.
|
||||||
|
@ -150,7 +150,7 @@ namespace inalloca_nonvirt {
|
||||||
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
||||||
// WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
|
// WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
|
||||||
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
||||||
// WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]])
|
// WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
|
||||||
|
|
||||||
struct C : B { using B::B; };
|
struct C : B { using B::B; };
|
||||||
C c(1, 2, 3, 4);
|
C c(1, 2, 3, 4);
|
||||||
|
@ -173,7 +173,7 @@ namespace inalloca_nonvirt {
|
||||||
// WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
|
// WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
|
||||||
// WIN32: call void @llvm.stackrestore(
|
// WIN32: call void @llvm.stackrestore(
|
||||||
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
||||||
// WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"(
|
// WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
|
||||||
|
|
||||||
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
|
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
|
||||||
// support that in the non-inlined case, so we force inlining.
|
// support that in the non-inlined case, so we force inlining.
|
||||||
|
@ -186,7 +186,7 @@ namespace inalloca_nonvirt {
|
||||||
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
||||||
// WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
|
// WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]])
|
||||||
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
||||||
// WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]])
|
// WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace inalloca_virt {
|
namespace inalloca_virt {
|
||||||
|
@ -224,7 +224,7 @@ namespace inalloca_virt {
|
||||||
// destroy the parameters, but that's not actually possible.
|
// destroy the parameters, but that's not actually possible.
|
||||||
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
||||||
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
||||||
// WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"(
|
// WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
|
||||||
|
|
||||||
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
|
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
|
||||||
// support that in the non-inlined case, so we force inlining.
|
// support that in the non-inlined case, so we force inlining.
|
||||||
|
@ -239,7 +239,7 @@ namespace inalloca_virt {
|
||||||
// WIN64: br
|
// WIN64: br
|
||||||
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
||||||
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
||||||
// WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]])
|
// WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
|
||||||
|
|
||||||
struct C : B { using B::B; };
|
struct C : B { using B::B; };
|
||||||
C c(1, 2, 3, 4);
|
C c(1, 2, 3, 4);
|
||||||
|
@ -281,7 +281,7 @@ namespace inalloca_virt {
|
||||||
//
|
//
|
||||||
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
||||||
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
// WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"(
|
||||||
// WIN32: call {{.*}} @"\01??_DQ@@QAE@XZ"(
|
// WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"(
|
||||||
|
|
||||||
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
|
// On Win64, the Q arguments would be destroyed in the callee. We don't yet
|
||||||
// support that in the non-inlined case, so we force inlining.
|
// support that in the non-inlined case, so we force inlining.
|
||||||
|
@ -301,7 +301,7 @@ namespace inalloca_virt {
|
||||||
// WIN64: br
|
// WIN64: br
|
||||||
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
||||||
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
// WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"(
|
||||||
// WIN64: call void @"\01??_DQ@@QEAA@XZ"({{.*}}* %[[TMP]])
|
// WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]])
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace inline_nonvirt {
|
namespace inline_nonvirt {
|
||||||
|
|
|
@ -138,6 +138,6 @@ S3 *f(S2 &s) {
|
||||||
// CHECK: [[CALL:%.*]] = invoke i8* @__RTDynamicCast
|
// CHECK: [[CALL:%.*]] = invoke i8* @__RTDynamicCast
|
||||||
|
|
||||||
// CHECK: [[BC:%.*]] = bitcast i8* [[CALL]] to %"struct.PR25606::S3"*
|
// CHECK: [[BC:%.*]] = bitcast i8* [[CALL]] to %"struct.PR25606::S3"*
|
||||||
// CHECK: call x86_thiscallcc void @"\01??_DCleanup@PR25606@@QAE@XZ"(
|
// CHECK: call x86_thiscallcc void @"\01??_DCleanup@PR25606@@QAEXXZ"(
|
||||||
// CHECK: ret %"struct.PR25606::S3"* [[BC]]
|
// CHECK: ret %"struct.PR25606::S3"* [[BC]]
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,7 +207,7 @@ F::~F() {
|
||||||
void foo() {
|
void foo() {
|
||||||
F f;
|
F f;
|
||||||
}
|
}
|
||||||
// DTORS3-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DF@test2@@UAE@XZ"({{.*}} {{.*}} comdat
|
// DTORS3-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DF@test2@@QAEXXZ"({{.*}} {{.*}} comdat
|
||||||
// Do an adjustment from C* to F*.
|
// Do an adjustment from C* to F*.
|
||||||
// DTORS3: getelementptr i8, i8* %{{.*}}, i32 20
|
// DTORS3: getelementptr i8, i8* %{{.*}}, i32 20
|
||||||
// DTORS3: bitcast i8* %{{.*}} to %"struct.test2::F"*
|
// DTORS3: bitcast i8* %{{.*}} to %"struct.test2::F"*
|
||||||
|
@ -361,12 +361,12 @@ struct D : B, C { ~D(); };
|
||||||
void call_vbase_complete(D *d) {
|
void call_vbase_complete(D *d) {
|
||||||
d->~D();
|
d->~D();
|
||||||
// CHECK: define void @"\01?call_vbase_complete@dtors@@YAXPAUD@1@@Z"
|
// CHECK: define void @"\01?call_vbase_complete@dtors@@YAXPAUD@1@@Z"
|
||||||
// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}})
|
// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
|
||||||
// CHECK: ret
|
// CHECK: ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// The complete dtor should call the base dtors for D and the vbase A (once).
|
// The complete dtor should call the base dtors for D and the vbase A (once).
|
||||||
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"({{.*}}) {{.*}} comdat
|
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"({{.*}}) {{.*}} comdat
|
||||||
// CHECK-NOT: call
|
// CHECK-NOT: call
|
||||||
// CHECK: call x86_thiscallcc void @"\01??1D@dtors@@QAE@XZ"
|
// CHECK: call x86_thiscallcc void @"\01??1D@dtors@@QAE@XZ"
|
||||||
// CHECK-NOT: call
|
// CHECK-NOT: call
|
||||||
|
@ -377,7 +377,7 @@ void call_vbase_complete(D *d) {
|
||||||
void destroy_d_complete() {
|
void destroy_d_complete() {
|
||||||
D d;
|
D d;
|
||||||
// CHECK: define void @"\01?destroy_d_complete@dtors@@YAXXZ"
|
// CHECK: define void @"\01?destroy_d_complete@dtors@@YAXXZ"
|
||||||
// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}})
|
// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
|
||||||
// CHECK: ret
|
// CHECK: ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +387,7 @@ void destroy_d_complete() {
|
||||||
void call_nv_deleting_dtor(D *d) {
|
void call_nv_deleting_dtor(D *d) {
|
||||||
delete d;
|
delete d;
|
||||||
// CHECK: define void @"\01?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z"
|
// CHECK: define void @"\01?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z"
|
||||||
// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}})
|
// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAEXXZ"(%"struct.dtors::D"* %{{[^,]+}})
|
||||||
// CHECK: call void @"\01??3@YAXPAX@Z"
|
// CHECK: call void @"\01??3@YAXPAX@Z"
|
||||||
// CHECK: ret
|
// CHECK: ret
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// CHECK-DAG: @"\01??_R0?AUV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUV@@\00" }, comdat
|
// CHECK-DAG: @"\01??_R0?AUV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_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* @"\01??_R0?AUV@@@8" to i8*), i32 0, i32 4, i32 4, i32 1, i8* null }, section ".xdata", comdat
|
// CHECK-DAG: @"_CT??_R0?AUV@@@81044" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_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: @"_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*)* @"\01??_DY@@QAE@XZ" to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" to i8*) }, section ".xdata", comdat
|
// CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"\01??_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* @"\01??_R0?AUDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Default*, %struct.Default*)* @"\01??_ODefault@@QAEXAAU0@@Z" 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* @"\01??_R0?AUDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Default*, %struct.Default*)* @"\01??_ODefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
|
||||||
// CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor14* @"\01??_R0?AUVariadic@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Variadic*, %struct.Variadic*)* @"\01??_OVariadic@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
|
// CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor14* @"\01??_R0?AUVariadic@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Variadic*, %struct.Variadic*)* @"\01??_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* @"\01??_R0?AUTemplateWithDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.TemplateWithDefault*, %struct.TemplateWithDefault*)* @"\01??$?_OH@TemplateWithDefault@@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* @"\01??_R0?AUTemplateWithDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.TemplateWithDefault*, %struct.TemplateWithDefault*)* @"\01??$?_OH@TemplateWithDefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
|
||||||
|
|
|
@ -84,7 +84,7 @@ B::~B() {
|
||||||
|
|
||||||
// CHECK: ret
|
// CHECK: ret
|
||||||
|
|
||||||
// CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DB@@UAE@XZ"(%struct.B*
|
// CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B*
|
||||||
// CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** {{.*}}
|
// CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** {{.*}}
|
||||||
// CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
|
// CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
|
||||||
// CHECK2: %[[B_i8:.*]] = getelementptr i8, i8* %[[THIS_i8]], i32 8
|
// CHECK2: %[[B_i8:.*]] = getelementptr i8, i8* %[[THIS_i8]], i32 8
|
||||||
|
@ -102,7 +102,7 @@ B::~B() {
|
||||||
// CHECK2: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
|
// CHECK2: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
|
||||||
// CHECK2: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4
|
// CHECK2: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4
|
||||||
// CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
|
// CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
|
||||||
// CHECK2: call x86_thiscallcc void @"\01??_DB@@UAE@XZ"(%struct.B* %[[THIS]])
|
// CHECK2: call x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B* %[[THIS]])
|
||||||
// ...
|
// ...
|
||||||
// CHECK2: ret
|
// CHECK2: ret
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ void call_complete_dtor() {
|
||||||
B b;
|
B b;
|
||||||
// CHECK: call x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"(%struct.B* %[[B:.*]], i32 1)
|
// CHECK: call x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"(%struct.B* %[[B:.*]], i32 1)
|
||||||
// CHECK-NOT: getelementptr
|
// CHECK-NOT: getelementptr
|
||||||
// CHECK: call x86_thiscallcc void @"\01??_DB@@UAE@XZ"(%struct.B* %[[B]])
|
// CHECK: call x86_thiscallcc void @"\01??_DB@@QAEXXZ"(%struct.B* %[[B]])
|
||||||
// CHECK: ret
|
// CHECK: ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,8 @@ public:
|
||||||
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD2Ev
|
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD2Ev
|
||||||
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD1Ev
|
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD1Ev
|
||||||
// Windows ignores calling convention on constructor/destructors.
|
// Windows ignores calling convention on constructor/destructors.
|
||||||
// CHECK-WIN64-DAG: define linkonce_odr void @"\01??_Dtest_class@@QEAA@XZ"
|
// CHECK-WIN64-DAG: define linkonce_odr void @"\01??_Dtest_class@@QEAAXXZ"
|
||||||
// CHECK-WIN32-DAG: define linkonce_odr x86_thiscallcc void @"\01??_Dtest_class@@QAE@XZ"
|
// CHECK-WIN32-DAG: define linkonce_odr x86_thiscallcc void @"\01??_Dtest_class@@QAEXXZ"
|
||||||
|
|
||||||
test_class& __regcall operator+=(const test_class&){
|
test_class& __regcall operator+=(const test_class&){
|
||||||
return *this;
|
return *this;
|
||||||
|
|
Loading…
Reference in New Issue