]> granicus.if.org Git - clang/commitdiff
More support for virtual destructor calls.
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 30 Nov 2009 22:07:18 +0000 (22:07 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 30 Nov 2009 22:07:18 +0000 (22:07 +0000)
Fixes pr5619

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90158 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXX.cpp

index 437fed7478af51c869497547ca22dad9f59c0473..34d1c8d984a1a7625de917a8ee60ec171f14d8a9 100644 (file)
@@ -603,16 +603,7 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
   Counter = Builder.CreateLoad(IndexPtr);
   Counter = Builder.CreateSub(Counter, One);
   llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx");
-  if (D->isVirtual()) {
-    const llvm::Type *Ty =
-      CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(D),
-                                     /*isVariadic=*/false);
-    
-    llvm::Value *Callee = BuildVirtualCall(D, Dtor_Deleting, Address, Ty);
-    EmitCXXMemberCall(D, Callee, Address, 0, 0);
-  }
-  else
-    EmitCXXDestructorCall(D, Dtor_Complete, Address);
+  EmitCXXDestructorCall(D, Dtor_Complete, Address);
 
   EmitBlock(ContinueBlock);
 
@@ -703,6 +694,15 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
 void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *D,
                                             CXXDtorType Type,
                                             llvm::Value *This) {
+  if (D->isVirtual()) {
+    const llvm::Type *Ty =
+      CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(D),
+                                     /*isVariadic=*/false);
+    
+    llvm::Value *Callee = BuildVirtualCall(D, Dtor_Deleting, This, Ty);
+    EmitCXXMemberCall(D, Callee, This, 0, 0);
+    return;
+  }
   llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(D, Type);
 
   EmitCXXMemberCall(D, Callee, This, 0, 0);
@@ -1777,12 +1777,12 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
     // Ignore trivial destructors.
     if (BaseClassDecl->hasTrivialDestructor())
       continue;
-
+    const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext());
+    
     llvm::Value *V = GetAddressOfBaseClass(LoadCXXThis(),
                                            ClassDecl, BaseClassDecl, 
                                            /*NullCheckValue=*/false);
-    EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()),
-                          Dtor_Base, V);
+    EmitCXXDestructorCall(D, Dtor_Base, V);
   }
 
   // If we're emitting a base destructor, we don't want to emit calls to the
@@ -1790,10 +1790,21 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
   if (DtorType == Dtor_Base)
     return;
   
-  // FIXME: Handle virtual bases.
+  // Handle virtual bases.
   for (CXXRecordDecl::reverse_base_class_const_iterator I = 
        ClassDecl->vbases_rbegin(), E = ClassDecl->vbases_rend(); I != E; ++I) {
-    assert(false && "FIXME: Handle virtual bases.");
+    const CXXBaseSpecifier &Base = *I;
+    CXXRecordDecl *BaseClassDecl
+    = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
+    
+    // Ignore trivial destructors.
+    if (BaseClassDecl->hasTrivialDestructor())
+      continue;
+    const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext());
+    llvm::Value *V = GetAddressOfBaseClass(LoadCXXThis(),
+                                           ClassDecl, BaseClassDecl, 
+                                           /*NullCheckValue=*/false);
+    EmitCXXDestructorCall(D, Dtor_Base, V);
   }
     
   // If we have a deleting destructor, emit a call to the delete operator.