]> granicus.if.org Git - clang/commitdiff
Follow-up to r192822: fix Clang assertion when building with -fexceptions
authorTimur Iskhodzhanov <timurrrr@google.com>
Thu, 17 Oct 2013 09:11:45 +0000 (09:11 +0000)
committerTimur Iskhodzhanov <timurrrr@google.com>
Thu, 17 Oct 2013 09:11:45 +0000 (09:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192875 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/MicrosoftCXXABI.cpp
test/CodeGenCXX/microsoft-abi-exceptions.cpp

index c1ea60d09a4b2c5bdc1b89ef039520713df12dfe..a8e074c7b379e05f62b79439f0ec2c2e3bca1b5d 100644 (file)
@@ -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);
index 383270a1f2eb5c0740f9ea99651888a44b881a26..c95adcd8eebc439f15a47daea7b9d46ff0e78800 100644 (file)
@@ -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: }
+}