Skip to content

Commit 8e6afbf

Browse files
author
Ariel Ben-Yehuda
authored
Rollup merge of rust-lang#40348 - nrc:save-extern-fn, r=@eddyb
Handle extern functions and statics in save-analysis r? @eddyb
2 parents 67cc915 + 4cf22cb commit 8e6afbf

File tree

3 files changed

+99
-9
lines changed

3 files changed

+99
-9
lines changed

src/librustc_save_analysis/dump_visitor.rs

+37-9
Original file line numberDiff line numberDiff line change
@@ -1375,15 +1375,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
13751375
debug!("visit_expr {:?}", ex.node);
13761376
self.process_macro_use(ex.span, ex.id);
13771377
match ex.node {
1378-
ast::ExprKind::Call(ref _f, ref _args) => {
1379-
// Don't need to do anything for function calls,
1380-
// because just walking the callee path does what we want.
1381-
visit::walk_expr(self, ex);
1382-
}
1383-
ast::ExprKind::Path(_, ref path) => {
1384-
self.process_path(ex.id, path, None);
1385-
visit::walk_expr(self, ex);
1386-
}
13871378
ast::ExprKind::Struct(ref path, ref fields, ref base) => {
13881379
let hir_expr = self.save_ctxt.tcx.hir.expect_expr(ex.id);
13891380
let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) {
@@ -1481,6 +1472,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
14811472
self.visit_expr(element);
14821473
self.nest_tables(count.id, |v| v.visit_expr(count));
14831474
}
1475+
// In particular, we take this branch for call and path expressions,
1476+
// where we'll index the idents involved just by continuing to walk.
14841477
_ => {
14851478
visit::walk_expr(self, ex)
14861479
}
@@ -1580,4 +1573,39 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
15801573
walk_list!(self, visit_ty, &l.ty);
15811574
walk_list!(self, visit_expr, &l.init);
15821575
}
1576+
1577+
fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
1578+
match item.node {
1579+
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
1580+
if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
1581+
down_cast_data!(fn_data, FunctionData, item.span);
1582+
if !self.span.filter_generated(Some(fn_data.span), item.span) {
1583+
self.dumper.function(fn_data.clone().lower(self.tcx));
1584+
}
1585+
1586+
self.nest_tables(item.id, |v| v.process_formals(&decl.inputs,
1587+
&fn_data.qualname));
1588+
self.process_generic_params(generics, item.span, &fn_data.qualname, item.id);
1589+
}
1590+
1591+
for arg in &decl.inputs {
1592+
self.visit_ty(&arg.ty);
1593+
}
1594+
1595+
if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
1596+
self.visit_ty(&ret_ty);
1597+
}
1598+
}
1599+
ast::ForeignItemKind::Static(ref ty, _) => {
1600+
if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
1601+
down_cast_data!(var_data, VariableData, item.span);
1602+
if !self.span.filter_generated(Some(var_data.span), item.span) {
1603+
self.dumper.variable(var_data.lower(self.tcx));
1604+
}
1605+
}
1606+
1607+
self.visit_ty(ty);
1608+
}
1609+
}
1610+
}
15831611
}

src/librustc_save_analysis/lib.rs

+57
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,48 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
116116
result
117117
}
118118

119+
pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
120+
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
121+
match item.node {
122+
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
123+
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn);
124+
Some(Data::FunctionData(FunctionData {
125+
id: item.id,
126+
name: item.ident.to_string(),
127+
qualname: qualname,
128+
declaration: None,
129+
span: sub_span.unwrap(),
130+
scope: self.enclosing_scope(item.id),
131+
value: make_signature(decl, generics),
132+
visibility: From::from(&item.vis),
133+
parent: None,
134+
docs: docs_for_attrs(&item.attrs),
135+
sig: self.sig_base_extern(item),
136+
attributes: item.attrs.clone(),
137+
}))
138+
}
139+
ast::ForeignItemKind::Static(ref ty, m) => {
140+
let keyword = if m { keywords::Mut } else { keywords::Static };
141+
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword);
142+
Some(Data::VariableData(VariableData {
143+
id: item.id,
144+
kind: VariableKind::Static,
145+
name: item.ident.to_string(),
146+
qualname: qualname,
147+
span: sub_span.unwrap(),
148+
scope: self.enclosing_scope(item.id),
149+
parent: None,
150+
value: String::new(),
151+
type_value: ty_to_string(ty),
152+
visibility: From::from(&item.vis),
153+
docs: docs_for_attrs(&item.attrs),
154+
sig: Some(self.sig_base_extern(item)),
155+
attributes: item.attrs.clone(),
156+
}))
157+
}
158+
}
159+
}
160+
119161
pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
120162
match item.node {
121163
ast::ItemKind::Fn(ref decl, .., ref generics, _) => {
@@ -748,6 +790,21 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
748790
}
749791
}
750792

793+
fn sig_base_extern(&self, item: &ast::ForeignItem) -> Signature {
794+
let text = self.span_utils.signature_string_for_span(item.span);
795+
let name = item.ident.to_string();
796+
let ident_start = text.find(&name).expect("Name not in signature?");
797+
let ident_end = ident_start + name.len();
798+
Signature {
799+
span: mk_sp(item.span.lo, item.span.lo + BytePos(text.len() as u32)),
800+
text: text,
801+
ident_start: ident_start,
802+
ident_end: ident_end,
803+
defs: vec![],
804+
refs: vec![],
805+
}
806+
}
807+
751808
#[inline]
752809
pub fn enclosing_scope(&self, id: NodeId) -> NodeId {
753810
self.tcx.hir.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID)

src/test/run-make/save-analysis-fail/foo.rs

+5
Original file line numberDiff line numberDiff line change
@@ -448,3 +448,8 @@ fn test_format_args() {
448448
print!("{0} + {} = {}", x, y);
449449
print!("x is {}, y is {1}, name is {n}", x, y, n = name);
450450
}
451+
452+
extern {
453+
static EXTERN_FOO: u8;
454+
fn extern_foo(a: u8, b: i32) -> String;
455+
}

0 commit comments

Comments
 (0)