@@ -870,6 +870,109 @@ void CIRGenFunction::destroyCXXObject(CIRGenFunction &cgf, Address addr,
870870 /* delegating=*/ false , addr, type);
871871}
872872
873+ namespace {
874+ class DestroyField final : public EHScopeStack::Cleanup {
875+ const FieldDecl *field;
876+ CIRGenFunction::Destroyer *destroyer;
877+
878+ public:
879+ DestroyField (const FieldDecl *field, CIRGenFunction::Destroyer *destroyer)
880+ : field(field), destroyer(destroyer) {}
881+
882+ void emit (CIRGenFunction &cgf) override {
883+ // Find the address of the field.
884+ Address thisValue = cgf.loadCXXThisAddress ();
885+ CanQualType recordTy =
886+ cgf.getContext ().getCanonicalTagType (field->getParent ());
887+ LValue thisLV = cgf.makeAddrLValue (thisValue, recordTy);
888+ LValue lv = cgf.emitLValueForField (thisLV, field);
889+ assert (lv.isSimple ());
890+
891+ assert (!cir::MissingFeatures::ehCleanupFlags ());
892+ cgf.emitDestroy (lv.getAddress (), field->getType (), destroyer);
893+ }
894+
895+ // This is a placeholder until EHCleanupScope is implemented.
896+ size_t getSize () const override {
897+ assert (!cir::MissingFeatures::ehCleanupScope ());
898+ return sizeof (DestroyField);
899+ }
900+ };
901+ } // namespace
902+
903+ // / Emit all code that comes at the end of class's destructor. This is to call
904+ // / destructors on members and base classes in reverse order of their
905+ // / construction.
906+ // /
907+ // / For a deleting destructor, this also handles the case where a destroying
908+ // / operator delete completely overrides the definition.
909+ void CIRGenFunction::enterDtorCleanups (const CXXDestructorDecl *dd,
910+ CXXDtorType dtorType) {
911+ assert ((!dd->isTrivial () || dd->hasAttr <DLLExportAttr>()) &&
912+ " Should not emit dtor epilogue for non-exported trivial dtor!" );
913+
914+ // The deleting-destructor phase just needs to call the appropriate
915+ // operator delete that Sema picked up.
916+ if (dtorType == Dtor_Deleting) {
917+ cgm.errorNYI (dd->getSourceRange (), " deleting destructor cleanups" );
918+ return ;
919+ }
920+
921+ const CXXRecordDecl *classDecl = dd->getParent ();
922+
923+ // Unions have no bases and do not call field destructors.
924+ if (classDecl->isUnion ())
925+ return ;
926+
927+ // The complete-destructor phase just destructs all the virtual bases.
928+ if (dtorType == Dtor_Complete) {
929+ assert (!cir::MissingFeatures::sanitizers ());
930+
931+ if (classDecl->getNumVBases ())
932+ cgm.errorNYI (dd->getSourceRange (), " virtual base destructor cleanups" );
933+
934+ return ;
935+ }
936+
937+ assert (dtorType == Dtor_Base);
938+ assert (!cir::MissingFeatures::sanitizers ());
939+
940+ // Destroy non-virtual bases.
941+ for (const CXXBaseSpecifier &base : classDecl->bases ()) {
942+ // Ignore virtual bases.
943+ if (base.isVirtual ())
944+ continue ;
945+
946+ CXXRecordDecl *baseClassDecl = base.getType ()->getAsCXXRecordDecl ();
947+
948+ if (baseClassDecl->hasTrivialDestructor ())
949+ assert (!cir::MissingFeatures::sanitizers ());
950+ else
951+ cgm.errorNYI (dd->getSourceRange (),
952+ " non-trivial base destructor cleanups" );
953+ }
954+
955+ assert (!cir::MissingFeatures::sanitizers ());
956+
957+ // Destroy direct fields.
958+ for (const FieldDecl *field : classDecl->fields ()) {
959+ QualType type = field->getType ();
960+ QualType::DestructionKind dtorKind = type.isDestructedType ();
961+ if (!dtorKind)
962+ continue ;
963+
964+ // Anonymous union members do not have their destructors called.
965+ const RecordType *rt = type->getAsUnionType ();
966+ if (rt && rt->getOriginalDecl ()->isAnonymousStructOrUnion ())
967+ continue ;
968+
969+ CleanupKind cleanupKind = getCleanupKind (dtorKind);
970+ assert (!cir::MissingFeatures::ehCleanupFlags ());
971+ ehStack.pushCleanup <DestroyField>(cleanupKind, field,
972+ getDestroyer (dtorKind));
973+ }
974+ }
975+
873976void CIRGenFunction::emitDelegatingCXXConstructorCall (
874977 const CXXConstructorDecl *ctor, const FunctionArgList &args) {
875978 assert (ctor->isDelegatingConstructor ());
0 commit comments