@@ -10,7 +10,9 @@ use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem};
1010use rustc_data_structures:: fx:: FxHashMap ;
1111use rustc_errors:: StashKey ;
1212use rustc_errors:: { Applicability , DiagCtxt , IntoDiagArg , MultiSpan } ;
13- use rustc_feature:: { AttributeDuplicates , AttributeType , BuiltinAttribute , BUILTIN_ATTRIBUTE_MAP } ;
13+ use rustc_feature:: {
14+ is_unsafe_attr, AttributeDuplicates , AttributeType , BuiltinAttribute , BUILTIN_ATTRIBUTE_MAP ,
15+ } ;
1416use rustc_hir:: def_id:: LocalModDefId ;
1517use rustc_hir:: intravisit:: { self , Visitor } ;
1618use rustc_hir:: { self as hir} ;
@@ -114,6 +116,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
114116 let mut seen = FxHashMap :: default ( ) ;
115117 let attrs = self . tcx . hir ( ) . attrs ( hir_id) ;
116118 for attr in attrs {
119+ self . check_unsafe_attr ( attr) ;
120+
117121 match attr. path ( ) . as_slice ( ) {
118122 [ sym:: diagnostic, sym:: do_not_recommend] => {
119123 self . check_do_not_recommend ( attr. span , hir_id, target)
@@ -308,6 +312,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
308312 true
309313 }
310314
315+
316+ /// Checks if `unsafe()` is applied to an invalid attribute.
317+ fn check_unsafe_attr ( & self , attr : & Attribute ) {
318+ if !attr. is_doc_comment ( ) {
319+ let attr_item = attr. get_normal_item ( ) ;
320+ if let ast:: Unsafe :: Yes ( unsafe_span) = attr_item. unsafety {
321+ if !is_unsafe_attr ( attr. name_or_empty ( ) ) {
322+ self . dcx ( ) . emit_err ( errors:: InvalidAttrUnsafe {
323+ span : unsafe_span,
324+ name : attr_item. path . clone ( ) ,
325+ } ) ;
326+ }
327+ }
328+ }
329+ }
330+
311331 /// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
312332 fn check_diagnostic_on_unimplemented (
313333 & self ,
0 commit comments