@@ -196,6 +196,7 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[
196
196
( "no_mangle" , Normal ) ,
197
197
( "no_link" , Normal ) ,
198
198
( "derive" , Normal ) ,
199
+ ( "deriving" , Normal ) , // deprecation err in expansion
199
200
( "should_fail" , Normal ) ,
200
201
( "should_panic" , Normal ) ,
201
202
( "ignore" , Normal ) ,
@@ -235,6 +236,9 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[
235
236
"the `#[rustc_move_fragments]` attribute \
236
237
is an experimental feature") ) ,
237
238
239
+ ( "allow_internal_unstable" , Gated ( "allow_internal_unstable" ,
240
+ EXPLAIN_ALLOW_INTERNAL_UNSTABLE ) ) ,
241
+
238
242
// FIXME: #14408 whitelist docs since rustdoc looks at them
239
243
( "doc" , Whitelisted ) ,
240
244
@@ -369,6 +373,33 @@ impl<'a> Context<'a> {
369
373
fn has_feature ( & self , feature : & str ) -> bool {
370
374
self . features . iter ( ) . any ( |& n| n == feature)
371
375
}
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
+ }
372
403
}
373
404
374
405
pub fn emit_feature_err ( diag : & SpanHandler , feature : & str , span : Span , explain : & str ) {
@@ -436,10 +467,7 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
436
467
}
437
468
438
469
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) ;
443
471
}
444
472
}
445
473
@@ -456,6 +484,12 @@ impl<'a> PostExpansionVisitor<'a> {
456
484
}
457
485
458
486
impl < ' 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
+
459
493
fn visit_name ( & mut self , sp : Span , name : ast:: Name ) {
460
494
if !token:: get_name ( name) . is_ascii ( ) {
461
495
self . gate_feature ( "non_ascii_idents" , sp,
@@ -556,12 +590,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
556
590
}
557
591
558
592
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
-
565
593
let links_to_llvm = match attr:: first_attr_value_str_by_name ( & i. attrs ,
566
594
"link_name" ) {
567
595
Some ( val) => val. starts_with ( "llvm." ) ,
@@ -636,33 +664,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
636
664
visit:: walk_expr ( self , e) ;
637
665
}
638
666
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
-
666
667
fn visit_pat ( & mut self , pattern : & ast:: Pat ) {
667
668
match pattern. node {
668
669
ast:: PatVec ( _, Some ( _) , ref last) if !last. is_empty ( ) => {
0 commit comments