about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2011-03-31 23:11:26 -0400
committerBrian Anderson <andersrb@gmail.com>2011-03-31 23:15:11 -0400
commitf16e7242d2433378a0530d31427fad4ddd36c69f (patch)
tree688abbbfa6505f59cd81134fe48aa4e9e30d172b /src/comp
parent524e80358254575bb699756c405050da6c920e28 (diff)
Initialize the alloca used to retrieve boxed block results to null.
This allows blocks to be used in conditional constructs where the block may
not ever execute: the drop glue will notice that it was never used and ignore
it.

Also, beef up the comments.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/trans.rs30
1 files changed, 19 insertions, 11 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index f6d59b9292d..c04e97489a8 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -5384,21 +5384,29 @@ fn trans_block(@block_ctxt cx, &ast.block b) -> result {
             if (is_terminated(bcx)) {
                 ret r;
             } else {
-                // The value resulting from the block gets copied into an
-                // alloca created in an enclosing scope and it's refcount
-                // bumped so that it can escape this block. This means that
-                // it will definitely live until the end of the enclosing
-                // scope, even if nobody uses it, which may be something of
-                // a surprise.
-
                 auto r_ty = ty.expr_ty(e);
 
                 if (ty.type_is_boxed(r_ty)) {
-
-                    // Create an alloca up in the llallocas block to hold the
-                    // expression result.
+                    // The value resulting from the block gets copied into an
+                    // alloca created in an outer scope and it's refcount
+                    // bumped so that it can escape this block. This means
+                    // that it will definitely live until the end of the
+                    // enclosing scope, even if nobody uses it, which may be
+                    // something of a surprise.
+
+                    // It's possible we never hit this block, so the alloca
+                    // must be initialized to null, then when the potential
+                    // value finally goes out of scope the drop glue will see
+                    // that it was never used and ignore it.
+
+                    // NB: Here we're building and initalizing the alloca in
+                    // the alloca context, not this block's context.
                     auto res_alloca = alloc_ty(bcx, r_ty);
-                    bcx = res_alloca.bcx;
+                    auto alloca_ty = type_of(bcx.fcx.ccx, r_ty);
+                    auto builder = new_builder(bcx.fcx.llallocas);
+                    builder.Store(C_null(alloca_ty), res_alloca.val);
+
+                    // Now we're working in our own block context again
                     auto res_copy = copy_ty(bcx, INIT,
                                             res_alloca.val, r.val, r_ty);
                     bcx = res_copy.bcx;