Skip to content

Commit 0cca08a

Browse files
James MillerAatch
James Miller
authored andcommitted
Add support for #[no_drop_flag] attribute
1 parent c6515ee commit 0cca08a

File tree

3 files changed

+63
-11
lines changed

3 files changed

+63
-11
lines changed

src/librustc/middle/trans/adt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
135135
ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
136136
};
137137
let packed = ty::lookup_packed(cx.tcx, def_id);
138-
let dtor = ty::ty_dtor(cx.tcx, def_id).is_present();
138+
let dtor = ty::ty_dtor(cx.tcx, def_id).has_drop_flag();
139139
let ftys =
140140
if dtor { ftys + [ty::mk_bool()] } else { ftys };
141141
return Univariant(mk_struct(cx, ftys, packed), dtor)

src/librustc/middle/trans/glue.rs

+49-8
Original file line numberDiff line numberDiff line change
@@ -406,13 +406,8 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
406406
build_return(bcx);
407407
}
408408

409-
pub fn trans_struct_drop(bcx: block,
410-
t: ty::t,
411-
v0: ValueRef,
412-
dtor_did: ast::def_id,
413-
class_did: ast::def_id,
414-
substs: &ty::substs)
415-
-> block {
409+
pub fn trans_struct_drop_flag(bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
410+
class_did: ast::def_id, substs: &ty::substs) -> block {
416411
let repr = adt::represent_type(bcx.ccx(), t);
417412
let drop_flag = adt::trans_drop_flag_ptr(bcx, repr, v0);
418413
do with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) |cx| {
@@ -454,6 +449,49 @@ pub fn trans_struct_drop(bcx: block,
454449
}
455450
}
456451

452+
pub fn trans_struct_drop(mut bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
453+
class_did: ast::def_id, substs: &ty::substs) -> block {
454+
let repr = adt::represent_type(bcx.ccx(), t);
455+
456+
// Find and call the actual destructor
457+
let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did,
458+
class_did, /*bad*/copy substs.tps);
459+
460+
// The second argument is the "self" argument for drop
461+
let params = unsafe {
462+
let ty = Type::from_ref(llvm::LLVMTypeOf(dtor_addr));
463+
ty.element_type().func_params()
464+
};
465+
466+
// Class dtors have no explicit args, so the params should
467+
// just consist of the environment (self)
468+
assert_eq!(params.len(), 1);
469+
470+
// Take a reference to the class (because it's using the Drop trait),
471+
// do so now.
472+
let llval = alloca(bcx, val_ty(v0));
473+
Store(bcx, v0, llval);
474+
475+
let self_arg = PointerCast(bcx, llval, params[0]);
476+
let args = ~[self_arg];
477+
478+
Call(bcx, dtor_addr, args);
479+
480+
// Drop the fields
481+
let field_tys = ty::struct_fields(bcx.tcx(), class_did, substs);
482+
for field_tys.iter().enumerate().advance |(i, fld)| {
483+
let llfld_a = adt::trans_field_ptr(bcx, repr, v0, 0, i);
484+
bcx = drop_ty(bcx, llfld_a, fld.mt.ty);
485+
}
486+
487+
// Zero out the struct
488+
unsafe {
489+
let ty = Type::from_ref(llvm::LLVMTypeOf(v0));
490+
memzero(bcx, v0, ty);
491+
}
492+
493+
bcx
494+
}
457495

458496
pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
459497
// NB: v0 is an *alias* of type t here, not a direct value.
@@ -474,7 +512,10 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
474512
ty::ty_struct(did, ref substs) => {
475513
let tcx = bcx.tcx();
476514
match ty::ty_dtor(tcx, did) {
477-
ty::TraitDtor(dtor) => {
515+
ty::TraitDtor(dtor, true) => {
516+
trans_struct_drop_flag(bcx, t, v0, dtor, did, substs)
517+
}
518+
ty::TraitDtor(dtor, false) => {
478519
trans_struct_drop(bcx, t, v0, dtor, did, substs)
479520
}
480521
ty::NoDtor => {

src/librustc/middle/ty.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -3855,7 +3855,7 @@ pub fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {
38553855

38563856
pub enum DtorKind {
38573857
NoDtor,
3858-
TraitDtor(def_id)
3858+
TraitDtor(def_id, bool)
38593859
}
38603860

38613861
impl DtorKind {
@@ -3869,13 +3869,24 @@ impl DtorKind {
38693869
pub fn is_present(&const self) -> bool {
38703870
!self.is_not_present()
38713871
}
3872+
3873+
pub fn has_drop_flag(&self) -> bool {
3874+
match self {
3875+
&NoDtor => false,
3876+
&TraitDtor(_, flag) => flag
3877+
}
3878+
}
38723879
}
38733880

38743881
/* If struct_id names a struct with a dtor, return Some(the dtor's id).
38753882
Otherwise return none. */
38763883
pub fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
38773884
match cx.destructor_for_type.find(&struct_id) {
3878-
Some(&method_def_id) => TraitDtor(method_def_id),
3885+
Some(&method_def_id) => {
3886+
let flag = has_attr(cx, struct_id, "no_drop_flag");
3887+
3888+
TraitDtor(method_def_id, flag)
3889+
}
38793890
None => NoDtor,
38803891
}
38813892
}

0 commit comments

Comments
 (0)