Zero locals that have initializers that might fail

This will avoid running cleanups on uninitialized memory

Issue #236
This commit is contained in:
Brian Anderson 2011-09-07 16:17:06 -07:00
parent 4eb3ce3280
commit 587b863772

View file

@ -4447,7 +4447,9 @@ fn init_local(bcx: @block_ctxt, local: &@ast::local) -> result {
// Make a note to drop this slot on the way out.
add_clean(bcx, llptr, ty);
if must_zero(local) { bcx = zero_alloca(bcx, llptr, ty).bcx; }
if must_zero(bcx_ccx(bcx), local) {
bcx = zero_alloca(bcx, llptr, ty).bcx;
}
alt local.node.init {
some(init) {
@ -4473,36 +4475,37 @@ fn init_local(bcx: @block_ctxt, local: &@ast::local) -> result {
bcx.fcx.lllocals, false);
ret rslt(bcx, llptr);
fn must_zero(local: &@ast::local) -> bool {
fn must_zero(ccx: &@crate_ctxt, local: &@ast::local) -> bool {
alt local.node.init {
some(init) { might_not_init(init.expr) }
some(init) { might_not_init(ccx, init.expr) }
none. { true }
}
}
fn might_not_init(expr: &@ast::expr) -> bool {
type env = @mutable bool;
let e = @mutable false;
// FIXME: Probably also need to account for expressions that
// fail but since we don't unwind yet, it doesn't seem to be a
// problem
fn might_not_init(ccx: &@crate_ctxt, expr: &@ast::expr) -> bool {
type env = {mutable mightnt: bool,
ccx: @crate_ctxt};
let e = {mutable mightnt: false,
ccx: ccx};
fn visit_expr(ex: &@ast::expr, e: &env, v: &vt<env>) {
let might_not_init = alt ex.node {
ast::expr_ret(_) { true }
ast::expr_break. { true }
ast::expr_cont. { true }
_ {
let ex_ty = ty::expr_ty(e.ccx.tcx, ex);
ty::type_is_bot(e.ccx.tcx, ex_ty)
}
};
if might_not_init {
e.mightnt = true;
} else { visit::visit_expr(ex, e, v); }
}
let visitor =
visit::mk_vt(
@{visit_expr:
fn (ex: &@ast::expr, e: &env, v: &vt<env>) {
let might_not_init =
alt ex.node {
ast::expr_ret(_) { true }
ast::expr_break. { true }
ast::expr_cont. { true }
_ { false }
};
if might_not_init {
*e = true;
} else { visit::visit_expr(ex, e, v); }
} with *visit::default_visitor()});
visit::mk_vt(@{visit_expr: visit_expr
with *visit::default_visitor()});
visitor.visit_expr(expr, e, visitor);
ret *e;
ret e.mightnt;
}
}