about summary refs log tree commit diff
diff options
context:
space:
mode:
authorjumbatm <jumbatm@gmail.com>2020-03-31 18:24:59 +1000
committerjumbatm <30644300+jumbatm@users.noreply.github.com>2020-06-20 16:54:32 +1000
commita540b1b38dc2a28c11e481f95f43daebb52493d3 (patch)
treea7612916832fd1ed318f4315361cc90a5f9a4d9f
parent033013cab3a861224fd55f494c8be1cb0349eb49 (diff)
downloadrust-a540b1b38dc2a28c11e481f95f43daebb52493d3.tar.gz
rust-a540b1b38dc2a28c11e481f95f43daebb52493d3.zip
Add ClashingExternDecl test case.
-rw-r--r--src/test/ui/lint/auxiliary/external_extern_fn.rs3
-rw-r--r--src/test/ui/lint/clashing-extern-fn.rs159
2 files changed, 162 insertions, 0 deletions
diff --git a/src/test/ui/lint/auxiliary/external_extern_fn.rs b/src/test/ui/lint/auxiliary/external_extern_fn.rs
new file mode 100644
index 00000000000..b2caebc6fee
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/external_extern_fn.rs
@@ -0,0 +1,3 @@
+extern {
+    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
new file mode 100644
index 00000000000..32f3a78f4e9
--- /dev/null
+++ b/src/test/ui/lint/clashing-extern-fn.rs
@@ -0,0 +1,159 @@
+// check-pass
+// aux-build:external_extern_fn.rs
+#![crate_type = "lib"]
+#![warn(clashing_extern_decl)]
+
+extern crate external_extern_fn;
+
+extern {
+    fn clash(x: u8);
+    fn no_clash(x: u8);
+}
+
+fn redeclared_different_signature() {
+    extern {
+        fn clash(x: u64); //~ WARN `clash` redeclared with a different signature
+    }
+
+    unsafe {
+        clash(123);
+        no_clash(123);
+    }
+}
+
+fn redeclared_same_signature() {
+    extern {
+        fn no_clash(x: u8);
+    }
+    unsafe {
+        no_clash(123);
+    }
+}
+
+extern {
+    fn extern_fn(x: u64);
+}
+
+fn extern_clash() {
+    extern {
+        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 {
+    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 {
+        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 {
+        fn different_mod(x: u8);
+    }
+}
+mod b {
+    extern {
+        fn different_mod(x: u64); //~ WARN `different_mod` redeclared with a different signature
+    }
+}
+
+extern {
+    fn variadic_decl(x: u8, ...);
+}
+
+fn variadic_clash() {
+    extern {
+        fn variadic_decl(x: u8); //~ WARN `variadic_decl` redeclared with a different signature
+    }
+}
+
+#[no_mangle]
+fn no_mangle_name(x: u8) { }
+
+extern {
+    #[link_name = "unique_link_name"]
+    fn link_name_specified(x: u8);
+}
+
+fn tricky_no_clash() {
+    extern {
+        // 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 ClashingExternDecl, 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
+        // This should not trigger the lint because two::Banana is structurally equivalent to
+        // one::Banana.
+        extern "C" { 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
+    }
+}