blob: 544614100ba28f28e39cae85702286ea574ecbb3 [file] [log] [blame]
// check-pass
// aux-build:external_extern_fn.rs
#![crate_type = "lib"]
#![warn(clashing_extern_declarations)]
extern crate external_extern_fn;
extern "C" {
fn clash(x: u8);
fn no_clash(x: u8);
}
fn redeclared_different_signature() {
extern "C" {
fn clash(x: u64); //~ WARN `clash` redeclared with a different signature
}
unsafe {
clash(123);
no_clash(123);
}
}
fn redeclared_same_signature() {
extern "C" {
fn no_clash(x: u8);
}
unsafe {
no_clash(123);
}
}
extern "C" {
fn extern_fn(x: u64);
}
fn extern_clash() {
extern "C" {
fn extern_fn(x: u32); //~ WARN `extern_fn` redeclared with a different signature
}
unsafe {
extern_fn(123);
}
}
fn extern_no_clash() {
unsafe {
external_extern_fn::extern_fn(123);
crate::extern_fn(123);
}
}
extern "C" {
fn some_other_new_name(x: i16);
#[link_name = "extern_link_name"]
fn some_new_name(x: i16);
#[link_name = "link_name_same"]
fn both_names_different(x: i16);
}
fn link_name_clash() {
extern "C" {
fn extern_link_name(x: u32);
//~^ WARN `extern_link_name` redeclared with a different signature
#[link_name = "some_other_new_name"]
//~^ WARN `some_other_extern_link_name` redeclares `some_other_new_name` with a different
fn some_other_extern_link_name(x: u32);
#[link_name = "link_name_same"]
//~^ WARN `other_both_names_different` redeclares `link_name_same` with a different
fn other_both_names_different(x: u32);
}
}
mod a {
extern "C" {
fn different_mod(x: u8);
}
}
mod b {
extern "C" {
fn different_mod(x: u64); //~ WARN `different_mod` redeclared with a different signature
}
}
extern "C" {
fn variadic_decl(x: u8, ...);
}
fn variadic_clash() {
extern "C" {
fn variadic_decl(x: u8); //~ WARN `variadic_decl` redeclared with a different signature
}
}
#[no_mangle]
fn no_mangle_name(x: u8) {}
extern "C" {
#[link_name = "unique_link_name"]
fn link_name_specified(x: u8);
}
fn tricky_no_clash() {
extern "C" {
// Shouldn't warn, because the declaration above actually declares a different symbol (and
// Rust's name resolution rules around shadowing will handle this gracefully).
fn link_name_specified() -> u32;
// The case of a no_mangle name colliding with an extern decl (see #28179) is related but
// shouldn't be reported by ClashingExternDeclarations, because this is an example of
// unmangled name clash causing bad behaviour in functions with a defined body.
fn no_mangle_name() -> u32;
}
}
mod banana {
mod one {
#[repr(C)]
struct Banana {
weight: u32,
length: u16,
}
extern "C" {
fn weigh_banana(count: *const Banana) -> u64;
}
}
mod two {
#[repr(C)]
struct Banana {
weight: u32,
length: u16,
} // note: distinct type
extern "C" {
// This should not trigger the lint because two::Banana is structurally equivalent to
// one::Banana.
fn weigh_banana(count: *const Banana) -> u64;
}
}
mod three {
// This _should_ trigger the lint, because repr(packed) should generate a struct that has a
// different layout.
#[repr(packed)]
struct Banana {
weight: u32,
length: u16,
}
#[allow(improper_ctypes)]
extern "C" {
fn weigh_banana(count: *const Banana) -> u64;
//~^ WARN `weigh_banana` redeclared with a different signature
}
}
}
mod sameish_members {
mod a {
#[repr(C)]
struct Point {
x: i16,
y: i16,
}
extern "C" {
fn draw_point(p: Point);
}
}
mod b {
#[repr(C)]
struct Point {
coordinates: [i16; 2],
}
// It's possible we are overconservative for this case, as accessing the elements of the
// coordinates array might end up correctly accessing `.x` and `.y`. However, this may not
// always be the case, for every architecture and situation. This is also a really odd
// thing to do anyway.
extern "C" {
fn draw_point(p: Point); //~ WARN `draw_point` redeclared with a different
}
}
}