@@ -798,43 +798,55 @@ fn check_heap_item(cx: &Context, it: &ast::item) {
798798 }
799799}
800800
801+ static crate_attrs: & ' static [ & ' static str ] = & [
802+ "crate_type" , "link" , "feature" , "no_uv" , "no_main" , "no_std" ,
803+ "desc" , "comment" , "license" , "copyright" , // not used in rustc now
804+ ] ;
805+
806+
807+ static obsolete_attrs: & ' static [ ( & ' static str , & ' static str ) ] = & [
808+ ( "abi" , "Use `extern \" abi\" fn` instead" ) ,
809+ ( "auto_encode" , "Use `#[deriving(Encodable)]` instead" ) ,
810+ ( "auto_decode" , "Use `#[deriving(Decodable)]` instead" ) ,
811+ ( "fast_ffi" , "Remove it" ) ,
812+ ( "fixed_stack_segment" , "Remove it" ) ,
813+ ( "rust_stack" , "Remove it" ) ,
814+ ] ;
815+
816+ static other_attrs: & ' static [ & ' static str ] = & [
817+ // item-level
818+ "address_insignificant" , // can be crate-level too
819+ "allow" , "deny" , "forbid" , "warn" , // lint options
820+ "deprecated" , "experimental" , "unstable" , "stable" , "locked" , "frozen" , //item stability
821+ "crate_map" , "cfg" , "doc" , "export_name" , "link_section" , "no_freeze" ,
822+ "no_mangle" , "no_send" , "static_assert" , "unsafe_no_drop_flag" ,
823+ "packed" , "simd" , "repr" , "deriving" , "unsafe_destructor" ,
824+
825+ //mod-level
826+ "path" , "link_name" , "link_args" , "nolink" , "macro_escape" , "no_implicit_prelude" ,
827+
828+ // fn-level
829+ "test" , "bench" , "should_fail" , "ignore" , "inline" , "lang" , "main" , "start" ,
830+ "no_split_stack" , "cold" ,
831+
832+ // internal attribute: bypass privacy inside items
833+ "!resolve_unexported" ,
834+ ] ;
835+
836+ fn check_crate_attrs_usage ( cx : & Context , attrs : & [ ast:: Attribute ] ) {
837+
838+ for attr in attrs. iter ( ) {
839+ let name = attr. node . value . name ( ) ;
840+ let mut iter = crate_attrs. iter ( ) . chain ( other_attrs. iter ( ) ) ;
841+ if !iter. any ( |other_attr| { name. equiv ( other_attr) } ) {
842+ cx. span_lint ( attribute_usage, attr. span , "unknown crate attribute" ) ;
843+ }
844+ }
845+ }
846+
801847fn check_attrs_usage ( cx : & Context , attrs : & [ ast:: Attribute ] ) {
802848 // check if element has crate-level, obsolete, or any unknown attributes.
803849
804- let crate_attrs = [
805- "crate_type" , "link" , "feature" , "no_uv" , "no_main" , "no_std" ,
806- "comment" , "license" , "copyright" , // not used in rustc now
807- ] ;
808-
809- let obsolete_attrs = [
810- ( "abi" , "Use `extern \" abi\" fn` instead" ) ,
811- ( "auto_encode" , "Use `#[deriving(Encodable)]` instead" ) ,
812- ( "auto_decode" , "Use `#[deriving(Decodable)]` instead" ) ,
813- ( "fast_ffi" , "Remove it" ) ,
814- ( "fixed_stack_segment" , "Remove it" ) ,
815- ( "rust_stack" , "Remove it" ) ,
816- ] ;
817-
818- let other_attrs = [
819- // item-level
820- "address_insignificant" , // can be crate-level too
821- "allow" , "deny" , "forbid" , "warn" , // lint options
822- "deprecated" , "experimental" , "unstable" , "stable" , "locked" , "frozen" , //item stability
823- "crate_map" , "cfg" , "doc" , "export_name" , "link_section" , "no_freeze" ,
824- "no_mangle" , "no_send" , "static_assert" , "unsafe_no_drop_flag" ,
825- "packed" , "simd" , "repr" , "deriving" , "unsafe_destructor" ,
826-
827- // mod-level
828- "path" , "link_name" , "link_args" , "nolink" , "macro_escape" , "no_implicit_prelude" ,
829-
830- // fn-level
831- "test" , "bench" , "should_fail" , "ignore" , "inline" , "lang" , "main" , "start" ,
832- "no_split_stack" , "cold" ,
833-
834- // internal attribute: bypass privacy inside items
835- "!resolve_unexported" ,
836- ] ;
837-
838850 for attr in attrs. iter ( ) {
839851 let name = attr. node . value . name ( ) ;
840852 for crate_attr in crate_attrs. iter ( ) {
@@ -1349,6 +1361,9 @@ pub fn check_crate(tcx: ty::ctxt,
13491361 v. visited_outermost = true ;
13501362 visit:: walk_crate ( v, crate , ( ) ) ;
13511363 }
1364+
1365+ check_crate_attrs_usage ( cx, crate . attrs) ;
1366+
13521367 visit:: walk_crate ( cx, crate , ( ) ) ;
13531368 }
13541369
0 commit comments