mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-19 19:17:31 +00:00
Validate inline attribute arguments
This commit is contained in:
parent
eb1b500a9a
commit
c9d0967383
@ -861,7 +861,7 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
|||||||
encode_attributes(rbml_w, &ast_method.attrs);
|
encode_attributes(rbml_w, &ast_method.attrs);
|
||||||
let scheme = ty::lookup_item_type(ecx.tcx, m.def_id);
|
let scheme = ty::lookup_item_type(ecx.tcx, m.def_id);
|
||||||
let any_types = !scheme.generics.types.is_empty();
|
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),
|
encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
|
||||||
ast_item_opt.unwrap()));
|
ast_item_opt.unwrap()));
|
||||||
}
|
}
|
||||||
@ -954,14 +954,6 @@ const FN_FAMILY: char = 'f';
|
|||||||
const STATIC_METHOD_FAMILY: char = 'F';
|
const STATIC_METHOD_FAMILY: char = 'F';
|
||||||
const METHOD_FAMILY: char = 'h';
|
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.
|
// Encodes the inherent implementations of a structure, enumeration, or trait.
|
||||||
fn encode_inherent_implementations(ecx: &EncodeContext,
|
fn encode_inherent_implementations(ecx: &EncodeContext,
|
||||||
rbml_w: &mut Encoder,
|
rbml_w: &mut Encoder,
|
||||||
@ -1067,7 +1059,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
|||||||
encode_name(rbml_w, item.ident.name);
|
encode_name(rbml_w, item.ident.name);
|
||||||
encode_path(rbml_w, path);
|
encode_path(rbml_w, path);
|
||||||
encode_attributes(rbml_w, &item.attrs);
|
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));
|
encode_inlined_item(ecx, rbml_w, IIItemRef(item));
|
||||||
}
|
}
|
||||||
if tps_len == 0 {
|
if tps_len == 0 {
|
||||||
|
@ -26,20 +26,10 @@ use syntax::abi;
|
|||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast_map;
|
use syntax::ast_map;
|
||||||
use syntax::ast_util::{is_local, PostExpansionMethod};
|
use syntax::ast_util::{is_local, PostExpansionMethod};
|
||||||
use syntax::attr::{InlineAlways, InlineHint, InlineNever, InlineNone};
|
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::visit::Visitor;
|
use syntax::visit::Visitor;
|
||||||
use syntax::visit;
|
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
|
// Returns true if the given set of generics implies that the item it's
|
||||||
// associated with must be inlined.
|
// associated with must be inlined.
|
||||||
fn generics_require_inlining(generics: &ast::Generics) -> bool {
|
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
|
// monomorphized or it was marked with `#[inline]`. This will only return
|
||||||
// true for functions.
|
// true for functions.
|
||||||
fn item_might_be_inlined(item: &ast::Item) -> bool {
|
fn item_might_be_inlined(item: &ast::Item) -> bool {
|
||||||
if attributes_specify_inlining(&item.attrs) {
|
if attr::requests_inline(&item.attrs) {
|
||||||
return true
|
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,
|
fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method,
|
||||||
impl_src: ast::DefId) -> bool {
|
impl_src: ast::DefId) -> bool {
|
||||||
if attributes_specify_inlining(&method.attrs) ||
|
if attr::requests_inline(&method.attrs) ||
|
||||||
generics_require_inlining(method.pe_generics()) {
|
generics_require_inlining(method.pe_generics()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -201,8 +191,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
|||||||
match *impl_item {
|
match *impl_item {
|
||||||
ast::MethodImplItem(ref method) => {
|
ast::MethodImplItem(ref method) => {
|
||||||
if generics_require_inlining(method.pe_generics()) ||
|
if generics_require_inlining(method.pe_generics()) ||
|
||||||
attributes_specify_inlining(
|
attr::requests_inline(&method.attrs) {
|
||||||
&method.attrs) {
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
let impl_did = self.tcx
|
let impl_did = self.tcx
|
||||||
|
@ -435,7 +435,7 @@ pub fn set_inline_hint(f: ValueRef) {
|
|||||||
pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
|
pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
|
||||||
use syntax::attr::*;
|
use syntax::attr::*;
|
||||||
// Set the inline hint if there is one
|
// 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),
|
InlineHint => set_inline_hint(llfn),
|
||||||
InlineAlways => set_always_inline(llfn),
|
InlineAlways => set_always_inline(llfn),
|
||||||
InlineNever => set_no_inline(llfn),
|
InlineNever => set_no_inline(llfn),
|
||||||
|
@ -292,7 +292,7 @@ pub enum InlineAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Determine what `#[inline]` attribute is present in `attrs`, if any.
|
/// 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]
|
// FIXME (#2809)---validate the usage of #[inline] and #[inline]
|
||||||
attrs.iter().fold(InlineNone, |ia,attr| {
|
attrs.iter().fold(InlineNone, |ia,attr| {
|
||||||
match attr.node.value.node {
|
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" => {
|
MetaList(ref n, ref items) if *n == "inline" => {
|
||||||
mark_used(attr);
|
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
|
InlineAlways
|
||||||
} else if contains_name(&items[..], "never") {
|
} else if contains_name(&items[..], "never") {
|
||||||
InlineNever
|
InlineNever
|
||||||
} else {
|
} else {
|
||||||
InlineHint
|
diagnostic.map(|d|{ d.span_err((*items[0]).span, "invalid argument"); });
|
||||||
|
InlineNone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => ia
|
_ => ia
|
||||||
@ -317,7 +321,7 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr {
|
|||||||
|
|
||||||
/// True if `#[inline]` or `#[inline(always)]` is present in `attrs`.
|
/// True if `#[inline]` or `#[inline(always)]` is present in `attrs`.
|
||||||
pub fn requests_inline(attrs: &[Attribute]) -> bool {
|
pub fn requests_inline(attrs: &[Attribute]) -> bool {
|
||||||
match find_inline_attr(attrs) {
|
match find_inline_attr(None, attrs) {
|
||||||
InlineHint | InlineAlways => true,
|
InlineHint | InlineAlways => true,
|
||||||
InlineNone | InlineNever => false,
|
InlineNone | InlineNever => false,
|
||||||
}
|
}
|
||||||
|
24
src/test/compile-fail/invalid-inline.rs
Normal file
24
src/test/compile-fail/invalid-inline.rs
Normal file
@ -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 <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(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() {}
|
Loading…
Reference in New Issue
Block a user