@@ -395,39 +395,11 @@ pub fn trans_struct_drop_flag(bcx: @mut Block, t: ty::t, v0: ValueRef, dtor_did:
395
395
let repr = adt:: represent_type ( bcx. ccx ( ) , t) ;
396
396
let drop_flag = adt:: trans_drop_flag_ptr ( bcx, repr, v0) ;
397
397
do with_cond( bcx, IsNotNull ( bcx, Load ( bcx, drop_flag) ) ) |cx| {
398
- let mut bcx = cx;
399
-
400
- // Find and call the actual destructor
401
- let dtor_addr = get_res_dtor ( bcx. ccx ( ) , dtor_did,
402
- class_did, substs. tps . clone ( ) ) ;
403
-
404
- // The second argument is the "self" argument for drop
405
- let params = unsafe {
406
- let ty = Type :: from_ref ( llvm:: LLVMTypeOf ( dtor_addr) ) ;
407
- ty. element_type ( ) . func_params ( )
408
- } ;
409
-
410
- // Class dtors have no explicit args, so the params should
411
- // just consist of the environment (self)
412
- assert_eq ! ( params. len( ) , 1 ) ;
413
-
414
- let self_arg = PointerCast ( bcx, v0, params[ 0 ] ) ;
415
- let args = ~[ self_arg] ;
416
-
417
- Call ( bcx, dtor_addr, args, [ ] ) ;
418
-
419
- // Drop the fields
420
- let field_tys = ty:: struct_fields ( bcx. tcx ( ) , class_did, substs) ;
421
- for ( i, fld) in field_tys. iter ( ) . enumerate ( ) {
422
- let llfld_a = adt:: trans_field_ptr ( bcx, repr, v0, 0 , i) ;
423
- bcx = drop_ty ( bcx, llfld_a, fld. mt . ty ) ;
424
- }
425
-
426
- bcx
398
+ trans_struct_drop ( cx, t, v0, dtor_did, class_did, substs)
427
399
}
428
400
}
429
401
430
- pub fn trans_struct_drop ( mut bcx : @mut Block , t : ty:: t , v0 : ValueRef , dtor_did : ast:: DefId ,
402
+ pub fn trans_struct_drop ( bcx : @mut Block , t : ty:: t , v0 : ValueRef , dtor_did : ast:: DefId ,
431
403
class_did : ast:: DefId , substs : & ty:: substs ) -> @mut Block {
432
404
let repr = adt:: represent_type ( bcx. ccx ( ) , t) ;
433
405
@@ -445,19 +417,24 @@ pub fn trans_struct_drop(mut bcx: @mut Block, t: ty::t, v0: ValueRef, dtor_did:
445
417
// just consist of the environment (self)
446
418
assert_eq ! ( params. len( ) , 1 ) ;
447
419
448
- let self_arg = PointerCast ( bcx, v0, params[ 0 ] ) ;
449
- let args = ~[ self_arg] ;
420
+ // Be sure to put all of the fields into a scope so we can use an invoke
421
+ // instruction to call the user destructor but still call the field
422
+ // destructors if the user destructor fails.
423
+ do with_scope( bcx, None , "field drops" ) |bcx| {
424
+ let self_arg = PointerCast ( bcx, v0, params[ 0 ] ) ;
425
+ let args = ~[ self_arg] ;
450
426
451
- Call ( bcx, dtor_addr, args, [ ] ) ;
427
+ // Add all the fields as a value which needs to be cleaned at the end of
428
+ // this scope.
429
+ let field_tys = ty:: struct_fields ( bcx. tcx ( ) , class_did, substs) ;
430
+ for ( i, fld) in field_tys. iter ( ) . enumerate ( ) {
431
+ let llfld_a = adt:: trans_field_ptr ( bcx, repr, v0, 0 , i) ;
432
+ add_clean ( bcx, llfld_a, fld. mt . ty ) ;
433
+ }
452
434
453
- // Drop the fields
454
- let field_tys = ty:: struct_fields ( bcx. tcx ( ) , class_did, substs) ;
455
- for ( i, fld) in field_tys. iter ( ) . enumerate ( ) {
456
- let llfld_a = adt:: trans_field_ptr ( bcx, repr, v0, 0 , i) ;
457
- bcx = drop_ty ( bcx, llfld_a, fld. mt . ty ) ;
435
+ let ( _, bcx) = invoke ( bcx, dtor_addr, args, [ ] ) ;
436
+ bcx
458
437
}
459
-
460
- bcx
461
438
}
462
439
463
440
pub fn make_drop_glue ( bcx : @mut Block , v0 : ValueRef , t : ty:: t ) -> @mut Block {
0 commit comments