@@ -196,6 +196,7 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[
196196 ( "no_mangle" , Normal ) ,
197197 ( "no_link" , Normal ) ,
198198 ( "derive" , Normal ) ,
199+ ( "deriving" , Normal ) , // deprecation err in expansion
199200 ( "should_fail" , Normal ) ,
200201 ( "should_panic" , Normal ) ,
201202 ( "ignore" , Normal ) ,
@@ -235,6 +236,9 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[
235236 "the `#[rustc_move_fragments]` attribute \
236237 is an experimental feature") ) ,
237238
239+ ( "allow_internal_unstable" , Gated ( "allow_internal_unstable" ,
240+ EXPLAIN_ALLOW_INTERNAL_UNSTABLE ) ) ,
241+
238242 // FIXME: #14408 whitelist docs since rustdoc looks at them
239243 ( "doc" , Whitelisted ) ,
240244
@@ -369,6 +373,33 @@ impl<'a> Context<'a> {
369373 fn has_feature ( & self , feature : & str ) -> bool {
370374 self . features . iter ( ) . any ( |& n| n == feature)
371375 }
376+
377+ fn check_attribute ( & self , attr : & ast:: Attribute ) {
378+ debug ! ( "check_attribute(attr = {:?})" , attr) ;
379+ let name = & * attr. name ( ) ;
380+ for & ( n, ty) in KNOWN_ATTRIBUTES {
381+ if n == name {
382+ if let Gated ( gate, desc) = ty {
383+ self . gate_feature ( gate, attr. span , desc) ;
384+ }
385+ debug ! ( "check_attribute: {:?} is known, {:?}" , name, ty) ;
386+ return ;
387+ }
388+ }
389+ if name. starts_with ( "rustc_" ) {
390+ self . gate_feature ( "rustc_attrs" , attr. span ,
391+ "unless otherwise specified, attributes \
392+ with the prefix `rustc_` \
393+ are reserved for internal compiler diagnostics") ;
394+ } else {
395+ self . gate_feature ( "custom_attribute" , attr. span ,
396+ format ! ( "The attribute `{}` is currently \
397+ unknown to the the compiler and \
398+ may have meaning \
399+ added to it in the future",
400+ name) . as_slice ( ) ) ;
401+ }
402+ }
372403}
373404
374405pub fn emit_feature_err ( diag : & SpanHandler , feature : & str , span : Span , explain : & str ) {
@@ -436,10 +467,7 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
436467 }
437468
438469 fn visit_attribute ( & mut self , attr : & ' v ast:: Attribute ) {
439- if attr. name ( ) == "allow_internal_unstable" {
440- self . context . gate_feature ( "allow_internal_unstable" , attr. span ,
441- EXPLAIN_ALLOW_INTERNAL_UNSTABLE )
442- }
470+ self . context . check_attribute ( attr) ;
443471 }
444472}
445473
@@ -456,6 +484,12 @@ impl<'a> PostExpansionVisitor<'a> {
456484}
457485
458486impl < ' a , ' v > Visitor < ' v > for PostExpansionVisitor < ' a > {
487+ fn visit_attribute ( & mut self , attr : & ast:: Attribute ) {
488+ if !self . context . cm . span_allows_unstable ( attr. span ) {
489+ self . context . check_attribute ( attr) ;
490+ }
491+ }
492+
459493 fn visit_name ( & mut self , sp : Span , name : ast:: Name ) {
460494 if !token:: get_name ( name) . is_ascii ( ) {
461495 self . gate_feature ( "non_ascii_idents" , sp,
@@ -556,12 +590,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
556590 }
557591
558592 fn visit_foreign_item ( & mut self , i : & ast:: ForeignItem ) {
559- if attr:: contains_name ( & i. attrs , "linkage" ) {
560- self . gate_feature ( "linkage" , i. span ,
561- "the `linkage` attribute is experimental \
562- and not portable across platforms")
563- }
564-
565593 let links_to_llvm = match attr:: first_attr_value_str_by_name ( & i. attrs ,
566594 "link_name" ) {
567595 Some ( val) => val. starts_with ( "llvm." ) ,
@@ -636,33 +664,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
636664 visit:: walk_expr ( self , e) ;
637665 }
638666
639- fn visit_attribute ( & mut self , attr : & ast:: Attribute ) {
640- debug ! ( "visit_attribute(attr = {:?})" , attr) ;
641- let name = & * attr. name ( ) ;
642- for & ( n, ty) in KNOWN_ATTRIBUTES {
643- if n == name {
644- if let Gated ( gate, desc) = ty {
645- self . gate_feature ( gate, attr. span , desc) ;
646- }
647- debug ! ( "visit_attribute: {:?} is known, {:?}" , name, ty) ;
648- return ;
649- }
650- }
651- if name. starts_with ( "rustc_" ) {
652- self . gate_feature ( "rustc_attrs" , attr. span ,
653- "unless otherwise specified, attributes \
654- with the prefix `rustc_` \
655- are reserved for internal compiler diagnostics") ;
656- } else {
657- self . gate_feature ( "custom_attribute" , attr. span ,
658- format ! ( "The attribute `{}` is currently \
659- unknown to the the compiler and \
660- may have meaning \
661- added to it in the future",
662- name) . as_slice ( ) ) ;
663- }
664- }
665-
666667 fn visit_pat ( & mut self , pattern : & ast:: Pat ) {
667668 match pattern. node {
668669 ast:: PatVec ( _, Some ( _) , ref last) if !last. is_empty ( ) => {
0 commit comments