@@ -7,7 +7,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
77use rustc_expand:: base:: { self , * } ;
88use rustc_parse:: parser:: Parser ;
99use rustc_parse_format as parse;
10- use rustc_session:: lint;
10+ use rustc_session:: lint:: { self , BuiltinLintDiagnostics } ;
1111use rustc_span:: symbol:: Ident ;
1212use rustc_span:: symbol:: { kw, sym, Symbol } ;
1313use rustc_span:: { InnerSpan , Span } ;
@@ -397,7 +397,11 @@ fn parse_reg<'a>(
397397 Ok ( result)
398398}
399399
400- fn expand_preparsed_asm ( ecx : & mut ExtCtxt < ' _ > , args : AsmArgs ) -> Option < ast:: InlineAsm > {
400+ fn expand_preparsed_asm (
401+ ecx : & mut ExtCtxt < ' _ > ,
402+ args : AsmArgs ,
403+ is_local_asm : bool ,
404+ ) -> Option < ast:: InlineAsm > {
401405 let mut template = vec ! [ ] ;
402406 // Register operands are implicitly used since they are not allowed to be
403407 // referenced in the template string.
@@ -469,6 +473,70 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
469473 }
470474 }
471475
476+ if is_local_asm {
477+ let find_label_span = |needle : & str | -> Option < Span > {
478+ if let Some ( snippet) = & template_snippet {
479+ if let Some ( pos) = snippet. find ( needle) {
480+ let end = pos
481+ + & snippet[ pos..]
482+ . find ( |c| c == ':' )
483+ . unwrap_or ( snippet[ pos..] . len ( ) - 1 ) ;
484+ let inner = InnerSpan :: new ( pos, end) ;
485+ return Some ( template_sp. from_inner ( inner) ) ;
486+ }
487+ }
488+
489+ None
490+ } ;
491+
492+ let mut found_labels = Vec :: new ( ) ;
493+
494+ // A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always
495+ let statements = template_str. split ( |c| matches ! ( c, '\n' | ';' ) ) ;
496+ for statement in statements {
497+ let mut start_idx = 0 ;
498+ for ( idx, _) in statement. match_indices ( ':' ) {
499+ let possible_label = statement[ start_idx..idx] . trim ( ) ;
500+ let mut chars = possible_label. chars ( ) ;
501+ if let Some ( c) = chars. next ( ) {
502+ // A label starts with an alphabetic character and continues with alphanumeric characters
503+ if c. is_alphabetic ( ) {
504+ if chars. all ( char:: is_alphanumeric) {
505+ found_labels. push ( possible_label) ;
506+ }
507+ }
508+ }
509+
510+ start_idx = idx + 1 ;
511+ }
512+ }
513+
514+ if found_labels. len ( ) > 0 {
515+ let spans =
516+ found_labels. into_iter ( ) . filter_map ( find_label_span) . collect :: < Vec < Span > > ( ) ;
517+ if spans. len ( ) > 0 {
518+ for span in spans. into_iter ( ) {
519+ ecx. parse_sess ( ) . buffer_lint_with_diagnostic (
520+ lint:: builtin:: NAMED_ASM_LABELS ,
521+ span,
522+ ecx. current_expansion . lint_node_id ,
523+ "do not use named labels in inline assembly" ,
524+ BuiltinLintDiagnostics :: NamedAsmLabel ( "Only GAS local labels of the form `N:` where N is a number may be used in inline asm" . to_string ( ) ) ,
525+ ) ;
526+ }
527+ } else {
528+ // If there were labels but we couldn't find a span, combine the warnings and use the template span
529+ ecx. parse_sess ( ) . buffer_lint_with_diagnostic (
530+ lint:: builtin:: NAMED_ASM_LABELS ,
531+ template_span,
532+ ecx. current_expansion . lint_node_id ,
533+ "do not use named labels in inline assembly" ,
534+ BuiltinLintDiagnostics :: NamedAsmLabel ( "Only GAS local labels of the form `N:` where N is a number may be used in inline asm" . to_string ( ) ) ,
535+ ) ;
536+ }
537+ }
538+ }
539+
472540 // Don't treat raw asm as a format string.
473541 if args. options . contains ( ast:: InlineAsmOptions :: RAW ) {
474542 template. push ( ast:: InlineAsmTemplatePiece :: String ( template_str. to_string ( ) ) ) ;
@@ -670,7 +738,7 @@ pub fn expand_asm<'cx>(
670738) -> Box < dyn base:: MacResult + ' cx > {
671739 match parse_args ( ecx, sp, tts, false ) {
672740 Ok ( args) => {
673- let expr = if let Some ( inline_asm) = expand_preparsed_asm ( ecx, args) {
741+ let expr = if let Some ( inline_asm) = expand_preparsed_asm ( ecx, args, true ) {
674742 P ( ast:: Expr {
675743 id : ast:: DUMMY_NODE_ID ,
676744 kind : ast:: ExprKind :: InlineAsm ( P ( inline_asm) ) ,
@@ -697,7 +765,7 @@ pub fn expand_global_asm<'cx>(
697765) -> Box < dyn base:: MacResult + ' cx > {
698766 match parse_args ( ecx, sp, tts, true ) {
699767 Ok ( args) => {
700- if let Some ( inline_asm) = expand_preparsed_asm ( ecx, args) {
768+ if let Some ( inline_asm) = expand_preparsed_asm ( ecx, args, false ) {
701769 MacEager :: items ( smallvec ! [ P ( ast:: Item {
702770 ident: Ident :: invalid( ) ,
703771 attrs: Vec :: new( ) ,
0 commit comments