about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-07-29 19:31:44 +0000
committerbors <bors@rust-lang.org>2014-07-29 19:31:44 +0000
commit87c78fd7e307e0be0eeb17df2d2ff1b1b4057254 (patch)
tree57f17445c3b2b4cd26e598b78fdf30ce2b22f7d9
parent6635fe7db4336ef31d2b372e7bfcce01d21853e0 (diff)
parenta1c95ecca14a047233ead0ca2f087e989a50e0f5 (diff)
downloadrust-87c78fd7e307e0be0eeb17df2d2ff1b1b4057254.tar.gz
rust-87c78fd7e307e0be0eeb17df2d2ff1b1b4057254.zip
auto merge of #16046 : dotdash/rust/call_ignore_alloca, r=pcwalton
-rw-r--r--src/librustc/middle/trans/callee.rs21
1 files changed, 12 insertions, 9 deletions
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index e2ad8b4fd46..b95bd08dd16 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -775,6 +775,8 @@ pub fn trans_call_inner<'a>(
     // We trans them in place in `trans_intrinsic_call`
     assert!(abi != synabi::RustIntrinsic);
 
+    let is_rust_fn = abi == synabi::Rust || abi == synabi::RustCall;
+
     // Generate a location to store the result. If the user does
     // not care about the result, just make a stack slot.
     let opt_llretslot = match dest {
@@ -783,7 +785,9 @@ pub fn trans_call_inner<'a>(
             None
         }
         Some(expr::SaveIn(dst)) => Some(dst),
-        Some(expr::Ignore) => {
+        Some(expr::Ignore) if !is_rust_fn ||
+                type_of::return_uses_outptr(ccx, ret_ty) ||
+                ty::type_needs_drop(bcx.tcx(), ret_ty) => {
             if !type_is_zero_size(ccx, ret_ty) {
                 Some(alloc_ty(bcx, ret_ty, "__llret"))
             } else {
@@ -791,6 +795,7 @@ pub fn trans_call_inner<'a>(
                 Some(C_undef(llty.ptr_to()))
             }
         }
+        Some(expr::Ignore) => None
     };
 
     let mut llresult = unsafe {
@@ -803,7 +808,7 @@ pub fn trans_call_inner<'a>(
     // and done, either the return value of the function will have been
     // written in opt_llretslot (if it is Some) or `llresult` will be
     // set appropriately (otherwise).
-    if abi == synabi::Rust || abi == synabi::RustCall {
+    if is_rust_fn {
         let mut llargs = Vec::new();
 
         // Push the out-pointer if we use an out-pointer for this
@@ -878,15 +883,13 @@ pub fn trans_call_inner<'a>(
 
     // If the caller doesn't care about the result of this fn call,
     // drop the temporary slot we made.
-    match dest {
-        None => {
-            assert!(!type_of::return_uses_outptr(bcx.ccx(), ret_ty));
-        }
-        Some(expr::Ignore) => {
+    match (dest, opt_llretslot) {
+        (Some(expr::Ignore), Some(llretslot)) => {
             // drop the value if it is not being saved.
-            bcx = glue::drop_ty(bcx, opt_llretslot.unwrap(), ret_ty);
+            bcx = glue::drop_ty(bcx, llretslot, ret_ty);
+            call_lifetime_end(bcx, llretslot);
         }
-        Some(expr::SaveIn(_)) => { }
+        _ => {}
     }
 
     if ty::type_is_bot(ret_ty) {