summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_trans/trans/mir/block.rs33
-rw-r--r--src/librustc_trans/trans/mir/lvalue.rs2
-rw-r--r--src/librustc_trans/trans/mir/mod.rs4
-rw-r--r--src/test/run-fail/mir_drop_panics.rs34
4 files changed, 66 insertions, 7 deletions
diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs
index bb43c5ae97e..5be585c4189 100644
--- a/src/librustc_trans/trans/mir/block.rs
+++ b/src/librustc_trans/trans/mir/block.rs
@@ -95,11 +95,36 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None);
             }
 
-            mir::Terminator::Drop { ref value, target, unwind: _ } => {
+            mir::Terminator::Drop { ref value, target, unwind } => {
                 let lvalue = self.trans_lvalue(bcx, value);
-                // FIXME: this does not account for possibility of unwinding (and totally should).
-                glue::drop_ty(bcx, lvalue.llval, lvalue.ty.to_ty(bcx.tcx()), DebugLoc::None);
-                build::Br(bcx, self.llblock(target), DebugLoc::None);
+                let ty = lvalue.ty.to_ty(bcx.tcx());
+                // Double check for necessity to drop
+                if !glue::type_needs_drop(bcx.tcx(), ty) {
+                    build::Br(bcx, self.llblock(target), DebugLoc::None);
+                    return;
+                }
+                let drop_fn = glue::get_drop_glue(bcx.ccx(), ty);
+                let drop_ty = glue::get_drop_glue_type(bcx.ccx(), ty);
+                let llvalue = if drop_ty != ty {
+                    build::PointerCast(bcx, lvalue.llval,
+                                       type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
+                } else {
+                    lvalue.llval
+                };
+                if let Some(unwind) = unwind {
+                    let uwbcx = self.bcx(unwind);
+                    let unwind = self.make_landing_pad(uwbcx);
+                    build::Invoke(bcx,
+                                  drop_fn,
+                                  &[llvalue],
+                                  self.llblock(target),
+                                  unwind.llbb,
+                                  None,
+                                  DebugLoc::None);
+                } else {
+                    build::Call(bcx, drop_fn, &[llvalue], None, DebugLoc::None);
+                    build::Br(bcx, self.llblock(target), DebugLoc::None);
+                }
             }
 
             mir::Terminator::Call { ref func, ref args, ref destination, ref cleanup } => {
diff --git a/src/librustc_trans/trans/mir/lvalue.rs b/src/librustc_trans/trans/mir/lvalue.rs
index a6ba069742d..d994f1ea7b0 100644
--- a/src/librustc_trans/trans/mir/lvalue.rs
+++ b/src/librustc_trans/trans/mir/lvalue.rs
@@ -65,7 +65,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 assert!(lvalue.llextra != ptr::null_mut());
                 lvalue.llextra
             }
-            _ => bcx.sess().bug("unexpected type in get_base_and_len"),
+            _ => bcx.sess().bug("unexpected type in lvalue_len"),
         }
     }
 
diff --git a/src/librustc_trans/trans/mir/mod.rs b/src/librustc_trans/trans/mir/mod.rs
index cfe48af35ca..b19ecc45a4e 100644
--- a/src/librustc_trans/trans/mir/mod.rs
+++ b/src/librustc_trans/trans/mir/mod.rs
@@ -195,8 +195,8 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>,
 mod analyze;
 mod block;
 mod constant;
+mod did;
 mod lvalue;
-mod rvalue;
 mod operand;
+mod rvalue;
 mod statement;
-mod did;
diff --git a/src/test/run-fail/mir_drop_panics.rs b/src/test/run-fail/mir_drop_panics.rs
new file mode 100644
index 00000000000..9868ff4c241
--- /dev/null
+++ b/src/test/run-fail/mir_drop_panics.rs
@@ -0,0 +1,34 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(rustc_attrs)]
+// error-pattern:panic 1
+// error-pattern:drop 2
+use std::io::{self, Write};
+
+struct Droppable(u32);
+impl Drop for Droppable {
+    fn drop(&mut self) {
+        if self.0 == 1 {
+            panic!("panic 1");
+        } else {
+            write!(io::stderr(), "drop {}", self.0);
+        }
+    }
+}
+
+#[rustc_mir]
+fn mir() {
+    let x = Droppable(2);
+    let y = Droppable(1);
+}
+
+fn main() {
+    mir();
+}