mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
lint/ctypes: check other types for ext. fn-ptr ty
Extend previous checks for external ABI fn-ptrs to use in internal statics, constants, type aliases and algebraic data types. Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
c75b080d7d
commit
9137fea30d
@ -1473,7 +1473,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let mut visitor = FnPtrFinder { visitor: &*self, spans: Vec::new(), tys: Vec::new() };
|
||||
self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty).visit_with(&mut visitor);
|
||||
self.cx
|
||||
.tcx
|
||||
.try_normalize_erasing_regions(self.cx.param_env, ty)
|
||||
.unwrap_or(ty)
|
||||
.visit_with(&mut visitor);
|
||||
hir::intravisit::Visitor::visit_ty(&mut visitor, hir_ty);
|
||||
|
||||
iter::zip(visitor.tys.drain(..), visitor.spans.drain(..)).collect()
|
||||
@ -1497,7 +1501,65 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
|
||||
}
|
||||
}
|
||||
|
||||
impl ImproperCTypesDefinitions {
|
||||
fn check_ty_maybe_containing_foreign_fnptr<'tcx>(
|
||||
&mut self,
|
||||
cx: &LateContext<'tcx>,
|
||||
hir_ty: &'tcx hir::Ty<'_>,
|
||||
ty: Ty<'tcx>,
|
||||
) {
|
||||
let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Definition };
|
||||
for (fn_ptr_ty, span) in vis.find_fn_ptr_ty_with_external_abi(hir_ty, ty) {
|
||||
vis.check_type_for_ffi_and_report_errors(span, fn_ptr_ty, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `ImproperCTypesDefinitions` checks items outside of foreign items (e.g. stuff that isn't in
|
||||
/// `extern "C" { }` blocks):
|
||||
///
|
||||
/// - `extern "<abi>" fn` definitions are checked in the same way as the
|
||||
/// `ImproperCtypesDeclarations` visitor checks functions if `<abi>` is external (e.g. "C").
|
||||
/// - All other items which contain types (e.g. other functions, struct definitions, etc) are
|
||||
/// checked for extern fn-ptrs with external ABIs.
|
||||
impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
||||
match item.kind {
|
||||
hir::ItemKind::Static(ty, ..)
|
||||
| hir::ItemKind::Const(ty, ..)
|
||||
| hir::ItemKind::TyAlias(ty, ..) => {
|
||||
self.check_ty_maybe_containing_foreign_fnptr(
|
||||
cx,
|
||||
ty,
|
||||
cx.tcx.type_of(item.owner_id).subst_identity(),
|
||||
);
|
||||
}
|
||||
// See `check_fn`..
|
||||
hir::ItemKind::Fn(..) => {}
|
||||
// See `check_field_def`..
|
||||
hir::ItemKind::Union(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) => {}
|
||||
// Doesn't define something that can contain a external type to be checked.
|
||||
hir::ItemKind::Impl(..)
|
||||
| hir::ItemKind::TraitAlias(..)
|
||||
| hir::ItemKind::Trait(..)
|
||||
| hir::ItemKind::OpaqueTy(..)
|
||||
| hir::ItemKind::GlobalAsm(..)
|
||||
| hir::ItemKind::ForeignMod { .. }
|
||||
| hir::ItemKind::Mod(..)
|
||||
| hir::ItemKind::Macro(..)
|
||||
| hir::ItemKind::Use(..)
|
||||
| hir::ItemKind::ExternCrate(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &'tcx hir::FieldDef<'tcx>) {
|
||||
self.check_ty_maybe_containing_foreign_fnptr(
|
||||
cx,
|
||||
field.ty,
|
||||
cx.tcx.type_of(field.def_id).subst_identity(),
|
||||
);
|
||||
}
|
||||
|
||||
fn check_fn(
|
||||
&mut self,
|
||||
cx: &LateContext<'tcx>,
|
||||
|
@ -1,5 +1,6 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(improper_ctypes_definitions)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_mut)]
|
||||
|
@ -7,3 +7,36 @@ pub fn bad(f: extern "C" fn([u8])) {}
|
||||
pub fn bad_twice(f: Result<extern "C" fn([u8]), extern "C" fn([u8])>) {}
|
||||
//~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
//~^^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
|
||||
struct BadStruct(extern "C" fn([u8]));
|
||||
//~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
|
||||
enum BadEnum {
|
||||
A(extern "C" fn([u8])),
|
||||
//~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
}
|
||||
|
||||
enum BadUnion {
|
||||
A(extern "C" fn([u8])),
|
||||
//~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
}
|
||||
|
||||
type Foo = extern "C" fn([u8]);
|
||||
//~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
|
||||
pub struct FfiUnsafe;
|
||||
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
extern "C" fn f(_: FfiUnsafe) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub static BAD: extern "C" fn(FfiUnsafe) = f;
|
||||
//~^ ERROR `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
||||
|
||||
pub static BAD_TWICE: Result<extern "C" fn(FfiUnsafe), extern "C" fn(FfiUnsafe)> = Ok(f);
|
||||
//~^ ERROR `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
||||
//~^^ ERROR `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
||||
|
||||
pub const BAD_CONST: extern "C" fn(FfiUnsafe) = f;
|
||||
//~^ ERROR `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
||||
|
@ -30,5 +30,97 @@ LL | pub fn bad_twice(f: Result<extern "C" fn([u8]), extern "C" fn([u8])>) {}
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-94223.rs:11:18
|
||||
|
|
||||
LL | struct BadStruct(extern "C" fn([u8]));
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-94223.rs:15:7
|
||||
|
|
||||
LL | A(extern "C" fn([u8])),
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-94223.rs:20:7
|
||||
|
|
||||
LL | A(extern "C" fn([u8])),
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-94223.rs:24:12
|
||||
|
|
||||
LL | type Foo = extern "C" fn([u8]);
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-94223.rs:34:17
|
||||
|
|
||||
LL | pub static BAD: extern "C" fn(FfiUnsafe) = f;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
|
||||
= note: this struct has unspecified layout
|
||||
note: the type is defined here
|
||||
--> $DIR/lint-ctypes-94223.rs:27:1
|
||||
|
|
||||
LL | pub struct FfiUnsafe;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-94223.rs:37:30
|
||||
|
|
||||
LL | pub static BAD_TWICE: Result<extern "C" fn(FfiUnsafe), extern "C" fn(FfiUnsafe)> = Ok(f);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
|
||||
= note: this struct has unspecified layout
|
||||
note: the type is defined here
|
||||
--> $DIR/lint-ctypes-94223.rs:27:1
|
||||
|
|
||||
LL | pub struct FfiUnsafe;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-94223.rs:37:56
|
||||
|
|
||||
LL | pub static BAD_TWICE: Result<extern "C" fn(FfiUnsafe), extern "C" fn(FfiUnsafe)> = Ok(f);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
|
||||
= note: this struct has unspecified layout
|
||||
note: the type is defined here
|
||||
--> $DIR/lint-ctypes-94223.rs:27:1
|
||||
|
|
||||
LL | pub struct FfiUnsafe;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-94223.rs:41:22
|
||||
|
|
||||
LL | pub const BAD_CONST: extern "C" fn(FfiUnsafe) = f;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
|
||||
= note: this struct has unspecified layout
|
||||
note: the type is defined here
|
||||
--> $DIR/lint-ctypes-94223.rs:27:1
|
||||
|
|
||||
LL | pub struct FfiUnsafe;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user