diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 5947fd7ebf1f..08921b9628cc 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -165,6 +165,9 @@ class MicrosoftCXXABI : public CGCXXABI { llvm::BasicBlock * EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, const CXXRecordDecl *RD) override; + + llvm::BasicBlock * + EmitDtorCompleteObjectHandler(CodeGenFunction &CGF); void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF, const CXXRecordDecl *RD) override; @@ -1135,6 +1138,25 @@ MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, return SkipVbaseCtorsBB; } +llvm::BasicBlock * +MicrosoftCXXABI::EmitDtorCompleteObjectHandler(CodeGenFunction &CGF) { + llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF); + assert(IsMostDerivedClass && + "ctor for a class with virtual bases must have an implicit parameter"); + llvm::Value *IsCompleteObject = + CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object"); + + llvm::BasicBlock *CallVbaseDtorsBB = CGF.createBasicBlock("Dtor.dtor_vbases"); + llvm::BasicBlock *SkipVbaseDtorsBB = CGF.createBasicBlock("Dtor.skip_vbases"); + CGF.Builder.CreateCondBr(IsCompleteObject, + CallVbaseDtorsBB, SkipVbaseDtorsBB); + + CGF.EmitBlock(CallVbaseDtorsBB); + // CGF will put the base dtor calls in this basic block for us later. + + return SkipVbaseDtorsBB; +} + void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers( CodeGenFunction &CGF, const CXXRecordDecl *RD) { // In most cases, an override for a vbase virtual method can adjust @@ -1512,11 +1534,21 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, This = adjustThisArgumentForVirtualFunctionCall(CGF, GlobalDecl(DD, Type), This, false); } + + llvm::BasicBlock *BaseDtorEndBB = nullptr; + if (ForVirtualBase && isa(CGF.CurCodeDecl)) { + BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF); + } CGF.EmitCXXDestructorCall(DD, Callee, This.getPointer(), /*ImplicitParam=*/nullptr, /*ImplicitParamTy=*/QualType(), nullptr, getFromDtorType(Type)); + if (BaseDtorEndBB) { + // Complete object handler should continue to be the remaining + CGF.Builder.CreateBr(BaseDtorEndBB); + CGF.EmitBlock(BaseDtorEndBB); + } } void MicrosoftCXXABI::emitVTableTypeMetadata(const VPtrInfo &Info, diff --git a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp index 004dc45652e4..61cb3f48913e 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -278,3 +278,38 @@ void f() { // WIN32-LIFETIME: %[[bc2:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8* // WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc2]]) } + +struct class_2 { + class_2(); + virtual ~class_2(); +}; +struct class_1 : virtual class_2 { + class_1(){throw "Unhandled exception";} + virtual ~class_1() {} +}; +struct class_0 : class_1 { + class_0() ; + virtual ~class_0() {} +}; + +class_0::class_0() { + // WIN32: define x86_thiscallcc %struct.class_0* @"\01??0class_0@@QAE@XZ"(%struct.class_0* returned %this, i32 %is_most_derived) + // WIN32: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4 + // WIN32: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]] + // WIN32: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0 + // WIN32: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] + // WIN32: [[INIT_VBASES]] + // WIN32: br label %[[SKIP_VBASES]] + // WIN32: [[SKIP_VBASES]] +// ehcleanup: + // WIN32: %[[CLEANUPPAD:.*]] = cleanuppad within none [] + // WIN32-NEXT: bitcast %{{.*}}* %{{.*}} to i8* + // WIN32-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i{{.*}} {{.}} + // WIN32-NEXT: bitcast i8* %{{.*}} to %{{.*}}* + // WIN32-NEXT: %[[SHOULD_CALL_VBASE_DTOR:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0 + // WIN32-NEXT: br i1 %[[SHOULD_CALL_VBASE_DTOR]], label %[[DTOR_VBASE:.*]], label %[[SKIP_VBASE:.*]] + // WIN32: [[DTOR_VBASE]] + // WIN32-NEXT: call x86_thiscallcc void @"\01??1class_2@@UAE@XZ" + // WIN32: br label %[[SKIP_VBASE]] + // WIN32: [[SKIP_VBASE]] +}