Skip to content

Commit 604a56b

Browse files
committed
error on a safe fn that uses C-variadics
1 parent 36a1678 commit 604a56b

File tree

5 files changed

+82
-5
lines changed

5 files changed

+82
-5
lines changed

compiler/rustc_ast_passes/messages.ftl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim
2424
.label = {ast_passes_auto_super_lifetime}
2525
.suggestion = remove the super traits or lifetime bounds
2626
27-
ast_passes_bad_c_variadic = only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg
28-
2927
ast_passes_bare_fn_invalid_safety = function pointers cannot be declared with `safe` safety qualifier
3028
.suggestion = remove safe from this item
3129
@@ -36,6 +34,13 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
3634
3735
ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
3836
37+
ast_passes_c_variadic_bad_calling_convention =
38+
only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg
39+
40+
ast_passes_c_variadic_safe_foreign_function =
41+
foreign functions with a C-variadic argument cannot be safe
42+
.suggestion = remove the `safe` keyword from this definition
43+
3944
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
4045
.const = `const` because of this
4146
.variadic = C-variadic because of this

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,21 @@ impl<'a> AstValidator<'a> {
554554
}
555555

556556
match (fk.ctxt(), fk.header()) {
557-
(Some(FnCtxt::Foreign), _) => return,
557+
(Some(FnCtxt::Foreign), Some(header)) => match header.safety {
558+
Safety::Default | Safety::Unsafe(_) => return,
559+
Safety::Safe(span) => {
560+
self.dcx().emit_err(errors::CVariadicSafeForeignFunction {
561+
// The span of the "safe " string that should be removed.
562+
safe_span: self
563+
.sess
564+
.psess
565+
.source_map()
566+
.span_until_non_whitespace(span.until(fk.decl().output.span())),
567+
});
568+
return;
569+
}
570+
},
571+
558572
(Some(FnCtxt::Free), Some(header)) => match header.ext {
559573
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _)
560574
| Extern::Explicit(StrLit { symbol_unescaped: sym::C_dash_unwind, .. }, _)

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,25 @@ pub(crate) struct ExternItemAscii {
308308
}
309309

310310
#[derive(Diagnostic)]
311-
#[diag(ast_passes_bad_c_variadic)]
311+
#[diag(ast_passes_c_variadic_bad_calling_convention)]
312312
pub(crate) struct BadCVariadic {
313313
#[primary_span]
314314
pub span: Vec<Span>,
315315
}
316316

317+
#[derive(Diagnostic)]
318+
#[diag(ast_passes_c_variadic_safe_foreign_function)]
319+
pub(crate) struct CVariadicSafeForeignFunction {
320+
#[primary_span]
321+
#[suggestion(
322+
ast_passes_suggestion,
323+
applicability = "machine-applicable",
324+
code = "",
325+
style = "verbose"
326+
)]
327+
pub safe_span: Span,
328+
}
329+
317330
#[derive(Diagnostic)]
318331
#[diag(ast_passes_item_underscore)]
319332
pub(crate) struct ItemUnderscore<'a> {

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,12 @@ trait T {
8383
//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg
8484
//~| ERROR `...` must be the last argument of a C-variadic function
8585
}
86+
87+
unsafe extern "C" {
88+
safe fn s_f1(...);
89+
//~^ ERROR foreign functions with a C-variadic argument cannot be safe
90+
safe fn printf(format: *const u8, ...);
91+
//~^ ERROR foreign functions with a C-variadic argument cannot be safe
92+
safe fn snprintf(s: *mut u8, n: usize, format: *const u8, ...);
93+
//~^ ERROR foreign functions with a C-variadic argument cannot be safe
94+
}

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

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,42 @@ error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` function
201201
LL | fn t_f6(..., x: isize);
202202
| ^^^
203203

204+
error: foreign functions with a C-variadic argument cannot be safe
205+
--> $DIR/variadic-ffi-semantic-restrictions.rs:88:5
206+
|
207+
LL | safe fn s_f1(...);
208+
| ^^^^^
209+
|
210+
help: remove the `safe` keyword from this definition
211+
|
212+
LL - safe fn s_f1(...);
213+
LL + fn s_f1(...);
214+
|
215+
216+
error: foreign functions with a C-variadic argument cannot be safe
217+
--> $DIR/variadic-ffi-semantic-restrictions.rs:90:5
218+
|
219+
LL | safe fn printf(format: *const u8, ...);
220+
| ^^^^^
221+
|
222+
help: remove the `safe` keyword from this definition
223+
|
224+
LL - safe fn printf(format: *const u8, ...);
225+
LL + fn printf(format: *const u8, ...);
226+
|
227+
228+
error: foreign functions with a C-variadic argument cannot be safe
229+
--> $DIR/variadic-ffi-semantic-restrictions.rs:92:5
230+
|
231+
LL | safe fn snprintf(s: *mut u8, n: usize, format: *const u8, ...);
232+
| ^^^^^
233+
|
234+
help: remove the `safe` keyword from this definition
235+
|
236+
LL - safe fn snprintf(s: *mut u8, n: usize, format: *const u8, ...);
237+
LL + fn snprintf(s: *mut u8, n: usize, format: *const u8, ...);
238+
|
239+
204240
error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
205241
--> $DIR/variadic-ffi-semantic-restrictions.rs:32:43
206242
|
@@ -225,6 +261,6 @@ LL | const fn i_f5(x: isize, ...) {}
225261
| |
226262
| the destructor for this type cannot be evaluated in constant functions
227263

228-
error: aborting due to 36 previous errors
264+
error: aborting due to 39 previous errors
229265

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

0 commit comments

Comments
 (0)