Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit ebd1ec0

Browse files
committed
Move cast_ptr_alignment to its own module
1 parent 9a24877 commit ebd1ec0

File tree

2 files changed

+85
-63
lines changed

2 files changed

+85
-63
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use rustc_hir::{Expr, ExprKind, GenericArg};
2+
use rustc_lint::LateContext;
3+
use rustc_middle::ty::{self, Ty};
4+
use rustc_span::symbol::sym;
5+
use rustc_target::abi::LayoutOf;
6+
7+
use if_chain::if_chain;
8+
9+
use crate::utils::{is_hir_ty_cfg_dependant, span_lint};
10+
11+
use super::CAST_PTR_ALIGNMENT;
12+
13+
pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
14+
if let ExprKind::Cast(ref cast_expr, cast_to) = expr.kind {
15+
if is_hir_ty_cfg_dependant(cx, cast_to) {
16+
return;
17+
}
18+
let (cast_from, cast_to) = (
19+
cx.typeck_results().expr_ty(cast_expr),
20+
cx.typeck_results().expr_ty(expr),
21+
);
22+
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
23+
} else if let ExprKind::MethodCall(method_path, _, args, _) = expr.kind {
24+
if_chain! {
25+
if method_path.ident.name == sym!(cast);
26+
if let Some(generic_args) = method_path.args;
27+
if let [GenericArg::Type(cast_to)] = generic_args.args;
28+
// There probably is no obvious reason to do this, just to be consistent with `as` cases.
29+
if !is_hir_ty_cfg_dependant(cx, cast_to);
30+
then {
31+
let (cast_from, cast_to) =
32+
(cx.typeck_results().expr_ty(&args[0]), cx.typeck_results().expr_ty(expr));
33+
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
34+
}
35+
}
36+
}
37+
}
38+
39+
fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_from: Ty<'tcx>, cast_to: Ty<'tcx>) {
40+
if_chain! {
41+
if let ty::RawPtr(from_ptr_ty) = &cast_from.kind();
42+
if let ty::RawPtr(to_ptr_ty) = &cast_to.kind();
43+
if let Ok(from_layout) = cx.layout_of(from_ptr_ty.ty);
44+
if let Ok(to_layout) = cx.layout_of(to_ptr_ty.ty);
45+
if from_layout.align.abi < to_layout.align.abi;
46+
// with c_void, we inherently need to trust the user
47+
if !is_c_void(cx, from_ptr_ty.ty);
48+
// when casting from a ZST, we don't know enough to properly lint
49+
if !from_layout.is_zst();
50+
then {
51+
span_lint(
52+
cx,
53+
CAST_PTR_ALIGNMENT,
54+
expr.span,
55+
&format!(
56+
"casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)",
57+
cast_from,
58+
cast_to,
59+
from_layout.align.abi.bytes(),
60+
to_layout.align.abi.bytes(),
61+
),
62+
);
63+
}
64+
}
65+
}
66+
67+
/// Check if the given type is either `core::ffi::c_void` or
68+
/// one of the platform specific `libc::<platform>::c_void` of libc.
69+
fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
70+
if let ty::Adt(adt, _) = ty.kind() {
71+
let names = cx.get_def_path(adt.did);
72+
73+
if names.is_empty() {
74+
return false;
75+
}
76+
if names[0] == sym::libc || names[0] == sym::core && *names.last().unwrap() == sym!(c_void) {
77+
return true;
78+
}
79+
}
80+
false
81+
}

clippy_lints/src/casts/mod.rs

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod cast_lossless;
22
mod cast_possible_truncation;
33
mod cast_possible_wrap;
44
mod cast_precision_loss;
5+
mod cast_ptr_alignment;
56
mod cast_sign_loss;
67
mod fn_to_numeric_cast;
78
mod fn_to_numeric_cast_with_truncation;
@@ -13,22 +14,18 @@ use std::borrow::Cow;
1314
use if_chain::if_chain;
1415
use rustc_ast::LitKind;
1516
use rustc_errors::Applicability;
16-
use rustc_hir::{Expr, ExprKind, GenericArg, MutTy, Mutability, TyKind, UnOp};
17+
use rustc_hir::{Expr, ExprKind, MutTy, Mutability, TyKind, UnOp};
1718
use rustc_lint::{LateContext, LateLintPass, LintContext};
1819
use rustc_middle::lint::in_external_macro;
19-
use rustc_middle::ty::{self, Ty, TypeAndMut, UintTy};
20+
use rustc_middle::ty::{self, TypeAndMut, UintTy};
2021
use rustc_semver::RustcVersion;
2122
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
22-
use rustc_span::symbol::sym;
23-
use rustc_target::abi::LayoutOf;
2423

2524
use crate::utils::sugg::Sugg;
2625
use crate::utils::{
2726
is_hir_ty_cfg_dependant, meets_msrv, snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then,
2827
};
2928

30-
use utils::int_ty_to_nbits;
31-
3229
declare_clippy_lint! {
3330
/// **What it does:** Checks for casts from any numerical to a float type where
3431
/// the receiving type cannot store all values from the original type without
@@ -270,22 +267,6 @@ declare_lint_pass!(Casts => [
270267
FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
271268
]);
272269

273-
/// Check if the given type is either `core::ffi::c_void` or
274-
/// one of the platform specific `libc::<platform>::c_void` of libc.
275-
fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
276-
if let ty::Adt(adt, _) = ty.kind() {
277-
let names = cx.get_def_path(adt.did);
278-
279-
if names.is_empty() {
280-
return false;
281-
}
282-
if names[0] == sym::libc || names[0] == sym::core && *names.last().unwrap() == sym!(c_void) {
283-
return true;
284-
}
285-
}
286-
false
287-
}
288-
289270
impl<'tcx> LateLintPass<'tcx> for Casts {
290271
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
291272
if expr.span.from_expansion() {
@@ -306,56 +287,16 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
306287

307288
fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
308289
fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
309-
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
310290
if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
311291
cast_possible_truncation::check(cx, expr, cast_from, cast_to);
312292
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
313293
cast_precision_loss::check(cx, expr, cast_from, cast_to);
314294
cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to);
315295
cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to);
316296
}
317-
} else if let ExprKind::MethodCall(method_path, _, args, _) = expr.kind {
318-
if_chain! {
319-
if method_path.ident.name == sym!(cast);
320-
if let Some(generic_args) = method_path.args;
321-
if let [GenericArg::Type(cast_to)] = generic_args.args;
322-
// There probably is no obvious reason to do this, just to be consistent with `as` cases.
323-
if !is_hir_ty_cfg_dependant(cx, cast_to);
324-
then {
325-
let (cast_from, cast_to) =
326-
(cx.typeck_results().expr_ty(&args[0]), cx.typeck_results().expr_ty(expr));
327-
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
328-
}
329-
}
330297
}
331-
}
332-
}
333298

334-
fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_from: Ty<'tcx>, cast_to: Ty<'tcx>) {
335-
if_chain! {
336-
if let ty::RawPtr(from_ptr_ty) = &cast_from.kind();
337-
if let ty::RawPtr(to_ptr_ty) = &cast_to.kind();
338-
if let Ok(from_layout) = cx.layout_of(from_ptr_ty.ty);
339-
if let Ok(to_layout) = cx.layout_of(to_ptr_ty.ty);
340-
if from_layout.align.abi < to_layout.align.abi;
341-
// with c_void, we inherently need to trust the user
342-
if !is_c_void(cx, from_ptr_ty.ty);
343-
// when casting from a ZST, we don't know enough to properly lint
344-
if !from_layout.is_zst();
345-
then {
346-
span_lint(
347-
cx,
348-
CAST_PTR_ALIGNMENT,
349-
expr.span,
350-
&format!(
351-
"casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)",
352-
cast_from,
353-
cast_to,
354-
from_layout.align.abi.bytes(),
355-
to_layout.align.abi.bytes(),
356-
),
357-
);
358-
}
299+
cast_ptr_alignment::check(cx, expr);
359300
}
360301
}
361302

0 commit comments

Comments
 (0)