From 693687ad8de13cc75049e00bbaa0e778e5d7665d Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 20 Dec 2015 14:10:53 +0100 Subject: [PATCH 1/7] improper_ctypes: extract some functions --- src/librustc_lint/types.rs | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index a1d029025b2fa..65941eaaa4da7 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -640,27 +640,31 @@ impl LintPass for ImproperCTypes { } } -impl LateLintPass for ImproperCTypes { - fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { - fn check_ty(cx: &LateContext, ty: &hir::Ty) { - let mut vis = ImproperCTypesVisitor { cx: cx }; - vis.visit_ty(ty); - } +fn check_ty(cx: &LateContext, ty: &hir::Ty) { + let mut vis = ImproperCTypesVisitor { cx: cx }; + vis.visit_ty(ty); +} - fn check_foreign_fn(cx: &LateContext, decl: &hir::FnDecl) { - for input in &decl.inputs { - check_ty(cx, &*input.ty); - } - if let hir::Return(ref ret_ty) = decl.output { - let tty = ast_ty_to_normalized(cx.tcx, ret_ty.id); - if !tty.is_nil() { - check_ty(cx, &ret_ty); - } - } +fn check_foreign_fn(cx: &LateContext, decl: &hir::FnDecl) { + for input in &decl.inputs { + check_ty(cx, &*input.ty); + } + if let hir::Return(ref ret_ty) = decl.output { + let tty = ast_ty_to_normalized(cx.tcx, ret_ty.id); + if !tty.is_nil() { + check_ty(cx, &ret_ty); } + } +} +fn should_check_abi(abi: abi::Abi) -> bool { + ![abi::RustIntrinsic, abi::PlatformIntrinsic].contains(&abi) +} + +impl LateLintPass for ImproperCTypes { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if let hir::ItemForeignMod(ref nmod) = it.node { - if nmod.abi != abi::RustIntrinsic && nmod.abi != abi::PlatformIntrinsic { + if should_check_abi(nmod.abi) { for ni in &nmod.items { match ni.node { hir::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &**decl), From 9953eaf36c637f59cf4c9bed888e22e016471041 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 20 Dec 2015 14:11:37 +0100 Subject: [PATCH 2/7] improper_ctypes: exclude some more abis --- src/librustc_lint/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 65941eaaa4da7..fc236edfc31a7 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -658,7 +658,7 @@ fn check_foreign_fn(cx: &LateContext, decl: &hir::FnDecl) { } fn should_check_abi(abi: abi::Abi) -> bool { - ![abi::RustIntrinsic, abi::PlatformIntrinsic].contains(&abi) + ![abi::RustIntrinsic, abi::PlatformIntrinsic, abi::Rust, abi::RustCall].contains(&abi) } impl LateLintPass for ImproperCTypes { From cc3d5e393ab0036a8d5cf6bec9f20f187b2e64f9 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 20 Dec 2015 14:13:33 +0100 Subject: [PATCH 3/7] improper_ctypes: also check extern fn's closes #19834 --- src/librustc_lint/types.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index fc236edfc31a7..549bb699bb5da 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -25,10 +25,10 @@ use syntax::{abi, ast}; use syntax::attr::{self, AttrMetaMethods}; use syntax::codemap::{self, Span}; use syntax::feature_gate::{emit_feature_err, GateIssue}; -use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64}; +use syntax::ast::{NodeId, TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64}; use rustc_front::hir; -use rustc_front::intravisit::{self, Visitor}; +use rustc_front::intravisit::{self, FnKind, Visitor}; use rustc_front::util::is_shift_binop; declare_lint! { @@ -674,4 +674,21 @@ impl LateLintPass for ImproperCTypes { } } } + + fn check_fn(&mut self, cx: &LateContext, + kind: FnKind, + decl: &hir::FnDecl, + _: &hir::Block, + _: Span, + _: NodeId) { + let abi = match kind { + FnKind::ItemFn(_, _, _, _, abi, _) => abi, + FnKind::Method(_, sig, _) => sig.abi, + FnKind::Closure => return, + }; + + if should_check_abi(abi) { + check_foreign_fn(cx, decl); + } + } } From 579627bd27ca5afa932e48a182cc5c992f709b19 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 20 Dec 2015 14:14:33 +0100 Subject: [PATCH 4/7] improper_ctypes: fix fallout --- src/libstd/sys/common/unwind/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/sys/common/unwind/mod.rs b/src/libstd/sys/common/unwind/mod.rs index aea5acc907176..0cb4eb4aab658 100644 --- a/src/libstd/sys/common/unwind/mod.rs +++ b/src/libstd/sys/common/unwind/mod.rs @@ -192,6 +192,7 @@ fn rust_panic(cause: Box) -> ! { /// Entry point of panic from the libcore crate. #[lang = "panic_fmt"] #[unwind] +#[allow(improper_ctypes)] pub extern fn rust_begin_unwind(msg: fmt::Arguments, file: &'static str, line: u32) -> ! { begin_unwind_fmt(msg, &(file, line)) From 653d32e6148494eb21a60fc43070c75398a28db5 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 20 Dec 2015 14:18:23 +0100 Subject: [PATCH 5/7] improper_ctypes test: use unsized trait for trait object --- src/test/compile-fail/lint-ctypes.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/compile-fail/lint-ctypes.rs b/src/test/compile-fail/lint-ctypes.rs index 5c49098d87053..02cf3dab61663 100644 --- a/src/test/compile-fail/lint-ctypes.rs +++ b/src/test/compile-fail/lint-ctypes.rs @@ -28,6 +28,7 @@ pub type RustFn = fn(); pub type RustBadRet = extern fn() -> Box; pub type CVoidRet = (); pub struct Foo; +pub trait Bar {} extern { pub fn ptr_type1(size: *const Foo); //~ ERROR: found struct without @@ -36,7 +37,7 @@ extern { pub fn str_type(p: &str); //~ ERROR: found Rust type pub fn box_type(p: Box); //~ ERROR found Rust type pub fn char_type(p: char); //~ ERROR found Rust type - pub fn trait_type(p: &Clone); //~ ERROR found Rust trait type + pub fn trait_type(p: &Bar); //~ ERROR found Rust trait type pub fn tuple_type(p: (i32, i32)); //~ ERROR found Rust tuple type pub fn tuple_type2(p: I32Pair); //~ ERROR found Rust tuple type pub fn zero_size(p: ZeroSize); //~ ERROR found zero-size struct From 4dd01efa223b809ebe0a1f6f916757c7ba139d83 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 20 Dec 2015 16:42:50 +0100 Subject: [PATCH 6/7] improper_ctypes test: move types to separate module --- src/test/compile-fail/lint-ctypes.rs | 36 +++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/test/compile-fail/lint-ctypes.rs b/src/test/compile-fail/lint-ctypes.rs index 02cf3dab61663..a32a26acd0471 100644 --- a/src/test/compile-fail/lint-ctypes.rs +++ b/src/test/compile-fail/lint-ctypes.rs @@ -11,24 +11,28 @@ #![deny(improper_ctypes)] #![feature(libc)] +use types::*; + extern crate libc; -trait Mirror { type It; } -impl Mirror for T { type It = Self; } -#[repr(C)] -pub struct StructWithProjection(*mut ::It); -#[repr(C)] -pub struct StructWithProjectionAndLifetime<'a>( - &'a mut as Mirror>::It -); -pub type I32Pair = (i32, i32); -#[repr(C)] -pub struct ZeroSize; -pub type RustFn = fn(); -pub type RustBadRet = extern fn() -> Box; -pub type CVoidRet = (); -pub struct Foo; -pub trait Bar {} +pub mod types { + pub trait Mirror { type It; } + impl Mirror for T { type It = Self; } + #[repr(C)] + pub struct StructWithProjection(*mut ::It); + #[repr(C)] + pub struct StructWithProjectionAndLifetime<'a>( + &'a mut as Mirror>::It + ); + pub type I32Pair = (i32, i32); + #[repr(C)] + pub struct ZeroSize; + pub type RustFn = fn(); + pub type RustBadRet = extern fn() -> Box; + pub type CVoidRet = (); + pub struct Foo; + pub trait Bar {} +} extern { pub fn ptr_type1(size: *const Foo); //~ ERROR: found struct without From 78462fe00eab4b8ca24cb7b8bed1f13ce4b2fb55 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sun, 20 Dec 2015 16:45:03 +0100 Subject: [PATCH 7/7] improper_ctypes test: add extern fn tests --- src/test/compile-fail/lint-ctypes.rs | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/test/compile-fail/lint-ctypes.rs b/src/test/compile-fail/lint-ctypes.rs index a32a26acd0471..298999542ea9c 100644 --- a/src/test/compile-fail/lint-ctypes.rs +++ b/src/test/compile-fail/lint-ctypes.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] #![deny(improper_ctypes)] #![feature(libc)] @@ -63,5 +64,37 @@ extern { pub fn good12(size: usize); } +pub mod extern_fn { + use libc; + use types::*; + + pub extern fn ptr_type1(size: *const Foo) {} //~ ERROR: found struct without + pub extern fn ptr_type2(size: *const Foo) {} //~ ERROR: found struct without + pub extern fn slice_type(p: &[u32]) {} //~ ERROR: found Rust slice type + pub extern fn str_type(p: &str) {} //~ ERROR: found Rust type + pub extern fn box_type(p: Box) {} //~ ERROR found Rust type + pub extern fn char_type(p: char) {} //~ ERROR found Rust type + pub extern fn trait_type(p: &Bar) {} //~ ERROR found Rust trait type + pub extern fn tuple_type(p: (i32, i32)) {} //~ ERROR found Rust tuple type + pub extern fn tuple_type2(p: I32Pair) {} //~ ERROR found Rust tuple type + pub extern fn zero_size(p: ZeroSize) {} //~ ERROR found zero-size struct + pub extern fn fn_type(p: RustFn) {} //~ ERROR found function pointer with Rust + pub extern fn fn_type2(p: fn()) {} //~ ERROR found function pointer with Rust + pub extern fn fn_contained(p: RustBadRet) {} //~ ERROR: found Rust type + + pub extern fn good1(size: *const libc::c_int) {} + pub extern fn good2(size: *const libc::c_uint) {} + pub extern fn good3(fptr: Option) {} + pub extern fn good4(aptr: &[u8; 4 as usize]) {} + pub extern fn good5(s: StructWithProjection) {} + pub extern fn good6(s: StructWithProjectionAndLifetime) {} + pub extern fn good7(fptr: extern fn() -> ()) {} + pub extern fn good8(fptr: extern fn() -> !) {} + pub extern fn good9() -> () {} + pub extern fn good10() -> CVoidRet {} + pub extern fn good11(size: isize) {} + pub extern fn good12(size: usize) {} +} + fn main() { }