Allow anonymous extern mods

Now you can write:

extern {
  f() -> int;
}

and f will be accessible in the enclosing scope.
This commit is contained in:
Tim Chevalier 2012-09-04 16:40:11 -07:00
parent c491bf939e
commit 451da07718
4 changed files with 53 additions and 20 deletions

View File

@ -239,7 +239,14 @@ fn map_item(i: @item, cx: ctx, v: vt) {
cx.map.insert(nitem.id,
node_foreign_item(nitem, abi,
/* FIXME (#2543) */
extend(cx, i.ident)));
if nm.sort == ast::named {
extend(cx, i.ident)
}
else {
/* Anonymous extern mods go
in the parent scope */
@copy cx.path
}));
}
}
item_class(struct_def, _) => {

View File

@ -109,7 +109,7 @@ fn visit_view_item(e: env, i: @ast::view_item) {
fn visit_item(e: env, i: @ast::item) {
match i.node {
ast::item_foreign_mod(_) => {
ast::item_foreign_mod(fm) => {
match attr::foreign_abi(i.attrs) {
either::Right(abi) => {
if abi != ast::foreign_abi_cdecl &&
@ -119,27 +119,36 @@ fn visit_item(e: env, i: @ast::item) {
}
let cstore = e.cstore;
let foreign_name =
match attr::first_attr_value_str_by_name(i.attrs, ~"link_name") {
Some(nn) => {
if nn == ~"" {
e.diag.span_fatal(
i.span,
~"empty #[link_name] not allowed; use #[nolink].");
}
nn
}
None => *e.intr.get(i.ident)
};
let mut already_added = false;
if vec::len(attr::find_attrs_by_name(i.attrs, ~"nolink")) == 0u {
already_added = !cstore::add_used_library(cstore, foreign_name);
}
let link_args = attr::find_attrs_by_name(i.attrs, ~"link_args");
if vec::len(link_args) > 0u && already_added {
e.diag.span_fatal(i.span, ~"library '" + foreign_name +
~"' already added: can't specify link_args.");
match fm.sort {
ast::named => {
let foreign_name =
match attr::first_attr_value_str_by_name(i.attrs,
~"link_name") {
Some(nn) => {
if nn == ~"" {
e.diag.span_fatal(
i.span,
~"empty #[link_name] not allowed; use #[nolink].");
}
nn
}
None => *e.intr.get(i.ident)
};
if attr::find_attrs_by_name(i.attrs, ~"nolink").is_empty() {
already_added = !cstore::add_used_library(cstore,
foreign_name);
}
if link_args.is_not_empty() && already_added {
e.diag.span_fatal(i.span, ~"library '" + foreign_name +
~"' already added: can't specify link_args.");
}
}
ast::anonymous => { /* do nothing */ }
}
for link_args.each |a| {
match attr::get_meta_item_value_str(attr::attr_meta(a)) {
Some(linkarg) => {

View File

@ -0,0 +1,9 @@
#[abi = "cdecl"];
#[link_name = "rustrt"];
#[link(name = "anonexternmod",
vers = "0.1")];
#[crate_type = "lib"];
extern {
fn last_os_error() -> ~str;
}

View File

@ -0,0 +1,8 @@
// aux-build:anon-extern-mod-cross-crate-1.rs
use anonexternmod;
import anonexternmod::*;
fn main() {
last_os_error();
}