Skip to content

Commit 5ce5313

Browse files
committed
add new lint [implicit_abi]
that detects external block without explicit label "C" Signed-off-by: J-ZhengLi <lizheng135@huawei.com>
1 parent cc5ab4a commit 5ce5313

File tree

7 files changed

+155
-0
lines changed

7 files changed

+155
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4580,6 +4580,7 @@ Released 2018-09-13
45804580
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
45814581
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
45824582
[`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params
4583+
[`implicit_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_abi
45834584
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
45844585
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
45854586
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return

clippy_lints/src/declared_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
198198
crate::if_let_mutex::IF_LET_MUTEX_INFO,
199199
crate::if_not_else::IF_NOT_ELSE_INFO,
200200
crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO,
201+
crate::implicit_abi::IMPLICIT_ABI_INFO,
201202
crate::implicit_hasher::IMPLICIT_HASHER_INFO,
202203
crate::implicit_return::IMPLICIT_RETURN_INFO,
203204
crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,

clippy_lints/src/implicit_abi.rs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use rustc_ast::ast::{Item, ItemKind};
3+
use rustc_errors::Applicability;
4+
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
5+
use rustc_session::{declare_lint_pass, declare_tool_lint};
6+
7+
declare_clippy_lint! {
8+
/// ### What it does
9+
/// Checks the external block without explicitly lable its ABI.
10+
///
11+
/// ### Why is this bad?
12+
/// Implicit ABI has negative impact on code readability.
13+
///
14+
/// ### Example
15+
/// ```rust
16+
/// extern {
17+
/// fn c_function();
18+
/// }
19+
/// ```
20+
/// Use instead:
21+
/// ```rust
22+
/// extern "C" {
23+
/// fn c_function();
24+
/// }
25+
/// ```
26+
#[clippy::version = "1.70.0"]
27+
pub IMPLICIT_ABI,
28+
restriction,
29+
"external block with implicit ABI"
30+
}
31+
32+
declare_lint_pass!(ImplicitAbi => [IMPLICIT_ABI]);
33+
34+
impl EarlyLintPass for ImplicitAbi {
35+
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
36+
if let ItemKind::ForeignMod(fm) = &item.kind {
37+
if fm.abi.is_none() {
38+
let extern_span = cx.sess().source_map().span_until_whitespace(item.span);
39+
span_lint_and_sugg(
40+
cx,
41+
IMPLICIT_ABI,
42+
extern_span,
43+
"missing ABI label on extern block",
44+
"explicitly states ABI instead",
45+
"extern \"C\"".to_string(),
46+
Applicability::MachineApplicable,
47+
);
48+
}
49+
}
50+
}
51+
}

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ mod guidelines;
142142
mod if_let_mutex;
143143
mod if_not_else;
144144
mod if_then_some_else_none;
145+
mod implicit_abi;
145146
mod implicit_hasher;
146147
mod implicit_return;
147148
mod implicit_saturating_add;
@@ -964,6 +965,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
964965
let mem_unsafe_functions = conf.mem_unsafe_functions.clone();
965966
store.register_late_pass(move |_| Box::new(guidelines::GuidelineLints::new(mem_unsafe_functions.clone())));
966967
store.register_late_pass(|_| Box::new(unsafe_block_in_proc_macro::UnsafeBlockInProcMacro::new()));
968+
store.register_early_pass(|| Box::new(implicit_abi::ImplicitAbi));
967969
// add lints here, do not remove this comment, it's used in `new_lint`
968970
}
969971

tests/ui/implicit_abi.fixed

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// run-rustfix
2+
#![allow(unused)]
3+
#![warn(clippy::implicit_abi)]
4+
5+
use std::ffi::{c_char, c_void};
6+
7+
#[repr(C)]
8+
pub struct External(i8);
9+
10+
extern "C" {
11+
fn foo();
12+
fn bar(a: u8, b: i32) -> u64;
13+
pub fn baz(a: c_char) -> c_void;
14+
pub fn qux(a: External) -> c_void;
15+
16+
pub static a: std::ffi::c_int;
17+
pub static b: External;
18+
static c: i8;
19+
}
20+
21+
#[rustfmt::skip]
22+
extern "C"
23+
{
24+
static SOME_PTR: *mut c_void;
25+
}
26+
27+
#[rustfmt::skip]
28+
extern "C" { fn my_c_fn(a: i8) -> c_void; }
29+
30+
// For reference, don't lint
31+
extern "C" {
32+
fn c_func();
33+
}
34+
// For reference, don't lint
35+
extern "system" {
36+
pub fn system_call();
37+
}
38+
39+
fn main() {}

tests/ui/implicit_abi.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// run-rustfix
2+
#![allow(unused)]
3+
#![warn(clippy::implicit_abi)]
4+
5+
use std::ffi::{c_char, c_void};
6+
7+
#[repr(C)]
8+
pub struct External(i8);
9+
10+
extern {
11+
fn foo();
12+
fn bar(a: u8, b: i32) -> u64;
13+
pub fn baz(a: c_char) -> c_void;
14+
pub fn qux(a: External) -> c_void;
15+
16+
pub static a: std::ffi::c_int;
17+
pub static b: External;
18+
static c: i8;
19+
}
20+
21+
#[rustfmt::skip]
22+
extern
23+
{
24+
static SOME_PTR: *mut c_void;
25+
}
26+
27+
#[rustfmt::skip]
28+
extern { fn my_c_fn(a: i8) -> c_void; }
29+
30+
// For reference, don't lint
31+
extern "C" {
32+
fn c_func();
33+
}
34+
// For reference, don't lint
35+
extern "system" {
36+
pub fn system_call();
37+
}
38+
39+
fn main() {}

tests/ui/implicit_abi.stderr

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: missing ABI label on extern block
2+
--> $DIR/implicit_abi.rs:10:1
3+
|
4+
LL | extern {
5+
| ^^^^^^ help: explicitly states ABI instead: `extern "C"`
6+
|
7+
= note: `-D clippy::implicit-abi` implied by `-D warnings`
8+
9+
error: missing ABI label on extern block
10+
--> $DIR/implicit_abi.rs:22:1
11+
|
12+
LL | extern
13+
| ^^^^^^ help: explicitly states ABI instead: `extern "C"`
14+
15+
error: missing ABI label on extern block
16+
--> $DIR/implicit_abi.rs:28:1
17+
|
18+
LL | extern { fn my_c_fn(a: i8) -> c_void; }
19+
| ^^^^^^ help: explicitly states ABI instead: `extern "C"`
20+
21+
error: aborting due to 3 previous errors
22+

0 commit comments

Comments
 (0)