Skip to content

Commit

Permalink
Add a suggestion to use unused asm arguments in comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Amanieu committed Jun 11, 2020
1 parent 34bb6d0 commit ddacc67
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 19 deletions.
47 changes: 29 additions & 18 deletions src/librustc_builtin_macros/asm.rs
Expand Up @@ -391,7 +391,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
used[*pos] = true;
}

let named_pos: FxHashSet<usize> = args.named_args.values().cloned().collect();
let named_pos: FxHashMap<usize, Symbol> =
args.named_args.iter().map(|(&sym, &idx)| (idx, sym)).collect();
let mut arg_spans = parser.arg_places.iter().map(|span| template_span.from_inner(*span));
let mut template = vec![];
for piece in unverified_pieces {
Expand All @@ -405,7 +406,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
let operand_idx = match arg.position {
parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => {
if idx >= args.operands.len()
|| named_pos.contains(&idx)
|| named_pos.contains_key(&idx)
|| args.reg_args.contains(&idx)
{
let msg = format!("invalid reference to argument at index {}", idx);
Expand All @@ -426,7 +427,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
};
err.note(&msg);

if named_pos.contains(&idx) {
if named_pos.contains_key(&idx) {
err.span_label(args.operands[idx].1, "named argument");
err.span_note(
args.operands[idx].1,
Expand Down Expand Up @@ -480,27 +481,31 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
}
}

let operands = args.operands;
let unused_operands: Vec<_> = used
.into_iter()
.enumerate()
.filter(|&(_, used)| !used)
.map(|(idx, _)| {
if named_pos.contains(&idx) {
// named argument
(operands[idx].1, "named argument never used")
let mut unused_operands = vec![];
let mut help_str = String::new();
for (idx, used) in used.into_iter().enumerate() {
if !used {
let msg = if let Some(sym) = named_pos.get(&idx) {
help_str.push_str(&format!(" {{{}}}", sym));
"named argument never used"
} else {
// positional argument
(operands[idx].1, "argument never used")
}
})
.collect();
help_str.push_str(&format!(" {{{}}}", idx));
"argument never used"
};
unused_operands.push((args.operands[idx].1, msg));
}
}
match unused_operands.len() {
0 => {}
1 => {
let (sp, msg) = unused_operands.into_iter().next().unwrap();
let mut err = ecx.struct_span_err(sp, msg);
err.span_label(sp, msg);
err.help(&format!(
"if this argument is intentionally unused, \
consider using it in an asm comment: `\"/*{} */\"`",
help_str
));
err.emit();
}
_ => {
Expand All @@ -511,6 +516,11 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
for (sp, msg) in unused_operands {
err.span_label(sp, msg);
}
err.help(&format!(
"if these arguments are intentionally unused, \
consider using them in an asm comment: `\"/*{} */\"`",
help_str
));
err.emit();
}
}
Expand All @@ -521,7 +531,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
parser.line_spans.iter().map(|span| template_span.from_inner(*span)).collect()
};

let inline_asm = ast::InlineAsm { template, operands, options: args.options, line_spans };
let inline_asm =
ast::InlineAsm { template, operands: args.operands, options: args.options, line_spans };
P(ast::Expr {
id: ast::DUMMY_NODE_ID,
kind: ast::ExprKind::InlineAsm(P(inline_asm)),
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/asm/bad-template.rs
Expand Up @@ -22,5 +22,7 @@ fn main() {
//~^ ERROR invalid reference to argument at index 0
asm!("{:foo}", in(reg) foo);
//~^ ERROR asm template modifier must be a single character
asm!("", in(reg) 0, in(reg) 1);
//~^ ERROR multiple unused asm arguments
}
}
18 changes: 17 additions & 1 deletion src/test/ui/asm/bad-template.stderr
Expand Up @@ -19,6 +19,8 @@ error: argument never used
|
LL | asm!("{1}", in(reg) foo);
| ^^^^^^^^^^^ argument never used
|
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`

error: there is no argument named `a`
--> $DIR/bad-template.rs:13:15
Expand Down Expand Up @@ -46,6 +48,8 @@ error: named argument never used
|
LL | asm!("{}", a = in(reg) foo);
| ^^^^^^^^^^^^^^^ named argument never used
|
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`

error: invalid reference to argument at index 1
--> $DIR/bad-template.rs:18:15
Expand All @@ -60,6 +64,8 @@ error: named argument never used
|
LL | asm!("{1}", a = in(reg) foo);
| ^^^^^^^^^^^^^^^ named argument never used
|
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`

error: invalid reference to argument at index 0
--> $DIR/bad-template.rs:21:15
Expand All @@ -82,5 +88,15 @@ error: asm template modifier must be a single character
LL | asm!("{:foo}", in(reg) foo);
| ^^^

error: aborting due to 10 previous errors
error: multiple unused asm arguments
--> $DIR/bad-template.rs:25:18
|
LL | asm!("", in(reg) 0, in(reg) 1);
| ^^^^^^^^^ ^^^^^^^^^ argument never used
| |
| argument never used
|
= help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`

error: aborting due to 11 previous errors

2 changes: 2 additions & 0 deletions src/test/ui/asm/parse-error.stderr
Expand Up @@ -127,6 +127,8 @@ error: argument never used
|
LL | asm!("{a}", a = const foo, a = const bar);
| ^^^^^^^^^^^^^ argument never used
|
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`

error: explicit register arguments cannot have names
--> $DIR/parse-error.rs:47:18
Expand Down

0 comments on commit ddacc67

Please sign in to comment.