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;