mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-04 09:53:04 +03:00
Rollup merge of #155821 - folkertdev:doc-va-list-clone, r=joshtriplett
c-variadic: document `Clone` and `Drop` instances and require `VaArgSafe: Copy` tracking issue: https://github.com/rust-lang/rust/issues/44930 Fixing some things that came up in the stabilization PR r? tgross35 cc @kpreid
This commit is contained in:
@@ -148,8 +148,9 @@ pub fn codegen_intrinsic_call(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// va_end uses the fallback body (a no-op).
|
||||
sym::va_start => bx.va_start(args[0].immediate()),
|
||||
sym::va_end => bx.va_end(args[0].immediate()),
|
||||
|
||||
sym::size_of_val => {
|
||||
let tp_ty = fn_args.type_at(0);
|
||||
let (_, meta) = args[0].val.pointer_parts();
|
||||
|
||||
@@ -251,6 +251,9 @@ pub(crate) const fn duplicate(&self) -> Self {
|
||||
|
||||
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
|
||||
impl<'f> const Clone for VaList<'f> {
|
||||
/// Clone the [`VaList`], producing a second independent cursor into the variable argument list.
|
||||
///
|
||||
/// Corresponds to `va_copy` in C.
|
||||
#[inline] // Avoid codegen when not used to help backends that don't support VaList.
|
||||
fn clone(&self) -> Self {
|
||||
// We only implement Clone and not Copy because some future target might not be able to
|
||||
@@ -263,8 +266,14 @@ fn clone(&self) -> Self {
|
||||
|
||||
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
|
||||
impl<'f> const Drop for VaList<'f> {
|
||||
/// Drop the [`VaList`].
|
||||
///
|
||||
/// Corresponds to `va_end` in C.
|
||||
#[inline] // Avoid codegen when not used to help backends that don't support VaList.
|
||||
fn drop(&mut self) {
|
||||
// Call the rust `va_end` intrinsic, which is a no-op and does not map to LLVM `va_end`.
|
||||
// The rust intrinsic exists as a hook for Miri to check for UB.
|
||||
//
|
||||
// SAFETY: this variable argument list is being dropped, so won't be read from again.
|
||||
unsafe { va_end(self) }
|
||||
}
|
||||
@@ -324,7 +333,7 @@ impl<T> Sealed for *const T {}
|
||||
// types with an alignment larger than 8, or with a non-scalar layout. Inline assembly can be used
|
||||
// to accept unsupported types in the meantime.
|
||||
#[lang = "va_arg_safe"]
|
||||
pub unsafe trait VaArgSafe: sealed::Sealed {}
|
||||
pub unsafe trait VaArgSafe: Copy + sealed::Sealed {}
|
||||
|
||||
crate::cfg_select! {
|
||||
any(target_arch = "avr", target_arch = "msp430") => {
|
||||
@@ -381,6 +390,12 @@ const fn va_arg_safe_check<T: VaArgSafe>() {}
|
||||
va_arg_safe_check::<crate::ffi::c_ulonglong>();
|
||||
|
||||
va_arg_safe_check::<crate::ffi::c_double>();
|
||||
|
||||
va_arg_safe_check::<*const crate::ffi::c_void>();
|
||||
va_arg_safe_check::<*mut crate::ffi::c_void>();
|
||||
|
||||
va_arg_safe_check::<*const crate::ffi::c_char>();
|
||||
va_arg_safe_check::<*mut crate::ffi::c_char>();
|
||||
};
|
||||
|
||||
impl<'f> VaList<'f> {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
//@ add-minicore
|
||||
//@ compile-flags: -Copt-level=3
|
||||
#![feature(c_variadic)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
unsafe extern "C" {
|
||||
fn g(v: *mut u8);
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn f(mut args: ...) {
|
||||
// CHECK: call void @llvm.va_start
|
||||
unsafe { g(&raw mut args as *mut u8) }
|
||||
// We expect one call to the LLVM va_end from our desugaring of `...`. The `Drop` implementation
|
||||
// should only call the rust va_end intrinsic, which is a no-op.
|
||||
//
|
||||
// CHECK: call void @llvm.va_end
|
||||
// CHECK-NOT: call void @llvm.va_end
|
||||
}
|
||||
Reference in New Issue
Block a user