diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 77927260068..4b528a0fdc7 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -14,11 +14,10 @@ //! conflicts between multiple such attributes attached to the same //! item. -use session::Session; +use ty::TyCtxt; -use syntax::ast; -use syntax::visit; -use syntax::visit::Visitor; +use hir; +use hir::intravisit::{self, Visitor, NestedVisitorMap}; #[derive(Copy, Clone, PartialEq)] enum Target { @@ -30,24 +29,26 @@ enum Target { } impl Target { - fn from_item(item: &ast::Item) -> Target { + fn from_item(item: &hir::Item) -> Target { match item.node { - ast::ItemKind::Fn(..) => Target::Fn, - ast::ItemKind::Struct(..) => Target::Struct, - ast::ItemKind::Union(..) => Target::Union, - ast::ItemKind::Enum(..) => Target::Enum, + hir::ItemFn(..) => Target::Fn, + hir::ItemStruct(..) => Target::Struct, + hir::ItemUnion(..) => Target::Union, + hir::ItemEnum(..) => Target::Enum, _ => Target::Other, } } } -struct CheckAttrVisitor<'a> { - sess: &'a Session, +struct CheckAttrVisitor<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, } -impl<'a> CheckAttrVisitor<'a> { +impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { /// Check any attribute. - fn check_attributes(&self, item: &ast::Item, target: Target) { + fn check_attributes(&self, item: &hir::Item, target: Target) { + self.tcx.target_features_enabled(self.tcx.hir.local_def_id(item.id)); + for attr in &item.attrs { if let Some(name) = attr.name() { if name == "inline" { @@ -55,20 +56,24 @@ impl<'a> CheckAttrVisitor<'a> { } } } + self.check_repr(item, target); } /// Check if an `#[inline]` is applied to a function. - fn check_inline(&self, attr: &ast::Attribute, item: &ast::Item, target: Target) { + fn check_inline(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) { if target != Target::Fn { - struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function") + struct_span_err!(self.tcx.sess, + attr.span, + E0518, + "attribute should be applied to function") .span_label(item.span, "not a function") .emit(); } } /// Check if the `#[repr]` attributes on `item` are valid. - fn check_repr(&self, item: &ast::Item, target: Target) { + fn check_repr(&self, item: &hir::Item, target: Target) { // Extract the names of all repr hints, e.g., [foo, bar, align] for: // ``` // #[repr(foo)] @@ -144,7 +149,7 @@ impl<'a> CheckAttrVisitor<'a> { } _ => continue, }; - struct_span_err!(self.sess, hint.span, E0517, + struct_span_err!(self.tcx.sess, hint.span, E0517, "attribute should be applied to {}", allowed_targets) .span_label(item.span, format!("not {} {}", article, allowed_targets)) .emit(); @@ -154,32 +159,37 @@ impl<'a> CheckAttrVisitor<'a> { if (int_reprs > 1) || (is_simd && is_c) || (int_reprs == 1 && is_c && is_c_like_enum(item)) { - // Just point at all repr hints. This is not ideal, but tracking precisely which ones - // are at fault is a huge hassle. + // Just point at all repr hints. This is not ideal, but tracking + // precisely which ones are at fault is a huge hassle. let spans: Vec<_> = hints.iter().map(|hint| hint.span).collect(); - span_warn!(self.sess, spans, E0566, + span_warn!(self.tcx.sess, spans, E0566, "conflicting representation hints"); } } } -impl<'a> Visitor<'a> for CheckAttrVisitor<'a> { - fn visit_item(&mut self, item: &'a ast::Item) { +impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + + fn visit_item(&mut self, item: &'tcx hir::Item) { let target = Target::from_item(item); self.check_attributes(item, target); - visit::walk_item(self, item); + intravisit::walk_item(self, item); } } -pub fn check_crate(sess: &Session, krate: &ast::Crate) { - visit::walk_crate(&mut CheckAttrVisitor { sess: sess }, krate); +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + let mut checker = CheckAttrVisitor { tcx }; + tcx.hir.krate().visit_all_item_likes(&mut checker.as_deep_visitor()); } -fn is_c_like_enum(item: &ast::Item) -> bool { - if let ast::ItemKind::Enum(ref def, _) = item.node { +fn is_c_like_enum(item: &hir::Item) -> bool { + if let hir::ItemEnum(ref def, _) = item.node { for variant in &def.variants { match variant.node.data { - ast::VariantData::Unit(_) => { /* continue */ } + hir::VariantData::Unit(_) => { /* continue */ } _ => { return false; } } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b7265762208..73c1b698087 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -210,10 +210,6 @@ pub fn compile_input(sess: &Session, Ok(())); } - time(sess.time_passes(), "attribute checking", || { - hir::check_attr::check_crate(sess, &expanded_crate); - }); - let opt_crate = if control.keep_ast { Some(&expanded_crate) } else { @@ -1038,6 +1034,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController, // tcx available. rustc_incremental::dep_graph_tcx_init(tcx); + time(sess.time_passes(), "attribute checking", || { + hir::check_attr::check_crate(tcx) + }); + time(time_passes, "stability checking", || stability::check_unstable_api_usage(tcx)); diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr index 92bda4d0446..444c4176994 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr @@ -1,3 +1,5 @@ +error[E0601]: main function not found + error[E0518]: attribute should be applied to function --> $DIR/issue-43106-gating-of-inline.rs:21:1 | @@ -37,7 +39,5 @@ error[E0518]: attribute should be applied to function 35 | #[inline = "2100"] impl S { } | ^^^^^^^^^^^^^^^^^^ ---------- not a function -error[E0601]: main function not found - error: aborting due to 6 previous errors diff --git a/src/test/ui/target-feature-wrong.rs b/src/test/ui/target-feature-wrong.rs index df24035e10b..e70d549ed57 100644 --- a/src/test/ui/target-feature-wrong.rs +++ b/src/test/ui/target-feature-wrong.rs @@ -10,6 +10,8 @@ // ignore-arm // ignore-aarch64 +// ignore-wasm +// ignore-emscripten #![feature(target_feature)] diff --git a/src/test/ui/target-feature-wrong.stderr b/src/test/ui/target-feature-wrong.stderr index 0cbfeb3a7b7..c5534bf147d 100644 --- a/src/test/ui/target-feature-wrong.stderr +++ b/src/test/ui/target-feature-wrong.stderr @@ -1,31 +1,31 @@ warning: #[target_feature = ".."] is deprecated and will eventually be removed, use #[target_feature(enable = "..")] instead - --> $DIR/target-feature-wrong.rs:16:1 + --> $DIR/target-feature-wrong.rs:18:1 | -16 | #[target_feature = "+sse2"] +18 | #[target_feature = "+sse2"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the feature named `foo` is not valid for this target - --> $DIR/target-feature-wrong.rs:18:18 - | -18 | #[target_feature(enable = "foo")] - | ^^^^^^^^^^^^^^ - -error: #[target_feature(..)] only accepts sub-keys of `enable` currently --> $DIR/target-feature-wrong.rs:20:18 | -20 | #[target_feature(bar)] - | ^^^ +20 | #[target_feature(enable = "foo")] + | ^^^^^^^^^^^^^^ error: #[target_feature(..)] only accepts sub-keys of `enable` currently --> $DIR/target-feature-wrong.rs:22:18 | -22 | #[target_feature(disable = "baz")] +22 | #[target_feature(bar)] + | ^^^ + +error: #[target_feature(..)] only accepts sub-keys of `enable` currently + --> $DIR/target-feature-wrong.rs:24:18 + | +24 | #[target_feature(disable = "baz")] | ^^^^^^^^^^^^^^^ error: #[target_feature(..)] can only be applied to `unsafe` function - --> $DIR/target-feature-wrong.rs:26:1 + --> $DIR/target-feature-wrong.rs:28:1 | -26 | #[target_feature(enable = "sse2")] +28 | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors