Move unchanging portions of context over to the Visitor.
This commit is contained in:
parent
9d0727736b
commit
bc13365007
@ -28,56 +28,53 @@ use util::ppaux::Repr;
|
|||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
struct Context {
|
struct Context {
|
||||||
tcx: ty::ctxt,
|
|
||||||
safe_stack: bool
|
safe_stack: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StackCheckVisitor;
|
struct StackCheckVisitor {
|
||||||
|
tcx: ty::ctxt,
|
||||||
|
}
|
||||||
|
|
||||||
impl Visitor<Context> for StackCheckVisitor {
|
impl Visitor<Context> for StackCheckVisitor {
|
||||||
fn visit_item(&mut self, i:@ast::item, e:Context) {
|
fn visit_item(&mut self, i:@ast::item, e:Context) {
|
||||||
stack_check_item(*self, i, e);
|
stack_check_item(self, i, e);
|
||||||
}
|
}
|
||||||
fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&ast::fn_decl,
|
fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&ast::fn_decl,
|
||||||
b:&ast::Block, s:Span, n:ast::NodeId, e:Context) {
|
b:&ast::Block, s:Span, n:ast::NodeId, e:Context) {
|
||||||
stack_check_fn(*self, fk, fd, b, s, n, e);
|
stack_check_fn(self, fk, fd, b, s, n, e);
|
||||||
}
|
}
|
||||||
fn visit_expr(&mut self, ex:@ast::Expr, e:Context) {
|
fn visit_expr(&mut self, ex:@ast::Expr, e:Context) {
|
||||||
stack_check_expr(*self, ex, e);
|
stack_check_expr(self, ex, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stack_check_crate(tcx: ty::ctxt,
|
pub fn stack_check_crate(tcx: ty::ctxt,
|
||||||
crate: &ast::Crate) {
|
crate: &ast::Crate) {
|
||||||
let new_cx = Context {
|
let new_cx = Context { safe_stack: false };
|
||||||
tcx: tcx,
|
let mut visitor = StackCheckVisitor { tcx: tcx };
|
||||||
safe_stack: false
|
|
||||||
};
|
|
||||||
let mut visitor = StackCheckVisitor;
|
|
||||||
visit::walk_crate(&mut visitor, crate, new_cx);
|
visit::walk_crate(&mut visitor, crate, new_cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stack_check_item(v: StackCheckVisitor,
|
fn stack_check_item(v: &mut StackCheckVisitor,
|
||||||
item: @ast::item,
|
item: @ast::item,
|
||||||
in_cx: Context) {
|
in_cx: Context) {
|
||||||
let mut v = v;
|
|
||||||
match item.node {
|
match item.node {
|
||||||
ast::item_fn(_, ast::extern_fn, _, _, _) => {
|
ast::item_fn(_, ast::extern_fn, _, _, _) => {
|
||||||
// an extern fn is already being called from C code...
|
// an extern fn is already being called from C code...
|
||||||
let new_cx = Context {safe_stack: true, ..in_cx};
|
let new_cx = Context {safe_stack: true};
|
||||||
visit::walk_item(&mut v, item, new_cx);
|
visit::walk_item(v, item, new_cx);
|
||||||
}
|
}
|
||||||
ast::item_fn(*) => {
|
ast::item_fn(*) => {
|
||||||
let safe_stack = fixed_stack_segment(item.attrs);
|
let safe_stack = fixed_stack_segment(item.attrs);
|
||||||
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
|
let new_cx = Context {safe_stack: safe_stack};
|
||||||
visit::walk_item(&mut v, item, new_cx);
|
visit::walk_item(v, item, new_cx);
|
||||||
}
|
}
|
||||||
ast::item_impl(_, _, _, ref methods) => {
|
ast::item_impl(_, _, _, ref methods) => {
|
||||||
// visit_method() would make this nicer
|
// visit_method() would make this nicer
|
||||||
for &method in methods.iter() {
|
for &method in methods.iter() {
|
||||||
let safe_stack = fixed_stack_segment(method.attrs);
|
let safe_stack = fixed_stack_segment(method.attrs);
|
||||||
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
|
let new_cx = Context {safe_stack: safe_stack};
|
||||||
visit::walk_method_helper(&mut v, method, new_cx);
|
visit::walk_method_helper(v, method, new_cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::item_trait(_, _, ref methods) => {
|
ast::item_trait(_, _, ref methods) => {
|
||||||
@ -85,15 +82,15 @@ fn stack_check_item(v: StackCheckVisitor,
|
|||||||
match *method {
|
match *method {
|
||||||
ast::provided(@ref method) => {
|
ast::provided(@ref method) => {
|
||||||
let safe_stack = fixed_stack_segment(method.attrs);
|
let safe_stack = fixed_stack_segment(method.attrs);
|
||||||
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
|
let new_cx = Context {safe_stack: safe_stack};
|
||||||
visit::walk_method_helper(&mut v, method, new_cx);
|
visit::walk_method_helper(v, method, new_cx);
|
||||||
}
|
}
|
||||||
ast::required(*) => ()
|
ast::required(*) => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
visit::walk_item(&mut v, item, in_cx);
|
visit::walk_item(v, item, in_cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +99,7 @@ fn stack_check_item(v: StackCheckVisitor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stack_check_fn<'a>(v: StackCheckVisitor,
|
fn stack_check_fn<'a>(v: &mut StackCheckVisitor,
|
||||||
fk: &visit::fn_kind,
|
fk: &visit::fn_kind,
|
||||||
decl: &ast::fn_decl,
|
decl: &ast::fn_decl,
|
||||||
body: &ast::Block,
|
body: &ast::Block,
|
||||||
@ -114,7 +111,7 @@ fn stack_check_fn<'a>(v: StackCheckVisitor,
|
|||||||
in_cx.safe_stack // see stack_check_item above
|
in_cx.safe_stack // see stack_check_item above
|
||||||
}
|
}
|
||||||
visit::fk_anon(*) | visit::fk_fn_block => {
|
visit::fk_anon(*) | visit::fk_fn_block => {
|
||||||
match ty::get(ty::node_id_to_type(in_cx.tcx, id)).sty {
|
match ty::get(ty::node_id_to_type(v.tcx, id)).sty {
|
||||||
ty::ty_bare_fn(*) |
|
ty::ty_bare_fn(*) |
|
||||||
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
|
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
|
||||||
false
|
false
|
||||||
@ -125,26 +122,25 @@ fn stack_check_fn<'a>(v: StackCheckVisitor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
|
let new_cx = Context {safe_stack: safe_stack};
|
||||||
debug!("stack_check_fn(safe_stack=%b, id=%?)", safe_stack, id);
|
debug!("stack_check_fn(safe_stack=%b, id=%?)", safe_stack, id);
|
||||||
let mut v = v;
|
visit::walk_fn(v, fk, decl, body, sp, id, new_cx);
|
||||||
visit::walk_fn(&mut v, fk, decl, body, sp, id, new_cx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stack_check_expr<'a>(v: StackCheckVisitor,
|
fn stack_check_expr<'a>(v: &mut StackCheckVisitor,
|
||||||
expr: @ast::Expr,
|
expr: @ast::Expr,
|
||||||
cx: Context) {
|
cx: Context) {
|
||||||
debug!("stack_check_expr(safe_stack=%b, expr=%s)",
|
debug!("stack_check_expr(safe_stack=%b, expr=%s)",
|
||||||
cx.safe_stack, expr.repr(cx.tcx));
|
cx.safe_stack, expr.repr(v.tcx));
|
||||||
if !cx.safe_stack {
|
if !cx.safe_stack {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ast::ExprCall(callee, _, _) => {
|
ast::ExprCall(callee, _, _) => {
|
||||||
let callee_ty = ty::expr_ty(cx.tcx, callee);
|
let callee_ty = ty::expr_ty(v.tcx, callee);
|
||||||
debug!("callee_ty=%s", callee_ty.repr(cx.tcx));
|
debug!("callee_ty=%s", callee_ty.repr(v.tcx));
|
||||||
match ty::get(callee_ty).sty {
|
match ty::get(callee_ty).sty {
|
||||||
ty::ty_bare_fn(ref fty) => {
|
ty::ty_bare_fn(ref fty) => {
|
||||||
if !fty.abis.is_rust() && !fty.abis.is_intrinsic() {
|
if !fty.abis.is_rust() && !fty.abis.is_intrinsic() {
|
||||||
call_to_extern_fn(cx, callee);
|
call_to_extern_fn(v, callee);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -153,18 +149,17 @@ fn stack_check_expr<'a>(v: StackCheckVisitor,
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut v = v;
|
visit::walk_expr(v, expr, cx);
|
||||||
visit::walk_expr(&mut v, expr, cx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_to_extern_fn(cx: Context, callee: @ast::Expr) {
|
fn call_to_extern_fn(v: &mut StackCheckVisitor, callee: @ast::Expr) {
|
||||||
// Permit direct calls to extern fns that are annotated with
|
// Permit direct calls to extern fns that are annotated with
|
||||||
// #[rust_stack]. This is naturally a horrible pain to achieve.
|
// #[rust_stack]. This is naturally a horrible pain to achieve.
|
||||||
match callee.node {
|
match callee.node {
|
||||||
ast::ExprPath(*) => {
|
ast::ExprPath(*) => {
|
||||||
match cx.tcx.def_map.find(&callee.id) {
|
match v.tcx.def_map.find(&callee.id) {
|
||||||
Some(&ast::DefFn(id, _)) if id.crate == ast::LOCAL_CRATE => {
|
Some(&ast::DefFn(id, _)) if id.crate == ast::LOCAL_CRATE => {
|
||||||
match cx.tcx.items.find(&id.node) {
|
match v.tcx.items.find(&id.node) {
|
||||||
Some(&ast_map::node_foreign_item(item, _, _, _)) => {
|
Some(&ast_map::node_foreign_item(item, _, _, _)) => {
|
||||||
if attr::contains_name(item.attrs, "rust_stack") {
|
if attr::contains_name(item.attrs, "rust_stack") {
|
||||||
return;
|
return;
|
||||||
@ -179,7 +174,7 @@ fn call_to_extern_fn(cx: Context, callee: @ast::Expr) {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.tcx.sess.add_lint(lint::cstack,
|
v.tcx.sess.add_lint(lint::cstack,
|
||||||
callee.id,
|
callee.id,
|
||||||
callee.span,
|
callee.span,
|
||||||
fmt!("invoking non-Rust fn in fn without \
|
fmt!("invoking non-Rust fn in fn without \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user