]> git.lizzy.rs Git - rust.git/commitdiff
Merge branch 'incr_attr_queries' of https://github.com/wesleywiser/rust into update...
authorAlex Crichton <alex@alexcrichton.com>
Wed, 7 Mar 2018 15:13:21 +0000 (07:13 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 7 Mar 2018 15:13:21 +0000 (07:13 -0800)
27 files changed:
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/check_attr.rs
src/librustc/hir/mod.rs
src/librustc/ich/impls_hir.rs
src/librustc/middle/reachable.rs
src/librustc/mir/mono.rs
src/librustc/ty/instance.rs
src/librustc/ty/maps/config.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/on_disk_cache.rs
src/librustc/ty/maps/plumbing.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/transform/inline.rs
src/librustc_trans/attributes.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/base.rs
src/librustc_trans/consts.rs
src/librustc_trans_utils/diagnostics.rs [deleted file]
src/librustc_trans_utils/lib.rs
src/librustc_trans_utils/symbol_names.rs
src/librustc_trans_utils/trans_crate.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/libsyntax/attr.rs
src/libsyntax/diagnostic_list.rs

index 84fdeba4ab3ccbe3742c52c591f306490979484b..ed46296389da4ba4f0ad96d6f5f83d3fca4183fe 100644 (file)
@@ -559,6 +559,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] IsReachableNonGeneric(DefId),
     [] IsMirAvailable(DefId),
     [] ItemAttrs(DefId),
+    [] TransFnAttrs(DefId),
     [] FnArgNames(DefId),
     [] DylibDepFormats(CrateNum),
     [] IsPanicRuntime(CrateNum),
@@ -626,8 +627,6 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [input] AllCrateNums,
     [] ExportedSymbols(CrateNum),
     [eval_always] CollectAndPartitionTranslationItems,
-    [] ExportName(DefId),
-    [] ContainsExternIndicator(DefId),
     [] IsTranslatedItem(DefId),
     [] CodegenUnit(InternedString),
     [] CompileCodegenUnit(InternedString),
@@ -637,7 +636,6 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
 
     [input] TargetFeaturesWhitelist,
-    [] TargetFeaturesEnabled(DefId),
 
     [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
 
index a073910fdc83f1d06d23d655189d044a56ea05b7..d22703452605b6bb242a0b91d956ef22fe47d955 100644 (file)
@@ -47,7 +47,7 @@ struct CheckAttrVisitor<'a, 'tcx: 'a> {
 impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
     /// Check any attribute.
     fn check_attributes(&self, item: &hir::Item, target: Target) {
-        self.tcx.target_features_enabled(self.tcx.hir.local_def_id(item.id));
+        self.tcx.trans_fn_attrs(self.tcx.hir.local_def_id(item.id));
 
         for attr in &item.attrs {
             if let Some(name) = attr.name() {
index c4873cb83076a1cb636a27aa3ba08b8cdb5ed7c2..f4638c23c5f4bf35c721f6e8f7915e42064061fa 100644 (file)
 use hir::def::Def;
 use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
 use util::nodemap::{NodeMap, FxHashSet};
+use mir::mono::Linkage;
 
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::codemap::{self, Spanned};
 use syntax::abi::Abi;
 use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
+use syntax::attr::InlineAttr;
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
@@ -2210,3 +2212,51 @@ pub struct TraitCandidate {
 pub fn provide(providers: &mut Providers) {
     providers.describe_def = map::describe_def;
 }
+
+#[derive(Clone, RustcEncodable, RustcDecodable, Hash)]
+pub struct TransFnAttrs {
+    pub flags: TransFnAttrFlags,
+    pub inline: InlineAttr,
+    pub export_name: Option<Symbol>,
+    pub target_features: Vec<Symbol>,
+    pub linkage: Option<Linkage>,
+}
+
+bitflags! {
+    #[derive(RustcEncodable, RustcDecodable)]
+    pub struct TransFnAttrFlags: u8 {
+        const COLD                      = 0b0000_0001;
+        const ALLOCATOR                 = 0b0000_0010;
+        const UNWIND                    = 0b0000_0100;
+        const RUSTC_ALLOCATOR_NOUNWIND  = 0b0000_1000;
+        const NAKED                     = 0b0001_0000;
+        const NO_MANGLE                 = 0b0010_0000;
+        const RUSTC_STD_INTERNAL_SYMBOL = 0b0100_0000;
+    }
+}
+
+impl TransFnAttrs {
+    pub fn new() -> TransFnAttrs {
+        TransFnAttrs {
+            flags: TransFnAttrFlags::empty(),
+            inline: InlineAttr::None,
+            export_name: None,
+            target_features: vec![],
+            linkage: None,
+        }
+    }
+
+    /// True if `#[inline]` or `#[inline(always)]` is present.
+    pub fn requests_inline(&self) -> bool {
+        match self.inline {
+            InlineAttr::Hint | InlineAttr::Always => true,
+            InlineAttr::None | InlineAttr::Never => false,
+        }
+    }
+
+    /// True if `#[no_mangle]` or `#[export_name(...)]` is present.
+    pub fn contains_extern_indicator(&self) -> bool {
+        self.flags.contains(TransFnAttrFlags::NO_MANGLE) || self.export_name.is_some()
+    }
+}
+
index 7dca96f94e655f8b4ff318f9f24d69d875391471..faad3f3563164e444e6d9fce75877ff8ce86025c 100644 (file)
@@ -19,6 +19,7 @@
                                            StableHasher, StableHasherResult};
 use std::mem;
 use syntax::ast;
+use syntax::attr;
 
 impl<'gcx> HashStable<StableHashingContext<'gcx>> for DefId {
     #[inline]
@@ -1138,6 +1139,43 @@ fn to_stable_hash_key(&self,
     }
 }
 
+impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrs
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'hir>,
+                                          hasher: &mut StableHasher<W>) {
+        let hir::TransFnAttrs {
+            flags,
+            inline,
+            export_name,
+            ref target_features,
+            linkage,
+        } = *self;
+
+        flags.hash_stable(hcx, hasher);
+        inline.hash_stable(hcx, hasher);
+        export_name.hash_stable(hcx, hasher);
+        target_features.hash_stable(hcx, hasher);
+        linkage.hash_stable(hcx, hasher);
+    }
+}
+
+impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrFlags
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'hir>,
+                                          hasher: &mut StableHasher<W>) {
+        self.bits().hash_stable(hcx, hasher);
+    }
+}
+
+impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'hir>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+    }
+}
 
 impl_stable_hash_for!(struct hir::Freevar {
     def,
index 5658b5b6832915ce29946bdb96fe9b85364c2122..48a62c8c14d6969e00b20916ba05ecd55ee4c682 100644 (file)
@@ -15,6 +15,7 @@
 // makes all other generics or inline functions that it references
 // reachable as well.
 
+use hir::TransFnAttrs;
 use hir::map as hir_map;
 use hir::def::Def;
 use hir::def_id::{DefId, CrateNum};
@@ -43,8 +44,8 @@ fn generics_require_inlining(generics: &hir::Generics) -> bool {
 // Returns true if the given item must be inlined because it may be
 // monomorphized or it was marked with `#[inline]`. This will only return
 // true for functions.
-fn item_might_be_inlined(item: &hir::Item) -> bool {
-    if attr::requests_inline(&item.attrs) {
+fn item_might_be_inlined(item: &hir::Item, attrs: TransFnAttrs) -> bool {
+    if attrs.requests_inline() {
         return true
     }
 
@@ -60,14 +61,15 @@ fn item_might_be_inlined(item: &hir::Item) -> bool {
 fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      impl_item: &hir::ImplItem,
                                      impl_src: DefId) -> bool {
-    if attr::requests_inline(&impl_item.attrs) ||
+    let trans_fn_attrs = tcx.trans_fn_attrs(impl_item.hir_id.owner_def_id());
+    if trans_fn_attrs.requests_inline() ||
         generics_require_inlining(&impl_item.generics) {
         return true
     }
     if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) {
         match tcx.hir.find(impl_node_id) {
             Some(hir_map::NodeItem(item)) =>
-                item_might_be_inlined(&item),
+                item_might_be_inlined(&item, trans_fn_attrs),
             Some(..) | None =>
                 span_bug!(impl_item.span, "impl did is not an item")
         }
@@ -160,7 +162,8 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
         match self.tcx.hir.find(node_id) {
             Some(hir_map::NodeItem(item)) => {
                 match item.node {
-                    hir::ItemFn(..) => item_might_be_inlined(&item),
+                    hir::ItemFn(..) =>
+                        item_might_be_inlined(&item, self.tcx.trans_fn_attrs(def_id)),
                     _ => false,
                 }
             }
@@ -176,8 +179,9 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
                 match impl_item.node {
                     hir::ImplItemKind::Const(..) => true,
                     hir::ImplItemKind::Method(..) => {
+                        let attrs = self.tcx.trans_fn_attrs(def_id);
                         if generics_require_inlining(&impl_item.generics) ||
-                                attr::requests_inline(&impl_item.attrs) {
+                                attrs.requests_inline() {
                             true
                         } else {
                             let impl_did = self.tcx
@@ -229,7 +233,7 @@ fn propagate_node(&mut self, node: &hir_map::Node<'tcx>,
                     false
                 };
                 let def_id = self.tcx.hir.local_def_id(item.id);
-                let is_extern = self.tcx.contains_extern_indicator(def_id);
+                let is_extern = self.tcx.trans_fn_attrs(def_id).contains_extern_indicator();
                 if reachable || is_extern {
                     self.reachable_symbols.insert(search_item);
                 }
@@ -246,7 +250,8 @@ fn propagate_node(&mut self, node: &hir_map::Node<'tcx>,
             hir_map::NodeItem(item) => {
                 match item.node {
                     hir::ItemFn(.., body) => {
-                        if item_might_be_inlined(&item) {
+                        let def_id = self.tcx.hir.local_def_id(item.id);
+                        if item_might_be_inlined(&item, self.tcx.trans_fn_attrs(def_id)) {
                             self.visit_nested_body(body);
                         }
                     }
index 7f8f2e9b90603f4a339b91cc96bf74a2bedaed89..d8eac2b415989a698fd0f7a1cd74372fbb2698f2 100644 (file)
@@ -73,7 +73,7 @@ pub struct CodegenUnit<'tcx> {
     size_estimate: Option<usize>,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub enum Linkage {
     External,
     AvailableExternally,
index f4b5ffbb7dc4044780382598c62258d2e636d425..a5f0abb9bc05c2348fccb8e4fb1b2cb4a29d2d82 100644 (file)
@@ -96,7 +96,6 @@ pub fn requires_local<'a>(
         &self,
         tcx: TyCtxt<'a, 'tcx, 'tcx>
     ) -> bool {
-        use syntax::attr::requests_inline;
         if self.is_inline(tcx) {
             return true
         }
@@ -106,8 +105,8 @@ pub fn requires_local<'a>(
             // available to normal end-users.
             return true
         }
-        requests_inline(&self.attrs(tcx)[..]) ||
-            tcx.is_const_fn(self.def_id())
+        let trans_fn_attrs = tcx.trans_fn_attrs(self.def_id());
+        trans_fn_attrs.requests_inline() || tcx.is_const_fn(self.def_id())
     }
 }
 
index cfc552bdc85c56a84a0b65aee363c43e75edd565..d880b022e2f18c90c981882b70a6b79d69bac763 100644 (file)
@@ -687,8 +687,8 @@ fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 impl_disk_cacheable_query!(mir_borrowck, |def_id| def_id.is_local());
 impl_disk_cacheable_query!(mir_const_qualif, |def_id| def_id.is_local());
 impl_disk_cacheable_query!(check_match, |def_id| def_id.is_local());
-impl_disk_cacheable_query!(contains_extern_indicator, |_| true);
 impl_disk_cacheable_query!(def_symbol_name, |_| true);
 impl_disk_cacheable_query!(type_of, |def_id| def_id.is_local());
 impl_disk_cacheable_query!(predicates_of, |def_id| def_id.is_local());
 impl_disk_cacheable_query!(used_trait_imports, |def_id| def_id.is_local());
+impl_disk_cacheable_query!(trans_fn_attrs, |_| true);
index 2ef97b2673d6efddb6456aa8a2af8f1418cd8f47..43a71f1c0d367ab385449be5ecd9a546e202b7d4 100644 (file)
@@ -12,7 +12,7 @@
 use errors::DiagnosticBuilder;
 use hir::def_id::{CrateNum, DefId, DefIndex};
 use hir::def::{Def, Export};
-use hir::{self, TraitCandidate, ItemLocalId};
+use hir::{self, TraitCandidate, ItemLocalId, TransFnAttrs};
 use hir::svh::Svh;
 use lint;
 use middle::borrowck::BorrowCheckResult;
     [] fn lookup_stability: LookupStability(DefId) -> Option<&'tcx attr::Stability>,
     [] fn lookup_deprecation_entry: LookupDeprecationEntry(DefId) -> Option<DeprecationEntry>,
     [] fn item_attrs: ItemAttrs(DefId) -> Lrc<[ast::Attribute]>,
+    [] fn trans_fn_attrs: trans_fn_attrs(DefId) -> TransFnAttrs,
     [] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
     [] fn impl_parent: ImplParent(DefId) -> Option<DefId>,
     [] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
     [] fn collect_and_partition_translation_items:
         collect_and_partition_translation_items_node(CrateNum)
         -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
-    [] fn export_name: ExportName(DefId) -> Option<Symbol>,
-    [] fn contains_extern_indicator: ContainsExternIndicator(DefId) -> bool,
     [] fn symbol_export_level: GetSymbolExportLevel(DefId) -> SymbolExportLevel,
     [] fn is_translated_item: IsTranslatedItem(DefId) -> bool,
     [] fn codegen_unit: CodegenUnit(InternedString) -> Arc<CodegenUnit<'tcx>>,
 
     [] fn target_features_whitelist:
         target_features_whitelist_node(CrateNum) -> Lrc<FxHashSet<String>>,
-    [] fn target_features_enabled: TargetFeaturesEnabled(DefId) -> Lrc<Vec<String>>,
 
     // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
     [] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>)
@@ -403,6 +401,10 @@ fn features_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
     DepConstructor::Features
 }
 
+fn trans_fn_attrs<'tcx>(id: DefId) -> DepConstructor<'tcx> {
+    DepConstructor::TransFnAttrs { 0: id }
+}
+
 fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
     DepConstructor::EraseRegionsTy { ty }
 }
index 65f2d476475e979eae28a4e212939938fb5e93d7..b18837ff35aa81b86348e3b47567b0e38c68bea3 100644 (file)
@@ -217,9 +217,9 @@ pub fn serialize<'a, 'tcx, E>(&self,
                 encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
                 encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
                 encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
-                encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?;
                 encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
                 encode_query_results::<check_match, _>(tcx, enc, qri)?;
+                encode_query_results::<trans_fn_attrs, _>(tcx, enc, qri)?;
             }
 
             // Encode diagnostics
index 13f286d6a26868250d6fb7d1b5b8eb2c7dfe8553..fcc69f3b2c39ee9e1acce9435222f15f768f432f 100644 (file)
@@ -854,6 +854,7 @@ macro_rules! force {
         DepKind::IsReachableNonGeneric => { force!(is_reachable_non_generic, def_id!()); }
         DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
         DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
+        DepKind::TransFnAttrs => { force!(trans_fn_attrs, def_id!()); }
         DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
         DepKind::DylibDepFormats => { force!(dylib_dependency_formats, krate!()); }
         DepKind::IsPanicRuntime => { force!(is_panic_runtime, krate!()); }
@@ -925,15 +926,10 @@ macro_rules! force {
         DepKind::CollectAndPartitionTranslationItems => {
             force!(collect_and_partition_translation_items, LOCAL_CRATE);
         }
-        DepKind::ExportName => { force!(export_name, def_id!()); }
-        DepKind::ContainsExternIndicator => {
-            force!(contains_extern_indicator, def_id!());
-        }
         DepKind::IsTranslatedItem => { force!(is_translated_item, def_id!()); }
         DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
 
         DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
-        DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); }
 
         DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); }
         DepKind::Features => { force!(features_query, LOCAL_CRATE); }
@@ -997,10 +993,10 @@ pub fn load_from_on_disk_cache(&self, tcx: TyCtxt) {
     MirConstQualif => mir_const_qualif,
     SymbolName => def_symbol_name,
     ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static,
-    ContainsExternIndicator => contains_extern_indicator,
     CheckMatch => check_match,
     TypeOfItem => type_of,
     GenericsOfItem => generics_of,
     PredicatesOfItem => predicates_of,
     UsedTraitImports => used_trait_imports,
+    TransFnAttrs => trans_fn_attrs,
 );
index d19ab89459146401069d45c7488d7fa80697c983..830121b446fca3e565f0a5921f805dcbf9997289 100644 (file)
@@ -832,7 +832,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
         } else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
             let generics = self.tcx.generics_of(def_id);
             let types = generics.parent_types as usize + generics.types.len();
-            let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs);
+            let needs_inline = types > 0 || tcx.trans_fn_attrs(def_id).requests_inline();
             let is_const_fn = sig.constness == hir::Constness::Const;
             let ast = if is_const_fn { Some(body) } else { None };
             let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
@@ -1123,7 +1123,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 hir::ItemConst(..) => self.encode_optimized_mir(def_id),
                 hir::ItemFn(_, _, constness, _, ref generics, _) => {
                     let has_tps = generics.ty_params().next().is_some();
-                    let needs_inline = has_tps || attr::requests_inline(&item.attrs);
+                    let needs_inline = has_tps || tcx.trans_fn_attrs(def_id).requests_inline();
                     let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
                     if needs_inline || constness == hir::Constness::Const || always_encode_mir {
                         self.encode_optimized_mir(def_id)
index 1fba436d405787f21c9b0ca5836da9cb9f3fec66..0f512569adf9757f1bd07d1f7e35056105029c36 100644 (file)
 //! this is not implemented however: a mono item will be produced
 //! regardless of whether it is actually needed or not.
 
-use rustc::hir;
+use rustc::hir::{self, TransFnAttrFlags};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 
 use rustc::hir::map as hir_map;
 
 use rustc_data_structures::bitvec::BitVector;
 
-use syntax::attr;
-
 use std::iter;
 
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
@@ -985,8 +983,8 @@ fn is_root(&self, def_id: DefId) -> bool {
             MonoItemCollectionMode::Lazy => {
                 self.entry_fn == Some(def_id) ||
                 self.tcx.is_reachable_non_generic(def_id) ||
-                attr::contains_name(&self.tcx.get_attrs(def_id),
-                                    "rustc_std_internal_symbol")
+                self.tcx.trans_fn_attrs(def_id).flags.contains(
+                    TransFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
             }
         }
     }
index 7c86f5a4b1a84fce0f87807b4745ba719715e4b6..38b8ffc6b9c806f6a3b04197b80f575058b26856 100644 (file)
@@ -21,7 +21,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
 use syntax::ast;
-use syntax::attr::{self, InlineAttr};
+use syntax::attr::InlineAttr;
 use std::fmt::{self, Write};
 use std::iter;
 use rustc::mir::mono::Linkage;
 use syntax::codemap::Span;
 pub use rustc::mir::mono::MonoItem;
 
-pub fn linkage_by_name(name: &str) -> Option<Linkage> {
-    use rustc::mir::mono::Linkage::*;
-
-    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
-    // applicable to variable declarations and may not really make sense for
-    // Rust code in the first place but whitelist them anyway and trust that
-    // the user knows what s/he's doing. Who knows, unanticipated use cases
-    // may pop up in the future.
-    //
-    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
-    // and don't have to be, LLVM treats them as no-ops.
-    match name {
-        "appending" => Some(Appending),
-        "available_externally" => Some(AvailableExternally),
-        "common" => Some(Common),
-        "extern_weak" => Some(ExternalWeak),
-        "external" => Some(External),
-        "internal" => Some(Internal),
-        "linkonce" => Some(LinkOnceAny),
-        "linkonce_odr" => Some(LinkOnceODR),
-        "private" => Some(Private),
-        "weak" => Some(WeakAny),
-        "weak_odr" => Some(WeakODR),
-        _ => None,
-    }
-}
-
 /// Describes how a translation item will be instantiated in object files.
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub enum InstantiationMode {
@@ -141,8 +114,7 @@ fn instantiation_mode(&self,
                 // creating one copy of this `#[inline]` function which may
                 // conflict with upstream crates as it could be an exported
                 // symbol.
-                let attrs = instance.def.attrs(tcx);
-                match attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs) {
+                match tcx.trans_fn_attrs(instance.def_id()).inline {
                     InlineAttr::Always => InstantiationMode::LocalCopy,
                     _ => {
                         InstantiationMode::GloballyShared  { may_conflict: true }
@@ -165,21 +137,8 @@ fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Linkage> {
             MonoItem::GlobalAsm(..) => return None,
         };
 
-        let attributes = tcx.get_attrs(def_id);
-        if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") {
-            if let Some(linkage) = linkage_by_name(&name.as_str()) {
-                Some(linkage)
-            } else {
-                let span = tcx.hir.span_if_local(def_id);
-                if let Some(span) = span {
-                    tcx.sess.span_fatal(span, "invalid linkage specified")
-                } else {
-                    tcx.sess.fatal(&format!("invalid linkage specified: {}", name))
-                }
-            }
-        } else {
-            None
-        }
+        let trans_fn_attrs = tcx.trans_fn_attrs(def_id);
+        trans_fn_attrs.linkage
     }
 
     /// Returns whether this instance is instantiable - whether it has no unsatisfied
index 08a9757fb326ac79ee9500b8dbf8c9588a4e5cfe..64c702b99cdb3940350a841bef58b4717fa5ea70 100644 (file)
@@ -11,6 +11,7 @@
 //! Inlining pass for MIR functions
 
 use rustc::hir;
+use rustc::hir::TransFnAttrFlags;
 use rustc::hir::def_id::DefId;
 
 use rustc_data_structures::bitvec::BitVector;
@@ -206,10 +207,9 @@ fn should_inline(&self,
             return false;
         }
 
-        let attrs = tcx.get_attrs(callsite.callee);
-        let hint = attr::find_inline_attr(None, &attrs[..]);
+        let trans_fn_attrs = tcx.trans_fn_attrs(callsite.callee);
 
-        let hinted = match hint {
+        let hinted = match trans_fn_attrs.inline {
             // Just treat inline(always) as a hint for now,
             // there are cases that prevent inlining that we
             // need to check for first.
@@ -239,7 +239,7 @@ fn should_inline(&self,
         };
 
         // Significantly lower the threshold for inlining cold functions
-        if attr::contains_name(&attrs[..], "cold") {
+        if trans_fn_attrs.flags.contains(TransFnAttrFlags::COLD) {
             threshold /= 5;
         }
 
@@ -344,7 +344,7 @@ fn should_inline(&self,
             }
         }
 
-        if let attr::InlineAttr::Always = hint {
+        if let attr::InlineAttr::Always = trans_fn_attrs.inline {
             debug!("INLINING {:?} because inline(always) [cost={}]", callsite, cost);
             true
         } else {
index ffa3f7f401164d2664a86a349148a6fc7909f165..d5ec8d1b5526256573cf69552de26dc754f878fd 100644 (file)
 
 use std::ffi::{CStr, CString};
 
-use rustc::hir::Unsafety;
+use rustc::hir::TransFnAttrFlags;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::session::config::Sanitizer;
-use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
-use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 
 use llvm::{self, Attribute, ValueRef};
 use llvm::AttributePlace::Function;
 use llvm_util;
 pub use syntax::attr::{self, InlineAttr};
-use syntax::ast;
 use context::CodegenCx;
 
 /// Mark LLVM function to use provided inline heuristic.
@@ -102,31 +99,42 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
 /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
 /// attributes.
 pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
-    use syntax::attr::*;
-    let attrs = cx.tcx.get_attrs(id);
-    inline(llfn, find_inline_attr(Some(cx.sess().diagnostic()), &attrs));
+    let trans_fn_attrs = cx.tcx.trans_fn_attrs(id);
+
+    inline(llfn, trans_fn_attrs.inline);
 
     set_frame_pointer_elimination(cx, llfn);
     set_probestack(cx, llfn);
 
-    for attr in attrs.iter() {
-        if attr.check_name("cold") {
-            Attribute::Cold.apply_llfn(Function, llfn);
-        } else if attr.check_name("naked") {
-            naked(llfn, true);
-        } else if attr.check_name("allocator") {
-            Attribute::NoAlias.apply_llfn(
-                llvm::AttributePlace::ReturnValue, llfn);
-        } else if attr.check_name("unwind") {
-            unwind(llfn, true);
-        } else if attr.check_name("rustc_allocator_nounwind") {
-            unwind(llfn, false);
-        }
+    if trans_fn_attrs.flags.contains(TransFnAttrFlags::COLD) {
+        Attribute::Cold.apply_llfn(Function, llfn);
+    }
+    if trans_fn_attrs.flags.contains(TransFnAttrFlags::NAKED) {
+        naked(llfn, true);
+    }
+    if trans_fn_attrs.flags.contains(TransFnAttrFlags::ALLOCATOR) {
+        Attribute::NoAlias.apply_llfn(
+            llvm::AttributePlace::ReturnValue, llfn);
+    }
+    if trans_fn_attrs.flags.contains(TransFnAttrFlags::UNWIND) {
+        unwind(llfn, true);
+    }
+    if trans_fn_attrs.flags.contains(TransFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
+        unwind(llfn, false);
     }
 
-    let target_features = cx.tcx.target_features_enabled(id);
-    if !target_features.is_empty() {
-        let val = CString::new(target_features.join(",")).unwrap();
+    let features =
+        trans_fn_attrs.target_features
+        .iter()
+        .map(|f| {
+            let feature = &*f.as_str();
+            format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
+        })
+        .collect::<Vec<String>>()
+        .join(",");
+
+    if !features.is_empty() {
+        let val = CString::new(features).unwrap();
         llvm::AddFunctionAttrStringValue(
             llfn, llvm::AttributePlace::Function,
             cstr("target-features\0"), &val);
@@ -145,89 +153,4 @@ pub fn provide(providers: &mut Providers) {
             .map(|c| c.to_string())
             .collect())
     };
-
-    providers.target_features_enabled = |tcx, id| {
-        let whitelist = tcx.target_features_whitelist(LOCAL_CRATE);
-        let mut target_features = Vec::new();
-        for attr in tcx.get_attrs(id).iter() {
-            if !attr.check_name("target_feature") {
-                continue
-            }
-            if let Some(val) = attr.value_str() {
-                for feat in val.as_str().split(",").map(|f| f.trim()) {
-                    if !feat.is_empty() && !feat.contains('\0') {
-                        target_features.push(feat.to_string());
-                    }
-                }
-                let msg = "#[target_feature = \"..\"] is deprecated and will \
-                           eventually be removed, use \
-                           #[target_feature(enable = \"..\")] instead";
-                tcx.sess.span_warn(attr.span, &msg);
-                continue
-            }
-
-            if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
-                let msg = "#[target_feature(..)] can only be applied to \
-                           `unsafe` function";
-                tcx.sess.span_err(attr.span, msg);
-            }
-            from_target_feature(tcx, attr, &whitelist, &mut target_features);
-        }
-        Lrc::new(target_features)
-    };
-}
-
-fn from_target_feature(
-    tcx: TyCtxt,
-    attr: &ast::Attribute,
-    whitelist: &FxHashSet<String>,
-    target_features: &mut Vec<String>,
-) {
-    let list = match attr.meta_item_list() {
-        Some(list) => list,
-        None => {
-            let msg = "#[target_feature] attribute must be of the form \
-                       #[target_feature(..)]";
-            tcx.sess.span_err(attr.span, &msg);
-            return
-        }
-    };
-
-    for item in list {
-        if !item.check_name("enable") {
-            let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
-                       currently";
-            tcx.sess.span_err(item.span, &msg);
-            continue
-        }
-        let value = match item.value_str() {
-            Some(list) => list,
-            None => {
-                let msg = "#[target_feature] attribute must be of the form \
-                           #[target_feature(enable = \"..\")]";
-                tcx.sess.span_err(item.span, &msg);
-                continue
-            }
-        };
-        let value = value.as_str();
-        for feature in value.split(',') {
-            if whitelist.contains(feature) {
-                let llvm_feature = llvm_util::to_llvm_feature(&tcx.sess, feature);
-                target_features.push(format!("+{}", llvm_feature));
-                continue
-            }
-
-            let msg = format!("the feature named `{}` is not valid for \
-                               this target", feature);
-            let mut err = tcx.sess.struct_span_err(item.span, &msg);
-
-            if feature.starts_with("+") {
-                let valid = whitelist.contains(&feature[1..]);
-                if valid {
-                    err.help("consider removing the leading `+` in the feature name");
-                }
-            }
-            err.emit();
-        }
-    }
 }
index 739ae768ca29ca3b9de94e131c9c47fa99f21b63..fd79ae7435ed1b74857c187b5aaa5d8fcde9b661 100644 (file)
@@ -13,6 +13,7 @@
 
 use monomorphize::Instance;
 use rustc::hir;
+use rustc::hir::TransFnAttrFlags;
 use rustc::hir::def_id::CrateNum;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol, metadata_symbol_name};
@@ -21,7 +22,6 @@
 use rustc::ty::maps::Providers;
 use rustc::util::nodemap::{FxHashMap, DefIdSet};
 use rustc_allocator::ALLOCATOR_METHODS;
-use syntax::attr;
 
 pub type ExportedSymbols = FxHashMap<
     CrateNum,
@@ -256,9 +256,10 @@ fn symbol_export_level_provider(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportL
     // special symbols in the standard library for various plumbing between
     // core/std/allocators/etc. For example symbols used to hook up allocation
     // are not considered for export
-    let is_extern = tcx.contains_extern_indicator(sym_def_id);
-    let std_internal = attr::contains_name(&tcx.get_attrs(sym_def_id),
-                                           "rustc_std_internal_symbol");
+    let trans_fn_attrs = tcx.trans_fn_attrs(sym_def_id);
+    let is_extern = trans_fn_attrs.contains_extern_indicator();
+    let std_internal = trans_fn_attrs.flags.contains(TransFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
+
     if is_extern && !std_internal {
         SymbolExportLevel::C
     } else {
index beb7a091bdcfe29ddd1d4254c4fc65fddf398df4..3708f6f6ec4fcf0124c11a8c762d0d5d592c3335 100644 (file)
@@ -90,7 +90,6 @@
 use mir::operand::OperandValue;
 
 pub use rustc_trans_utils::check_for_rustc_errors_attr;
-pub use rustc_mir::monomorphize::item::linkage_by_name;
 
 pub struct StatRecorder<'a, 'tcx: 'a> {
     cx: &'a CodegenCx<'a, 'tcx>,
index fd9cb8c5a6bed38ff33bf598ca72b64ce75cd0f0..0ce3f729305b41cac5369c25c62cfabecdbe441b 100644 (file)
@@ -146,20 +146,12 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
             hir_map::NodeForeignItem(&hir::ForeignItem {
                 ref attrs, span, node: hir::ForeignItemStatic(..), ..
             }) => {
-
-                let g = if let Some(name) =
-                        attr::first_attr_value_str_by_name(&attrs, "linkage") {
+                let g = if let Some(linkage) = cx.tcx.trans_fn_attrs(def_id).linkage {
                     // If this is a static with a linkage specified, then we need to handle
                     // it a little specially. The typesystem prevents things like &T and
                     // extern "C" fn() from being non-null, so we can't just declare a
                     // static and call it a day. Some linkages (like weak) will make it such
                     // that the static actually has a null value.
-                    let linkage = match base::linkage_by_name(&name.as_str()) {
-                        Some(linkage) => linkage,
-                        None => {
-                            cx.sess().span_fatal(span, "invalid linkage specified");
-                        }
-                    };
                     let llty2 = match ty.sty {
                         ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx),
                         _ => {
diff --git a/src/librustc_trans_utils/diagnostics.rs b/src/librustc_trans_utils/diagnostics.rs
deleted file mode 100644 (file)
index 13fa15f..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![allow(non_snake_case)]
-
-register_long_diagnostics! {
-
-E0558: r##"
-The `export_name` attribute was malformed.
-
-Erroneous code example:
-
-```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
-#[export_name] // error: export_name attribute has invalid format
-pub fn something() {}
-
-fn main() {}
-```
-
-The `export_name` attribute expects a string in order to determine the name of
-the exported symbol. Example:
-
-```
-#[export_name = "some_function"] // ok!
-pub fn something() {}
-
-fn main() {}
-```
-"##,
-
-}
index 915f8d4588d9f7a0b338aae317d6c08695f33ee7..6a3fd21f3a771580390119ac49ff7e9ff7a02a9a 100644 (file)
@@ -37,7 +37,6 @@
 extern crate rustc_back;
 extern crate rustc_mir;
 extern crate rustc_incremental;
-#[macro_use]
 extern crate syntax;
 extern crate syntax_pos;
 #[macro_use] extern crate rustc_data_structures;
@@ -46,7 +45,6 @@
 
 use rustc::ty::TyCtxt;
 
-pub mod diagnostics;
 pub mod link;
 pub mod trans_crate;
 pub mod symbol_names;
index fb299bf7eea0c4ebadd4bea011c7ca19b7b16036..f9f93730255e6e302409d59615671653c1030cbf 100644 (file)
@@ -120,29 +120,6 @@ pub fn provide(providers: &mut Providers) {
         def_symbol_name,
         symbol_name,
 
-        export_name: |tcx, id| {
-            tcx.get_attrs(id).iter().fold(None, |ia, attr| {
-                if attr.check_name("export_name") {
-                    if let s @ Some(_) = attr.value_str() {
-                        s
-                    } else {
-                        struct_span_err!(tcx.sess, attr.span, E0558,
-                                         "export_name attribute has invalid format")
-                            .span_label(attr.span, "did you mean #[export_name=\"*\"]?")
-                            .emit();
-                        None
-                    }
-                } else {
-                    ia
-                }
-            })
-        },
-
-        contains_extern_indicator: |tcx, id| {
-            attr::contains_name(&tcx.get_attrs(id), "no_mangle") ||
-                tcx.export_name(id).is_some()
-        },
-
         ..*providers
     };
 }
@@ -287,7 +264,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
         return tcx.item_name(def_id).to_string();
     }
 
-    if let Some(name) = tcx.export_name(def_id) {
+    if let Some(name) = tcx.trans_fn_attrs(def_id).export_name {
         // Use provided name
         return name.to_string();
     }
index 784c662e3712586e086420aa2b7f4fefb6bf183f..0d4811c4b025dfd05c14eeaf3a9b5ac93f6ed70f 100644 (file)
@@ -44,6 +44,7 @@
 use rustc::middle::cstore::MetadataLoader;
 use rustc::dep_graph::DepGraph;
 use rustc_back::target::Target;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_mir::monomorphize::collector;
 use link::{build_link_meta, out_filename};
 
@@ -200,8 +201,9 @@ fn metadata_loader(&self) -> Box<MetadataLoader> {
 
     fn provide(&self, providers: &mut Providers) {
         ::symbol_names::provide(providers);
-        providers.target_features_enabled = |_tcx, _id| {
-            Lrc::new(Vec::new()) // Just a dummy
+
+        providers.target_features_whitelist = |_tcx, _cnum| {
+            Lrc::new(FxHashSet()) // Just a dummy
         };
     }
     fn provide_extern(&self, _providers: &mut Providers) {}
@@ -235,12 +237,8 @@ fn trans_crate<'a, 'tcx>(
                 MonoItem::Fn(inst) => {
                     let def_id = inst.def_id();
                     if def_id.is_local()  {
-                        let _ = tcx.export_name(def_id);
-                        let _ = tcx.contains_extern_indicator(def_id);
                         let _ = inst.def.is_inline(tcx);
-                        let attrs = inst.def.attrs(tcx);
-                        let _ =
-                            ::syntax::attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs);
+                        let _ = tcx.trans_fn_attrs(def_id);
                     }
                 }
                 _ => {}
index f7158593f0b6e37cd64d51e121afc009e2033392..1a7d8bb56780eb7cb7b444e7aa304bcec007648c 100644 (file)
 use middle::lang_items::SizedTraitLangItem;
 use middle::const_val::ConstVal;
 use middle::resolve_lifetime as rl;
+use rustc::mir::mono::Linkage;
 use rustc::traits::Reveal;
 use rustc::ty::subst::Substs;
 use rustc::ty::{ToPredicate, ReprOptions};
 use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::ty::util::IntTypeExt;
+use rustc::util::nodemap::FxHashSet;
 use util::nodemap::FxHashMap;
 
 use rustc_const_math::ConstInt;
 
 use syntax::{abi, ast};
+use syntax::ast::MetaItemKind;
+use syntax::attr::{InlineAttr, list_contains_name, mark_used};
 use syntax::codemap::Spanned;
 use syntax::symbol::{Symbol, keywords};
 use syntax_pos::{Span, DUMMY_SP};
 
-use rustc::hir::{self, map as hir_map};
+use rustc::hir::{self, map as hir_map, TransFnAttrs, TransFnAttrFlags, Unsafety};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::def::{Def, CtorKind};
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 
 ///////////////////////////////////////////////////////////////////////////
 // Main entry point
@@ -71,6 +75,7 @@ pub fn provide(providers: &mut Providers) {
         impl_trait_ref,
         impl_polarity,
         is_foreign_item,
+        trans_fn_attrs,
         ..*providers
     };
 }
@@ -1723,3 +1728,186 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id)
     }
 }
+
+fn from_target_feature(
+    tcx: TyCtxt,
+    attr: &ast::Attribute,
+    whitelist: &FxHashSet<String>,
+    target_features: &mut Vec<Symbol>,
+) {
+    let list = match attr.meta_item_list() {
+        Some(list) => list,
+        None => {
+            let msg = "#[target_feature] attribute must be of the form \
+                       #[target_feature(..)]";
+            tcx.sess.span_err(attr.span, &msg);
+            return
+        }
+    };
+
+    for item in list {
+        if !item.check_name("enable") {
+            let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
+                       currently";
+            tcx.sess.span_err(item.span, &msg);
+            continue
+        }
+        let value = match item.value_str() {
+            Some(list) => list,
+            None => {
+                let msg = "#[target_feature] attribute must be of the form \
+                           #[target_feature(enable = \"..\")]";
+                tcx.sess.span_err(item.span, &msg);
+                continue
+            }
+        };
+        let value = value.as_str();
+        for feature in value.split(',') {
+            if whitelist.contains(feature) {
+                target_features.push(Symbol::intern(feature));
+                continue
+            }
+
+            let msg = format!("the feature named `{}` is not valid for \
+                               this target", feature);
+            let mut err = tcx.sess.struct_span_err(item.span, &msg);
+
+            if feature.starts_with("+") {
+                let valid = whitelist.contains(&feature[1..]);
+                if valid {
+                    err.help("consider removing the leading `+` in the feature name");
+                }
+            }
+            err.emit();
+        }
+    }
+}
+
+fn linkage_by_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, name: &str) -> Linkage {
+    use rustc::mir::mono::Linkage::*;
+
+    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
+    // applicable to variable declarations and may not really make sense for
+    // Rust code in the first place but whitelist them anyway and trust that
+    // the user knows what s/he's doing. Who knows, unanticipated use cases
+    // may pop up in the future.
+    //
+    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
+    // and don't have to be, LLVM treats them as no-ops.
+    match name {
+        "appending" => Appending,
+        "available_externally" => AvailableExternally,
+        "common" => Common,
+        "extern_weak" => ExternalWeak,
+        "external" => External,
+        "internal" => Internal,
+        "linkonce" => LinkOnceAny,
+        "linkonce_odr" => LinkOnceODR,
+        "private" => Private,
+        "weak" => WeakAny,
+        "weak_odr" => WeakODR,
+        _ => {
+            let span = tcx.hir.span_if_local(def_id);
+            if let Some(span) = span {
+                tcx.sess.span_fatal(span, "invalid linkage specified")
+            } else {
+                tcx.sess.fatal(&format!("invalid linkage specified: {}", name))
+            }
+        }
+    }
+}
+
+fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAttrs {
+    let attrs = tcx.get_attrs(id);
+
+    let mut trans_fn_attrs = TransFnAttrs::new();
+
+    let whitelist = tcx.target_features_whitelist(LOCAL_CRATE);
+
+    for attr in attrs.iter() {
+        if attr.check_name("cold") {
+            trans_fn_attrs.flags |= TransFnAttrFlags::COLD;
+        } else if attr.check_name("allocator") {
+            trans_fn_attrs.flags |= TransFnAttrFlags::ALLOCATOR;
+        } else if attr.check_name("unwind") {
+            trans_fn_attrs.flags |= TransFnAttrFlags::UNWIND;
+        } else if attr.check_name("rustc_allocator_nounwind") {
+            trans_fn_attrs.flags |= TransFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND;
+        } else if attr.check_name("naked") {
+            trans_fn_attrs.flags |= TransFnAttrFlags::NAKED;
+        } else if attr.check_name("no_mangle") {
+            trans_fn_attrs.flags |= TransFnAttrFlags::NO_MANGLE;
+        } else if attr.check_name("rustc_std_internal_symbol") {
+            trans_fn_attrs.flags |= TransFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+        } else if attr.check_name("inline") {
+            trans_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
+                if attr.path != "inline" {
+                    return ia;
+                }
+                let meta = match attr.meta() {
+                    Some(meta) => meta.node,
+                    None => return ia,
+                };
+                match meta {
+                    MetaItemKind::Word => {
+                        mark_used(attr);
+                        InlineAttr::Hint
+                    }
+                    MetaItemKind::List(ref items) => {
+                        mark_used(attr);
+                        if items.len() != 1 {
+                            span_err!(tcx.sess.diagnostic(), attr.span, E0534,
+                                        "expected one argument");
+                            InlineAttr::None
+                        } else if list_contains_name(&items[..], "always") {
+                            InlineAttr::Always
+                        } else if list_contains_name(&items[..], "never") {
+                            InlineAttr::Never
+                        } else {
+                            span_err!(tcx.sess.diagnostic(), items[0].span, E0535,
+                                        "invalid argument");
+
+                            InlineAttr::None
+                        }
+                    }
+                    _ => ia,
+                }
+            });
+        } else if attr.check_name("export_name") {
+            if let s @ Some(_) = attr.value_str() {
+                trans_fn_attrs.export_name = s;
+            } else {
+                struct_span_err!(tcx.sess, attr.span, E0558,
+                                    "export_name attribute has invalid format")
+                    .span_label(attr.span, "did you mean #[export_name=\"*\"]?")
+                    .emit();
+            }
+        } else if attr.check_name("target_feature") {
+            if let Some(val) = attr.value_str() {
+                for feat in val.as_str().split(",").map(|f| f.trim()) {
+                    if !feat.is_empty() && !feat.contains('\0') {
+                        trans_fn_attrs.target_features.push(Symbol::intern(feat));
+                    }
+                }
+                let msg = "#[target_feature = \"..\"] is deprecated and will \
+                           eventually be removed, use \
+                           #[target_feature(enable = \"..\")] instead";
+                tcx.sess.span_warn(attr.span, &msg);
+                continue
+            }
+
+            if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
+                let msg = "#[target_feature(..)] can only be applied to \
+                           `unsafe` function";
+                tcx.sess.span_err(attr.span, msg);
+            }
+            from_target_feature(tcx, attr, &whitelist, &mut trans_fn_attrs.target_features);
+        } else if attr.check_name("linkage") {
+            if let Some(val) = attr.value_str() {
+                trans_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str()));
+            }
+        }
+    }
+
+    trans_fn_attrs
+}
index 6c195a991c24e9f2b2b8a29a74e55f77d919f24e..96b2ec745f132266794706278fa2fdf2a48d04eb 100644 (file)
@@ -3705,6 +3705,98 @@ fn fly(&self) {} // And now that's ok!
 ```
 "##,
 
+E0534: r##"
+The `inline` attribute was malformed.
+
+Erroneous code example:
+
+```ignore (compile_fail not working here; see Issue #43707)
+#[inline()] // error: expected one argument
+pub fn something() {}
+
+fn main() {}
+```
+
+The parenthesized `inline` attribute requires the parameter to be specified:
+
+```
+#[inline(always)]
+fn something() {}
+```
+
+or:
+
+```
+#[inline(never)]
+fn something() {}
+```
+
+Alternatively, a paren-less version of the attribute may be used to hint the
+compiler about inlining opportunity:
+
+```
+#[inline]
+fn something() {}
+```
+
+For more information about the inline attribute, read:
+https://doc.rust-lang.org/reference.html#inline-attributes
+"##,
+
+E0535: r##"
+An unknown argument was given to the `inline` attribute.
+
+Erroneous code example:
+
+```ignore (compile_fail not working here; see Issue #43707)
+#[inline(unknown)] // error: invalid argument
+pub fn something() {}
+
+fn main() {}
+```
+
+The `inline` attribute only supports two arguments:
+
+ * always
+ * never
+
+All other arguments given to the `inline` attribute will return this error.
+Example:
+
+```
+#[inline(never)] // ok!
+pub fn something() {}
+
+fn main() {}
+```
+
+For more information about the inline attribute, https:
+read://doc.rust-lang.org/reference.html#inline-attributes
+"##,
+
+E0558: r##"
+The `export_name` attribute was malformed.
+
+Erroneous code example:
+
+```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
+#[export_name] // error: export_name attribute has invalid format
+pub fn something() {}
+
+fn main() {}
+```
+
+The `export_name` attribute expects a string in order to determine the name of
+the exported symbol. Example:
+
+```
+#[export_name = "some_function"] // ok!
+pub fn something() {}
+
+fn main() {}
+```
+"##,
+
 E0559: r##"
 An unknown field was specified into an enum's structure variant.
 
index d0822b69aa692d079bc926331595db5ed2f2cc67..4818248129e70a1659a06b85c3c8c85bef99fd48 100644 (file)
@@ -520,7 +520,7 @@ pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
     first_attr_value_str_by_name(attrs, "crate_name")
 }
 
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum InlineAttr {
     None,
     Hint,
@@ -528,43 +528,6 @@ pub enum InlineAttr {
     Never,
 }
 
-/// Determine what `#[inline]` attribute is present in `attrs`, if any.
-pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> InlineAttr {
-    attrs.iter().fold(InlineAttr::None, |ia, attr| {
-        if attr.path != "inline" {
-            return ia;
-        }
-        let meta = match attr.meta() {
-            Some(meta) => meta.node,
-            None => return ia,
-        };
-        match meta {
-            MetaItemKind::Word => {
-                mark_used(attr);
-                InlineAttr::Hint
-            }
-            MetaItemKind::List(ref items) => {
-                mark_used(attr);
-                if items.len() != 1 {
-                    diagnostic.map(|d|{ span_err!(d, attr.span, E0534, "expected one argument"); });
-                    InlineAttr::None
-                } else if list_contains_name(&items[..], "always") {
-                    InlineAttr::Always
-                } else if list_contains_name(&items[..], "never") {
-                    InlineAttr::Never
-                } else {
-                    diagnostic.map(|d| {
-                        span_err!(d, items[0].span, E0535, "invalid argument");
-                    });
-
-                    InlineAttr::None
-                }
-            }
-            _ => ia,
-        }
-    })
-}
-
 #[derive(Copy, Clone, PartialEq)]
 pub enum UnwindAttr {
     Allowed,
@@ -610,13 +573,6 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
     })
 }
 
-/// True if `#[inline]` or `#[inline(always)]` is present in `attrs`.
-pub fn requests_inline(attrs: &[Attribute]) -> bool {
-    match find_inline_attr(None, attrs) {
-        InlineAttr::Hint | InlineAttr::Always => true,
-        InlineAttr::None | InlineAttr::Never => false,
-    }
-}
 
 /// Tests if a cfg-pattern matches the cfg set
 pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool {
index 84ab0336f1671ceb5ac88a31008ad3be9eb2f9bc..549ef88afcc63b1811be51180469f24c0d836894 100644 (file)
@@ -37,75 +37,6 @@ struct Bar<'a> {
 [RFC 438]: https://github.com/rust-lang/rfcs/pull/438
 "##,
 
-E0534: r##"
-The `inline` attribute was malformed.
-
-Erroneous code example:
-
-```ignore (compile_fail not working here; see Issue #43707)
-#[inline()] // error: expected one argument
-pub fn something() {}
-
-fn main() {}
-```
-
-The parenthesized `inline` attribute requires the parameter to be specified:
-
-```
-#[inline(always)]
-fn something() {}
-```
-
-or:
-
-```
-#[inline(never)]
-fn something() {}
-```
-
-Alternatively, a paren-less version of the attribute may be used to hint the
-compiler about inlining opportunity:
-
-```
-#[inline]
-fn something() {}
-```
-
-For more information about the inline attribute, read:
-https://doc.rust-lang.org/reference.html#inline-attributes
-"##,
-
-E0535: r##"
-An unknown argument was given to the `inline` attribute.
-
-Erroneous code example:
-
-```ignore (compile_fail not working here; see Issue #43707)
-#[inline(unknown)] // error: invalid argument
-pub fn something() {}
-
-fn main() {}
-```
-
-The `inline` attribute only supports two arguments:
-
- * always
- * never
-
-All other arguments given to the `inline` attribute will return this error.
-Example:
-
-```
-#[inline(never)] // ok!
-pub fn something() {}
-
-fn main() {}
-```
-
-For more information about the inline attribute, https:
-read://doc.rust-lang.org/reference.html#inline-attributes
-"##,
-
 E0536: r##"
 The `not` cfg-predicate was malformed.