From a7c8b10c35671a19f01241c1d8aff07260597dbf Mon Sep 17 00:00:00 2001 From: Timur Iskhodzhanov Date: Thu, 17 Oct 2013 09:11:45 +0000 Subject: [PATCH] Follow-up to r192822: fix Clang assertion when building with -fexceptions git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192875 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MicrosoftCXXABI.cpp | 19 ++++++--- test/CodeGenCXX/microsoft-abi-exceptions.cpp | 41 +++++++++++++++++++- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index c1ea60d09a..a8e074c7b3 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -587,14 +587,20 @@ llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualCall( bool AvoidVirtualOffset = false; if (isa(MD) && GD.getDtorType() == Dtor_Base) { // A base destructor can only be called from a complete destructor of the - // same record type or another destructor of a more derived type. + // same record type or another destructor of a more derived type; + // or a constructor of the same record type if an exception is thrown. + assert(isa(CGF.CurGD.getDecl()) || + isa(CGF.CurGD.getDecl())); const CXXRecordDecl *CurRD = - cast(CGF.CurGD.getDecl())->getParent(); + cast(CGF.CurGD.getDecl())->getParent(); if (MD->getParent() == CurRD) { - assert(CGF.CurGD.getDtorType() == Dtor_Complete); - // We're calling the main base dtor from a complete dtor, so we know the - // "this" offset statically. + if (isa(CGF.CurGD.getDecl())) + assert(CGF.CurGD.getDtorType() == Dtor_Complete); + if (isa(CGF.CurGD.getDecl())) + assert(CGF.CurGD.getCtorType() == Ctor_Complete); + // We're calling the main base dtor from a complete structor, + // so we know the "this" offset statically. AvoidVirtualOffset = true; } else { // Let's see if we try to call a destructor of a non-virtual base. @@ -604,6 +610,8 @@ llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualCall( continue; // If we call a base destructor for a non-virtual base, we statically // know where it expects the vfptr and "this" to be. + // The total offset should reflect the adjustment done by + // adjustThisParameterInVirtualFunctionPrologue(). AvoidVirtualOffset = true; break; } @@ -613,7 +621,6 @@ llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualCall( if (AvoidVirtualOffset) { const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(MD->getParent()); - // This reflects the logic from VFTableBuilder::ComputeThisOffset(). StaticOffset += Layout.getVBaseClassOffset(ML.VBase); } else { This = CGF.Builder.CreateBitCast(This, charPtrTy); diff --git a/test/CodeGenCXX/microsoft-abi-exceptions.cpp b/test/CodeGenCXX/microsoft-abi-exceptions.cpp index 383270a1f2..c95adcd8ee 100644 --- a/test/CodeGenCXX/microsoft-abi-exceptions.cpp +++ b/test/CodeGenCXX/microsoft-abi-exceptions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -cxx-abi microsoft -fexceptions | FileCheck -check-prefix WIN32 %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -cxx-abi microsoft -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s struct A { A(); @@ -116,3 +116,42 @@ int HasConditionalDeactivatedCleanups(bool cond) { // WIN32: br i1 %[[isactive]] // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) // WIN32: } + +namespace crash_on_partial_destroy { +struct A { + virtual ~A(); +}; + +struct B : virtual A { + // Has an implicit destructor. +}; + +struct C : B { + C(); +}; + +void foo(); +// We used to crash when emitting this. +C::C() { foo(); } + +// Verify that we don't bother with a vbtable lookup when adjusting the this +// pointer to call a base destructor from a constructor while unwinding. +// WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} { +// WIN32: landingpad +// +// We shouldn't do any vbptr loads, just constant GEPs. +// WIN32-NOT: load +// WIN32: getelementptr inbounds i8* %{{.*}}, i64 4 +// WIN32-NOT: load +// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"* +// WIN32: invoke x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ" +// +// WIN32-NOT: load +// WIN32: bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8* +// WIN32-NOT: load +// WIN32: getelementptr inbounds i8* %{{.*}}, i64 4 +// WIN32-NOT: load +// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"* +// WIN32: invoke x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ" +// WIN32: } +} -- 2.40.0