@@ -171,9 +171,12 @@ pub(super) fn handle_needs(
171171 } ,
172172 ] ;
173173
174- let ( name, comment) = match ln. split_once ( [ ':' , ' ' ] ) {
175- Some ( ( name, comment) ) => ( name, Some ( comment) ) ,
176- None => ( ln, None ) ,
174+ // Because `needs-atomic` accepts one argument after colon to specify data size, we check whther
175+ // comment starts with colon.
176+ let ( name, comment, comment_starts_with_colon) = if let Some ( index) = ln. find ( [ ':' , ' ' ] ) {
177+ ( & ln[ ..index] , Some ( & ln[ index + 1 ..] ) , ln. as_bytes ( ) [ index] == b':' )
178+ } else {
179+ ( ln, None , false )
177180 } ;
178181
179182 if !name. starts_with ( "needs-" ) {
@@ -185,6 +188,69 @@ pub(super) fn handle_needs(
185188 return IgnoreDecision :: Continue ;
186189 }
187190
191+ // Check here because `needs-atomic` requires parsing comments.
192+ if name == "needs-atomic" {
193+ let mut comment = comment;
194+
195+ // Parse the comment to specify data size.
196+ // Just comments not arguments are also accepted.
197+ // No arguments are handled as (none).
198+ let size = if !comment_starts_with_colon {
199+ // Comments starting with spaces are not arguments.
200+ None
201+ } else {
202+ if let Some ( comment_content) = comment {
203+ if comment_content. trim ( ) . is_empty ( ) {
204+ None
205+ } else {
206+ let ( size, rest) = match comment_content. trim_start ( ) . split_once ( [ ':' , ' ' ] ) {
207+ Some ( ( size, rest) ) => ( size, Some ( rest) ) ,
208+ None => ( comment_content. trim ( ) , None ) ,
209+ } ;
210+
211+ if size == "ptr" {
212+ comment = rest;
213+ Some ( config. target_cfg ( ) . pointer_width as _ )
214+ } else if let Ok ( size) = size. parse ( ) {
215+ if ![ 128 , 64 , 32 , 16 , 8 ] . contains ( & size) {
216+ // Numeric literals but non data size are disallowed.
217+ return IgnoreDecision :: Error {
218+ message : "expected values for `needs-atomic` are: (none), `128`,\
219+ `16`, `32`, `64`, `8`, and `ptr"
220+ . into ( ) ,
221+ } ;
222+ } else {
223+ comment = rest;
224+ Some ( size)
225+ }
226+ } else {
227+ // Comments starting with non-numeric literals are not arguments.
228+ None
229+ }
230+ }
231+ } else {
232+ None
233+ }
234+ } ;
235+
236+ return if config. has_atomic ( size) {
237+ IgnoreDecision :: Continue
238+ } else {
239+ let base = if let Some ( size) = size {
240+ format ! ( "ignored on targets without {size}-bit atomic operations" )
241+ } else {
242+ format ! ( "ignored on targets without atomic operations" )
243+ } ;
244+ IgnoreDecision :: Ignore {
245+ reason : if let Some ( comment) = comment {
246+ format ! ( "{base}: ({})" , comment. trim( ) )
247+ } else {
248+ base
249+ } ,
250+ }
251+ } ;
252+ }
253+
188254 let mut found_valid = false ;
189255 for need in needs {
190256 if need. name == name {
0 commit comments