Skip to content

Commit 0ab1a47

Browse files
authored
Rollup merge of #155821 - folkertdev:doc-va-list-clone, r=joshtriplett
c-variadic: document `Clone` and `Drop` instances and require `VaArgSafe: Copy` tracking issue: #44930 Fixing some things that came up in the stabilization PR r? tgross35 cc @kpreid
2 parents 5b91e27 + ac12c69 commit 0ab1a47

3 files changed

Lines changed: 37 additions & 2 deletions

File tree

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
148148
return Ok(());
149149
}
150150

151+
// va_end uses the fallback body (a no-op).
151152
sym::va_start => bx.va_start(args[0].immediate()),
152-
sym::va_end => bx.va_end(args[0].immediate()),
153+
153154
sym::size_of_val => {
154155
let tp_ty = fn_args.type_at(0);
155156
let (_, meta) = args[0].val.pointer_parts();

library/core/src/ffi/va_list.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ impl VaList<'_> {
251251

252252
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
253253
impl<'f> const Clone for VaList<'f> {
254+
/// Clone the [`VaList`], producing a second independent cursor into the variable argument list.
255+
///
256+
/// Corresponds to `va_copy` in C.
254257
#[inline] // Avoid codegen when not used to help backends that don't support VaList.
255258
fn clone(&self) -> Self {
256259
// We only implement Clone and not Copy because some future target might not be able to
@@ -263,8 +266,14 @@ impl<'f> const Clone for VaList<'f> {
263266

264267
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
265268
impl<'f> const Drop for VaList<'f> {
269+
/// Drop the [`VaList`].
270+
///
271+
/// Corresponds to `va_end` in C.
266272
#[inline] // Avoid codegen when not used to help backends that don't support VaList.
267273
fn drop(&mut self) {
274+
// Call the rust `va_end` intrinsic, which is a no-op and does not map to LLVM `va_end`.
275+
// The rust intrinsic exists as a hook for Miri to check for UB.
276+
//
268277
// SAFETY: this variable argument list is being dropped, so won't be read from again.
269278
unsafe { va_end(self) }
270279
}
@@ -324,7 +333,7 @@ mod sealed {
324333
// types with an alignment larger than 8, or with a non-scalar layout. Inline assembly can be used
325334
// to accept unsupported types in the meantime.
326335
#[lang = "va_arg_safe"]
327-
pub unsafe trait VaArgSafe: sealed::Sealed {}
336+
pub unsafe trait VaArgSafe: Copy + sealed::Sealed {}
328337

329338
crate::cfg_select! {
330339
any(target_arch = "avr", target_arch = "msp430") => {
@@ -381,6 +390,12 @@ const _: () = {
381390
va_arg_safe_check::<crate::ffi::c_ulonglong>();
382391

383392
va_arg_safe_check::<crate::ffi::c_double>();
393+
394+
va_arg_safe_check::<*const crate::ffi::c_void>();
395+
va_arg_safe_check::<*mut crate::ffi::c_void>();
396+
397+
va_arg_safe_check::<*const crate::ffi::c_char>();
398+
va_arg_safe_check::<*mut crate::ffi::c_char>();
384399
};
385400

386401
impl<'f> VaList<'f> {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ add-minicore
2+
//@ compile-flags: -Copt-level=3
3+
#![feature(c_variadic)]
4+
#![crate_type = "lib"]
5+
6+
unsafe extern "C" {
7+
fn g(v: *mut u8);
8+
}
9+
10+
#[unsafe(no_mangle)]
11+
pub unsafe extern "C" fn f(mut args: ...) {
12+
// CHECK: call void @llvm.va_start
13+
unsafe { g(&raw mut args as *mut u8) }
14+
// We expect one call to the LLVM va_end from our desugaring of `...`. The `Drop` implementation
15+
// should only call the rust va_end intrinsic, which is a no-op.
16+
//
17+
// CHECK: call void @llvm.va_end
18+
// CHECK-NOT: call void @llvm.va_end
19+
}

0 commit comments

Comments
 (0)