Skip to content

Commit 9196844

Browse files
committed
c-variadic: reject functions with unsupported extern ABI
1 parent 0c96200 commit 9196844

File tree

9 files changed

+79
-40
lines changed

9 files changed

+79
-40
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,6 +2325,11 @@ impl FnSig {
23252325
}
23262326
}
23272327
}
2328+
2329+
/// The span of the header's extern, or where to insert it if empty.
2330+
pub fn extern_span(&self) -> Span {
2331+
self.header.ext.span().unwrap_or(self.safety_span().shrink_to_hi())
2332+
}
23282333
}
23292334

23302335
/// A constraint on an associated item.

compiler/rustc_ast_passes/messages.ftl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim
5757
.label = {ast_passes_auto_super_lifetime}
5858
.suggestion = remove the super traits or lifetime bounds
5959
60-
ast_passes_bad_c_variadic = defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
61-
6260
ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
6361
.cannot_have = cannot have a body
6462
.invalid = the invalid body
@@ -68,11 +66,16 @@ ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
6866
6967
ast_passes_c_variadic_associated_function = associated functions cannot have a C variable argument list
7068
69+
ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"` functions
70+
.label = `extern "{$abi}"` because of this
71+
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
72+
7173
ast_passes_c_variadic_must_be_unsafe =
7274
functions with a C variable argument list must be unsafe
7375
.suggestion = add the `unsafe` keyword to this definition
7476
7577
ast_passes_c_variadic_no_extern = `...` is not supported for non-extern functions
78+
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
7679
7780
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
7881
.const = `const` because of this

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,6 @@ impl<'a> AstValidator<'a> {
698698
FnCtxt::Foreign => return,
699699
FnCtxt::Free => match sig.header.ext {
700700
Extern::Implicit(_) => {
701-
// Implicitly defaults to C.
702701
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
703702
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
704703
span: variadic_param.span,
@@ -708,7 +707,11 @@ impl<'a> AstValidator<'a> {
708707
}
709708
Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
710709
if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
711-
self.dcx().emit_err(errors::BadCVariadic { span: variadic_param.span });
710+
self.dcx().emit_err(errors::CVariadicBadExtern {
711+
span: variadic_param.span,
712+
abi: symbol_unescaped,
713+
extern_span: sig.extern_span(),
714+
});
712715
}
713716

714717
if !matches!(sig.header.safety, Safety::Unsafe(_)) {

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ pub(crate) struct CVariadicAssociatedFunction {
327327

328328
#[derive(Diagnostic)]
329329
#[diag(ast_passes_c_variadic_no_extern)]
330+
#[help]
330331
pub(crate) struct CVariadicNoExtern {
331332
#[primary_span]
332333
pub span: Span,
@@ -348,10 +349,14 @@ pub(crate) struct CVariadicMustBeUnsafe {
348349
}
349350

350351
#[derive(Diagnostic)]
351-
#[diag(ast_passes_bad_c_variadic)]
352-
pub(crate) struct BadCVariadic {
352+
#[diag(ast_passes_c_variadic_bad_extern)]
353+
#[help]
354+
pub(crate) struct CVariadicBadExtern {
353355
#[primary_span]
354356
pub span: Span,
357+
pub abi: Symbol,
358+
#[label]
359+
pub extern_span: Span,
355360
}
356361

357362
#[derive(Diagnostic)]

tests/ui/c-variadic/issue-86053-1.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ error: `...` is not supported for non-extern functions
5151
|
5252
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
5353
| ^^^
54+
|
55+
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
5456

5557
error[E0412]: cannot find type `F` in this scope
5658
--> $DIR/issue-86053-1.rs:11:48

tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,6 @@ extern "cmse-nonsecure-entry" fn wrapped_trait_object(x: WrapperTransparent) ->
6767
}
6868

6969
unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
70-
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
70+
//~^ ERROR `...` is not supported for `extern "cmse-nonsecure-entry"` functions
7171
//~| ERROR requires `va_list` lang_item
7272
}

tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
1+
error: `...` is not supported for `extern "cmse-nonsecure-entry"` functions
22
--> $DIR/generics.rs:69:60
33
|
44
LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
5-
| ^^^^^^
5+
| ----------------------------- ^^^^^^
6+
| |
7+
| `extern "cmse-nonsecure-entry"` because of this
8+
|
9+
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
610

711
error[E0798]: functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type
812
--> $DIR/generics.rs:30:1

tests/ui/parser/variadic-ffi-semantic-restrictions.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ fn f1_1(x: isize, ...) {}
99
fn f1_2(...) {}
1010
//~^ ERROR `...` is not supported for non-extern functions
1111

12+
unsafe extern "Rust" fn f1_3(...) {}
13+
//~^ ERROR `...` is not supported for `extern "Rust"` functions
14+
1215
extern "C" fn f2_1(x: isize, ...) {}
1316
//~^ ERROR functions with a C variable argument list must be unsafe
1417

tests/ui/parser/variadic-ffi-semantic-restrictions.stderr

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,30 @@ error: `...` is not supported for non-extern functions
33
|
44
LL | fn f1_1(x: isize, ...) {}
55
| ^^^
6+
|
7+
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
68

79
error: `...` is not supported for non-extern functions
810
--> $DIR/variadic-ffi-semantic-restrictions.rs:9:9
911
|
1012
LL | fn f1_2(...) {}
1113
| ^^^
14+
|
15+
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
1216

13-
error: functions with a C variable argument list must be unsafe
17+
error: `...` is not supported for `extern "Rust"` functions
1418
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
1519
|
20+
LL | unsafe extern "Rust" fn f1_3(...) {}
21+
| ------------- ^^^
22+
| |
23+
| `extern "Rust"` because of this
24+
|
25+
= help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
26+
27+
error: functions with a C variable argument list must be unsafe
28+
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:30
29+
|
1630
LL | extern "C" fn f2_1(x: isize, ...) {}
1731
| ^^^
1832
|
@@ -22,7 +36,7 @@ LL | unsafe extern "C" fn f2_1(x: isize, ...) {}
2236
| ++++++
2337

2438
error: functions with a C variable argument list must be unsafe
25-
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
39+
--> $DIR/variadic-ffi-semantic-restrictions.rs:18:20
2640
|
2741
LL | extern "C" fn f2_2(...) {}
2842
| ^^^
@@ -33,13 +47,13 @@ LL | unsafe extern "C" fn f2_2(...) {}
3347
| ++++++
3448

3549
error: `...` must be the last argument of a C-variadic function
36-
--> $DIR/variadic-ffi-semantic-restrictions.rs:18:20
50+
--> $DIR/variadic-ffi-semantic-restrictions.rs:21:20
3751
|
3852
LL | extern "C" fn f2_3(..., x: isize) {}
3953
| ^^^
4054

4155
error: functions with a C variable argument list must be unsafe
42-
--> $DIR/variadic-ffi-semantic-restrictions.rs:21:30
56+
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:30
4357
|
4458
LL | extern "C" fn f3_1(x: isize, ...) {}
4559
| ^^^
@@ -50,7 +64,7 @@ LL | unsafe extern "C" fn f3_1(x: isize, ...) {}
5064
| ++++++
5165

5266
error: functions with a C variable argument list must be unsafe
53-
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:20
67+
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
5468
|
5569
LL | extern "C" fn f3_2(...) {}
5670
| ^^^
@@ -61,25 +75,25 @@ LL | unsafe extern "C" fn f3_2(...) {}
6175
| ++++++
6276

6377
error: `...` must be the last argument of a C-variadic function
64-
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
78+
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:20
6579
|
6680
LL | extern "C" fn f3_3(..., x: isize) {}
6781
| ^^^
6882

6983
error: functions cannot be both `const` and C-variadic
70-
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:1
84+
--> $DIR/variadic-ffi-semantic-restrictions.rs:33:1
7185
|
7286
LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
7387
| ^^^^^ `const` because of this ^^^ C-variadic because of this
7488

7589
error: functions cannot be both `const` and C-variadic
76-
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:1
90+
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:1
7791
|
7892
LL | const extern "C" fn f4_2(x: isize, ...) {}
7993
| ^^^^^ `const` because of this ^^^ C-variadic because of this
8094

8195
error: functions with a C variable argument list must be unsafe
82-
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:36
96+
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
8397
|
8498
LL | const extern "C" fn f4_2(x: isize, ...) {}
8599
| ^^^
@@ -90,19 +104,19 @@ LL | const unsafe extern "C" fn f4_2(x: isize, ...) {}
90104
| ++++++
91105

92106
error: `...` must be the last argument of a C-variadic function
93-
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:26
107+
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:26
94108
|
95109
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
96110
| ^^^
97111

98112
error: functions cannot be both `const` and C-variadic
99-
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:1
113+
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:1
100114
|
101115
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
102116
| ^^^^^ `const` because of this ^^^ C-variadic because of this
103117

104118
error: functions with a C variable argument list must be unsafe
105-
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:41
119+
--> $DIR/variadic-ffi-semantic-restrictions.rs:42:41
106120
|
107121
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
108122
| ^^^
@@ -113,121 +127,121 @@ LL | const unsafe extern "C" fn f4_3(..., x: isize, ...) {}
113127
| ++++++
114128

115129
error: `...` must be the last argument of a C-variadic function
116-
--> $DIR/variadic-ffi-semantic-restrictions.rs:45:13
130+
--> $DIR/variadic-ffi-semantic-restrictions.rs:48:13
117131
|
118132
LL | fn e_f2(..., x: isize);
119133
| ^^^
120134

121135
error: associated functions cannot have a C variable argument list
122-
--> $DIR/variadic-ffi-semantic-restrictions.rs:52:23
136+
--> $DIR/variadic-ffi-semantic-restrictions.rs:55:23
123137
|
124138
LL | fn i_f1(x: isize, ...) {}
125139
| ^^^
126140

127141
error: associated functions cannot have a C variable argument list
128-
--> $DIR/variadic-ffi-semantic-restrictions.rs:54:13
142+
--> $DIR/variadic-ffi-semantic-restrictions.rs:57:13
129143
|
130144
LL | fn i_f2(...) {}
131145
| ^^^
132146

133147
error: `...` must be the last argument of a C-variadic function
134-
--> $DIR/variadic-ffi-semantic-restrictions.rs:56:13
148+
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
135149
|
136150
LL | fn i_f3(..., x: isize, ...) {}
137151
| ^^^
138152

139153
error: associated functions cannot have a C variable argument list
140-
--> $DIR/variadic-ffi-semantic-restrictions.rs:56:28
154+
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:28
141155
|
142156
LL | fn i_f3(..., x: isize, ...) {}
143157
| ^^^
144158

145159
error: `...` must be the last argument of a C-variadic function
146-
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:13
160+
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:13
147161
|
148162
LL | fn i_f4(..., x: isize, ...) {}
149163
| ^^^
150164

151165
error: associated functions cannot have a C variable argument list
152-
--> $DIR/variadic-ffi-semantic-restrictions.rs:59:28
166+
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:28
153167
|
154168
LL | fn i_f4(..., x: isize, ...) {}
155169
| ^^^
156170

157171
error: functions cannot be both `const` and C-variadic
158-
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:5
172+
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:5
159173
|
160174
LL | const fn i_f5(x: isize, ...) {}
161175
| ^^^^^ ^^^ C-variadic because of this
162176
| |
163177
| `const` because of this
164178

165179
error: associated functions cannot have a C variable argument list
166-
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:29
180+
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
167181
|
168182
LL | const fn i_f5(x: isize, ...) {}
169183
| ^^^
170184

171185
error: associated functions cannot have a C variable argument list
172-
--> $DIR/variadic-ffi-semantic-restrictions.rs:69:23
186+
--> $DIR/variadic-ffi-semantic-restrictions.rs:72:23
173187
|
174188
LL | fn t_f1(x: isize, ...) {}
175189
| ^^^
176190

177191
error: associated functions cannot have a C variable argument list
178-
--> $DIR/variadic-ffi-semantic-restrictions.rs:71:23
192+
--> $DIR/variadic-ffi-semantic-restrictions.rs:74:23
179193
|
180194
LL | fn t_f2(x: isize, ...);
181195
| ^^^
182196

183197
error: associated functions cannot have a C variable argument list
184-
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
198+
--> $DIR/variadic-ffi-semantic-restrictions.rs:76:13
185199
|
186200
LL | fn t_f3(...) {}
187201
| ^^^
188202

189203
error: associated functions cannot have a C variable argument list
190-
--> $DIR/variadic-ffi-semantic-restrictions.rs:75:13
204+
--> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
191205
|
192206
LL | fn t_f4(...);
193207
| ^^^
194208

195209
error: `...` must be the last argument of a C-variadic function
196-
--> $DIR/variadic-ffi-semantic-restrictions.rs:77:13
210+
--> $DIR/variadic-ffi-semantic-restrictions.rs:80:13
197211
|
198212
LL | fn t_f5(..., x: isize) {}
199213
| ^^^
200214

201215
error: `...` must be the last argument of a C-variadic function
202-
--> $DIR/variadic-ffi-semantic-restrictions.rs:79:13
216+
--> $DIR/variadic-ffi-semantic-restrictions.rs:82:13
203217
|
204218
LL | fn t_f6(..., x: isize);
205219
| ^^^
206220

207221
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
208-
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:43
222+
--> $DIR/variadic-ffi-semantic-restrictions.rs:33:43
209223
|
210224
LL | const unsafe extern "C" fn f4_1(x: isize, ...) {}
211225
| ^^^ - value is dropped here
212226
| |
213227
| the destructor for this type cannot be evaluated in constant functions
214228

215229
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
216-
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:36
230+
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:36
217231
|
218232
LL | const extern "C" fn f4_2(x: isize, ...) {}
219233
| ^^^ - value is dropped here
220234
| |
221235
| the destructor for this type cannot be evaluated in constant functions
222236

223237
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
224-
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:29
238+
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:29
225239
|
226240
LL | const fn i_f5(x: isize, ...) {}
227241
| ^^^ - value is dropped here
228242
| |
229243
| the destructor for this type cannot be evaluated in constant functions
230244

231-
error: aborting due to 32 previous errors
245+
error: aborting due to 33 previous errors
232246

233247
For more information about this error, try `rustc --explain E0493`.

0 commit comments

Comments
 (0)