move not_unsafe_ptr_arg_deref to its own module
This commit is contained in:
parent
7c028de05f
commit
9782fc4285
@ -1,13 +1,11 @@
|
|||||||
|
mod not_unsafe_ptr_arg_deref;
|
||||||
mod too_many_arguments;
|
mod too_many_arguments;
|
||||||
mod too_many_lines;
|
mod too_many_lines;
|
||||||
|
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
|
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::snippet_opt;
|
||||||
use clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item, type_is_unsafe_function};
|
use clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item};
|
||||||
use clippy_utils::{
|
use clippy_utils::{attr_by_name, attrs::is_proc_macro, match_def_path, must_use_attr, return_ty, trait_ref_of_method};
|
||||||
attr_by_name, attrs::is_proc_macro, iter_input_pats, match_def_path, must_use_attr, path_to_local, return_ty,
|
|
||||||
trait_ref_of_method,
|
|
||||||
};
|
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::Attribute;
|
use rustc_ast::ast::Attribute;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
@ -258,14 +256,7 @@ fn check_fn(
|
|||||||
) {
|
) {
|
||||||
too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold);
|
too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold);
|
||||||
too_many_lines::check(cx, span, body, self.too_many_lines_threshold);
|
too_many_lines::check(cx, span, body, self.too_many_lines_threshold);
|
||||||
|
not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, hir_id);
|
||||||
let unsafety = match kind {
|
|
||||||
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
|
|
||||||
intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
|
|
||||||
intravisit::FnKind::Closure => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
Self::check_raw_ptr(cx, unsafety, decl, body, hir_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
|
||||||
@ -323,6 +314,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<
|
|||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
|
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
|
||||||
too_many_arguments::check_trait_item(cx, item, self.too_many_arguments_threshold);
|
too_many_arguments::check_trait_item(cx, item, self.too_many_arguments_threshold);
|
||||||
|
not_unsafe_ptr_arg_deref::check_trait_item(cx, item);
|
||||||
|
|
||||||
if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind {
|
if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind {
|
||||||
let is_public = cx.access_levels.is_exported(item.hir_id());
|
let is_public = cx.access_levels.is_exported(item.hir_id());
|
||||||
@ -338,8 +330,6 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitIte
|
|||||||
}
|
}
|
||||||
if let hir::TraitFn::Provided(eid) = *eid {
|
if let hir::TraitFn::Provided(eid) = *eid {
|
||||||
let body = cx.tcx.hir().body(eid);
|
let body = cx.tcx.hir().body(eid);
|
||||||
Self::check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id());
|
|
||||||
|
|
||||||
if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
|
if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
|
||||||
check_must_use_candidate(
|
check_must_use_candidate(
|
||||||
cx,
|
cx,
|
||||||
@ -356,35 +346,6 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitIte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Functions {
|
|
||||||
fn check_raw_ptr(
|
|
||||||
cx: &LateContext<'tcx>,
|
|
||||||
unsafety: hir::Unsafety,
|
|
||||||
decl: &'tcx hir::FnDecl<'_>,
|
|
||||||
body: &'tcx hir::Body<'_>,
|
|
||||||
hir_id: hir::HirId,
|
|
||||||
) {
|
|
||||||
let expr = &body.value;
|
|
||||||
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) {
|
|
||||||
let raw_ptrs = iter_input_pats(decl, body)
|
|
||||||
.zip(decl.inputs.iter())
|
|
||||||
.filter_map(|(arg, ty)| raw_ptr_arg(arg, ty))
|
|
||||||
.collect::<FxHashSet<_>>();
|
|
||||||
|
|
||||||
if !raw_ptrs.is_empty() {
|
|
||||||
let typeck_results = cx.tcx.typeck_body(body.id());
|
|
||||||
let mut v = DerefVisitor {
|
|
||||||
cx,
|
|
||||||
ptrs: raw_ptrs,
|
|
||||||
typeck_results,
|
|
||||||
};
|
|
||||||
|
|
||||||
intravisit::walk_expr(&mut v, expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_result_unit_err(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_span: Span, fn_header_span: Span) {
|
fn check_result_unit_err(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_span: Span, fn_header_span: Span) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if !in_external_macro(cx.sess(), item_span);
|
if !in_external_macro(cx.sess(), item_span);
|
||||||
@ -524,71 +485,6 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raw_ptr_arg(arg: &hir::Param<'_>, ty: &hir::Ty<'_>) -> Option<hir::HirId> {
|
|
||||||
if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.kind, &ty.kind) {
|
|
||||||
Some(id)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DerefVisitor<'a, 'tcx> {
|
|
||||||
cx: &'a LateContext<'tcx>,
|
|
||||||
ptrs: FxHashSet<hir::HirId>,
|
|
||||||
typeck_results: &'a ty::TypeckResults<'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
|
|
||||||
type Map = Map<'tcx>;
|
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
|
|
||||||
match expr.kind {
|
|
||||||
hir::ExprKind::Call(ref f, args) => {
|
|
||||||
let ty = self.typeck_results.expr_ty(f);
|
|
||||||
|
|
||||||
if type_is_unsafe_function(self.cx, ty) {
|
|
||||||
for arg in args {
|
|
||||||
self.check_arg(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hir::ExprKind::MethodCall(_, _, args, _) => {
|
|
||||||
let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
|
|
||||||
let base_type = self.cx.tcx.type_of(def_id);
|
|
||||||
|
|
||||||
if type_is_unsafe_function(self.cx, base_type) {
|
|
||||||
for arg in args {
|
|
||||||
self.check_arg(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hir::ExprKind::Unary(hir::UnOp::Deref, ref ptr) => self.check_arg(ptr),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
intravisit::walk_expr(self, expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
|
|
||||||
intravisit::NestedVisitorMap::None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
|
|
||||||
fn check_arg(&self, ptr: &hir::Expr<'_>) {
|
|
||||||
if let Some(id) = path_to_local(ptr) {
|
|
||||||
if self.ptrs.contains(&id) {
|
|
||||||
span_lint(
|
|
||||||
self.cx,
|
|
||||||
NOT_UNSAFE_PTR_ARG_DEREF,
|
|
||||||
ptr.span,
|
|
||||||
"this public function dereferences a raw pointer but is not marked `unsafe`",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct StaticMutVisitor<'a, 'tcx> {
|
struct StaticMutVisitor<'a, 'tcx> {
|
||||||
cx: &'a LateContext<'tcx>,
|
cx: &'a LateContext<'tcx>,
|
||||||
mutates_static: bool,
|
mutates_static: bool,
|
||||||
|
125
clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
Normal file
125
clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
|
use rustc_hir::{self as hir, intravisit};
|
||||||
|
use rustc_lint::LateContext;
|
||||||
|
use rustc_middle::{hir::map::Map, ty};
|
||||||
|
|
||||||
|
use clippy_utils::diagnostics::span_lint;
|
||||||
|
use clippy_utils::ty::type_is_unsafe_function;
|
||||||
|
use clippy_utils::{iter_input_pats, path_to_local};
|
||||||
|
|
||||||
|
use super::NOT_UNSAFE_PTR_ARG_DEREF;
|
||||||
|
|
||||||
|
pub(super) fn check_fn(
|
||||||
|
cx: &LateContext<'tcx>,
|
||||||
|
kind: intravisit::FnKind<'tcx>,
|
||||||
|
decl: &'tcx hir::FnDecl<'tcx>,
|
||||||
|
body: &'tcx hir::Body<'tcx>,
|
||||||
|
hir_id: hir::HirId,
|
||||||
|
) {
|
||||||
|
let unsafety = match kind {
|
||||||
|
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
|
||||||
|
intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
|
||||||
|
intravisit::FnKind::Closure => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
check_raw_ptr(cx, unsafety, decl, body, hir_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn check_trait_item(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
|
||||||
|
if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind {
|
||||||
|
let body = cx.tcx.hir().body(eid);
|
||||||
|
check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_raw_ptr(
|
||||||
|
cx: &LateContext<'tcx>,
|
||||||
|
unsafety: hir::Unsafety,
|
||||||
|
decl: &'tcx hir::FnDecl<'tcx>,
|
||||||
|
body: &'tcx hir::Body<'tcx>,
|
||||||
|
hir_id: hir::HirId,
|
||||||
|
) {
|
||||||
|
let expr = &body.value;
|
||||||
|
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) {
|
||||||
|
let raw_ptrs = iter_input_pats(decl, body)
|
||||||
|
.zip(decl.inputs.iter())
|
||||||
|
.filter_map(|(arg, ty)| raw_ptr_arg(arg, ty))
|
||||||
|
.collect::<FxHashSet<_>>();
|
||||||
|
|
||||||
|
if !raw_ptrs.is_empty() {
|
||||||
|
let typeck_results = cx.tcx.typeck_body(body.id());
|
||||||
|
let mut v = DerefVisitor {
|
||||||
|
cx,
|
||||||
|
ptrs: raw_ptrs,
|
||||||
|
typeck_results,
|
||||||
|
};
|
||||||
|
|
||||||
|
intravisit::walk_expr(&mut v, expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn raw_ptr_arg(arg: &hir::Param<'_>, ty: &hir::Ty<'_>) -> Option<hir::HirId> {
|
||||||
|
if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.kind, &ty.kind) {
|
||||||
|
Some(id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DerefVisitor<'a, 'tcx> {
|
||||||
|
cx: &'a LateContext<'tcx>,
|
||||||
|
ptrs: FxHashSet<hir::HirId>,
|
||||||
|
typeck_results: &'a ty::TypeckResults<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
|
||||||
|
type Map = Map<'tcx>;
|
||||||
|
|
||||||
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
|
||||||
|
match expr.kind {
|
||||||
|
hir::ExprKind::Call(ref f, args) => {
|
||||||
|
let ty = self.typeck_results.expr_ty(f);
|
||||||
|
|
||||||
|
if type_is_unsafe_function(self.cx, ty) {
|
||||||
|
for arg in args {
|
||||||
|
self.check_arg(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hir::ExprKind::MethodCall(_, _, args, _) => {
|
||||||
|
let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
|
||||||
|
let base_type = self.cx.tcx.type_of(def_id);
|
||||||
|
|
||||||
|
if type_is_unsafe_function(self.cx, base_type) {
|
||||||
|
for arg in args {
|
||||||
|
self.check_arg(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hir::ExprKind::Unary(hir::UnOp::Deref, ref ptr) => self.check_arg(ptr),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
intravisit::walk_expr(self, expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
|
||||||
|
intravisit::NestedVisitorMap::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
|
||||||
|
fn check_arg(&self, ptr: &hir::Expr<'_>) {
|
||||||
|
if let Some(id) = path_to_local(ptr) {
|
||||||
|
if self.ptrs.contains(&id) {
|
||||||
|
span_lint(
|
||||||
|
self.cx,
|
||||||
|
NOT_UNSAFE_PTR_ARG_DEREF,
|
||||||
|
ptr.span,
|
||||||
|
"this public function dereferences a raw pointer but is not marked `unsafe`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user