Move named_asm_labels
to a HIR lint
This commit is contained in:
parent
f66e825f73
commit
0b81c2eb82
10 changed files with 304 additions and 147 deletions
|
@ -7,10 +7,10 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
|
|||
use rustc_expand::base::{self, *};
|
||||
use rustc_parse::parser::Parser;
|
||||
use rustc_parse_format as parse;
|
||||
use rustc_session::lint::{self, BuiltinLintDiagnostics};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::{InnerSpan, MultiSpan, Span};
|
||||
use rustc_span::{InnerSpan, Span};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use smallvec::smallvec;
|
||||
|
||||
|
@ -484,11 +484,7 @@ fn parse_reg<'a>(
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
fn expand_preparsed_asm(
|
||||
ecx: &mut ExtCtxt<'_>,
|
||||
args: AsmArgs,
|
||||
is_local_asm: bool,
|
||||
) -> Option<ast::InlineAsm> {
|
||||
fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::InlineAsm> {
|
||||
let mut template = vec![];
|
||||
// Register operands are implicitly used since they are not allowed to be
|
||||
// referenced in the template string.
|
||||
|
@ -501,6 +497,8 @@ fn expand_preparsed_asm(
|
|||
let mut line_spans = Vec::with_capacity(args.templates.len());
|
||||
let mut curarg = 0;
|
||||
|
||||
let mut template_strs = Vec::with_capacity(args.templates.len());
|
||||
|
||||
for template_expr in args.templates.into_iter() {
|
||||
if !template.is_empty() {
|
||||
template.push(ast::InlineAsmTemplatePiece::String("\n".to_string()));
|
||||
|
@ -524,8 +522,13 @@ fn expand_preparsed_asm(
|
|||
ast::StrStyle::Raw(raw) => Some(raw as usize),
|
||||
};
|
||||
|
||||
let template_str = &template_str.as_str();
|
||||
let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok();
|
||||
template_strs.push((
|
||||
template_str,
|
||||
template_snippet.as_ref().map(|s| Symbol::intern(s)),
|
||||
template_sp,
|
||||
));
|
||||
let template_str = &template_str.as_str();
|
||||
|
||||
if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch {
|
||||
let find_span = |needle: &str| -> Span {
|
||||
|
@ -560,72 +563,6 @@ fn expand_preparsed_asm(
|
|||
}
|
||||
}
|
||||
|
||||
// Lint against the use of named labels in inline `asm!` but not `global_asm!`
|
||||
if is_local_asm {
|
||||
let find_label_span = |needle: &str| -> Option<Span> {
|
||||
if let Some(snippet) = &template_snippet {
|
||||
if let Some(pos) = snippet.find(needle) {
|
||||
let end = pos
|
||||
+ &snippet[pos..]
|
||||
.find(|c| c == ':')
|
||||
.unwrap_or(snippet[pos..].len() - 1);
|
||||
let inner = InnerSpan::new(pos, end);
|
||||
return Some(template_sp.from_inner(inner));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
};
|
||||
|
||||
let mut found_labels = Vec::new();
|
||||
|
||||
// A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always
|
||||
let statements = template_str.split(|c| matches!(c, '\n' | ';'));
|
||||
for statement in statements {
|
||||
// If there's a comment, trim it from the statement
|
||||
let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]);
|
||||
let mut start_idx = 0;
|
||||
for (idx, _) in statement.match_indices(':') {
|
||||
let possible_label = statement[start_idx..idx].trim();
|
||||
let mut chars = possible_label.chars();
|
||||
if let Some(c) = chars.next() {
|
||||
// A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
|
||||
if (c.is_alphabetic() || matches!(c, '.' | '_'))
|
||||
&& chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
|
||||
{
|
||||
found_labels.push(possible_label);
|
||||
} else {
|
||||
// If we encounter a non-label, there cannot be any further labels, so stop checking
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Empty string means a leading ':' in this section, which is not a label
|
||||
break;
|
||||
}
|
||||
|
||||
start_idx = idx + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if found_labels.len() > 0 {
|
||||
let spans =
|
||||
found_labels.into_iter().filter_map(find_label_span).collect::<Vec<Span>>();
|
||||
// If there were labels but we couldn't find a span, combine the warnings and use the template span
|
||||
let target_spans: MultiSpan =
|
||||
if spans.len() > 0 { spans.into() } else { template_sp.into() };
|
||||
ecx.parse_sess().buffer_lint_with_diagnostic(
|
||||
lint::builtin::NAMED_ASM_LABELS,
|
||||
target_spans,
|
||||
ecx.current_expansion.lint_node_id,
|
||||
"avoid using named labels in inline assembly",
|
||||
BuiltinLintDiagnostics::NamedAsmLabel(
|
||||
"only local labels of the form `<number>:` should be used in inline asm"
|
||||
.to_string(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't treat raw asm as a format string.
|
||||
if args.options.contains(ast::InlineAsmOptions::RAW) {
|
||||
template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string()));
|
||||
|
@ -819,6 +756,7 @@ fn expand_preparsed_asm(
|
|||
|
||||
Some(ast::InlineAsm {
|
||||
template,
|
||||
template_strs: template_strs.into_boxed_slice(),
|
||||
operands: args.operands,
|
||||
clobber_abi: args.clobber_abi,
|
||||
options: args.options,
|
||||
|
@ -833,7 +771,7 @@ pub fn expand_asm<'cx>(
|
|||
) -> Box<dyn base::MacResult + 'cx> {
|
||||
match parse_args(ecx, sp, tts, false) {
|
||||
Ok(args) => {
|
||||
let expr = if let Some(inline_asm) = expand_preparsed_asm(ecx, args, true) {
|
||||
let expr = if let Some(inline_asm) = expand_preparsed_asm(ecx, args) {
|
||||
P(ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::ExprKind::InlineAsm(P(inline_asm)),
|
||||
|
@ -860,7 +798,7 @@ pub fn expand_global_asm<'cx>(
|
|||
) -> Box<dyn base::MacResult + 'cx> {
|
||||
match parse_args(ecx, sp, tts, true) {
|
||||
Ok(args) => {
|
||||
if let Some(inline_asm) = expand_preparsed_asm(ecx, args, false) {
|
||||
if let Some(inline_asm) = expand_preparsed_asm(ecx, args) {
|
||||
MacEager::items(smallvec![P(ast::Item {
|
||||
ident: Ident::invalid(),
|
||||
attrs: Vec::new(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue