about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-02-12 02:16:13 +0000
committerbors <bors@rust-lang.org>2016-02-12 02:16:13 +0000
commit4b2c7030fd3c8773fc9d567ae240e896d5616be7 (patch)
tree8385625ed7515ff7e0364776c6d64786200ea7c6
parent78a5d5b54e0ff91bda8518df7ed9673cc657a4e6 (diff)
parent0ff055ad6640e26a4ddf783682545320de0d1c03 (diff)
downloadrust-4b2c7030fd3c8773fc9d567ae240e896d5616be7.tar.gz
rust-4b2c7030fd3c8773fc9d567ae240e896d5616be7.zip
Auto merge of #30830 - arcnmx:static-extern, r=alexcrichton
See #29676

r? @alexcrichton
-rw-r--r--src/librustc/middle/cstore.rs6
-rw-r--r--src/librustc/middle/reachable.rs20
-rw-r--r--src/librustc_metadata/csearch.rs11
-rw-r--r--src/librustc_metadata/decoder.rs40
-rw-r--r--src/librustc_trans/trans/base.rs3
-rw-r--r--src/libsyntax/attr.rs5
6 files changed, 42 insertions, 43 deletions
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 1e21d6aabe9..c2c23f6a032 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -187,8 +187,7 @@ pub trait CrateStore<'tcx> : Any {
     fn is_defaulted_trait(&self, did: DefId) -> bool;
     fn is_impl(&self, did: DefId) -> bool;
     fn is_default_impl(&self, impl_did: DefId) -> bool;
-    fn is_extern_fn(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool;
-    fn is_static(&self, did: DefId) -> bool;
+    fn is_extern_item(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool;
     fn is_static_method(&self, did: DefId) -> bool;
     fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool;
     fn is_typedef(&self, did: DefId) -> bool;
@@ -357,8 +356,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     fn is_defaulted_trait(&self, did: DefId) -> bool { unimplemented!() }
     fn is_impl(&self, did: DefId) -> bool { unimplemented!() }
     fn is_default_impl(&self, impl_did: DefId) -> bool { unimplemented!() }
-    fn is_extern_fn(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool { unimplemented!() }
-    fn is_static(&self, did: DefId) -> bool { unimplemented!() }
+    fn is_extern_item(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool { unimplemented!() }
     fn is_static_method(&self, did: DefId) -> bool { unimplemented!() }
     fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false }
     fn is_typedef(&self, did: DefId) -> bool { unimplemented!() }
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index d34c3b74217..d2e1b3edc3a 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -229,16 +229,18 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
     fn propagate_node(&mut self, node: &ast_map::Node,
                       search_item: ast::NodeId) {
         if !self.any_library {
-            // If we are building an executable, then there's no need to flag
-            // anything as external except for `extern fn` types. These
-            // functions may still participate in some form of native interface,
-            // but all other rust-only interfaces can be private (they will not
-            // participate in linkage after this product is produced)
+            // If we are building an executable, only explicitly extern
+            // types need to be exported.
             if let ast_map::NodeItem(item) = *node {
-                if let hir::ItemFn(_, _, _, abi, _, _) = item.node {
-                    if abi != Abi::Rust {
-                        self.reachable_symbols.insert(search_item);
-                    }
+                let reachable = if let hir::ItemFn(_, _, _, abi, _, _) = item.node {
+                    abi != Abi::Rust
+                } else {
+                    false
+                };
+                let is_extern = attr::contains_extern_indicator(&self.tcx.sess.diagnostic(),
+                                                                &item.attrs);
+                if reachable || is_extern {
+                    self.reachable_symbols.insert(search_item);
                 }
             }
         } else {
diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs
index 06a2727ea28..5eade3bc0a5 100644
--- a/src/librustc_metadata/csearch.rs
+++ b/src/librustc_metadata/csearch.rs
@@ -260,16 +260,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         decoder::is_default_impl(&*cdata, impl_did.index)
     }
 
-    fn is_extern_fn(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool
-    {
-        let cdata = self.get_crate_data(did.krate);
-        decoder::is_extern_fn(&*cdata, did.index, tcx)
-    }
-
-    fn is_static(&self, did: DefId) -> bool
-    {
+    fn is_extern_item(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool {
         let cdata = self.get_crate_data(did.krate);
-        decoder::is_static(&*cdata, did.index)
+        decoder::is_extern_item(&*cdata, did.index, tcx)
     }
 
     fn is_static_method(&self, def: DefId) -> bool
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 5ba9e566e00..8409a0c74b8 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1567,11 +1567,29 @@ pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool {
     }
 }
 
-pub fn is_static(cdata: Cmd, id: DefIndex) -> bool {
-    let item_doc = cdata.lookup_item(id);
-    match item_family(item_doc) {
+pub fn is_extern_item(cdata: Cmd, id: DefIndex, tcx: &ty::ctxt) -> bool {
+    let item_doc = match cdata.get_item(id) {
+        Some(doc) => doc,
+        None => return false,
+    };
+    let applicable = match item_family(item_doc) {
         ImmStatic | MutStatic => true,
+        Fn => {
+            let ty::TypeScheme { generics, ty } = get_type(cdata, id, tcx);
+            let no_generics = generics.types.is_empty();
+            match ty.sty {
+                ty::TyBareFn(_, fn_ty) if fn_ty.abi != Abi::Rust => return no_generics,
+                _ => no_generics,
+            }
+        },
         _ => false,
+    };
+
+    if applicable {
+        attr::contains_extern_indicator(tcx.sess.diagnostic(),
+                                        &get_attributes(item_doc))
+    } else {
+        false
     }
 }
 
@@ -1693,22 +1711,6 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
     }).collect()
 }
 
-pub fn is_extern_fn(cdata: Cmd, id: DefIndex, tcx: &ty::ctxt) -> bool {
-    let item_doc = match cdata.get_item(id) {
-        Some(doc) => doc,
-        None => return false,
-    };
-    if let Fn = item_family(item_doc) {
-        let ty::TypeScheme { generics, ty } = get_type(cdata, id, tcx);
-        generics.types.is_empty() && match ty.sty {
-            ty::TyBareFn(_, fn_ty) => fn_ty.abi != Abi::Rust,
-            _ => false,
-        }
-    } else {
-        false
-    }
-}
-
 pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind {
     let closure_doc = cdata.lookup_item(closure_id);
     let closure_kind_doc = reader::get_doc(closure_doc, tag_items_closure_kind);
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index c2d962b032f..4748c62921d 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -3281,8 +3281,7 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>,
         for cnum in sess.cstore.crates() {
             let syms = sess.cstore.reachable_ids(cnum);
             reachable_symbols.extend(syms.into_iter().filter(|did| {
-                sess.cstore.is_extern_fn(shared_ccx.tcx(), *did) ||
-                sess.cstore.is_static(*did)
+                sess.cstore.is_extern_item(shared_ccx.tcx(), *did)
             }).map(|did| {
                 sess.cstore.item_symbol(did)
             }));
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index cc5f30e2184..9953947eb52 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -316,6 +316,11 @@ pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option<Inte
     })
 }
 
+pub fn contains_extern_indicator(diag: &Handler, attrs: &[Attribute]) -> bool {
+    contains_name(attrs, "no_mangle") ||
+        find_export_name_attr(diag, attrs).is_some()
+}
+
 #[derive(Copy, Clone, PartialEq)]
 pub enum InlineAttr {
     None,