diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 629b19300e6..bb7fd40ced5 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -861,7 +861,7 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_attributes(rbml_w, &ast_method.attrs); let scheme = ty::lookup_item_type(ecx.tcx, m.def_id); let any_types = !scheme.generics.types.is_empty(); - if any_types || is_default_impl || should_inline(&ast_method.attrs) { + if any_types || is_default_impl || attr::requests_inline(&ast_method.attrs) { encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id), ast_item_opt.unwrap())); } @@ -954,14 +954,6 @@ const FN_FAMILY: char = 'f'; const STATIC_METHOD_FAMILY: char = 'F'; const METHOD_FAMILY: char = 'h'; -fn should_inline(attrs: &[ast::Attribute]) -> bool { - use syntax::attr::*; - match find_inline_attr(attrs) { - InlineNone | InlineNever => false, - InlineHint | InlineAlways => true - } -} - // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(ecx: &EncodeContext, rbml_w: &mut Encoder, @@ -1067,7 +1059,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_name(rbml_w, item.ident.name); encode_path(rbml_w, path); encode_attributes(rbml_w, &item.attrs); - if tps_len > 0 || should_inline(&item.attrs) { + if tps_len > 0 || attr::requests_inline(&item.attrs) { encode_inlined_item(ecx, rbml_w, IIItemRef(item)); } if tps_len == 0 { diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 7774314b6e0..4fd5a02b052 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -26,20 +26,10 @@ use syntax::abi; use syntax::ast; use syntax::ast_map; use syntax::ast_util::{is_local, PostExpansionMethod}; -use syntax::attr::{InlineAlways, InlineHint, InlineNever, InlineNone}; use syntax::attr; use syntax::visit::Visitor; use syntax::visit; -// Returns true if the given set of attributes contains the `#[inline]` -// attribute. -fn attributes_specify_inlining(attrs: &[ast::Attribute]) -> bool { - match attr::find_inline_attr(attrs) { - InlineNone | InlineNever => false, - InlineAlways | InlineHint => true, - } -} - // Returns true if the given set of generics implies that the item it's // associated with must be inlined. fn generics_require_inlining(generics: &ast::Generics) -> bool { @@ -50,7 +40,7 @@ fn generics_require_inlining(generics: &ast::Generics) -> bool { // monomorphized or it was marked with `#[inline]`. This will only return // true for functions. fn item_might_be_inlined(item: &ast::Item) -> bool { - if attributes_specify_inlining(&item.attrs) { + if attr::requests_inline(&item.attrs) { return true } @@ -65,7 +55,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool { fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method, impl_src: ast::DefId) -> bool { - if attributes_specify_inlining(&method.attrs) || + if attr::requests_inline(&method.attrs) || generics_require_inlining(method.pe_generics()) { return true } @@ -201,8 +191,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { match *impl_item { ast::MethodImplItem(ref method) => { if generics_require_inlining(method.pe_generics()) || - attributes_specify_inlining( - &method.attrs) { + attr::requests_inline(&method.attrs) { true } else { let impl_did = self.tcx diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 9c0aa9f6957..6b4f4c11003 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -435,7 +435,7 @@ pub fn set_inline_hint(f: ValueRef) { pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) { use syntax::attr::*; // Set the inline hint if there is one - match find_inline_attr(attrs) { + match find_inline_attr(Some(ccx.sess().diagnostic()), attrs) { InlineHint => set_inline_hint(llfn), InlineAlways => set_always_inline(llfn), InlineNever => set_no_inline(llfn), diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 62e676891a0..4fc08c0c2b2 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -292,7 +292,7 @@ pub enum InlineAttr { } /// Determine what `#[inline]` attribute is present in `attrs`, if any. -pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { +pub fn find_inline_attr(diagnostic: Option<&SpanHandler>, attrs: &[Attribute]) -> InlineAttr { // FIXME (#2809)---validate the usage of #[inline] and #[inline] attrs.iter().fold(InlineNone, |ia,attr| { match attr.node.value.node { @@ -302,12 +302,16 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { } MetaList(ref n, ref items) if *n == "inline" => { mark_used(attr); - if contains_name(&items[..], "always") { + if items.len() != 1 { + diagnostic.map(|d|{ d.span_err(attr.span, "expected one argument"); }); + InlineNone + } else if contains_name(&items[..], "always") { InlineAlways } else if contains_name(&items[..], "never") { InlineNever } else { - InlineHint + diagnostic.map(|d|{ d.span_err((*items[0]).span, "invalid argument"); }); + InlineNone } } _ => ia @@ -317,7 +321,7 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { /// True if `#[inline]` or `#[inline(always)]` is present in `attrs`. pub fn requests_inline(attrs: &[Attribute]) -> bool { - match find_inline_attr(attrs) { + match find_inline_attr(None, attrs) { InlineHint | InlineAlways => true, InlineNone | InlineNever => false, } diff --git a/src/test/compile-fail/invalid-inline.rs b/src/test/compile-fail/invalid-inline.rs new file mode 100644 index 00000000000..ad89087d660 --- /dev/null +++ b/src/test/compile-fail/invalid-inline.rs @@ -0,0 +1,24 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![allow(dead_code)] + +#[inline(please_no)] //~ ERROR invalid argument +fn a() { +} + +#[inline(please,no)] //~ ERROR expected one argument +fn b() { +} + +#[inline()] //~ ERROR expected one argument +fn c() { +} + +fn main() {}