Skip to content

Commit

Permalink
Check validity of inline attributes earlier
Browse files Browse the repository at this point in the history
  • Loading branch information
jgouly committed Nov 19, 2017
1 parent c5c70ef commit b28f2d9
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 31 deletions.
34 changes: 34 additions & 0 deletions src/librustc/hir/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ impl Target {
_ => Target::Other,
}
}

fn from_trait_item(_item: &ast::TraitItem) -> Target {
// TODO
Target::Fn
}

fn from_impl_item(_item: &ast::ImplItem) -> Target {
// TODO
Target::Fn
}
}

struct CheckAttrVisitor<'a> {
Expand All @@ -64,6 +74,14 @@ impl<'a> CheckAttrVisitor<'a> {
.span_label(item.span, "not a function")
.emit();
}
if ::std::env::var_os("ATTR").is_some() {
println!("check_inline attr = {:?}", attr);
}
let x = ::syntax::attr::process_inline_attr(Some(self.sess.diagnostic()), attr);
match x {
Ok(_) => {},
Err(mut y) => y.emit(),
}
}

/// Check if an `#[repr]` attr is valid.
Expand Down Expand Up @@ -157,6 +175,22 @@ impl<'a> Visitor<'a> for CheckAttrVisitor<'a> {
}
visit::walk_item(self, item);
}

fn visit_trait_item(&mut self, item: &'a ast::TraitItem) {
let target = Target::from_trait_item(item);
for attr in &item.attrs {
self.check_attribute(attr, target);
}
visit::walk_trait_item(self, item);
}

fn visit_impl_item(&mut self, item: &'a ast::ImplItem) {
let target = Target::from_impl_item(item);
for attr in &item.attrs {
self.check_attribute(attr, target);
}
visit::walk_impl_item(self, item);
}
}

pub fn check_crate(sess: &Session, krate: &ast::Crate) {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub fn set_probestack(ccx: &CrateContext, llfn: ValueRef) {
/// attributes.
pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
use syntax::attr::*;
inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
inline(llfn, find_inline_attr(None, attrs));

set_frame_pointer_elimination(ccx, llfn);
set_probestack(ccx, llfn);
Expand Down
69 changes: 40 additions & 29 deletions src/libsyntax/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind};
use codemap::{Spanned, respan, dummy_spanned};
use syntax_pos::{Span, DUMMY_SP};
use errors::Handler;
use errors::{DiagnosticBuilder, Handler};
use feature_gate::{Features, GatedCfg};
use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
use parse::parser::Parser;
Expand Down Expand Up @@ -528,39 +528,50 @@ pub enum InlineAttr {
Never,
}

pub fn process_inline_attr<'a>(session: Option<&'a Handler>, attr: &Attribute) -> Result<InlineAttr, DiagnosticBuilder<'a>> {
let meta = match attr.meta() {
Some(meta) => meta.node,
None =>{ assert!(false, "Unimplemented!"); return Ok(InlineAttr::None); },
};
match meta {
MetaItemKind::Word => {
mark_used(attr);
Ok(InlineAttr::Hint)
}
MetaItemKind::List(ref items) => {
mark_used(attr);
if items.len() != 1 {
session.map_or(Ok(InlineAttr::None), |s|
Err(struct_span_err!(s, attr.span, E0534, "expected one argument"))
)
} else if items[0].check_name("always") {
Ok(InlineAttr::Always)
} else if items[0].check_name("never") {
Ok(InlineAttr::Never)
} else {
session.map_or(Ok(InlineAttr::None), |s|
Err(struct_span_err!(s, items[0].span, E0535, "invalid argument"))
)
}
}
_ => Ok(InlineAttr::None),
}
}

/// Determine what `#[inline]` attribute is present in `attrs`, if any.
pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> InlineAttr {
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,
if !_diagnostic.is_some() && ::std::env::var_os("ASSERT").is_some() {
println!("find_inline_attr attr = {:?}", attr);
assert!(is_used(attr), "Attr should be marked as used already!");
}
let inline_attr = process_inline_attr(None, attr);
match inline_attr {
Ok(a) => a,
Err(_) => { assert!(false, "Should have diganosed inline attr already!"); return ia; },
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
"the `#[target_feature]` attribute is an experimental feature",
cfg_fn!(target_feature))),
("export_name", Whitelisted, Ungated),
("inline", Whitelisted, Ungated),
("inline", Normal, Ungated),
("link", Whitelisted, Ungated),
("link_name", Whitelisted, Ungated),
("link_section", Whitelisted, Ungated),
Expand Down

0 comments on commit b28f2d9

Please sign in to comment.