summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp19
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp41
2 files changed, 53 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index c1ea60d09a4..a8e074c7b37 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -587,14 +587,20 @@ llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualCall(
bool AvoidVirtualOffset = false;
if (isa<CXXDestructorDecl>(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<CXXDestructorDecl>(CGF.CurGD.getDecl()) ||
+ isa<CXXConstructorDecl>(CGF.CurGD.getDecl()));
const CXXRecordDecl *CurRD =
- cast<CXXDestructorDecl>(CGF.CurGD.getDecl())->getParent();
+ cast<CXXMethodDecl>(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<CXXDestructorDecl>(CGF.CurGD.getDecl()))
+ assert(CGF.CurGD.getDtorType() == Dtor_Complete);
+ if (isa<CXXConstructorDecl>(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/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp b/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp
index 383270a1f2e..c95adcd8eeb 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp
+++ b/clang/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: }
+}
OpenPOWER on IntegriCloud