11use std:: borrow:: Cow ;
22
33use rustc_ast as ast;
4- use rustc_ast:: { AttrStyle , NodeId } ;
4+ use rustc_ast:: { AttrStyle , NodeId , Safety } ;
55use rustc_errors:: DiagCtxtHandle ;
66use rustc_feature:: { AttributeTemplate , Features } ;
77use rustc_hir:: attrs:: AttributeKind ;
@@ -146,6 +146,7 @@ impl<'sess> AttributeParser<'sess, Early> {
146146 normal_attr. item . span ( ) ,
147147 attr. style ,
148148 path. get_attribute_path ( ) ,
149+ Some ( normal_attr. item . unsafety ) ,
149150 ParsedDescription :: Attribute ,
150151 target_span,
151152 target_node_id,
@@ -165,6 +166,7 @@ impl<'sess> AttributeParser<'sess, Early> {
165166 inner_span : Span ,
166167 attr_style : AttrStyle ,
167168 attr_path : AttrPath ,
169+ attr_safety : Option < Safety > ,
168170 parsed_description : ParsedDescription ,
169171 target_span : Span ,
170172 target_node_id : NodeId ,
@@ -181,14 +183,24 @@ impl<'sess> AttributeParser<'sess, Early> {
181183 sess,
182184 stage : Early { emit_errors } ,
183185 } ;
186+ let mut emit_lint = |lint| {
187+ crate :: lints:: emit_attribute_lint ( & lint, sess) ;
188+ } ;
189+ if let Some ( safety) = attr_safety {
190+ parser. check_attribute_safety (
191+ & attr_path,
192+ inner_span,
193+ safety,
194+ & mut emit_lint,
195+ target_node_id,
196+ )
197+ }
184198 let mut cx: AcceptContext < ' _ , ' sess , Early > = AcceptContext {
185199 shared : SharedContext {
186200 cx : & mut parser,
187201 target_span,
188202 target_id : target_node_id,
189- emit_lint : & mut |lint| {
190- crate :: lints:: emit_attribute_lint ( & lint, sess) ;
191- } ,
203+ emit_lint : & mut emit_lint,
192204 } ,
193205 attr_span,
194206 inner_span,
@@ -288,6 +300,15 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
288300 // }
289301 ast:: AttrKind :: Normal ( n) => {
290302 attr_paths. push ( PathParser ( Cow :: Borrowed ( & n. item . path ) ) ) ;
303+ let attr_path = AttrPath :: from_ast ( & n. item . path , lower_span) ;
304+
305+ self . check_attribute_safety (
306+ & attr_path,
307+ lower_span ( n. item . span ( ) ) ,
308+ n. item . unsafety ,
309+ & mut emit_lint,
310+ target_id,
311+ ) ;
291312
292313 let parts =
293314 n. item . path . segments . iter ( ) . map ( |seg| seg. ident . name ) . collect :: < Vec < _ > > ( ) ;
@@ -301,7 +322,6 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
301322 ) else {
302323 continue ;
303324 } ;
304- let path = parser. path ( ) ;
305325 let args = parser. args ( ) ;
306326 for accept in accepts {
307327 let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
@@ -312,11 +332,11 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
312332 emit_lint : & mut emit_lint,
313333 } ,
314334 attr_span : lower_span ( attr. span ) ,
315- inner_span : lower_span ( attr . get_normal_item ( ) . span ( ) ) ,
335+ inner_span : lower_span ( n . item . span ( ) ) ,
316336 attr_style : attr. style ,
317337 parsed_description : ParsedDescription :: Attribute ,
318338 template : & accept. template ,
319- attr_path : path . get_attribute_path ( ) ,
339+ attr_path : attr_path . clone ( ) ,
320340 } ;
321341
322342 ( accept. accept_fn ) ( & mut cx, args) ;
@@ -341,7 +361,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
341361 // );
342362
343363 attributes. push ( Attribute :: Unparsed ( Box :: new ( AttrItem {
344- path : AttrPath :: from_ast ( & n . item . path ) ,
364+ path : attr_path . clone ( ) ,
345365 args : self . lower_attr_args ( & n. item . args , lower_span) ,
346366 id : HashIgnoredAttrId { attr_id : attr. id } ,
347367 style : attr. style ,
0 commit comments