From 9196844f0d86242ee3d6a446fe681b6b2d2d674c Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 8 Sep 2025 19:27:07 +0200 Subject: c-variadic: reject functions with unsupported extern ABI --- compiler/rustc_ast/src/ast.rs | 5 +++++ compiler/rustc_ast_passes/messages.ftl | 7 +++++-- compiler/rustc_ast_passes/src/ast_validation.rs | 7 +++++-- compiler/rustc_ast_passes/src/errors.rs | 9 +++++++-- 4 files changed, 22 insertions(+), 6 deletions(-) (limited to 'compiler') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 915bae9e5f5..3e8fddd9954 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2325,6 +2325,11 @@ impl FnSig { } } } + + /// The span of the header's extern, or where to insert it if empty. + pub fn extern_span(&self) -> Span { + self.header.ext.span().unwrap_or(self.safety_span().shrink_to_hi()) + } } /// A constraint on an associated item. diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 1aa38a1beda..8dcf3e3aa38 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -57,8 +57,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim .label = {ast_passes_auto_super_lifetime} .suggestion = remove the super traits or lifetime bounds -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 - ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block .cannot_have = cannot have a body .invalid = the invalid body @@ -68,11 +66,16 @@ 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_bad_extern = `...` is not supported for `extern "{$abi}"` functions + .label = `extern "{$abi}"` because of this + .help = only `extern "C"` and `extern "C-unwind"` functions may 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 + .help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic .const = `const` because of this diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 7b32778ddf0..a6ef89b553d 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -698,7 +698,6 @@ impl<'a> AstValidator<'a> { FnCtxt::Foreign => return, FnCtxt::Free => match sig.header.ext { Extern::Implicit(_) => { - // Implicitly defaults to C. if !matches!(sig.header.safety, Safety::Unsafe(_)) { self.dcx().emit_err(errors::CVariadicMustBeUnsafe { span: variadic_param.span, @@ -708,7 +707,11 @@ impl<'a> AstValidator<'a> { } Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => { 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::CVariadicBadExtern { + span: variadic_param.span, + abi: symbol_unescaped, + extern_span: sig.extern_span(), + }); } if !matches!(sig.header.safety, Safety::Unsafe(_)) { diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 946a22d2e75..ae805042c54 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -327,6 +327,7 @@ pub(crate) struct CVariadicAssociatedFunction { #[derive(Diagnostic)] #[diag(ast_passes_c_variadic_no_extern)] +#[help] pub(crate) struct CVariadicNoExtern { #[primary_span] pub span: Span, @@ -348,10 +349,14 @@ pub(crate) struct CVariadicMustBeUnsafe { } #[derive(Diagnostic)] -#[diag(ast_passes_bad_c_variadic)] -pub(crate) struct BadCVariadic { +#[diag(ast_passes_c_variadic_bad_extern)] +#[help] +pub(crate) struct CVariadicBadExtern { #[primary_span] pub span: Span, + pub abi: Symbol, + #[label] + pub extern_span: Span, } #[derive(Diagnostic)] -- cgit 1.4.1-3-g733a5