Auto merge of #70946 - jumbatm:clashing-extern-decl, r=nagisa

Add a lint to catch clashing `extern` fn declarations.

Closes #69390.

Adds lint `clashing_extern_decl` to detect when, within a single crate, an extern function of the same name is declared with different types. Because two symbols of the same name cannot be resolved to two different functions at link time, and one function cannot possibly have two types, a clashing extern declaration is almost certainly a mistake.

This lint does not run between crates because a project may have dependencies which both rely on the same extern function, but declare it in a different (but valid) way. For example, they may both declare an opaque type for one or more of the arguments (which would end up distinct types), or use types that are valid conversions in the language the extern fn is defined in. In these cases, we can't say that the clashing declaration is incorrect.

r? @eddyb
This commit is contained in:
bors 2020-06-21 02:20:07 +00:00
commit 228a0ed7b0
14 changed files with 568 additions and 11 deletions

View file

@ -1,6 +1,7 @@
// build-pass
#![allow(dead_code)]
#![allow(non_camel_case_types)]
#![warn(clashing_extern_decl)]
// pretty-expanded FIXME #23616
@ -20,6 +21,7 @@ mod b {
use super::rust_task;
extern {
pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
//~^ WARN `rust_task_is_unwinding` redeclared with a different signature
}
}
}

View file

@ -0,0 +1,19 @@
warning: `rust_task_is_unwinding` redeclared with a different signature
--> $DIR/issue-1866.rs:23:13
|
LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
| ------------------------------------------------------------ `rust_task_is_unwinding` previously declared here
...
LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
note: the lint level is defined here
--> $DIR/issue-1866.rs:4:9
|
LL | #![warn(clashing_extern_decl)]
| ^^^^^^^^^^^^^^^^^^^^
= note: expected `unsafe extern "C" fn(*const usize) -> bool`
found `unsafe extern "C" fn(*const bool) -> bool`
warning: 1 warning emitted

View file

@ -1,11 +1,13 @@
// run-pass
#![allow(dead_code)]
#![warn(clashing_extern_decl)]
// pretty-expanded FIXME #23616
extern {
#[link_name = "malloc"]
fn malloc1(len: i32) -> *const u8;
#[link_name = "malloc"]
//~^ WARN `malloc2` redeclares `malloc` with a different signature
fn malloc2(len: i32, foo: i32) -> *const u8;
}

View file

@ -0,0 +1,21 @@
warning: `malloc2` redeclares `malloc` with a different signature
--> $DIR/issue-5791.rs:9:5
|
LL | / #[link_name = "malloc"]
LL | | fn malloc1(len: i32) -> *const u8;
| |______________________________________- `malloc` previously declared here
LL | / #[link_name = "malloc"]
LL | |
LL | | fn malloc2(len: i32, foo: i32) -> *const u8;
| |________________________________________________^ this signature doesn't match the previous declaration
|
note: the lint level is defined here
--> $DIR/issue-5791.rs:3:9
|
LL | #![warn(clashing_extern_decl)]
| ^^^^^^^^^^^^^^^^^^^^
= note: expected `unsafe extern "C" fn(i32) -> *const u8`
found `unsafe extern "C" fn(i32, i32) -> *const u8`
warning: 1 warning emitted