Skip to content

Commit a515258

Browse files
committed
improper_ctypes: extern "C" fns
1 parent 2e4da3c commit a515258

File tree

16 files changed

+493
-22
lines changed

16 files changed

+493
-22
lines changed

src/libpanic_abort/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
// Rust's "try" function, but if we're aborting on panics we just call the
2222
// function as there's nothing else we need to do here.
2323
#[rustc_std_internal_symbol]
24+
#[allow(improper_ctypes)]
2425
pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
2526
data: *mut u8,
2627
_data_ptr: *mut usize,

src/libpanic_unwind/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ mod dwarf;
6969
// hairy and tightly coupled, for more information see the compiler's
7070
// implementation of this.
7171
#[no_mangle]
72+
#[allow(improper_ctypes)]
7273
pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8),
7374
data: *mut u8,
7475
data_ptr: *mut usize,

src/librustc_codegen_llvm/back/write.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
239239
}
240240
}
241241

242+
#[allow(improper_ctypes)]
242243
unsafe extern "C" fn report_inline_asm(cgcx: &CodegenContext<LlvmCodegenBackend>,
243244
msg: &str,
244245
cookie: c_uint) {

src/librustc_codegen_llvm/llvm/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ pub struct RustString {
8787
}
8888

8989
/// Appending to a Rust string -- used by RawRustStringOstream.
90+
#[allow(improper_ctypes)]
9091
#[no_mangle]
9192
pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString,
9293
ptr: *const c_char,

src/librustc_lint/types.rs

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc::hir::{ExprKind, Node};
44
use crate::hir::def_id::DefId;
55
use rustc::hir::lowering::is_range_literal;
66
use rustc::ty::subst::SubstsRef;
7-
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
7+
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt, TypeFoldable};
88
use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx, SizeSkeleton};
99
use rustc::{lint, util};
1010
use rustc_index::vec::Idx;
@@ -835,16 +835,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
835835
ty::Array(ty, _) => self.check_type_for_ffi(cache, ty),
836836

837837
ty::FnPtr(sig) => {
838-
match sig.abi() {
839-
Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => {
840-
return FfiUnsafe {
841-
ty,
842-
reason: "this function pointer has Rust-specific calling convention",
843-
help: Some("consider using an `extern fn(...) -> ...` \
844-
function pointer instead"),
845-
}
846-
}
847-
_ => {}
838+
if self.is_internal_abi(sig.abi()) {
839+
return FfiUnsafe {
840+
ty,
841+
reason: "this function pointer has Rust-specific calling convention",
842+
help: Some("consider using an `extern fn(...) -> ...` \
843+
function pointer instead"),
844+
};
848845
}
849846

850847
let sig = cx.erase_late_bound_regions(&sig);
@@ -871,7 +868,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
871868

872869
ty::Foreign(..) => FfiSafe,
873870

874-
ty::Param(..) |
871+
// `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe,
872+
// so they are currently ignored for the purposes of this lint, see #65134.
873+
ty::Param(..) | ty::Projection(..) => FfiSafe,
874+
875875
ty::Infer(..) |
876876
ty::Bound(..) |
877877
ty::Error |
@@ -880,7 +880,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
880880
ty::GeneratorWitness(..) |
881881
ty::Placeholder(..) |
882882
ty::UnnormalizedProjection(..) |
883-
ty::Projection(..) |
884883
ty::Opaque(..) |
885884
ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty),
886885
}
@@ -912,8 +911,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
912911
}
913912

914913
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
915-
use crate::rustc::ty::TypeFoldable;
916-
917914
struct ProhibitOpaqueTypes<'tcx> {
918915
ty: Option<Ty<'tcx>>,
919916
};
@@ -952,10 +949,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
952949
return;
953950
}
954951

955-
// it is only OK to use this function because extern fns cannot have
956-
// any generic types right now:
957-
let ty = self.cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
958-
952+
let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
959953
match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
960954
FfiResult::FfiSafe => {}
961955
FfiResult::FfiPhantom(ty) => {
@@ -989,15 +983,21 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
989983
let ty = self.cx.tcx.type_of(def_id);
990984
self.check_type_for_ffi_and_report_errors(span, ty);
991985
}
986+
987+
fn is_internal_abi(&self, abi: Abi) -> bool {
988+
if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
989+
true
990+
} else {
991+
false
992+
}
993+
}
992994
}
993995

994996
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
995997
fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem) {
996998
let mut vis = ImproperCTypesVisitor { cx };
997999
let abi = cx.tcx.hir().get_foreign_abi(it.hir_id);
998-
if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
999-
// Don't worry about types in internal ABIs.
1000-
} else {
1000+
if !vis.is_internal_abi(abi) {
10011001
match it.kind {
10021002
hir::ForeignItemKind::Fn(ref decl, _, _) => {
10031003
vis.check_foreign_fn(it.hir_id, decl);
@@ -1009,6 +1009,29 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
10091009
}
10101010
}
10111011
}
1012+
1013+
fn check_fn(
1014+
&mut self,
1015+
cx: &LateContext<'a, 'tcx>,
1016+
kind: hir::intravisit::FnKind<'tcx>,
1017+
decl: &'tcx hir::FnDecl,
1018+
_: &'tcx hir::Body,
1019+
_: Span,
1020+
hir_id: hir::HirId,
1021+
) {
1022+
use hir::intravisit::FnKind;
1023+
1024+
let abi = match kind {
1025+
FnKind::ItemFn(_, _, header, ..) => (header.abi),
1026+
FnKind::Method(_, sig, ..) => (sig.header.abi),
1027+
_ => return,
1028+
};
1029+
1030+
let mut vis = ImproperCTypesVisitor { cx };
1031+
if !vis.is_internal_abi(abi) {
1032+
vis.check_foreign_fn(hir_id, decl);
1033+
}
1034+
}
10121035
}
10131036

10141037
declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);

src/test/ui/abi/abi-sysv64-register-usage.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub extern "sysv64" fn all_the_registers(rdi: i64, rsi: i64, rdx: i64,
3333

3434
// this struct contains 8 i64's, while only 6 can be passed in registers.
3535
#[cfg(target_arch = "x86_64")]
36+
#[repr(C)]
3637
#[derive(PartialEq, Eq, Debug)]
3738
pub struct LargeStruct(i64, i64, i64, i64, i64, i64, i64, i64);
3839

src/test/ui/align-with-extern-c-fn.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#[repr(align(16))]
1111
pub struct A(i64);
1212

13+
#[allow(improper_ctypes)]
1314
pub extern "C" fn foo(x: A) {}
1415

1516
fn main() {

src/test/ui/issues/issue-16441.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
struct Empty;
66

77
// This used to cause an ICE
8+
#[allow(improper_ctypes)]
89
extern "C" fn ice(_a: Empty) {}
910

1011
fn main() {

src/test/ui/issues/issue-26997.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub struct Foo {
66
}
77

88
impl Foo {
9+
#[allow(improper_ctypes)]
910
pub extern fn foo_new() -> Foo {
1011
Foo { x: 21, y: 33 }
1112
}

src/test/ui/issues/issue-28600.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
struct Test;
55

66
impl Test {
7+
#[allow(improper_ctypes)]
78
#[allow(dead_code)]
89
#[allow(unused_variables)]
910
pub extern fn test(val: &str) {

src/test/ui/issues/issue-38763.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#[repr(C)]
55
pub struct Foo(i128);
66

7+
#[allow(improper_ctypes)]
78
#[no_mangle]
89
pub extern "C" fn foo(x: Foo) -> Foo { x }
910

src/test/ui/issues/issue-51907.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ trait Foo {
66

77
struct Bar;
88
impl Foo for Bar {
9+
#[allow(improper_ctypes)]
910
extern fn borrow(&self) {}
11+
#[allow(improper_ctypes)]
1012
extern fn take(self: Box<Self>) {}
1113
}
1214

0 commit comments

Comments
 (0)