Rollup merge of #149557 - folkertdev:c-variadic-not-supported, r=workingjubilee

c-variadic: bpf and spirv do not support c-variadic definitions

tracking issue: https://github.com/rust-lang/rust/issues/44930

Emit a nice error message on bpf and spirv targets when a c-variadic function is defined. Spirv also does not support c-variadic calls, bpf appears to allow them.

r? ```@workingjubilee```
This commit is contained in:
Matthias Krüger 2025-12-04 08:46:24 +01:00 committed by GitHub
commit 62a42e8a31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 36 additions and 0 deletions

View file

@ -80,6 +80,8 @@ ast_passes_c_variadic_must_be_unsafe =
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_c_variadic_not_supported = the `{$target}` target does not support c-variadic functions
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
.const = `const` because of this
.variadic = C-variadic because of this

View file

@ -710,6 +710,14 @@ impl<'a> AstValidator<'a> {
match fn_ctxt {
FnCtxt::Foreign => return,
FnCtxt::Free | FnCtxt::Assoc(_) => {
if !self.sess.target.arch.supports_c_variadic_definitions() {
self.dcx().emit_err(errors::CVariadicNotSupported {
variadic_span: variadic_param.span,
target: &*self.sess.target.llvm_target,
});
return;
}
match sig.header.ext {
Extern::Implicit(_) => {
if !matches!(sig.header.safety, Safety::Unsafe(_)) {

View file

@ -733,6 +733,14 @@ pub(crate) struct CoroutineAndCVariadic {
pub variadic_span: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_c_variadic_not_supported)]
pub(crate) struct CVariadicNotSupported<'a> {
#[primary_span]
pub variadic_span: Span,
pub target: &'a str,
}
#[derive(Diagnostic)]
#[diag(ast_passes_pattern_in_foreign, code = E0130)]
// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`)

View file

@ -1925,6 +1925,24 @@ impl Arch {
Self::Other(name) => rustc_span::Symbol::intern(name),
}
}
pub fn supports_c_variadic_definitions(&self) -> bool {
use Arch::*;
match self {
// These targets just do not support c-variadic definitions.
Bpf | SpirV => false,
// We don't know if the target supports c-variadic definitions, but we don't want
// to needlessly restrict custom target.json configurations.
Other(_) => true,
AArch64 | AmdGpu | Arm | Arm64EC | Avr | CSky | Hexagon | LoongArch32 | LoongArch64
| M68k | Mips | Mips32r6 | Mips64 | Mips64r6 | Msp430 | Nvptx64 | PowerPC
| PowerPC64 | PowerPC64LE | RiscV32 | RiscV64 | S390x | Sparc | Sparc64 | Wasm32
| Wasm64 | X86 | X86_64 | Xtensa => true,
}
}
}
crate::target_spec_enum! {