Patch to instantiate destructors used to destruct
base and data members when they are needed.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80967 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 075c945..e5a4c6f 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1284,6 +1284,81 @@
   }
 }
 
+void
+Sema::computeBaseOrMembersToDestroy(CXXDestructorDecl *Destructor) {
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext());
+  llvm::SmallVector<uintptr_t, 32> AllToDestruct;
+  
+  for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
+       E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+    if (VBase->getType()->isDependentType())
+      continue;
+    // Skip over virtual bases which have trivial destructors.
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
+    if (BaseClassDecl->hasTrivialDestructor())
+      continue;
+    if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context))
+      MarkDeclarationReferenced(Destructor->getLocation(), 
+                                const_cast<CXXDestructorDecl*>(Dtor));
+    
+    uintptr_t Member = 
+    reinterpret_cast<uintptr_t>(VBase->getType().getTypePtr()) 
+      | CXXDestructorDecl::VBASE;
+    AllToDestruct.push_back(Member);
+  }
+  for (CXXRecordDecl::base_class_iterator Base =
+       ClassDecl->bases_begin(),
+       E = ClassDecl->bases_end(); Base != E; ++Base) {
+    if (Base->isVirtual())
+      continue;
+    if (Base->getType()->isDependentType())
+      continue;
+    // Skip over virtual bases which have trivial destructors.
+    CXXRecordDecl *BaseClassDecl
+    = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (BaseClassDecl->hasTrivialDestructor())
+      continue;
+    if (const CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context))
+      MarkDeclarationReferenced(Destructor->getLocation(), 
+                                const_cast<CXXDestructorDecl*>(Dtor));
+    uintptr_t Member = 
+    reinterpret_cast<uintptr_t>(Base->getType().getTypePtr()) 
+      | CXXDestructorDecl::DRCTNONVBASE;
+    AllToDestruct.push_back(Member);
+  }
+  
+  // non-static data members.
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+       E = ClassDecl->field_end(); Field != E; ++Field) {
+    QualType FieldType = Context.getBaseElementType((*Field)->getType());
+    
+    if (const RecordType* RT = FieldType->getAs<RecordType>()) {
+      // Skip over virtual bases which have trivial destructors.
+      CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+      if (FieldClassDecl->hasTrivialDestructor())
+        continue;
+      if (const CXXDestructorDecl *Dtor = 
+            FieldClassDecl->getDestructor(Context))
+        MarkDeclarationReferenced(Destructor->getLocation(), 
+                                  const_cast<CXXDestructorDecl*>(Dtor));
+      uintptr_t Member = reinterpret_cast<uintptr_t>(*Field);
+      AllToDestruct.push_back(Member);
+    }
+  }
+  
+  unsigned NumDestructions = AllToDestruct.size();
+  if (NumDestructions > 0) {
+    Destructor->setNumBaseOrMemberDestructions(NumDestructions);
+    uintptr_t *BaseOrMemberDestructions = 
+      new (Context) uintptr_t [NumDestructions];
+    // Insert in reverse order.
+    for (int Idx = NumDestructions-1, i=0 ; Idx >= 0; --Idx)
+      BaseOrMemberDestructions[i++] = AllToDestruct[Idx];
+    Destructor->setBaseOrMemberDestructions(BaseOrMemberDestructions);
+  }
+}
+
 void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {
   if (!CDtorDecl)
     return;