Add lint for inline assembly syntax style preference

This commit is contained in:
Jethro Beekman 2020-09-28 15:30:47 +02:00
parent db6fb90bc0
commit 0690f9c5d5
6 changed files with 223 additions and 0 deletions

View file

@ -1635,6 +1635,8 @@ Released 2018-09-13
[`inherent_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string [`inherent_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string
[`inherent_to_string_shadow_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string_shadow_display [`inherent_to_string_shadow_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string_shadow_display
[`inline_always`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_always [`inline_always`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_always
[`inline_asm_x86_att_syntax`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_asm_x86_att_syntax
[`inline_asm_x86_intel_syntax`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_asm_x86_intel_syntax
[`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body [`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body
[`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one [`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one
[`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic

View file

@ -0,0 +1,125 @@
use std::fmt;
use crate::utils::span_lint_and_help;
use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions};
use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
use rustc_session::{declare_lint_pass, declare_tool_lint};
#[derive(Clone, Copy, PartialEq, Eq)]
enum AsmStyle {
Intel,
Att,
}
impl fmt::Display for AsmStyle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AsmStyle::Intel => f.write_str("Intel"),
AsmStyle::Att => f.write_str("AT&T"),
}
}
}
impl std::ops::Not for AsmStyle {
type Output = AsmStyle;
fn not(self) -> AsmStyle {
match self {
AsmStyle::Intel => AsmStyle::Att,
AsmStyle::Att => AsmStyle::Intel,
}
}
}
fn check_expr_asm_syntax(lint: &'static Lint, cx: &EarlyContext<'_>, expr: &Expr, check_for: AsmStyle) {
if let ExprKind::InlineAsm(ref inline_asm) = expr.kind {
let style = if inline_asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
AsmStyle::Att
} else {
AsmStyle::Intel
};
if style == check_for {
span_lint_and_help(
cx,
lint,
expr.span,
&format!("{} x86 assembly syntax used", style),
None,
&format!("use {} x86 assembly syntax", !style),
);
}
}
}
declare_clippy_lint! {
/// **What it does:** Checks for usage of Intel x86 assembly syntax.
///
/// **Why is this bad?** The lint has been enabled to indicate a preference
/// for AT&T x86 assembly syntax.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// ```rust,no_run
/// # #![feature(asm)]
/// # unsafe { let ptr = "".as_ptr();
/// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
/// # }
/// ```
/// Use instead:
/// ```rust,no_run
/// # #![feature(asm)]
/// # unsafe { let ptr = "".as_ptr();
/// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
/// # }
/// ```
pub INLINE_ASM_X86_INTEL_SYNTAX,
restriction,
"prefer AT&T x86 assembly syntax"
}
declare_lint_pass!(InlineAsmX86IntelSyntax => [INLINE_ASM_X86_INTEL_SYNTAX]);
impl EarlyLintPass for InlineAsmX86IntelSyntax {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
check_expr_asm_syntax(Self::get_lints()[0], cx, expr, AsmStyle::Intel);
}
}
declare_clippy_lint! {
/// **What it does:** Checks for usage of AT&T x86 assembly syntax.
///
/// **Why is this bad?** The lint has been enabled to indicate a preference
/// for Intel x86 assembly syntax.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// ```rust,no_run
/// # #![feature(asm)]
/// # unsafe { let ptr = "".as_ptr();
/// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
/// # }
/// ```
/// Use instead:
/// ```rust,no_run
/// # #![feature(asm)]
/// # unsafe { let ptr = "".as_ptr();
/// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
/// # }
/// ```
pub INLINE_ASM_X86_ATT_SYNTAX,
restriction,
"prefer Intel x86 assembly syntax"
}
declare_lint_pass!(InlineAsmX86AttSyntax => [INLINE_ASM_X86_ATT_SYNTAX]);
impl EarlyLintPass for InlineAsmX86AttSyntax {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
check_expr_asm_syntax(Self::get_lints()[0], cx, expr, AsmStyle::Att);
}
}

View file

@ -153,6 +153,7 @@ mod utils;
mod approx_const; mod approx_const;
mod arithmetic; mod arithmetic;
mod as_conversions; mod as_conversions;
mod asm_syntax;
mod assertions_on_constants; mod assertions_on_constants;
mod assign_ops; mod assign_ops;
mod async_yields_async; mod async_yields_async;
@ -487,6 +488,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&arithmetic::FLOAT_ARITHMETIC, &arithmetic::FLOAT_ARITHMETIC,
&arithmetic::INTEGER_ARITHMETIC, &arithmetic::INTEGER_ARITHMETIC,
&as_conversions::AS_CONVERSIONS, &as_conversions::AS_CONVERSIONS,
&asm_syntax::INLINE_ASM_X86_ATT_SYNTAX,
&asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX,
&assertions_on_constants::ASSERTIONS_ON_CONSTANTS, &assertions_on_constants::ASSERTIONS_ON_CONSTANTS,
&assign_ops::ASSIGN_OP_PATTERN, &assign_ops::ASSIGN_OP_PATTERN,
&assign_ops::MISREFACTORED_ASSIGN_OP, &assign_ops::MISREFACTORED_ASSIGN_OP,
@ -1123,12 +1126,16 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem); store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>(); let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods)); store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
LintId::of(&arithmetic::FLOAT_ARITHMETIC), LintId::of(&arithmetic::FLOAT_ARITHMETIC),
LintId::of(&arithmetic::INTEGER_ARITHMETIC), LintId::of(&arithmetic::INTEGER_ARITHMETIC),
LintId::of(&as_conversions::AS_CONVERSIONS), LintId::of(&as_conversions::AS_CONVERSIONS),
LintId::of(&asm_syntax::INLINE_ASM_X86_ATT_SYNTAX),
LintId::of(&asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX),
LintId::of(&create_dir::CREATE_DIR), LintId::of(&create_dir::CREATE_DIR),
LintId::of(&dbg_macro::DBG_MACRO), LintId::of(&dbg_macro::DBG_MACRO),
LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE), LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE),

View file

@ -899,6 +899,20 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
deprecation: None, deprecation: None,
module: "attrs", module: "attrs",
}, },
Lint {
name: "inline_asm_x86_att_syntax",
group: "restriction",
desc: "prefer Intel x86 assembly syntax",
deprecation: None,
module: "asm_syntax",
},
Lint {
name: "inline_asm_x86_intel_syntax",
group: "restriction",
desc: "prefer AT&T x86 assembly syntax",
deprecation: None,
module: "asm_syntax",
},
Lint { Lint {
name: "inline_fn_without_body", name: "inline_fn_without_body",
group: "correctness", group: "correctness",

31
tests/ui/asm_syntax.rs Normal file
View file

@ -0,0 +1,31 @@
#![feature(asm)]
// only-x86 only-x86_64
#[warn(clippy::inline_asm_x86_intel_syntax)]
mod warn_intel {
pub(super) unsafe fn use_asm() {
asm!("");
asm!("", options());
asm!("", options(nostack));
asm!("", options(att_syntax));
asm!("", options(nostack, att_syntax));
}
}
#[warn(clippy::inline_asm_x86_att_syntax)]
mod warn_att {
pub(super) unsafe fn use_asm() {
asm!("");
asm!("", options());
asm!("", options(nostack));
asm!("", options(att_syntax));
asm!("", options(nostack, att_syntax));
}
}
fn main() {
unsafe {
warn_att::use_asm();
warn_intel::use_asm();
}
}

View file

@ -0,0 +1,44 @@
error: Intel x86 assembly syntax used
--> $DIR/asm_syntax.rs:7:9
|
LL | asm!("");
| ^^^^^^^^^
|
= note: `-D clippy::inline-asm-x86-intel-syntax` implied by `-D warnings`
= help: use AT&T x86 assembly syntax
error: Intel x86 assembly syntax used
--> $DIR/asm_syntax.rs:8:9
|
LL | asm!("", options());
| ^^^^^^^^^^^^^^^^^^^^
|
= help: use AT&T x86 assembly syntax
error: Intel x86 assembly syntax used
--> $DIR/asm_syntax.rs:9:9
|
LL | asm!("", options(nostack));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: use AT&T x86 assembly syntax
error: AT&T x86 assembly syntax used
--> $DIR/asm_syntax.rs:21:9
|
LL | asm!("", options(att_syntax));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::inline-asm-x86-att-syntax` implied by `-D warnings`
= help: use Intel x86 assembly syntax
error: AT&T x86 assembly syntax used
--> $DIR/asm_syntax.rs:22:9
|
LL | asm!("", options(nostack, att_syntax));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: use Intel x86 assembly syntax
error: aborting due to 5 previous errors