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_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::ty::{is_must_use_ty, is_type_diagnostic_item, type_is_unsafe_function};
|
||||
use clippy_utils::{
|
||||
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 clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item};
|
||||
use clippy_utils::{attr_by_name, attrs::is_proc_macro, match_def_path, must_use_attr, return_ty, trait_ref_of_method};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::Attribute;
|
||||
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_lines::check(cx, span, body, self.too_many_lines_threshold);
|
||||
|
||||
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);
|
||||
not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, hir_id);
|
||||
}
|
||||
|
||||
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<'_>) {
|
||||
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 {
|
||||
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 {
|
||||
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) {
|
||||
check_must_use_candidate(
|
||||
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) {
|
||||
if_chain! {
|
||||
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> {
|
||||
cx: &'a LateContext<'tcx>,
|
||||
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