@@ -944,8 +944,8 @@ performs the following actions in sequence:
944944$(UL
945945 $(LI
946946 Calls `.object.destroy(x)` (if `x` is a class or interface object) or
947- `typeid (*x).destroy(x )` (if `x` is pointer to a struct) to destroy the referred entity.
948- Arrays of structs call `typeid(*x).destroy(x )` for each element.
947+ `(*x).__xdtor( )` (if `x` is pointer to a struct and a custom destructor exists ) to destroy the referred entity.
948+ Arrays of structs with a custom destructor call `x.__xdtor( )` for each element in the array .
949949 )
950950 $(LI
951951 Frees the memory allocated for `x`. If `x` is a reference to a class
@@ -968,34 +968,48 @@ See_Also: $(REF destroy, object), $(REF free, core,GC)
968968*/
969969void __delete (T)(ref T x) @system
970970{
971+ static void _destructRecurse (S)(ref S s)
972+ if (is (S == struct ))
973+ {
974+ static if (__traits(hasMember, S, " __xdtor" ) &&
975+ // Bugzilla 14746: Check that it's the exact member of S.
976+ __traits (isSame , S, __traits(parent, s.__xdtor)))
977+ s.__xdtor();
978+ }
979+
971980 // See also: https://github.com/dlang/dmd/blob/v2.078.0/src/dmd/e2ir.d#L3886
972981 static if (is (T == interface ))
973982 {
974- ( cast ( Object ) x). destroy ;
983+ .object. destroy (x) ;
975984 }
976985 else static if (is (T == class ))
977986 {
978- ( cast ( Object ) x). destroy ;
987+ .object. destroy (x) ;
979988 }
980989 else static if (is (T == U* , U))
981990 {
982991 static if (is (U == struct ))
983- typeid (U). destroy ( x);
992+ _destructRecurse( * x);
984993 }
985994 else static if (is (T : E[], E))
986995 {
987996 static if (is (E == struct ))
988997 {
989998 foreach (ref e; x)
990- typeid (E). destroy (& e);
999+ _destructRecurse( e);
9911000 }
9921001 }
9931002 else
9941003 {
9951004 static assert (0 , " It is not possible to delete: `" ~ T.stringof ~ " `" );
9961005 }
9971006
998- static if (is (T == interface ) || is (T == class ) || is (T == U2 * , U2 ) || is (T : E2 [], E2 ))
1007+ static if (is (T == interface ) || is (T == class ))
1008+ {
1009+ GC .free(cast (void * ) x);
1010+ x = null ;
1011+ }
1012+ else static if (is (T == U2 * , U2 ) || is (T : E2 [], E2 ))
9991013 {
10001014 GC .free(&x);
10011015 x = null ;
@@ -1018,11 +1032,14 @@ unittest
10181032 B a = b;
10191033 b.test = 10 ;
10201034
1035+ assert (GC .addrOf(cast (void * ) b) != null );
10211036 __delete(b);
10221037 assert (b is null );
10231038 assert (dtorCalled);
1039+ assert (GC .addrOf(cast (void * ) b) == null );
10241040 // but be careful, a still points to it
10251041 assert (a ! is null );
1042+ assert (GC .addrOf(cast (void * ) a) ! is null );
10261043}
10271044
10281045// / Deleting interfaces
@@ -1049,9 +1066,11 @@ unittest
10491066 A a = new B();
10501067 a.quack();
10511068
1069+ assert (GC .addrOf(cast (void * ) a) != null );
10521070 __delete(a);
10531071 assert (a is null );
10541072 assert (dtorCalled);
1073+ assert (GC .addrOf(cast (void * ) a) == null );
10551074}
10561075
10571076// / Deleting structs
@@ -1067,39 +1086,27 @@ unittest
10671086 }
10681087 }
10691088 auto a = new A(" foo" );
1070- __delete(a);
10711089
1090+ assert (GC .addrOf(cast (void * ) a) != null );
1091+ __delete(a);
10721092 assert (a is null );
10731093 assert (dtorCalled);
1094+ assert (GC .addrOf(cast (void * ) a) == null );
10741095}
10751096
10761097// / Deleting arrays
10771098unittest
10781099{
10791100 int [] a = [1 , 2 , 3 ];
10801101 auto b = a;
1081- __delete(b);
1082- assert (b is null );
1083- }
10841102
1085- // / Deleting pointers
1086- unittest
1087- {
1088- bool dtorCalled;
1089- class A
1090- {
1091- string test;
1092- ~this ()
1093- {
1094- dtorCalled = true ;
1095- }
1096- }
1097- A a = new A();
1098- a.test = " exists" ;
1099- auto b = &a;
1103+ assert (GC .addrOf(b.ptr) != null );
11001104 __delete(b);
11011105 assert (b is null );
1102- assert (! dtorCalled);
1106+ assert (GC .addrOf(b.ptr) == null );
1107+ // but be careful, a still points to it
1108+ assert (a ! is null );
1109+ assert (GC .addrOf(a.ptr) ! is null );
11031110}
11041111
11051112// / Deleting arrays of structs
@@ -1115,17 +1122,22 @@ unittest
11151122 }
11161123 }
11171124 auto arr = [A(1 ), A(2 ), A(3 )];
1125+
1126+ assert (GC .addrOf(arr.ptr) != null );
11181127 __delete(arr);
11191128 assert (dtorCalled == 3 );
1129+ assert (GC .addrOf(arr.ptr) == null );
11201130}
11211131
11221132// Deleting raw memory
11231133unittest
11241134{
11251135 import core.memory : GC ;
11261136 auto a = GC .malloc(5 );
1137+ assert (GC .addrOf(cast (void * ) a) != null );
11271138 __delete(a);
11281139 assert (a is null );
1140+ assert (GC .addrOf(cast (void * ) a) == null );
11291141}
11301142
11311143// __delete returns with no effect if x is null
0 commit comments