Skip to content

Commit 3d62203

Browse files
committed
Add [extern_without_abi] lint
1 parent 2536745 commit 3d62203

13 files changed

+157
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5456,6 +5456,7 @@ Released 2018-09-13
54565456
[`explicit_write`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_write
54575457
[`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice
54585458
[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_with_drain
5459+
[`extern_without_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#extern_without_abi
54595460
[`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes
54605461
[`extra_unused_type_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_type_parameters
54615462
[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
173173
crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO,
174174
crate::exit::EXIT_INFO,
175175
crate::explicit_write::EXPLICIT_WRITE_INFO,
176+
crate::extern_without_abi::EXTERN_WITHOUT_ABI_INFO,
176177
crate::extra_unused_type_parameters::EXTRA_UNUSED_TYPE_PARAMETERS_INFO,
177178
crate::fallible_impl_from::FALLIBLE_IMPL_FROM_INFO,
178179
crate::field_scoped_visibility_modifiers::FIELD_SCOPED_VISIBILITY_MODIFIERS_INFO,
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use clippy_utils::diagnostics::span_lint;
2+
use rustc_ast::visit::FnKind;
3+
use rustc_ast::{Extern, FnHeader, FnSig, ForeignMod, Item, ItemKind, NodeId};
4+
use rustc_lint::{EarlyContext, EarlyLintPass};
5+
use rustc_session::declare_lint_pass;
6+
use rustc_span::Span;
7+
8+
const LINT_MSG: &str = "`extern` missing explicit ABI";
9+
10+
declare_clippy_lint! {
11+
/// ### What it does
12+
/// Checks for usage of `extern` without an explicit ABI.
13+
///
14+
/// ### Why is this bad?
15+
/// Explicitly declaring the ABI improves readability.
16+
//
17+
/// ### Example
18+
/// ```no_run
19+
/// extern fn foo() {}
20+
///
21+
/// extern {
22+
/// fn bar();
23+
/// }
24+
/// ```
25+
/// Use instead:
26+
/// ```no_run
27+
/// extern "C" fn foo() {}
28+
///
29+
/// extern "C" {
30+
/// fn bar();
31+
/// }
32+
/// ```
33+
#[clippy::version = "1.83.0"]
34+
pub EXTERN_WITHOUT_ABI,
35+
style,
36+
"`extern` missing explicit ABI"
37+
}
38+
39+
declare_lint_pass!(ExternWithoutAbi => [EXTERN_WITHOUT_ABI]);
40+
41+
impl EarlyLintPass for ExternWithoutAbi {
42+
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
43+
if let ItemKind::ForeignMod(ref foreign_mod) = item.kind
44+
&& let ForeignMod { abi: None, .. } = foreign_mod
45+
{
46+
span_lint(cx, EXTERN_WITHOUT_ABI, item.span, LINT_MSG);
47+
}
48+
}
49+
50+
fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: Span, _: NodeId) {
51+
if let FnKind::Fn(_, _, sig, ..) = kind
52+
&& let FnSig { header, .. } = sig
53+
&& let FnHeader {
54+
ext: Extern::Implicit(span),
55+
..
56+
} = header
57+
{
58+
span_lint(cx, EXTERN_WITHOUT_ABI, *span, LINT_MSG);
59+
}
60+
}
61+
}

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ mod excessive_nesting;
135135
mod exhaustive_items;
136136
mod exit;
137137
mod explicit_write;
138+
mod extern_without_abi;
138139
mod extra_unused_type_parameters;
139140
mod fallible_impl_from;
140141
mod field_scoped_visibility_modifiers;
@@ -942,5 +943,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
942943
store.register_late_pass(move |_| Box::new(manual_div_ceil::ManualDivCeil::new(conf)));
943944
store.register_late_pass(|_| Box::new(manual_is_power_of_two::ManualIsPowerOfTwo));
944945
store.register_late_pass(|_| Box::new(non_zero_suggestions::NonZeroSuggestions));
946+
store.register_early_pass(|| Box::new(extern_without_abi::ExternWithoutAbi));
945947
// add lints here, do not remove this comment, it's used in `new_lint`
946948
}

tests/ui/boxed_local.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![allow(
22
clippy::borrowed_box,
3+
clippy::extern_without_abi,
34
clippy::needless_pass_by_value,
45
clippy::unused_unit,
56
clippy::redundant_clone,

tests/ui/boxed_local.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: local variable doesn't need to be boxed here
2-
--> tests/ui/boxed_local.rs:39:13
2+
--> tests/ui/boxed_local.rs:40:13
33
|
44
LL | fn warn_arg(x: Box<A>) {
55
| ^
@@ -8,19 +8,19 @@ LL | fn warn_arg(x: Box<A>) {
88
= help: to override `-D warnings` add `#[allow(clippy::boxed_local)]`
99

1010
error: local variable doesn't need to be boxed here
11-
--> tests/ui/boxed_local.rs:122:12
11+
--> tests/ui/boxed_local.rs:123:12
1212
|
1313
LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {}
1414
| ^^^^^^^^^^^
1515

1616
error: local variable doesn't need to be boxed here
17-
--> tests/ui/boxed_local.rs:187:44
17+
--> tests/ui/boxed_local.rs:188:44
1818
|
1919
LL | fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 {
2020
| ^
2121

2222
error: local variable doesn't need to be boxed here
23-
--> tests/ui/boxed_local.rs:195:16
23+
--> tests/ui/boxed_local.rs:196:16
2424
|
2525
LL | fn foo(x: Box<u32>) {}
2626
| ^

tests/ui/doc/doc-fixable.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
//! This file tests for the `DOC_MARKDOWN` lint.
33

4-
#![allow(dead_code, incomplete_features)]
4+
#![allow(dead_code, incomplete_features, clippy::extern_without_abi)]
55
#![warn(clippy::doc_markdown)]
66
#![feature(custom_inner_attributes, generic_const_exprs, const_option)]
77
#![rustfmt::skip]

tests/ui/doc/doc-fixable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
//! This file tests for the `DOC_MARKDOWN` lint.
33
4-
#![allow(dead_code, incomplete_features)]
4+
#![allow(dead_code, incomplete_features, clippy::extern_without_abi)]
55
#![warn(clippy::doc_markdown)]
66
#![feature(custom_inner_attributes, generic_const_exprs, const_option)]
77
#![rustfmt::skip]

tests/ui/extern_without_abi.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![warn(clippy::extern_without_abi)]
2+
3+
fn main() {}
4+
5+
#[rustfmt::skip]
6+
extern fn foo() {}
7+
//~^ ERROR: `extern` missing explicit ABI
8+
9+
extern "C" fn bar() {}
10+
11+
extern "system" fn baz() {}
12+
13+
#[rustfmt::skip]
14+
extern {
15+
//~^ ERROR: `extern` missing explicit ABI
16+
static QUX: std::ffi::c_int;
17+
18+
fn quux();
19+
}
20+
21+
extern "C" {
22+
static CORGE: std::ffi::c_int;
23+
24+
fn grault();
25+
}
26+
27+
extern "system" {
28+
static GARPLY: std::ffi::c_int;
29+
30+
fn waldo();
31+
}

tests/ui/extern_without_abi.stderr

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error: `extern` missing explicit ABI
2+
--> tests/ui/extern_without_abi.rs:6:1
3+
|
4+
LL | extern fn foo() {}
5+
| ^^^^^^
6+
|
7+
= note: `-D clippy::extern-without-abi` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::extern_without_abi)]`
9+
10+
error: `extern` missing explicit ABI
11+
--> tests/ui/extern_without_abi.rs:14:1
12+
|
13+
LL | / extern {
14+
LL | |
15+
LL | | static QUX: std::ffi::c_int;
16+
... |
17+
LL | | }
18+
| |_^
19+
20+
error: aborting due to 2 previous errors
21+

tests/ui/missing_const_for_fn/could_be_const.fixed

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#![warn(clippy::missing_const_for_fn)]
2-
#![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
2+
#![allow(
3+
incomplete_features,
4+
clippy::extern_without_abi,
5+
clippy::let_and_return,
6+
clippy::missing_transmute_annotations
7+
)]
38
#![feature(const_mut_refs)]
49
#![feature(const_trait_impl)]
510

tests/ui/missing_const_for_fn/could_be_const.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#![warn(clippy::missing_const_for_fn)]
2-
#![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
2+
#![allow(
3+
incomplete_features,
4+
clippy::extern_without_abi,
5+
clippy::let_and_return,
6+
clippy::missing_transmute_annotations
7+
)]
38
#![feature(const_mut_refs)]
49
#![feature(const_trait_impl)]
510

0 commit comments

Comments
 (0)