@@ -2563,8 +2563,10 @@ fn trans_cast(cx: block, e: @ast::expr, id: ast::node_id,
2563
2563
ret store_in_dest ( e_res. bcx , newval, dest) ;
2564
2564
}
2565
2565
2566
- fn trans_arg_expr ( cx : block , arg : ty:: arg , lldestty : TypeRef ,
2567
- e : @ast:: expr ) -> result {
2566
+ // temp_cleanups: cleanups that should run only if failure occurs before the
2567
+ // call takes place:
2568
+ fn trans_arg_expr ( cx : block , arg : ty:: arg , lldestty : TypeRef , e : @ast:: expr ,
2569
+ & temp_cleanups: [ ValueRef ] ) -> result {
2568
2570
let ccx = cx. ccx ( ) ;
2569
2571
let e_ty = expr_ty ( cx, e) ;
2570
2572
let is_bot = ty:: type_is_bot ( e_ty) ;
@@ -2612,6 +2614,11 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef,
2612
2614
if lv. kind != temporary && !move_out {
2613
2615
bcx = take_ty ( bcx, val, e_ty) ;
2614
2616
}
2617
+
2618
+ // In the event that failure occurs before the call actually
2619
+ // happens, have to cleanup this copy:
2620
+ add_clean_temp_mem ( bcx, val, e_ty) ;
2621
+ temp_cleanups += [ val] ;
2615
2622
} else if ty:: type_is_immediate ( e_ty) && lv. kind != owned {
2616
2623
let r = do_spill ( bcx, val, e_ty) ;
2617
2624
val = r. val ;
@@ -2638,6 +2645,7 @@ fn trans_args(cx: block, llenv: ValueRef,
2638
2645
args : [ ValueRef ] ,
2639
2646
retslot : ValueRef } {
2640
2647
2648
+ let temp_cleanups = [ ] ;
2641
2649
let args = ty:: ty_fn_args ( fn_ty) ;
2642
2650
let llargs: [ ValueRef ] = [ ] ;
2643
2651
let lltydescs: [ ValueRef ] = [ ] ;
@@ -2718,11 +2726,19 @@ fn trans_args(cx: block, llenv: ValueRef,
2718
2726
let arg_tys = type_of_explicit_args ( ccx, args) ;
2719
2727
let i = 0 u;
2720
2728
for e: @ast:: expr in es {
2721
- let r = trans_arg_expr ( bcx, args[ i] , arg_tys[ i] , e) ;
2729
+ let r = trans_arg_expr ( bcx, args[ i] , arg_tys[ i] , e, temp_cleanups ) ;
2722
2730
bcx = r. bcx ;
2723
2731
llargs += [ r. val ] ;
2724
2732
i += 1 u;
2725
2733
}
2734
+
2735
+ // now that all arguments have been successfully built, we can revoke any
2736
+ // temporary cleanups, as they are only needed if argument construction
2737
+ // should fail (for example, cleanup of copy mode args).
2738
+ vec:: iter ( temp_cleanups) { |c|
2739
+ revoke_clean ( bcx, c)
2740
+ }
2741
+
2726
2742
ret { bcx : bcx,
2727
2743
args : llargs,
2728
2744
retslot : llretslot} ;
0 commit comments