Skip to content

Commit

Permalink
Auto merge of #40348 - nrc:save-extern-fn, r=eddyb
Browse files Browse the repository at this point in the history
Handle extern functions and statics in save-analysis

r? @eddyb
  • Loading branch information
bors committed Apr 5, 2017
2 parents 46f71a0 + d76daf5 commit 91ae22a
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 9 deletions.
46 changes: 37 additions & 9 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1401,15 +1401,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
debug!("visit_expr {:?}", ex.node);
self.process_macro_use(ex.span, ex.id);
match ex.node {
ast::ExprKind::Call(ref _f, ref _args) => {
// Don't need to do anything for function calls,
// because just walking the callee path does what we want.
visit::walk_expr(self, ex);
}
ast::ExprKind::Path(_, ref path) => {
self.process_path(ex.id, path, None);
visit::walk_expr(self, ex);
}
ast::ExprKind::Struct(ref path, ref fields, ref base) => {
let hir_expr = self.save_ctxt.tcx.hir.expect_expr(ex.id);
let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) {
Expand Down Expand Up @@ -1507,6 +1498,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
self.visit_expr(element);
self.nest_tables(count.id, |v| v.visit_expr(count));
}
// In particular, we take this branch for call and path expressions,
// where we'll index the idents involved just by continuing to walk.
_ => {
visit::walk_expr(self, ex)
}
Expand Down Expand Up @@ -1606,4 +1599,39 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
walk_list!(self, visit_ty, &l.ty);
walk_list!(self, visit_expr, &l.init);
}

fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
match item.node {
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
down_cast_data!(fn_data, FunctionData, item.span);
if !self.span.filter_generated(Some(fn_data.span), item.span) {
self.dumper.function(fn_data.clone().lower(self.tcx));
}

self.nest_tables(item.id, |v| v.process_formals(&decl.inputs,
&fn_data.qualname));
self.process_generic_params(generics, item.span, &fn_data.qualname, item.id);
}

for arg in &decl.inputs {
self.visit_ty(&arg.ty);
}

if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
self.visit_ty(&ret_ty);
}
}
ast::ForeignItemKind::Static(ref ty, _) => {
if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
down_cast_data!(var_data, VariableData, item.span);
if !self.span.filter_generated(Some(var_data.span), item.span) {
self.dumper.variable(var_data.lower(self.tcx));
}
}

self.visit_ty(ty);
}
}
}
}
59 changes: 59 additions & 0 deletions src/librustc_save_analysis/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,50 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
result
}

pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
match item.node {
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
filter!(self.span_utils, sub_span, item.span, None);
Some(Data::FunctionData(FunctionData {
id: item.id,
name: item.ident.to_string(),
qualname: qualname,
declaration: None,
span: sub_span.unwrap(),
scope: self.enclosing_scope(item.id),
value: make_signature(decl, generics),
visibility: From::from(&item.vis),
parent: None,
docs: docs_for_attrs(&item.attrs),
sig: self.sig_base_extern(item),
attributes: item.attrs.clone(),
}))
}
ast::ForeignItemKind::Static(ref ty, m) => {
let keyword = if m { keywords::Mut } else { keywords::Static };
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword);
filter!(self.span_utils, sub_span, item.span, None);
Some(Data::VariableData(VariableData {
id: item.id,
kind: VariableKind::Static,
name: item.ident.to_string(),
qualname: qualname,
span: sub_span.unwrap(),
scope: self.enclosing_scope(item.id),
parent: None,
value: String::new(),
type_value: ty_to_string(ty),
visibility: From::from(&item.vis),
docs: docs_for_attrs(&item.attrs),
sig: Some(self.sig_base_extern(item)),
attributes: item.attrs.clone(),
}))
}
}
}

pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
match item.node {
ast::ItemKind::Fn(ref decl, .., ref generics, _) => {
Expand Down Expand Up @@ -751,6 +795,21 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
}
}

fn sig_base_extern(&self, item: &ast::ForeignItem) -> Signature {
let text = self.span_utils.signature_string_for_span(item.span);
let name = item.ident.to_string();
let ident_start = text.find(&name).expect("Name not in signature?");
let ident_end = ident_start + name.len();
Signature {
span: Span { hi: item.span.lo + BytePos(text.len() as u32), ..item.span },
text: text,
ident_start: ident_start,
ident_end: ident_end,
defs: vec![],
refs: vec![],
}
}

#[inline]
pub fn enclosing_scope(&self, id: NodeId) -> NodeId {
self.tcx.hir.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID)
Expand Down
5 changes: 5 additions & 0 deletions src/test/run-make/save-analysis-fail/foo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,3 +448,8 @@ fn test_format_args() {
print!("{0} + {} = {}", x, y);
print!("x is {}, y is {1}, name is {n}", x, y, n = name);
}

extern {
static EXTERN_FOO: u8;
fn extern_foo(a: u8, b: i32) -> String;
}

0 comments on commit 91ae22a

Please sign in to comment.