c-variadic: reject non-unsafe functions
This commit is contained in:
parent
5de9bc73e7
commit
0c96200f26
6 changed files with 98 additions and 21 deletions
|
|
@ -2309,6 +2309,22 @@ impl FnSig {
|
|||
|
||||
self.span.shrink_to_lo()
|
||||
}
|
||||
|
||||
/// The span of the header's safety, or where to insert it if empty.
|
||||
pub fn safety_span(&self) -> Span {
|
||||
match self.header.safety {
|
||||
Safety::Unsafe(span) | Safety::Safe(span) => span,
|
||||
Safety::Default => {
|
||||
// Insert after the `coroutine_kind` if available.
|
||||
if let Some(extern_span) = self.header.ext.span() {
|
||||
return extern_span.shrink_to_lo();
|
||||
}
|
||||
|
||||
// Insert right at the front of the signature.
|
||||
self.header_span().shrink_to_hi()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A constraint on an associated item.
|
||||
|
|
@ -3553,6 +3569,13 @@ impl Extern {
|
|||
None => Extern::Implicit(span),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(self) -> Option<Span> {
|
||||
match self {
|
||||
Extern::None => None,
|
||||
Extern::Implicit(span) | Extern::Explicit(_, span) => Some(span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A function header.
|
||||
|
|
|
|||
|
|
@ -68,6 +68,10 @@ ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
|
|||
|
||||
ast_passes_c_variadic_associated_function = associated functions cannot have a C variable argument list
|
||||
|
||||
ast_passes_c_variadic_must_be_unsafe =
|
||||
functions with a C variable argument list must be unsafe
|
||||
.suggestion = add the `unsafe` keyword to this definition
|
||||
|
||||
ast_passes_c_variadic_no_extern = `...` is not supported for non-extern functions
|
||||
|
||||
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
|
||||
|
|
|
|||
|
|
@ -698,20 +698,25 @@ impl<'a> AstValidator<'a> {
|
|||
FnCtxt::Foreign => return,
|
||||
FnCtxt::Free => match sig.header.ext {
|
||||
Extern::Implicit(_) => {
|
||||
if matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
return;
|
||||
// Implicitly defaults to C.
|
||||
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||
span: variadic_param.span,
|
||||
unsafe_span: sig.safety_span(),
|
||||
});
|
||||
}
|
||||
|
||||
self.dcx().emit_err(errors::BadCVariadic { span: variadic_param.span });
|
||||
}
|
||||
Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
|
||||
if matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
|
||||
if matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
return;
|
||||
}
|
||||
if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
|
||||
self.dcx().emit_err(errors::BadCVariadic { span: variadic_param.span });
|
||||
}
|
||||
|
||||
self.dcx().emit_err(errors::BadCVariadic { span: variadic_param.span });
|
||||
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||
span: variadic_param.span,
|
||||
unsafe_span: sig.safety_span(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Extern::None => {
|
||||
let err = errors::CVariadicNoExtern { span: variadic_param.span };
|
||||
|
|
|
|||
|
|
@ -332,6 +332,21 @@ pub(crate) struct CVariadicNoExtern {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_c_variadic_must_be_unsafe)]
|
||||
pub(crate) struct CVariadicMustBeUnsafe {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
#[suggestion(
|
||||
ast_passes_suggestion,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "unsafe ",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub unsafe_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_bad_c_variadic)]
|
||||
pub(crate) struct BadCVariadic {
|
||||
|
|
|
|||
|
|
@ -10,19 +10,19 @@ fn f1_2(...) {}
|
|||
//~^ ERROR `...` is not supported for non-extern functions
|
||||
|
||||
extern "C" fn f2_1(x: isize, ...) {}
|
||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
//~^ ERROR functions with a C variable argument list must be unsafe
|
||||
|
||||
extern "C" fn f2_2(...) {}
|
||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
//~^ ERROR functions with a C variable argument list must be unsafe
|
||||
|
||||
extern "C" fn f2_3(..., x: isize) {}
|
||||
//~^ ERROR `...` must be the last argument of a C-variadic function
|
||||
|
||||
extern "C" fn f3_1(x: isize, ...) {}
|
||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
//~^ ERROR functions with a C variable argument list must be unsafe
|
||||
|
||||
extern "C" fn f3_2(...) {}
|
||||
//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
//~^ ERROR functions with a C variable argument list must be unsafe
|
||||
|
||||
extern "C" fn f3_3(..., x: isize) {}
|
||||
//~^ ERROR `...` must be the last argument of a C-variadic function
|
||||
|
|
@ -33,12 +33,12 @@ const unsafe extern "C" fn f4_1(x: isize, ...) {}
|
|||
|
||||
const extern "C" fn f4_2(x: isize, ...) {}
|
||||
//~^ ERROR functions cannot be both `const` and C-variadic
|
||||
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
//~| ERROR functions with a C variable argument list must be unsafe
|
||||
//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time
|
||||
|
||||
const extern "C" fn f4_3(..., x: isize, ...) {}
|
||||
//~^ ERROR functions cannot be both `const` and C-variadic
|
||||
//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
//~| ERROR functions with a C variable argument list must be unsafe
|
||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
|
||||
extern "C" {
|
||||
|
|
|
|||
|
|
@ -10,17 +10,27 @@ error: `...` is not supported for non-extern functions
|
|||
LL | fn f1_2(...) {}
|
||||
| ^^^
|
||||
|
||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
|
||||
|
|
||||
LL | extern "C" fn f2_1(x: isize, ...) {}
|
||||
| ^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "C" fn f2_1(x: isize, ...) {}
|
||||
| ++++++
|
||||
|
||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
||||
|
|
||||
LL | extern "C" fn f2_2(...) {}
|
||||
| ^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "C" fn f2_2(...) {}
|
||||
| ++++++
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:18:20
|
||||
|
|
@ -28,17 +38,27 @@ error: `...` must be the last argument of a C-variadic function
|
|||
LL | extern "C" fn f2_3(..., x: isize) {}
|
||||
| ^^^
|
||||
|
||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:21:30
|
||||
|
|
||||
LL | extern "C" fn f3_1(x: isize, ...) {}
|
||||
| ^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "C" fn f3_1(x: isize, ...) {}
|
||||
| ++++++
|
||||
|
||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:20
|
||||
|
|
||||
LL | extern "C" fn f3_2(...) {}
|
||||
| ^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "C" fn f3_2(...) {}
|
||||
| ++++++
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
|
||||
|
|
@ -58,11 +78,16 @@ error: functions cannot be both `const` and C-variadic
|
|||
LL | const extern "C" fn f4_2(x: isize, ...) {}
|
||||
| ^^^^^ `const` because of this ^^^ C-variadic because of this
|
||||
|
||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:34:36
|
||||
|
|
||||
LL | const extern "C" fn f4_2(x: isize, ...) {}
|
||||
| ^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | const unsafe extern "C" fn f4_2(x: isize, ...) {}
|
||||
| ++++++
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:26
|
||||
|
|
@ -76,11 +101,16 @@ error: functions cannot be both `const` and C-variadic
|
|||
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
|
||||
| ^^^^^ `const` because of this ^^^ C-variadic because of this
|
||||
|
||||
error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
error: functions with a C variable argument list must be unsafe
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:39:41
|
||||
|
|
||||
LL | const extern "C" fn f4_3(..., x: isize, ...) {}
|
||||
| ^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | const unsafe extern "C" fn f4_3(..., x: isize, ...) {}
|
||||
| ++++++
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:45:13
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue