@@ -870,6 +870,109 @@ void CIRGenFunction::destroyCXXObject(CIRGenFunction &cgf, Address addr,
870
870
/* delegating=*/ false , addr, type);
871
871
}
872
872
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
+
873
976
void CIRGenFunction::emitDelegatingCXXConstructorCall (
874
977
const CXXConstructorDecl *ctor, const FunctionArgList &args) {
875
978
assert (ctor->isDelegatingConstructor ());
0 commit comments