Fix c_void false positive caused by libc refactoring

The path of `libc::c_void` has changes in 5c1a6b8a6d
The DefId path is now always platform specific like
`libc::windows::c_void`. This fixes our c_void detection to only check
the first and last elements.
This commit is contained in:
Philipp Hansch 2018-12-08 11:57:25 +01:00
parent f13d23de41
commit d90cad24a1
No known key found for this signature in database
GPG Key ID: B6FA06A6E0E2665B
3 changed files with 38 additions and 25 deletions

View File

@ -28,8 +28,9 @@
use crate::utils::paths;
use crate::utils::{
clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro, int_bits, last_path_segment,
match_def_path, match_path, match_type, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt,
match_def_path, match_path, multispan_sugg, opt_def_id, same_tys, sext, snippet, snippet_opt,
snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext,
AbsolutePathBuffer
};
use if_chain::if_chain;
use std::borrow::Cow;
@ -1023,6 +1024,21 @@ fn get_lints(&self) -> LintArray {
}
}
// Check if the given type is either `core::ffi::c_void` or
// one of the platform specific `libc::<platform>::c_void` of libc.
fn is_c_void(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>) -> bool {
if let ty::Adt(adt, _) = ty.sty {
let mut apb = AbsolutePathBuffer { names: vec![] };
tcx.push_item_path(&mut apb, adt.did, false);
if apb.names.is_empty() { return false }
if apb.names[0] == "libc" || apb.names[0] == "core" && *apb.names.last().unwrap() == "c_void" {
return true
}
}
false
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CastPass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprKind::Cast(ref ex, _) = expr.node {
@ -1114,10 +1130,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi);
if from_align < to_align;
// with c_void, we inherently need to trust the user
if ! (
match_type(cx, from_ptr_ty.ty, &paths::C_VOID)
|| match_type(cx, from_ptr_ty.ty, &paths::C_VOID_LIBC)
);
if !is_c_void(cx.tcx, from_ptr_ty.ty);
then {
span_lint(
cx,

View File

@ -29,6 +29,7 @@
use crate::syntax::errors::DiagnosticBuilder;
use crate::syntax::source_map::{Span, DUMMY_SP};
use crate::syntax::symbol::{keywords, Symbol};
use crate::syntax::symbol;
use if_chain::if_chain;
use matches::matches;
use std::borrow::Cow;
@ -74,6 +75,25 @@ pub fn in_macro(span: Span) -> bool {
span.ctxt().outer().expn_info().is_some()
}
/// Used to store the absolute path to a type.
///
/// See `match_def_path` for usage.
#[derive(Debug)]
pub struct AbsolutePathBuffer {
pub names: Vec<symbol::LocalInternedString>,
}
impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
fn root_mode(&self) -> &ty::item_path::RootMode {
const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
ABSOLUTE
}
fn push(&mut self, text: &str) {
self.names.push(symbol::Symbol::intern(text).as_str());
}
}
/// Check if a `DefId`'s path matches the given absolute type path usage.
///
/// # Examples
@ -83,24 +103,6 @@ pub fn in_macro(span: Span) -> bool {
///
/// See also the `paths` module.
pub fn match_def_path(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, path: &[&str]) -> bool {
use crate::syntax::symbol;
#[derive(Debug)]
struct AbsolutePathBuffer {
names: Vec<symbol::LocalInternedString>,
}
impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
fn root_mode(&self) -> &ty::item_path::RootMode {
const ABSOLUTE: &ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
ABSOLUTE
}
fn push(&mut self, text: &str) {
self.names.push(symbol::Symbol::intern(text).as_str());
}
}
let mut apb = AbsolutePathBuffer { names: vec![] };
tcx.push_item_path(&mut apb, def_id, false);

View File

@ -27,8 +27,6 @@
pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"];
pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"];
pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"];
pub const C_VOID: [&str; 3] = ["core", "ffi", "c_void"];
pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"];
pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"];
pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];