summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs95
1 files changed, 35 insertions, 60 deletions
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index 3bbfa52e8..2c0bf551f 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -5,8 +5,11 @@ use rustc_span::def_id::LocalDefId;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::type_is_unsafe_function;
+use clippy_utils::visitors::for_each_expr_with_closures;
use clippy_utils::{iter_input_pats, path_to_local};
+use core::ops::ControlFlow;
+
use super::NOT_UNSAFE_PTR_ARG_DEREF;
pub(super) fn check_fn<'tcx>(
@@ -28,7 +31,7 @@ pub(super) fn check_fn<'tcx>(
pub(super) fn check_trait_item<'tcx>(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.def_id);
+ check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.owner_id.def_id);
}
}
@@ -39,21 +42,34 @@ fn check_raw_ptr<'tcx>(
body: &'tcx hir::Body<'tcx>,
def_id: LocalDefId,
) {
- let expr = &body.value;
- if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(def_id) {
+ if unsafety == hir::Unsafety::Normal && cx.effective_visibilities.is_exported(def_id) {
let raw_ptrs = iter_input_pats(decl, body)
.filter_map(|arg| raw_ptr_arg(cx, arg))
.collect::<HirIdSet>();
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);
+ let typeck = cx.tcx.typeck_body(body.id());
+ let _: Option<!> = for_each_expr_with_closures(cx, body.value, |e| {
+ match e.kind {
+ hir::ExprKind::Call(f, args) if type_is_unsafe_function(cx, typeck.expr_ty(f)) => {
+ for arg in args {
+ check_arg(cx, &raw_ptrs, arg);
+ }
+ },
+ hir::ExprKind::MethodCall(_, recv, args, _) => {
+ let def_id = typeck.type_dependent_def_id(e.hir_id).unwrap();
+ if cx.tcx.fn_sig(def_id).skip_binder().unsafety == hir::Unsafety::Unsafe {
+ check_arg(cx, &raw_ptrs, recv);
+ for arg in args {
+ check_arg(cx, &raw_ptrs, arg);
+ }
+ }
+ },
+ hir::ExprKind::Unary(hir::UnOp::Deref, ptr) => check_arg(cx, &raw_ptrs, ptr),
+ _ => (),
+ }
+ ControlFlow::Continue(())
+ });
}
}
}
@@ -70,54 +86,13 @@ fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<hir::HirId>
}
}
-struct DerefVisitor<'a, 'tcx> {
- cx: &'a LateContext<'tcx>,
- ptrs: HirIdSet,
- typeck_results: &'a ty::TypeckResults<'tcx>,
-}
-
-impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
- fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
- match expr.kind {
- hir::ExprKind::Call(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(_, receiver, 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) {
- self.check_arg(receiver);
- for arg in args {
- self.check_arg(arg);
- }
- }
- },
- hir::ExprKind::Unary(hir::UnOp::Deref, ptr) => self.check_arg(ptr),
- _ => (),
- }
-
- intravisit::walk_expr(self, expr);
- }
-}
-
-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 might dereference a raw pointer but is not marked `unsafe`",
- );
- }
- }
+fn check_arg(cx: &LateContext<'_>, raw_ptrs: &HirIdSet, arg: &hir::Expr<'_>) {
+ if path_to_local(arg).map_or(false, |id| raw_ptrs.contains(&id)) {
+ span_lint(
+ cx,
+ NOT_UNSAFE_PTR_ARG_DEREF,
+ arg.span,
+ "this public function might dereference a raw pointer but is not marked `unsafe`",
+ );
}
}