diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index a1d029025b2fa..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! { @@ -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, abi::Rust, abi::RustCall].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), @@ -670,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); + } + } } 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)) diff --git a/src/test/compile-fail/lint-ctypes.rs b/src/test/compile-fail/lint-ctypes.rs index 5c49098d87053..298999542ea9c 100644 --- a/src/test/compile-fail/lint-ctypes.rs +++ b/src/test/compile-fail/lint-ctypes.rs @@ -8,26 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_variables)] #![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 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 @@ -36,7 +42,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 @@ -58,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() { }