Skip to content

Commit 4b2266b

Browse files
committed
Add ClashingLocalDecl test case.
1 parent f182c4a commit 4b2266b

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
extern {
2+
pub fn extern_fn(x: u8);
3+
}
+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
// check-pass
2+
// aux-build:external_extern_fn.rs
3+
#![crate_type = "lib"]
4+
#![warn(clashing_extern_decl)]
5+
6+
extern crate external_extern_fn;
7+
8+
extern {
9+
fn clash(x: u8);
10+
fn no_clash(x: u8);
11+
}
12+
13+
fn redeclared_different_signature() {
14+
extern {
15+
fn clash(x: u64); //~ WARN `clash` redeclared with a different signature
16+
}
17+
18+
unsafe {
19+
clash(123);
20+
no_clash(123);
21+
}
22+
}
23+
24+
fn redeclared_same_signature() {
25+
extern {
26+
fn no_clash(x: u8);
27+
}
28+
unsafe {
29+
no_clash(123);
30+
}
31+
}
32+
33+
extern {
34+
fn extern_fn(x: u64);
35+
}
36+
37+
fn extern_clash() {
38+
extern {
39+
fn extern_fn(x: u32); //~ WARN `extern_fn` redeclared with a different signature
40+
}
41+
unsafe {
42+
extern_fn(123);
43+
}
44+
}
45+
46+
fn extern_no_clash() {
47+
unsafe {
48+
external_extern_fn::extern_fn(123);
49+
crate::extern_fn(123);
50+
}
51+
}
52+
extern {
53+
fn some_other_new_name(x: i16);
54+
55+
#[link_name = "extern_link_name"]
56+
fn some_new_name(x: i16);
57+
58+
#[link_name = "link_name_same"]
59+
fn both_names_different(x: i16);
60+
}
61+
62+
fn link_name_clash() {
63+
extern {
64+
fn extern_link_name(x: u32);
65+
//~^ WARN `extern_link_name` redeclared with a different signature
66+
67+
#[link_name = "some_other_new_name"]
68+
//~^ WARN `some_other_extern_link_name` redeclares `some_other_new_name` with a different
69+
fn some_other_extern_link_name(x: u32);
70+
71+
#[link_name = "link_name_same"]
72+
//~^ WARN `other_both_names_different` redeclares `link_name_same` with a different
73+
fn other_both_names_different(x: u32);
74+
}
75+
}
76+
77+
mod a {
78+
extern {
79+
fn different_mod(x: u8);
80+
}
81+
}
82+
mod b {
83+
extern {
84+
fn different_mod(x: u64); //~ WARN `different_mod` redeclared with a different signature
85+
}
86+
}
87+
88+
extern {
89+
fn variadic_decl(x: u8, ...);
90+
}
91+
92+
fn variadic_clash() {
93+
extern {
94+
fn variadic_decl(x: u8); //~ WARN `variadic_decl` redeclared with a different signature
95+
}
96+
}
97+
98+
#[no_mangle]
99+
fn no_mangle_name(x: u8) { }
100+
101+
extern {
102+
#[link_name = "unique_link_name"]
103+
fn link_name_specified(x: u8);
104+
}
105+
106+
fn tricky_no_clash() {
107+
extern {
108+
// Shouldn't warn, because the declaration above actually declares a different symbol (and
109+
// Rust's name resolution rules around shadowing will handle this gracefully).
110+
fn link_name_specified() -> u32;
111+
112+
// The case of a no_mangle name colliding with an extern decl (see #28179) is related but
113+
// shouldn't be reported by ClashingExternDecl, because this is an example of unmangled
114+
// name clash causing bad behaviour in functions with a defined body.
115+
fn no_mangle_name() -> u32;
116+
}
117+
}
118+
119+
mod banana {
120+
mod one {
121+
#[repr(C)] struct Banana { weight: u32, length: u16 }
122+
extern "C" { fn weigh_banana(count: *const Banana) -> u64; }
123+
}
124+
125+
mod two {
126+
#[repr(C)] struct Banana { weight: u32, length: u16 } // note: distinct type
127+
// This should not trigger the lint because two::Banana is structurally equivalent to
128+
// one::Banana.
129+
extern "C" { fn weigh_banana(count: *const Banana) -> u64; }
130+
}
131+
132+
mod three {
133+
// This _should_ trigger the lint, because repr(packed) should generate a struct that has a
134+
// different layout.
135+
#[repr(packed)] struct Banana { weight: u32, length: u16 }
136+
#[allow(improper_ctypes)]
137+
extern "C" { fn weigh_banana(count: *const Banana) -> u64; }
138+
//~^ WARN `weigh_banana` redeclared with a different signature
139+
}
140+
}
141+
142+
mod sameish_members {
143+
mod a {
144+
#[repr(C)]
145+
struct Point { x: i16, y: i16 }
146+
147+
extern "C" { fn draw_point(p: Point); }
148+
}
149+
mod b {
150+
#[repr(C)]
151+
struct Point { coordinates: [i16; 2] }
152+
153+
// It's possible we are overconservative for this case, as accessing the elements of the
154+
// coordinates array might end up correctly accessing `.x` and `.y`. However, this may not
155+
// always be the case, for every architecture and situation. This is also a really odd
156+
// thing to do anyway.
157+
extern "C" { fn draw_point(p: Point); } //~ WARN `draw_point` redeclared with a different
158+
}
159+
}

0 commit comments

Comments
 (0)