Skip to content

Commit b28f2d9

Browse files
committed
Check validity of inline attributes earlier
1 parent c5c70ef commit b28f2d9

File tree

4 files changed

+76
-31
lines changed

4 files changed

+76
-31
lines changed

src/librustc/hir/check_attr.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ impl Target {
3939
_ => Target::Other,
4040
}
4141
}
42+
43+
fn from_trait_item(_item: &ast::TraitItem) -> Target {
44+
// TODO
45+
Target::Fn
46+
}
47+
48+
fn from_impl_item(_item: &ast::ImplItem) -> Target {
49+
// TODO
50+
Target::Fn
51+
}
4252
}
4353

4454
struct CheckAttrVisitor<'a> {
@@ -64,6 +74,14 @@ impl<'a> CheckAttrVisitor<'a> {
6474
.span_label(item.span, "not a function")
6575
.emit();
6676
}
77+
if ::std::env::var_os("ATTR").is_some() {
78+
println!("check_inline attr = {:?}", attr);
79+
}
80+
let x = ::syntax::attr::process_inline_attr(Some(self.sess.diagnostic()), attr);
81+
match x {
82+
Ok(_) => {},
83+
Err(mut y) => y.emit(),
84+
}
6785
}
6886

6987
/// Check if an `#[repr]` attr is valid.
@@ -157,6 +175,22 @@ impl<'a> Visitor<'a> for CheckAttrVisitor<'a> {
157175
}
158176
visit::walk_item(self, item);
159177
}
178+
179+
fn visit_trait_item(&mut self, item: &'a ast::TraitItem) {
180+
let target = Target::from_trait_item(item);
181+
for attr in &item.attrs {
182+
self.check_attribute(attr, target);
183+
}
184+
visit::walk_trait_item(self, item);
185+
}
186+
187+
fn visit_impl_item(&mut self, item: &'a ast::ImplItem) {
188+
let target = Target::from_impl_item(item);
189+
for attr in &item.attrs {
190+
self.check_attribute(attr, target);
191+
}
192+
visit::walk_impl_item(self, item);
193+
}
160194
}
161195

162196
pub fn check_crate(sess: &Session, krate: &ast::Crate) {

src/librustc_trans/attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub fn set_probestack(ccx: &CrateContext, llfn: ValueRef) {
9696
/// attributes.
9797
pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
9898
use syntax::attr::*;
99-
inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
99+
inline(llfn, find_inline_attr(None, attrs));
100100

101101
set_frame_pointer_elimination(ccx, llfn);
102102
set_probestack(ccx, llfn);

src/libsyntax/attr.rs

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
2020
use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind};
2121
use codemap::{Spanned, respan, dummy_spanned};
2222
use syntax_pos::{Span, DUMMY_SP};
23-
use errors::Handler;
23+
use errors::{DiagnosticBuilder, Handler};
2424
use feature_gate::{Features, GatedCfg};
2525
use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
2626
use parse::parser::Parser;
@@ -528,39 +528,50 @@ pub enum InlineAttr {
528528
Never,
529529
}
530530

531+
pub fn process_inline_attr<'a>(session: Option<&'a Handler>, attr: &Attribute) -> Result<InlineAttr, DiagnosticBuilder<'a>> {
532+
let meta = match attr.meta() {
533+
Some(meta) => meta.node,
534+
None =>{ assert!(false, "Unimplemented!"); return Ok(InlineAttr::None); },
535+
};
536+
match meta {
537+
MetaItemKind::Word => {
538+
mark_used(attr);
539+
Ok(InlineAttr::Hint)
540+
}
541+
MetaItemKind::List(ref items) => {
542+
mark_used(attr);
543+
if items.len() != 1 {
544+
session.map_or(Ok(InlineAttr::None), |s|
545+
Err(struct_span_err!(s, attr.span, E0534, "expected one argument"))
546+
)
547+
} else if items[0].check_name("always") {
548+
Ok(InlineAttr::Always)
549+
} else if items[0].check_name("never") {
550+
Ok(InlineAttr::Never)
551+
} else {
552+
session.map_or(Ok(InlineAttr::None), |s|
553+
Err(struct_span_err!(s, items[0].span, E0535, "invalid argument"))
554+
)
555+
}
556+
}
557+
_ => Ok(InlineAttr::None),
558+
}
559+
}
560+
531561
/// Determine what `#[inline]` attribute is present in `attrs`, if any.
532-
pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> InlineAttr {
562+
pub fn find_inline_attr(_diagnostic: Option<&Handler>, attrs: &[Attribute]) -> InlineAttr {
533563
attrs.iter().fold(InlineAttr::None, |ia, attr| {
534564
if attr.path != "inline" {
535565
return ia;
536566
}
537-
let meta = match attr.meta() {
538-
Some(meta) => meta.node,
539-
None => return ia,
540-
};
541-
match meta {
542-
MetaItemKind::Word => {
543-
mark_used(attr);
544-
InlineAttr::Hint
545-
}
546-
MetaItemKind::List(ref items) => {
547-
mark_used(attr);
548-
if items.len() != 1 {
549-
diagnostic.map(|d|{ span_err!(d, attr.span, E0534, "expected one argument"); });
550-
InlineAttr::None
551-
} else if list_contains_name(&items[..], "always") {
552-
InlineAttr::Always
553-
} else if list_contains_name(&items[..], "never") {
554-
InlineAttr::Never
555-
} else {
556-
diagnostic.map(|d| {
557-
span_err!(d, items[0].span, E0535, "invalid argument");
558-
});
559-
560-
InlineAttr::None
561-
}
562-
}
563-
_ => ia,
567+
if !_diagnostic.is_some() && ::std::env::var_os("ASSERT").is_some() {
568+
println!("find_inline_attr attr = {:?}", attr);
569+
assert!(is_used(attr), "Attr should be marked as used already!");
570+
}
571+
let inline_attr = process_inline_attr(None, attr);
572+
match inline_attr {
573+
Ok(a) => a,
574+
Err(_) => { assert!(false, "Should have diganosed inline attr already!"); return ia; },
564575
}
565576
})
566577
}

src/libsyntax/feature_gate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
841841
"the `#[target_feature]` attribute is an experimental feature",
842842
cfg_fn!(target_feature))),
843843
("export_name", Whitelisted, Ungated),
844-
("inline", Whitelisted, Ungated),
844+
("inline", Normal, Ungated),
845845
("link", Whitelisted, Ungated),
846846
("link_name", Whitelisted, Ungated),
847847
("link_section", Whitelisted, Ungated),

0 commit comments

Comments
 (0)