Skip to content

Commit 4f6422c

Browse files
committed
Squashed commit of the following:
commit 3a413b7 Merge: d5a1eff 4d8af6f Author: surechen <[email protected]> Date: Mon Jun 26 11:32:14 2023 +0800 Merge pull request rust-lang#5 from mojave2/lint_loop_exit new_lint loop_without_break_or_return commit 4d8af6f Author: mojave2 <[email protected]> Date: Sun Jun 25 19:21:11 2023 +0800 new_line loop_without_break_or_return Signed-off-by: mojave2 <[email protected]> commit d5a1eff Merge: af6c9d4 9cd4b13 Author: surechen <[email protected]> Date: Mon Jun 26 11:23:44 2023 +0800 Merge pull request rust-lang#2 from mojave2/dev_stable new_lint non_reentrant_functions commit 9cd4b13 Author: mojave2 <[email protected]> Date: Wed Jun 21 17:44:12 2023 +0800 update_lint non_reentrant_functions Signed-off-by: mojave2 <[email protected]> commit c900d4a Author: mojave2 <[email protected]> Date: Mon Jun 19 18:37:16 2023 +0800 update_lint non_reentrant_functions Signed-off-by: mojave2 <[email protected]> commit 9845b3a Author: mojave2 <[email protected]> Date: Sat Jun 17 16:32:10 2023 +0800 improve implementation by dogfood Signed-off-by: mojave2 <[email protected]> commit a3a1415 Author: mojave2 <[email protected]> Date: Sat Jun 17 15:29:11 2023 +0800 doc-comment non_reentrant_functions Signed-off-by: mojave2 <[email protected]> commit eb80bb0 Author: mojave2 <[email protected]> Date: Sat Jun 17 15:14:34 2023 +0800 new_lint non_reentrant_functions Signed-off-by: mojave2 <[email protected]> commit af6c9d4 Merge: 38ab3a3 33ddd19 Author: surechen <[email protected]> Date: Mon Jun 26 10:54:08 2023 +0800 Merge pull request rust-lang#7 from J-ZhengLi/dev_stable fix test fail after dev fmt of [`implicit_abi`] commit 33ddd19 Author: J-ZhengLi <[email protected]> Date: Mon Jun 26 10:15:26 2023 +0800 fix test fail after dev fmt of [`implicit_abi`] Signed-off-by: J-ZhengLi <[email protected]> commit 38ab3a3 Merge: 83e42a2 5ce5313 Author: surechen <[email protected]> Date: Mon Jun 26 09:47:22 2023 +0800 Merge pull request rust-lang#1 from J-ZhengLi/dev_stable add new lints: [`mem_unsafe_functions`], [`unsafe_block_in_proc_macro`] and [`implicit_abi`] commit 5ce5313 Author: J-ZhengLi <[email protected]> Date: Wed Jun 21 11:24:29 2023 +0800 add new lint [`implicit_abi`] that detects external block without explicit label "C" Signed-off-by: J-ZhengLi <[email protected]> commit cc5ab4a Author: J-ZhengLi <[email protected]> Date: Tue Jun 20 12:44:02 2023 +0800 add new lint [`unsafe_block_in_proc_macro`] that detects unsafe block in `quote!` Signed-off-by: J-ZhengLi <[email protected]> commit c091b77 Author: J-ZhengLi <[email protected]> Date: Sat Jun 17 15:59:56 2023 +0800 add configuration for lint [`mem_unsafe_functions`]; finish implement lint [`mem_unsafe_functions`]; add simple description for unimplemented lints; Signed-off-by: J-ZhengLi <[email protected]> commit a50f308 Author: J-ZhengLi <[email protected]> Date: Fri Jun 16 17:45:56 2023 +0800 init following new lints: [`passing_string_to_c_functions`] [`untrusted_lib_loading`] [`falliable_memory_allocation`] Signed-off-by: J-ZhengLi <[email protected]> commit da3cc15 Author: J-ZhengLi <[email protected]> Date: Fri Jun 16 14:11:59 2023 +0800 add `guidelines` type and barebone for [`mem_unsafe_functions`] lint Signed-off-by: J-ZhengLi <[email protected]> # Conflicts: # clippy_lints/src/lib.rs
1 parent 8b7e60e commit 4f6422c

31 files changed

+1448
-0
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4532,6 +4532,7 @@ Released 2018-09-13
45324532
[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_with_drain
45334533
[`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes
45344534
[`extra_unused_type_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_type_parameters
4535+
[`falliable_memory_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#falliable_memory_allocation
45354536
[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from
45364537
[`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default
45374538
[`filetype_is_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#filetype_is_file
@@ -4579,6 +4580,7 @@ Released 2018-09-13
45794580
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
45804581
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
45814582
[`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
45824584
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
45834585
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
45844586
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
@@ -4650,6 +4652,7 @@ Released 2018-09-13
46504652
[`lines_filter_map_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok
46514653
[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
46524654
[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
4655+
[`loop_without_break_or_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#loop_without_break_or_return
46534656
[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
46544657
[`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
46554658
[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
@@ -4707,6 +4710,7 @@ Released 2018-09-13
47074710
[`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none
47084711
[`mem_replace_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default
47094712
[`mem_replace_with_uninit`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_uninit
4713+
[`mem_unsafe_functions`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_unsafe_functions
47104714
[`min_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_max
47114715
[`misaligned_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#misaligned_transmute
47124716
[`mismatched_target_os`]: https://rust-lang.github.io/rust-clippy/master/index.html#mismatched_target_os
@@ -4779,6 +4783,7 @@ Released 2018-09-13
47794783
[`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi
47804784
[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
47814785
[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
4786+
[`non_reentrant_functions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_reentrant_functions
47824787
[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
47834788
[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
47844789
[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options
@@ -4813,6 +4818,7 @@ Released 2018-09-13
48134818
[`partial_pub_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#partial_pub_fields
48144819
[`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl
48154820
[`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none
4821+
[`passing_string_to_c_functions`]: https://rust-lang.github.io/rust-clippy/master/index.html#passing_string_to_c_functions
48164822
[`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite
48174823
[`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch
48184824
[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false
@@ -5003,13 +5009,15 @@ Released 2018-09-13
50035009
[`unnested_or_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns
50045010
[`unreachable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreachable
50055011
[`unreadable_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal
5012+
[`unsafe_block_in_proc_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_block_in_proc_macro
50065013
[`unsafe_derive_deserialize`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_derive_deserialize
50075014
[`unsafe_removed_from_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_removed_from_name
50085015
[`unsafe_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_vector_initialization
50095016
[`unseparated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#unseparated_literal_suffix
50105017
[`unsound_collection_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsound_collection_transmute
50115018
[`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice
50125019
[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice
5020+
[`untrusted_lib_loading`]: https://rust-lang.github.io/rust-clippy/master/index.html#untrusted_lib_loading
50135021
[`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async
50145022
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
50155023
[`unused_format_specs`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_format_specs

clippy_lints/src/declared_lints.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,14 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
192192
crate::functions::TOO_MANY_ARGUMENTS_INFO,
193193
crate::functions::TOO_MANY_LINES_INFO,
194194
crate::future_not_send::FUTURE_NOT_SEND_INFO,
195+
crate::guidelines::FALLIABLE_MEMORY_ALLOCATION_INFO,
196+
crate::guidelines::MEM_UNSAFE_FUNCTIONS_INFO,
197+
crate::guidelines::PASSING_STRING_TO_C_FUNCTIONS_INFO,
198+
crate::guidelines::UNTRUSTED_LIB_LOADING_INFO,
195199
crate::if_let_mutex::IF_LET_MUTEX_INFO,
196200
crate::if_not_else::IF_NOT_ELSE_INFO,
197201
crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO,
202+
crate::implicit_abi::IMPLICIT_ABI_INFO,
198203
crate::implicit_hasher::IMPLICIT_HASHER_INFO,
199204
crate::implicit_return::IMPLICIT_RETURN_INFO,
200205
crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
@@ -240,6 +245,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
240245
crate::literal_representation::MISTYPED_LITERAL_SUFFIXES_INFO,
241246
crate::literal_representation::UNREADABLE_LITERAL_INFO,
242247
crate::literal_representation::UNUSUAL_BYTE_GROUPINGS_INFO,
248+
crate::loop_without_break_or_return::LOOP_WITHOUT_BREAK_OR_RETURN_INFO,
243249
crate::loops::EMPTY_LOOP_INFO,
244250
crate::loops::EXPLICIT_COUNTER_LOOP_INFO,
245251
crate::loops::EXPLICIT_INTO_ITER_LOOP_INFO,
@@ -467,6 +473,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
467473
crate::non_expressive_names::MANY_SINGLE_CHAR_NAMES_INFO,
468474
crate::non_expressive_names::SIMILAR_NAMES_INFO,
469475
crate::non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS_INFO,
476+
crate::non_reentrant_functions::NON_REENTRANT_FUNCTIONS_INFO,
470477
crate::non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY_INFO,
471478
crate::nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES_INFO,
472479
crate::octal_escapes::OCTAL_ESCAPES_INFO,
@@ -629,6 +636,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
629636
crate::unnecessary_struct_initialization::UNNECESSARY_STRUCT_INITIALIZATION_INFO,
630637
crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO,
631638
crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO,
639+
crate::unsafe_block_in_proc_macro::UNSAFE_BLOCK_IN_PROC_MACRO_INFO,
632640
crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO,
633641
crate::unused_async::UNUSED_ASYNC_INFO,
634642
crate::unused_io_amount::UNUSED_IO_AMOUNT_INFO,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use clippy_utils::diagnostics::span_lint_and_help;
2+
use if_chain::if_chain;
3+
use rustc_hir::def::Res;
4+
use rustc_hir::def_id::DefIdSet;
5+
use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath};
6+
use rustc_lint::LateContext;
7+
8+
use super::MEM_UNSAFE_FUNCTIONS;
9+
10+
/// Check extern function definitions.
11+
///
12+
/// The main purpose of this function is to load `def_ids` of declared external functions.
13+
pub(super) fn check_foreign_item(item: &Item<'_>, blacklist: &[String], blacklist_ids: &mut DefIdSet) {
14+
if let ItemKind::ForeignMod { items, .. } = item.kind {
15+
for f_item in items {
16+
if blacklist.contains(&f_item.ident.as_str().to_string()) {
17+
let f_did = f_item.id.hir_id().owner.def_id.to_def_id();
18+
blacklist_ids.insert(f_did);
19+
}
20+
}
21+
}
22+
}
23+
24+
/// Check function call expression
25+
///
26+
/// Will lint if the name of called function was blacklisted by the configuration.
27+
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, blacklist_ids: &DefIdSet) {
28+
if_chain! {
29+
if let ExprKind::Call(fn_expr, _) = &expr.kind;
30+
if let ExprKind::Path(qpath) = &fn_expr.kind;
31+
if let QPath::Resolved(_, path) = qpath;
32+
if let Res::Def(_, did) = path.res;
33+
if blacklist_ids.contains(&did);
34+
then {
35+
span_lint_and_help(
36+
cx,
37+
MEM_UNSAFE_FUNCTIONS,
38+
fn_expr.span,
39+
"use of potentially dangerous memory manipulation function",
40+
None,
41+
"consider using its safe version",
42+
);
43+
}
44+
}
45+
}

clippy_lints/src/guidelines/mod.rs

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
mod falliable_memory_allocation;
2+
mod mem_unsafe_functions;
3+
mod passing_string_to_c_functions;
4+
mod untrusted_lib_loading;
5+
6+
use clippy_utils::def_path_def_ids;
7+
use rustc_hir as hir;
8+
use rustc_hir::def_id::{DefId, DefIdSet};
9+
use rustc_hir::intravisit;
10+
use rustc_lint::{LateContext, LateLintPass};
11+
use rustc_session::{declare_tool_lint, impl_lint_pass};
12+
use rustc_span::def_id::LocalDefId;
13+
use rustc_span::Span;
14+
15+
declare_clippy_lint! {
16+
/// ### What it does
17+
/// Checks for direct usage of external functions that modify memory
18+
/// without concerning about memory safety, such as `memcpy`, `strcpy`, `strcat` etc.
19+
///
20+
/// ### Why is this bad?
21+
/// These function can be dangerous when used incorrectly,
22+
/// which could potentially introduce vulnerablities such as buffer overflow to the software.
23+
///
24+
/// ### Example
25+
/// ```rust
26+
/// extern "C" {
27+
/// fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void;
28+
/// }
29+
/// let ptr = unsafe { memcpy(dest, src, size); }
30+
/// // Or use via libc
31+
/// let ptr = unsafe { libc::memcpy(dest, src, size); }
32+
#[clippy::version = "1.70.0"]
33+
pub MEM_UNSAFE_FUNCTIONS,
34+
nursery,
35+
"use of potentially dangerous external functions"
36+
}
37+
38+
declare_clippy_lint! {
39+
/// ### What it does
40+
///
41+
/// ### Why is this bad?
42+
///
43+
/// ### Example
44+
/// ```rust
45+
/// // example code where clippy issues a warning
46+
/// ```
47+
/// Use instead:
48+
/// ```rust
49+
/// // example code which does not raise clippy warning
50+
/// ```
51+
#[clippy::version = "1.70.0"]
52+
pub UNTRUSTED_LIB_LOADING,
53+
nursery,
54+
"attempt to load dynamic library from untrusted source"
55+
}
56+
57+
declare_clippy_lint! {
58+
/// ### What it does
59+
///
60+
/// ### Why is this bad?
61+
///
62+
/// ### Example
63+
/// ```rust
64+
/// // example code where clippy issues a warning
65+
/// ```
66+
/// Use instead:
67+
/// ```rust
68+
/// // example code which does not raise clippy warning
69+
/// ```
70+
#[clippy::version = "1.70.0"]
71+
pub PASSING_STRING_TO_C_FUNCTIONS,
72+
nursery,
73+
"passing string or str to extern C function"
74+
}
75+
76+
declare_clippy_lint! {
77+
/// ### What it does
78+
///
79+
/// ### Why is this bad?
80+
///
81+
/// ### Example
82+
/// ```rust
83+
/// // example code where clippy issues a warning
84+
/// ```
85+
/// Use instead:
86+
/// ```rust
87+
/// // example code which does not raise clippy warning
88+
/// ```
89+
#[clippy::version = "1.70.0"]
90+
pub FALLIABLE_MEMORY_ALLOCATION,
91+
nursery,
92+
"memory allocation without checking arguments and result"
93+
}
94+
95+
#[derive(Clone, Default)]
96+
pub struct GuidelineLints {
97+
mem_uns_fns: Vec<String>,
98+
mem_uns_fns_ty_ids: DefIdSet,
99+
}
100+
101+
impl GuidelineLints {
102+
pub fn new(mem_uns_fns: Vec<String>) -> Self {
103+
Self {
104+
mem_uns_fns,
105+
mem_uns_fns_ty_ids: DefIdSet::new(),
106+
}
107+
}
108+
}
109+
110+
impl_lint_pass!(GuidelineLints => [
111+
MEM_UNSAFE_FUNCTIONS,
112+
UNTRUSTED_LIB_LOADING,
113+
PASSING_STRING_TO_C_FUNCTIONS,
114+
FALLIABLE_MEMORY_ALLOCATION,
115+
]);
116+
117+
impl<'tcx> LateLintPass<'tcx> for GuidelineLints {
118+
fn check_fn(
119+
&mut self,
120+
_cx: &LateContext<'tcx>,
121+
_kind: intravisit::FnKind<'tcx>,
122+
_decl: &'tcx hir::FnDecl<'_>,
123+
_body: &'tcx hir::Body<'_>,
124+
_span: Span,
125+
_def_id: LocalDefId,
126+
) {
127+
}
128+
129+
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
130+
// Resolve function names to def_ids from configuration
131+
for uns_fns in &self.mem_uns_fns {
132+
// Path like function names such as `libc::foo` or `aa::bb::cc::bar`,
133+
// this only works with dependencies.
134+
if uns_fns.contains("::") {
135+
let path: Vec<&str> = uns_fns.split("::").collect();
136+
for did in def_path_def_ids(cx, path.as_slice()) {
137+
self.mem_uns_fns_ty_ids.insert(did);
138+
}
139+
}
140+
// Plain function names, then we should take its libc variant into account
141+
else if let Some(did) = libc_fn_def_id(cx, uns_fns) {
142+
self.mem_uns_fns_ty_ids.insert(did);
143+
}
144+
}
145+
}
146+
147+
fn check_item(&mut self, _cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
148+
mem_unsafe_functions::check_foreign_item(item, &self.mem_uns_fns, &mut self.mem_uns_fns_ty_ids);
149+
}
150+
151+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
152+
mem_unsafe_functions::check(cx, expr, &self.mem_uns_fns_ty_ids);
153+
}
154+
}
155+
156+
fn libc_fn_def_id(cx: &LateContext<'_>, fn_name: &str) -> Option<DefId> {
157+
let path = &["libc", fn_name];
158+
def_path_def_ids(cx, path).next()
159+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

clippy_lints/src/implicit_abi.rs

Lines changed: 51 additions & 0 deletions
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+
}

0 commit comments

Comments
 (0)