about summary refs log tree commit diff
path: root/src/test/ui
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-07-30 14:36:41 +0000
committerbors <bors@rust-lang.org>2020-07-30 14:36:41 +0000
commit6b09c37ddc240e25748e53d7a8f81f252def6dee (patch)
treecf776af8e0a57ff674b2828f93a0ceb5bdc002f0 /src/test/ui
parent21867225a74d3b07c2b65e32c67f45197db36896 (diff)
parent0bd292dea1a8f6e60ac8957ac0fcd0d237034918 (diff)
downloadrust-6b09c37ddc240e25748e53d7a8f81f252def6dee.tar.gz
rust-6b09c37ddc240e25748e53d7a8f81f252def6dee.zip
Auto merge of #73990 - jumbatm:clashing-extern-decl, r=nagisa
Fix incorrect clashing_extern_declarations warnings.

Fixes #73735, fixes #73872.

Fix clashing_extern_declarations warning for `#[repr(transparent)]` structs and safely-FFI-convertible enums, and not warning for clashes of struct members of different types, but the same size.

r? @nagisa
Diffstat (limited to 'src/test/ui')
-rw-r--r--src/test/ui/lint/auxiliary/external_extern_fn.rs2
-rw-r--r--src/test/ui/lint/clashing-extern-fn.rs173
-rw-r--r--src/test/ui/lint/clashing-extern-fn.stderr122
3 files changed, 235 insertions, 62 deletions
diff --git a/src/test/ui/lint/auxiliary/external_extern_fn.rs b/src/test/ui/lint/auxiliary/external_extern_fn.rs
index b2caebc6fee..c2a8cadc6b5 100644
--- a/src/test/ui/lint/auxiliary/external_extern_fn.rs
+++ b/src/test/ui/lint/auxiliary/external_extern_fn.rs
@@ -1,3 +1,3 @@
-extern {
+extern "C" {
     pub fn extern_fn(x: u8);
 }
diff --git a/src/test/ui/lint/clashing-extern-fn.rs b/src/test/ui/lint/clashing-extern-fn.rs
index 544614100ba..d6ac7ccccc7 100644
--- a/src/test/ui/lint/clashing-extern-fn.rs
+++ b/src/test/ui/lint/clashing-extern-fn.rs
@@ -3,52 +3,40 @@
 #![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
+mod redeclared_different_signature {
+    mod a {
+        extern "C" {
+            fn clash(x: u8);
+        }
     }
-
-    unsafe {
-        clash(123);
-        no_clash(123);
+    mod b {
+        extern "C" {
+            fn clash(x: u64); //~ WARN `clash` redeclared with a different signature
+        }
     }
 }
 
-fn redeclared_same_signature() {
-    extern "C" {
-        fn no_clash(x: u8);
+mod redeclared_same_signature {
+    mod a {
+        extern "C" {
+            fn no_clash(x: u8);
+        }
     }
-    unsafe {
-        no_clash(123);
+    mod b {
+        extern "C" {
+            fn no_clash(x: u8);
+        }
     }
 }
 
-extern "C" {
-    fn extern_fn(x: u64);
-}
-
-fn extern_clash() {
+extern crate external_extern_fn;
+mod extern_no_clash {
+    // Should not clash with external_extern_fn::extern_fn.
     extern "C" {
-        fn extern_fn(x: u32); //~ WARN `extern_fn` redeclared with a different signature
-    }
-    unsafe {
-        extern_fn(123);
+        fn extern_fn(x: u8);
     }
 }
 
-fn extern_no_clash() {
-    unsafe {
-        external_extern_fn::extern_fn(123);
-        crate::extern_fn(123);
-    }
-}
 extern "C" {
     fn some_other_new_name(x: i16);
 
@@ -134,9 +122,9 @@ mod 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.
+        extern "C" {
             fn weigh_banana(count: *const Banana) -> u64;
         }
     }
@@ -180,7 +168,120 @@ mod sameish_members {
         // 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
+            fn draw_point(p: Point);
+            //~^ WARN `draw_point` redeclared with a different signature
+        }
+    }
+}
+
+mod same_sized_members_clash {
+    mod a {
+        #[repr(C)]
+        struct Point3 {
+            x: f32,
+            y: f32,
+            z: f32,
+        }
+        extern "C" { fn origin() -> Point3; }
+    }
+    mod b {
+        #[repr(C)]
+        struct Point3 {
+            x: i32,
+            y: i32,
+            z: i32, // NOTE: Incorrectly redeclared as i32
+        }
+        extern "C" { fn origin() -> Point3; }
+        //~^ WARN `origin` redeclared with a different signature
+    }
+}
+
+mod transparent {
+    #[repr(transparent)]
+    struct T(usize);
+    mod a {
+        use super::T;
+        extern "C" {
+            fn transparent() -> T;
+            fn transparent_incorrect() -> T;
+        }
+    }
+
+    mod b {
+        extern "C" {
+            // Shouldn't warn here, because repr(transparent) guarantees that T's layout is the
+            // same as just the usize.
+            fn transparent() -> usize;
+
+            // Should warn, because there's a signedness conversion here:
+            fn transparent_incorrect() -> isize;
+            //~^ WARN `transparent_incorrect` redeclared with a different signature
+        }
+    }
+}
+
+mod missing_return_type {
+    mod a {
+        extern "C" {
+            fn missing_return_type() -> usize;
+        }
+    }
+
+    mod b {
+        extern "C" {
+            // This should output a warning because we can't assume that the first declaration is
+            // the correct one -- if this one is the correct one, then calling the usize-returning
+            // version would allow reads into uninitialised memory.
+            fn missing_return_type();
+            //~^ WARN `missing_return_type` redeclared with a different signature
+        }
+    }
+}
+
+mod non_zero_and_non_null {
+    mod a {
+        extern "C" {
+            fn non_zero_usize() -> core::num::NonZeroUsize;
+            fn non_null_ptr() -> core::ptr::NonNull<usize>;
+        }
+    }
+    mod b {
+        extern "C" {
+            // If there's a clash in either of these cases you're either gaining an incorrect
+            // invariant that the value is non-zero, or you're missing out on that invariant. Both
+            // cases are warning for, from both a caller-convenience and optimisation perspective.
+            fn non_zero_usize() -> usize;
+            //~^ WARN `non_zero_usize` redeclared with a different signature
+            fn non_null_ptr() -> *const usize;
+            //~^ WARN `non_null_ptr` redeclared with a different signature
+        }
+    }
+}
+
+mod null_optimised_enums {
+    mod a {
+        extern "C" {
+            fn option_non_zero_usize() -> usize;
+            fn option_non_zero_isize() -> isize;
+            fn option_non_null_ptr() -> *const usize;
+
+            fn option_non_zero_usize_incorrect() -> usize;
+            fn option_non_null_ptr_incorrect() -> *const usize;
+        }
+    }
+    mod b {
+        extern "C" {
+            // This should be allowed, because these conversions are guaranteed to be FFI-safe (see
+            // #60300)
+            fn option_non_zero_usize() -> Option<core::num::NonZeroUsize>;
+            fn option_non_zero_isize() -> Option<core::num::NonZeroIsize>;
+            fn option_non_null_ptr() -> Option<core::ptr::NonNull<usize>>;
+
+            // However, these should be incorrect (note isize instead of usize)
+            fn option_non_zero_usize_incorrect() -> isize;
+            //~^ WARN `option_non_zero_usize_incorrect` redeclared with a different signature
+            fn option_non_null_ptr_incorrect() -> *const isize;
+            //~^ WARN `option_non_null_ptr_incorrect` redeclared with a different signature
         }
     }
 }
diff --git a/src/test/ui/lint/clashing-extern-fn.stderr b/src/test/ui/lint/clashing-extern-fn.stderr
index 96e51ab5a3e..cca0c4c59eb 100644
--- a/src/test/ui/lint/clashing-extern-fn.stderr
+++ b/src/test/ui/lint/clashing-extern-fn.stderr
@@ -1,11 +1,11 @@
 warning: `clash` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:15:9
+  --> $DIR/clashing-extern-fn.rs:14:13
    |
-LL |     fn clash(x: u8);
-   |     ---------------- `clash` previously declared here
+LL |             fn clash(x: u8);
+   |             ---------------- `clash` previously declared here
 ...
-LL |         fn clash(x: u64);
-   |         ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+LL |             fn clash(x: u64);
+   |             ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
    |
 note: the lint level is defined here
   --> $DIR/clashing-extern-fn.rs:4:9
@@ -15,20 +15,8 @@ LL | #![warn(clashing_extern_declarations)]
    = note: expected `unsafe extern "C" fn(u8)`
               found `unsafe extern "C" fn(u64)`
 
-warning: `extern_fn` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:39:9
-   |
-LL |     fn extern_fn(x: u64);
-   |     --------------------- `extern_fn` previously declared here
-...
-LL |         fn extern_fn(x: u32);
-   |         ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
-   |
-   = note: expected `unsafe extern "C" fn(u64)`
-              found `unsafe extern "C" fn(u32)`
-
 warning: `extern_link_name` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:64:9
+  --> $DIR/clashing-extern-fn.rs:52:9
    |
 LL | /     #[link_name = "extern_link_name"]
 LL | |     fn some_new_name(x: i16);
@@ -41,7 +29,7 @@ LL |           fn extern_link_name(x: u32);
               found `unsafe extern "C" fn(u32)`
 
 warning: `some_other_extern_link_name` redeclares `some_other_new_name` with a different signature
-  --> $DIR/clashing-extern-fn.rs:67:9
+  --> $DIR/clashing-extern-fn.rs:55:9
    |
 LL |       fn some_other_new_name(x: i16);
    |       ------------------------------- `some_other_new_name` previously declared here
@@ -55,7 +43,7 @@ LL | |         fn some_other_extern_link_name(x: u32);
               found `unsafe extern "C" fn(u32)`
 
 warning: `other_both_names_different` redeclares `link_name_same` with a different signature
-  --> $DIR/clashing-extern-fn.rs:71:9
+  --> $DIR/clashing-extern-fn.rs:59:9
    |
 LL | /     #[link_name = "link_name_same"]
 LL | |     fn both_names_different(x: i16);
@@ -70,7 +58,7 @@ LL | |         fn other_both_names_different(x: u32);
               found `unsafe extern "C" fn(u32)`
 
 warning: `different_mod` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:84:9
+  --> $DIR/clashing-extern-fn.rs:72:9
    |
 LL |         fn different_mod(x: u8);
    |         ------------------------ `different_mod` previously declared here
@@ -82,7 +70,7 @@ LL |         fn different_mod(x: u64);
               found `unsafe extern "C" fn(u64)`
 
 warning: `variadic_decl` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:94:9
+  --> $DIR/clashing-extern-fn.rs:82:9
    |
 LL |     fn variadic_decl(x: u8, ...);
    |     ----------------------------- `variadic_decl` previously declared here
@@ -94,7 +82,7 @@ LL |         fn variadic_decl(x: u8);
               found `unsafe extern "C" fn(u8)`
 
 warning: `weigh_banana` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:154:13
+  --> $DIR/clashing-extern-fn.rs:142:13
    |
 LL |             fn weigh_banana(count: *const Banana) -> u64;
    |             --------------------------------------------- `weigh_banana` previously declared here
@@ -106,7 +94,7 @@ LL |             fn weigh_banana(count: *const Banana) -> u64;
               found `unsafe extern "C" fn(*const banana::three::Banana) -> u64`
 
 warning: `draw_point` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:183:13
+  --> $DIR/clashing-extern-fn.rs:171:13
    |
 LL |             fn draw_point(p: Point);
    |             ------------------------ `draw_point` previously declared here
@@ -117,5 +105,89 @@ LL |             fn draw_point(p: Point);
    = note: expected `unsafe extern "C" fn(sameish_members::a::Point)`
               found `unsafe extern "C" fn(sameish_members::b::Point)`
 
-warning: 9 warnings emitted
+warning: `origin` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:194:22
+   |
+LL |         extern "C" { fn origin() -> Point3; }
+   |                      ---------------------- `origin` previously declared here
+...
+LL |         extern "C" { fn origin() -> Point3; }
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> same_sized_members_clash::a::Point3`
+              found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3`
+
+warning: `transparent_incorrect` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:217:13
+   |
+LL |             fn transparent_incorrect() -> T;
+   |             -------------------------------- `transparent_incorrect` previously declared here
+...
+LL |             fn transparent_incorrect() -> isize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> transparent::T`
+              found `unsafe extern "C" fn() -> isize`
+
+warning: `missing_return_type` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:235:13
+   |
+LL |             fn missing_return_type() -> usize;
+   |             ---------------------------------- `missing_return_type` previously declared here
+...
+LL |             fn missing_return_type();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> usize`
+              found `unsafe extern "C" fn()`
+
+warning: `non_zero_usize` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:253:13
+   |
+LL |             fn non_zero_usize() -> core::num::NonZeroUsize;
+   |             ----------------------------------------------- `non_zero_usize` previously declared here
+...
+LL |             fn non_zero_usize() -> usize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> std::num::NonZeroUsize`
+              found `unsafe extern "C" fn() -> usize`
+
+warning: `non_null_ptr` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:255:13
+   |
+LL |             fn non_null_ptr() -> core::ptr::NonNull<usize>;
+   |             ----------------------------------------------- `non_null_ptr` previously declared here
+...
+LL |             fn non_null_ptr() -> *const usize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> std::ptr::NonNull<usize>`
+              found `unsafe extern "C" fn() -> *const usize`
+
+warning: `option_non_zero_usize_incorrect` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:281:13
+   |
+LL |             fn option_non_zero_usize_incorrect() -> usize;
+   |             ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here
+...
+LL |             fn option_non_zero_usize_incorrect() -> isize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> usize`
+              found `unsafe extern "C" fn() -> isize`
+
+warning: `option_non_null_ptr_incorrect` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:283:13
+   |
+LL |             fn option_non_null_ptr_incorrect() -> *const usize;
+   |             --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here
+...
+LL |             fn option_non_null_ptr_incorrect() -> *const isize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> *const usize`
+              found `unsafe extern "C" fn() -> *const isize`
+
+warning: 15 warnings emitted