Rollup merge of #97971 - Soveu:varargs, r=jackh726
Enable varargs support for calling conventions other than C or cdecl This patch makes it possible to use varargs for calling conventions, which are either based on C (efiapi) or C is based on them (sysv64 and win64). Also pinging ``@phlopsi,`` because he noticed first this oversight when writing a library for UEFI.
This commit is contained in:
commit
9911229650
12 changed files with 174 additions and 35 deletions
|
@ -106,7 +106,7 @@ use rustc_middle::middle;
|
|||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::util;
|
||||
use rustc_session::config::EntryFnType;
|
||||
use rustc_session::{config::EntryFnType, parse::feature_err};
|
||||
use rustc_span::{symbol::sym, Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
|
@ -118,20 +118,40 @@ use astconv::AstConv;
|
|||
use bounds::Bounds;
|
||||
|
||||
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
|
||||
match (decl.c_variadic, abi) {
|
||||
// The function has the correct calling convention, or isn't a "C-variadic" function.
|
||||
(false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl { .. }) => {}
|
||||
// The function is a "C-variadic" function with an incorrect calling convention.
|
||||
(true, _) => {
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0045,
|
||||
"C-variadic function must have C or cdecl calling convention"
|
||||
);
|
||||
err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
|
||||
}
|
||||
const ERROR_HEAD: &str = "C-variadic function must have a compatible calling convention";
|
||||
const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`";
|
||||
const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
|
||||
const UNSTABLE_EXPLAIN: &str =
|
||||
"using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
|
||||
|
||||
if !decl.c_variadic || matches!(abi, Abi::C { .. } | Abi::Cdecl { .. }) {
|
||||
return;
|
||||
}
|
||||
|
||||
let extended_abi_support = tcx.features().extended_varargs_abi_support;
|
||||
let conventions = match (extended_abi_support, abi.supports_varargs()) {
|
||||
// User enabled additional ABI support for varargs and function ABI matches those ones.
|
||||
(true, true) => return,
|
||||
|
||||
// Using this ABI would be ok, if the feature for additional ABI support was enabled.
|
||||
// Return CONVENTIONS_STABLE, because we want the other error to look the same.
|
||||
(false, true) => {
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::extended_varargs_abi_support,
|
||||
span,
|
||||
UNSTABLE_EXPLAIN,
|
||||
)
|
||||
.emit();
|
||||
CONVENTIONS_STABLE
|
||||
}
|
||||
|
||||
(false, false) => CONVENTIONS_STABLE,
|
||||
(true, false) => CONVENTIONS_UNSTABLE,
|
||||
};
|
||||
|
||||
let mut err = struct_span_err!(tcx.sess, span, E0045, "{}, like {}", ERROR_HEAD, conventions);
|
||||
err.span_label(span, ERROR_HEAD).emit();
|
||||
}
|
||||
|
||||
fn require_same_types<'tcx>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue