Skip to content

Commit 5ec3ee9

Browse files
committed
Make the improper_ctypes lint more robust
It now checks extern fns in addition to foreign fns and checks `DefStruct` defs as well. There is room for improvement: for example, I believe that pointers should be safe in extern fn signatures regardless of the pointee's representation. The `FIXME` on `rust_begin_unwind_fmt` is because I don't think it should be, or needs to be, C ABI (cc @eddyb) and it takes a problematic `fmt::Arguments` structure by value. Fix rust-lang#20098, fix rust-lang#19834
1 parent 19f73b4 commit 5ec3ee9

File tree

4 files changed

+67
-10
lines changed

4 files changed

+67
-10
lines changed

src/librustc/lint/builtin.rs

+18-9
Original file line numberDiff line numberDiff line change
@@ -405,15 +405,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
405405
match self.cx.tcx.def_map.borrow()[path_id].clone() {
406406
def::DefPrimTy(ast::TyInt(ast::TyI)) => {
407407
self.cx.span_lint(IMPROPER_CTYPES, sp,
408-
"found rust type `int` in foreign module, while \
409-
libc::c_int or libc::c_long should be used");
408+
"found rust type `int` in foreign module or \
409+
extern fn, while libc::c_int or libc::c_long \
410+
should be used");
410411
}
411412
def::DefPrimTy(ast::TyUint(ast::TyU)) => {
412413
self.cx.span_lint(IMPROPER_CTYPES, sp,
413-
"found rust type `uint` in foreign module, while \
414-
libc::c_uint or libc::c_ulong should be used");
414+
"found rust type `uint` in foreign module or \
415+
extern fn, while libc::c_uint or libc::c_ulong \
416+
should be used");
415417
}
416-
def::DefTy(..) => {
418+
def::DefTy(..) | def::DefStruct(..) => {
417419
let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&ty_id) {
418420
Some(&ty::atttce_resolved(t)) => t,
419421
_ => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
@@ -422,8 +424,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
422424
if !ty::is_ffi_safe(self.cx.tcx, tty) {
423425
self.cx.span_lint(IMPROPER_CTYPES, sp,
424426
"found type without foreign-function-safe
425-
representation annotation in foreign module, consider \
426-
adding a #[repr(...)] attribute to the type");
427+
representation annotation in foreign module or \
428+
extern fn, consider adding a #[repr(...)] \
429+
attribute to the type");
427430
}
428431
}
429432
_ => ()
@@ -455,7 +458,7 @@ impl LintPass for ImproperCTypes {
455458
vis.visit_ty(ty);
456459
}
457460

458-
fn check_foreign_fn(cx: &Context, decl: &ast::FnDecl) {
461+
fn check_fn(cx: &Context, decl: &ast::FnDecl) {
459462
for input in decl.inputs.iter() {
460463
check_ty(cx, &*input.ty);
461464
}
@@ -468,11 +471,17 @@ impl LintPass for ImproperCTypes {
468471
ast::ItemForeignMod(ref nmod) if nmod.abi != abi::RustIntrinsic => {
469472
for ni in nmod.items.iter() {
470473
match ni.node {
471-
ast::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &**decl),
474+
ast::ForeignItemFn(ref decl, _) => check_fn(cx, &**decl),
472475
ast::ForeignItemStatic(ref t, _) => check_ty(cx, &**t)
473476
}
474477
}
475478
}
479+
ast::ItemFn(ref decl, _, abi, _, _) => {
480+
match abi {
481+
abi::Rust | abi::RustIntrinsic | abi::RustCall => (),
482+
_ => check_fn(cx, &**decl)
483+
}
484+
}
476485
_ => (),
477486
}
478487
}

src/libstd/rt/unwind.rs

+2
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ pub mod eabi {
482482
#[cfg(not(test))]
483483
/// Entry point of panic from the libcore crate.
484484
#[lang = "panic_fmt"]
485+
#[allow(improper_ctypes)] // FIXME(tomjakubowski)
485486
pub extern fn rust_begin_unwind(msg: fmt::Arguments,
486487
file: &'static str, line: uint) -> ! {
487488
begin_unwind_fmt(msg, &(file, line))
@@ -492,6 +493,7 @@ pub extern fn rust_begin_unwind(msg: fmt::Arguments,
492493
#[cfg(not(test))]
493494
/// Entry point of panic from the libcore crate.
494495
#[lang = "panic_fmt"]
496+
#[allow(improper_ctypes)] // FIXME(tomjakubowski)
495497
pub extern fn rust_begin_unwind(msg: &fmt::Arguments,
496498
file: &'static str, line: uint) -> ! {
497499
begin_unwind_fmt(msg, &(file, line))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![deny(improper_ctypes)]
12+
13+
#[repr(C)]
14+
pub struct Foo {
15+
_x: String
16+
}
17+
18+
extern {
19+
pub fn bad(f: Foo); //~ ERROR found type without foreign-function-safe
20+
}
21+
22+
fn main() {
23+
}

src/test/compile-fail/lint-ctypes.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -12,15 +12,38 @@
1212

1313
extern crate libc;
1414

15+
#[deriving(Copy)]
16+
pub struct Bad {
17+
_x: u32
18+
}
19+
20+
#[deriving(Copy)]
21+
#[repr(C)]
22+
pub struct Good {
23+
_x: u32
24+
}
25+
1526
extern {
1627
pub fn bare_type1(size: int); //~ ERROR: found rust type
1728
pub fn bare_type2(size: uint); //~ ERROR: found rust type
1829
pub fn ptr_type1(size: *const int); //~ ERROR: found rust type
1930
pub fn ptr_type2(size: *const uint); //~ ERROR: found rust type
31+
pub fn non_c_repr_type(b: Bad); //~ ERROR: found type without foreign-function-safe
2032

2133
pub fn good1(size: *const libc::c_int);
2234
pub fn good2(size: *const libc::c_uint);
35+
pub fn good3(g: Good);
2336
}
2437

38+
pub extern fn ex_bare_type1(_: int) {} //~ ERROR: found rust type
39+
pub extern fn ex_bare_type2(_: uint) {} //~ ERROR: found rust type
40+
pub extern fn ex_ptr_type1(_: *const int) {} //~ ERROR: found rust type
41+
pub extern fn ex_ptr_type2(_: *const uint) {} //~ ERROR: found rust type
42+
pub extern fn ex_non_c_repr_type(_: Bad) {} //~ ERROR: found type without foreign-function-safe
43+
44+
pub extern fn ex_good1(_: *const libc::c_int) {}
45+
pub extern fn ex_good2(_: *const libc::c_uint) {}
46+
pub extern fn ex_good3(_: Good) {}
47+
2548
fn main() {
2649
}

0 commit comments

Comments
 (0)