]> git.lizzy.rs Git - rust.git/commitdiff
Validate inline attribute arguments
authorSimonas Kazlauskas <git@kazlauskas.me>
Wed, 18 Feb 2015 18:30:17 +0000 (20:30 +0200)
committerSimonas Kazlauskas <git@kazlauskas.me>
Sun, 22 Feb 2015 11:44:28 +0000 (13:44 +0200)
src/librustc/metadata/encoder.rs
src/librustc/middle/reachable.rs
src/librustc_trans/trans/base.rs
src/libsyntax/attr.rs
src/test/compile-fail/invalid-inline.rs [new file with mode: 0644]

index 629b19300e62ce6fc4c8c897a004758b9a46d13b..bb7fd40ced55f18ed587e1a850139650c4247077 100644 (file)
@@ -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 @@ fn encode_inlined_item(ecx: &EncodeContext,
 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 add_to_index(item: &ast::Item, rbml_w: &Encoder,
         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 {
index 7774314b6e08848ce58dd2611bbead69b066071a..4fd5a02b05216a4293eb404cbbc8cce2df2db56a 100644 (file)
 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 @@ fn def_id_represents_local_inlined_item(&self, def_id: ast::DefId) -> bool {
                 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
index 9c0aa9f69576ee09e163615d02614eec9edcf5df..6b4f4c11003b458ff6a2d097fab8df594e159455 100644 (file)
@@ -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),
index 62e676891a0e6c349fc6581cacf302c8de2484e5..4fc08c0c2b28caaccfcabe40924c848cbcf917ac 100644 (file)
@@ -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 (file)
index 0000000..ad89087
--- /dev/null
@@ -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() {}