Skip to content

Commit c9d0967

Browse files
committed
Validate inline attribute arguments
1 parent eb1b500 commit c9d0967

File tree

5 files changed

+38
-29
lines changed

5 files changed

+38
-29
lines changed

Diff for: src/librustc/metadata/encoder.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
861861
encode_attributes(rbml_w, &ast_method.attrs);
862862
let scheme = ty::lookup_item_type(ecx.tcx, m.def_id);
863863
let any_types = !scheme.generics.types.is_empty();
864-
if any_types || is_default_impl || should_inline(&ast_method.attrs) {
864+
if any_types || is_default_impl || attr::requests_inline(&ast_method.attrs) {
865865
encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
866866
ast_item_opt.unwrap()));
867867
}
@@ -954,14 +954,6 @@ const FN_FAMILY: char = 'f';
954954
const STATIC_METHOD_FAMILY: char = 'F';
955955
const METHOD_FAMILY: char = 'h';
956956

957-
fn should_inline(attrs: &[ast::Attribute]) -> bool {
958-
use syntax::attr::*;
959-
match find_inline_attr(attrs) {
960-
InlineNone | InlineNever => false,
961-
InlineHint | InlineAlways => true
962-
}
963-
}
964-
965957
// Encodes the inherent implementations of a structure, enumeration, or trait.
966958
fn encode_inherent_implementations(ecx: &EncodeContext,
967959
rbml_w: &mut Encoder,
@@ -1067,7 +1059,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
10671059
encode_name(rbml_w, item.ident.name);
10681060
encode_path(rbml_w, path);
10691061
encode_attributes(rbml_w, &item.attrs);
1070-
if tps_len > 0 || should_inline(&item.attrs) {
1062+
if tps_len > 0 || attr::requests_inline(&item.attrs) {
10711063
encode_inlined_item(ecx, rbml_w, IIItemRef(item));
10721064
}
10731065
if tps_len == 0 {

Diff for: src/librustc/middle/reachable.rs

+3-14
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,10 @@ use syntax::abi;
2626
use syntax::ast;
2727
use syntax::ast_map;
2828
use syntax::ast_util::{is_local, PostExpansionMethod};
29-
use syntax::attr::{InlineAlways, InlineHint, InlineNever, InlineNone};
3029
use syntax::attr;
3130
use syntax::visit::Visitor;
3231
use syntax::visit;
3332

34-
// Returns true if the given set of attributes contains the `#[inline]`
35-
// attribute.
36-
fn attributes_specify_inlining(attrs: &[ast::Attribute]) -> bool {
37-
match attr::find_inline_attr(attrs) {
38-
InlineNone | InlineNever => false,
39-
InlineAlways | InlineHint => true,
40-
}
41-
}
42-
4333
// Returns true if the given set of generics implies that the item it's
4434
// associated with must be inlined.
4535
fn generics_require_inlining(generics: &ast::Generics) -> bool {
@@ -50,7 +40,7 @@ fn generics_require_inlining(generics: &ast::Generics) -> bool {
5040
// monomorphized or it was marked with `#[inline]`. This will only return
5141
// true for functions.
5242
fn item_might_be_inlined(item: &ast::Item) -> bool {
53-
if attributes_specify_inlining(&item.attrs) {
43+
if attr::requests_inline(&item.attrs) {
5444
return true
5545
}
5646

@@ -65,7 +55,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool {
6555

6656
fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method,
6757
impl_src: ast::DefId) -> bool {
68-
if attributes_specify_inlining(&method.attrs) ||
58+
if attr::requests_inline(&method.attrs) ||
6959
generics_require_inlining(method.pe_generics()) {
7060
return true
7161
}
@@ -201,8 +191,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
201191
match *impl_item {
202192
ast::MethodImplItem(ref method) => {
203193
if generics_require_inlining(method.pe_generics()) ||
204-
attributes_specify_inlining(
205-
&method.attrs) {
194+
attr::requests_inline(&method.attrs) {
206195
true
207196
} else {
208197
let impl_did = self.tcx

Diff for: src/librustc_trans/trans/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ pub fn set_inline_hint(f: ValueRef) {
435435
pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
436436
use syntax::attr::*;
437437
// Set the inline hint if there is one
438-
match find_inline_attr(attrs) {
438+
match find_inline_attr(Some(ccx.sess().diagnostic()), attrs) {
439439
InlineHint => set_inline_hint(llfn),
440440
InlineAlways => set_always_inline(llfn),
441441
InlineNever => set_no_inline(llfn),

Diff for: src/libsyntax/attr.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ pub enum InlineAttr {
292292
}
293293

294294
/// Determine what `#[inline]` attribute is present in `attrs`, if any.
295-
pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr {
295+
pub fn find_inline_attr(diagnostic: Option<&SpanHandler>, attrs: &[Attribute]) -> InlineAttr {
296296
// FIXME (#2809)---validate the usage of #[inline] and #[inline]
297297
attrs.iter().fold(InlineNone, |ia,attr| {
298298
match attr.node.value.node {
@@ -302,12 +302,16 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr {
302302
}
303303
MetaList(ref n, ref items) if *n == "inline" => {
304304
mark_used(attr);
305-
if contains_name(&items[..], "always") {
305+
if items.len() != 1 {
306+
diagnostic.map(|d|{ d.span_err(attr.span, "expected one argument"); });
307+
InlineNone
308+
} else if contains_name(&items[..], "always") {
306309
InlineAlways
307310
} else if contains_name(&items[..], "never") {
308311
InlineNever
309312
} else {
310-
InlineHint
313+
diagnostic.map(|d|{ d.span_err((*items[0]).span, "invalid argument"); });
314+
InlineNone
311315
}
312316
}
313317
_ => ia
@@ -317,7 +321,7 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr {
317321

318322
/// True if `#[inline]` or `#[inline(always)]` is present in `attrs`.
319323
pub fn requests_inline(attrs: &[Attribute]) -> bool {
320-
match find_inline_attr(attrs) {
324+
match find_inline_attr(None, attrs) {
321325
InlineHint | InlineAlways => true,
322326
InlineNone | InlineNever => false,
323327
}

Diff for: src/test/compile-fail/invalid-inline.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
#![allow(dead_code)]
11+
12+
#[inline(please_no)] //~ ERROR invalid argument
13+
fn a() {
14+
}
15+
16+
#[inline(please,no)] //~ ERROR expected one argument
17+
fn b() {
18+
}
19+
20+
#[inline()] //~ ERROR expected one argument
21+
fn c() {
22+
}
23+
24+
fn main() {}

0 commit comments

Comments
 (0)