@@ -2,7 +2,9 @@ use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, UsedBy};
22use  rustc_session:: parse:: feature_err; 
33
44use  super :: prelude:: * ; 
5- use  crate :: session_diagnostics:: { NakedFunctionIncompatibleAttribute ,  NullOnExport } ; 
5+ use  crate :: session_diagnostics:: { 
6+     NakedFunctionIncompatibleAttribute ,  NullOnExport ,  NullOnObjcClass ,  NullOnObjcSelector , 
7+ } ; 
68
79pub ( crate )  struct  OptimizeParser ; 
810
@@ -148,6 +150,64 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
148150    } 
149151} 
150152
153+ pub ( crate )  struct  ObjcClassParser ; 
154+ 
155+ impl < S :  Stage >  SingleAttributeParser < S >  for  ObjcClassParser  { 
156+     const  PATH :  & [ rustc_span:: Symbol ]  = & [ sym:: rustc_objc_class] ; 
157+     const  ATTRIBUTE_ORDER :  AttributeOrder  = AttributeOrder :: KeepInnermost ; 
158+     const  ON_DUPLICATE :  OnDuplicate < S >  = OnDuplicate :: Error ; 
159+     const  ALLOWED_TARGETS :  AllowedTargets  =
160+         AllowedTargets :: AllowList ( & [ Allow ( Target :: ForeignStatic ) ] ) ; 
161+     const  TEMPLATE :  AttributeTemplate  = template ! ( NameValueStr :  "ClassName" ) ; 
162+ 
163+     fn  convert ( cx :  & mut  AcceptContext < ' _ ,  ' _ ,  S > ,  args :  & ArgParser < ' _ > )  -> Option < AttributeKind >  { 
164+         let  Some ( nv)  = args. name_value ( )  else  { 
165+             cx. expected_name_value ( cx. attr_span ,  None ) ; 
166+             return  None ; 
167+         } ; 
168+         let  Some ( classname)  = nv. value_as_str ( )  else  { 
169+             cx. expected_string_literal ( nv. value_span ,  Some ( nv. value_as_lit ( ) ) ) ; 
170+             return  None ; 
171+         } ; 
172+         if  classname. as_str ( ) . contains ( '\0' )  { 
173+             // `#[rustc_objc_class = ...]` will be converted to a null-terminated string, 
174+             // so it may not contain any null characters. 
175+             cx. emit_err ( NullOnObjcClass  {  span :  cx. attr_span  } ) ; 
176+             return  None ; 
177+         } 
178+         Some ( AttributeKind :: ObjcClass  {  classname,  span :  cx. attr_span  } ) 
179+     } 
180+ } 
181+ 
182+ pub ( crate )  struct  ObjcSelectorParser ; 
183+ 
184+ impl < S :  Stage >  SingleAttributeParser < S >  for  ObjcSelectorParser  { 
185+     const  PATH :  & [ rustc_span:: Symbol ]  = & [ sym:: rustc_objc_selector] ; 
186+     const  ATTRIBUTE_ORDER :  AttributeOrder  = AttributeOrder :: KeepInnermost ; 
187+     const  ON_DUPLICATE :  OnDuplicate < S >  = OnDuplicate :: Error ; 
188+     const  ALLOWED_TARGETS :  AllowedTargets  =
189+         AllowedTargets :: AllowList ( & [ Allow ( Target :: ForeignStatic ) ] ) ; 
190+     const  TEMPLATE :  AttributeTemplate  = template ! ( NameValueStr :  "methodName" ) ; 
191+ 
192+     fn  convert ( cx :  & mut  AcceptContext < ' _ ,  ' _ ,  S > ,  args :  & ArgParser < ' _ > )  -> Option < AttributeKind >  { 
193+         let  Some ( nv)  = args. name_value ( )  else  { 
194+             cx. expected_name_value ( cx. attr_span ,  None ) ; 
195+             return  None ; 
196+         } ; 
197+         let  Some ( methname)  = nv. value_as_str ( )  else  { 
198+             cx. expected_string_literal ( nv. value_span ,  Some ( nv. value_as_lit ( ) ) ) ; 
199+             return  None ; 
200+         } ; 
201+         if  methname. as_str ( ) . contains ( '\0' )  { 
202+             // `#[rustc_objc_selector = ...]` will be converted to a null-terminated string, 
203+             // so it may not contain any null characters. 
204+             cx. emit_err ( NullOnObjcSelector  {  span :  cx. attr_span  } ) ; 
205+             return  None ; 
206+         } 
207+         Some ( AttributeKind :: ObjcSelector  {  methname,  span :  cx. attr_span  } ) 
208+     } 
209+ } 
210+ 
151211#[ derive( Default ) ]  
152212pub ( crate )  struct  NakedParser  { 
153213    span :  Option < Span > , 
0 commit comments