Skip to content

Commit a2277f0

Browse files
committed
simpler version
1 parent d590083 commit a2277f0

File tree

2 files changed

+43
-41
lines changed

2 files changed

+43
-41
lines changed

clippy_lints/src/pointer_in_nomem_asm_block.rs

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,57 @@ use rustc_hir::*;
22
use rustc_lint::{LateContext, LateLintPass};
33
use rustc_session::declare_lint_pass;
44
use rustc_ast::InlineAsmOptions;
5-
use clippy_utils::diagnostics::span_lint;
5+
use clippy_utils::diagnostics::span_lint_and_then;
6+
use rustc_span::{BytePos, Span};
7+
use rustc_errors::Applicability;
68

7-
#[derive(Clone, Copy, PartialEq, Eq)]
8-
enum AsmMemoryOptions {
9-
NoMem,
10-
Readonly,
11-
}
12-
13-
fn has_in_operand_pointer(cx: &LateContext<'_>, asm_op: &InlineAsmOperand<'_>) -> Option<Mutability> {
9+
fn has_in_operand_pointer(cx: &LateContext<'_>, asm_op: &InlineAsmOperand<'_>) -> bool {
1410
let asm_in_expr = match asm_op {
11+
InlineAsmOperand::SymStatic { .. }
12+
| InlineAsmOperand::Out { .. }
13+
| InlineAsmOperand::Const { .. }
14+
| InlineAsmOperand::SymFn { .. }
15+
| InlineAsmOperand::Label { .. } => return false,
1516
InlineAsmOperand::In { expr, .. } => expr,
1617
InlineAsmOperand::InOut { expr, .. } => expr,
1718
InlineAsmOperand::SplitInOut { in_expr, ..} => in_expr,
18-
InlineAsmOperand::SymStatic { .. } => return Some(Mutability::Not),
19-
InlineAsmOperand::Out { .. } => return None,
20-
InlineAsmOperand::Const { .. } => return None,
21-
InlineAsmOperand::SymFn { .. } => return None,
22-
InlineAsmOperand::Label { .. } => return None,
2319
};
2420

2521
return match cx.typeck_results().expr_ty(asm_in_expr).kind() {
26-
rustc_middle::ty::TyKind::RawPtr(_, mutbl) => Some(*mutbl),
27-
rustc_middle::ty::TyKind::Ref(_, _, mutbl) => Some(*mutbl),
28-
_ => None,
22+
rustc_middle::ty::TyKind::RawPtr(..) => true,
23+
rustc_middle::ty::TyKind::Ref(..) => true,
24+
_ => false,
2925
};
3026
}
3127

32-
fn yeet_lint(cx: &LateContext<'_>, span: rustc_span::Span, msg: &'static str) {
33-
span_lint(cx, POINTER_IN_NOMEM_ASM_BLOCK, span, msg);
28+
fn shift_span_by_two_bytes(s: Span) -> Span {
29+
s.with_lo(s.lo() + BytePos(2))
3430
}
3531

36-
fn check_asm(cx: &LateContext<'_>, asm: &InlineAsm<'_>) {
37-
let nomem = asm.options.contains(InlineAsmOptions::NOMEM);
38-
let rdonly = asm.options.contains(InlineAsmOptions::READONLY);
39-
let memopt = match (nomem, rdonly) {
40-
(false, false) => return, // nothing to check
41-
(false, true) => AsmMemoryOptions::Readonly,
42-
(true, false) => AsmMemoryOptions::NoMem,
43-
(true, true) => return, // just return, rustc should fail anyway
44-
};
32+
fn yeet_lint(cx: &LateContext<'_>, asm: &InlineAsm<'_>, asm_span: Span, op_spans: Vec<Span>) {
33+
let last_op_span = asm.operands.last().unwrap().1;
34+
let probably_asm_options_span = asm_span.trim_start(last_op_span).map(shift_span_by_two_bytes);
4535

46-
for (asm_op, asm_op_span) in asm.operands {
47-
let p = match has_in_operand_pointer(cx, asm_op) {
48-
Some(p) => p,
49-
None => continue,
50-
};
36+
span_lint_and_then(cx, POINTER_IN_NOMEM_ASM_BLOCK, op_spans, "passing pointer to nomem asm block", |diag| {
37+
if let Some(probably_asm_options_span) = probably_asm_options_span {
38+
diag.span_suggestion(probably_asm_options_span, "heeelppp", "suggg", Applicability::MaybeIncorrect);
39+
}
40+
// note_span.inspect(|s| { diag.span_note(*s, "declared here"); });
41+
});
42+
}
43+
44+
fn check_asm(cx: &LateContext<'_>, asm: &InlineAsm<'_>, asm_span: Span) {
45+
if !asm.options.contains(InlineAsmOptions::NOMEM) || asm.operands.is_empty() {
46+
return;
47+
}
5148

52-
let msg = match (p, memopt) {
53-
(Mutability::Not, AsmMemoryOptions::Readonly) => continue,
54-
(Mutability::Not, AsmMemoryOptions::NoMem) => "const pointer in nomem",
55-
(Mutability::Mut, AsmMemoryOptions::Readonly) => "mut pointer in readonly",
56-
(Mutability::Mut, AsmMemoryOptions::NoMem) => "mut pointer in nomem",
57-
};
49+
let spans = asm.operands.iter()
50+
.filter(|(op, _span)| has_in_operand_pointer(cx, op))
51+
.map(|(_op, span)| *span)
52+
.collect::<Vec<Span>>();
5853

59-
yeet_lint(cx, *asm_op_span, msg);
54+
if !spans.is_empty() {
55+
yeet_lint(cx, asm, asm_span, spans);
6056
}
6157
}
6258

@@ -84,7 +80,7 @@ declare_lint_pass!(PointerInNomemAsmBlock => [POINTER_IN_NOMEM_ASM_BLOCK]);
8480
impl<'tcx> LateLintPass<'tcx> for PointerInNomemAsmBlock {
8581
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
8682
if let ExprKind::InlineAsm(asm) = &expr.kind {
87-
check_asm(cx, asm);
83+
check_asm(cx, asm, expr.span);
8884
}
8985
}
9086
}

tests/ui/pointer_in_nomem_asm_block.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
#![no_std]
44

55
unsafe fn nomem_bad(p: &i32) {
6-
core::arch::asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
6+
core::arch::asm!(
7+
"asdf {p1}, {p2}, {p3}",
8+
p1 = in(reg) p,
9+
p2 = in(reg) p as *const _ as usize,
10+
p3 = in(reg) p,
11+
options(nomem, nostack, preserves_flags)
12+
);
713
}
814

915
unsafe fn readonly_bad(p: &mut i32) {

0 commit comments

Comments
 (0)