about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-05-23 15:22:04 -0700
committerBrian Anderson <banderson@mozilla.com>2013-05-23 15:33:34 -0700
commitd213443a67c8dbef562ad207c62308e57c230511 (patch)
tree1dfe5f9ae423b9c083f38aac302d774d4b2d69d3 /src
parent6e2b082adc84c22ea3b023f4f08d7b21857fc399 (diff)
downloadrust-d213443a67c8dbef562ad207c62308e57c230511.tar.gz
rust-d213443a67c8dbef562ad207c62308e57c230511.zip
rustc: Check for null before dropping ~objects. #5192
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/trans/glue.rs31
-rw-r--r--src/test/run-pass/unique-object-move.rs24
2 files changed, 41 insertions, 14 deletions
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index d8c85112747..ed46ab0ce37 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -546,20 +546,23 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
         decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx))
       }
       ty::ty_trait(_, _, ty::UniqTraitStore, _) => {
-        let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
-        let llvtable = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable]));
-
-        // Cast the vtable to a pointer to a pointer to a tydesc.
-        let llvtable = PointerCast(bcx,
-                                   llvtable,
-                                   T_ptr(T_ptr(ccx.tydesc_type)));
-        let lltydesc = Load(bcx, llvtable);
-        call_tydesc_glue_full(bcx,
-                              lluniquevalue,
-                              lltydesc,
-                              abi::tydesc_field_free_glue,
-                              None);
-        bcx
+          let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
+          // Only drop the value when it is non-null
+          do with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue))) |bcx| {
+              let llvtable = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable]));
+
+              // Cast the vtable to a pointer to a pointer to a tydesc.
+              let llvtable = PointerCast(bcx,
+                                         llvtable,
+                                         T_ptr(T_ptr(ccx.tydesc_type)));
+              let lltydesc = Load(bcx, llvtable);
+              call_tydesc_glue_full(bcx,
+                                    lluniquevalue,
+                                    lltydesc,
+                                    abi::tydesc_field_free_glue,
+                                    None);
+              bcx
+          }
       }
       ty::ty_opaque_closure_ptr(ck) => {
         closure::make_opaque_cbox_drop_glue(bcx, ck, v0)
diff --git a/src/test/run-pass/unique-object-move.rs b/src/test/run-pass/unique-object-move.rs
new file mode 100644
index 00000000000..540de165213
--- /dev/null
+++ b/src/test/run-pass/unique-object-move.rs
@@ -0,0 +1,24 @@
+// Copyright 2012 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.
+
+// Issue #5192
+
+pub trait EventLoop { }
+
+pub struct UvEventLoop {
+    uvio: int
+}
+
+impl EventLoop for UvEventLoop { }
+
+pub fn main() {
+    let loop_: ~EventLoop = ~UvEventLoop { uvio: 0 } as ~EventLoop;
+    let loop2_ = loop_;
+}
\ No newline at end of file