Rollup merge of #155614 - folkertdev:rename-next-arg, r=tgross35

c-variadic: rename `VaList::arg` to `VaList::next_arg`

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

per [the T-libs-api meeting](https://hackmd.io/d9D6vUnuTnCWygkc3hffEw#nominated-rusttf44930-Tracking-issue-for-RFC-2137-Support-defining-C-compatible-variadic-functions-in-Rust-c_variadic), rename `VaList::arg` to `VaList::next_arg`.
This commit is contained in:
Jonathan Brouwer
2026-04-23 09:38:23 +02:00
committed by GitHub
29 changed files with 205 additions and 196 deletions
+4 -4
View File
@@ -204,7 +204,7 @@ struct VaListInner {
/// unsafe fn vmy_func(count: u32, mut ap: VaList<'_>) -> i32 {
/// let mut sum = 0;
/// for _ in 0..count {
/// sum += unsafe { ap.arg::<i32>() };
/// sum += unsafe { ap.next_arg::<i32>() };
/// }
/// sum
/// }
@@ -213,7 +213,7 @@ struct VaListInner {
/// assert_eq!(unsafe { my_func(3, 42i32, -7i32, 20i32) }, 55);
/// ```
///
/// The [`VaList::arg`] method reads the next argument from the variable argument list,
/// The [`VaList::next_arg`] method reads the next argument from the variable argument list,
/// and is equivalent to C `va_arg`.
///
/// Cloning a `VaList` performs the equivalent of C `va_copy`, producing an independent cursor
@@ -284,7 +284,7 @@ impl<T> Sealed for *mut T {}
impl<T> Sealed for *const T {}
}
/// Types that are valid to read using [`VaList::arg`].
/// Types that are valid to read using [`VaList::next_arg`].
///
/// This trait is implemented for primitive types that have a variable argument application-binary
/// interface (ABI) on the current platform. It is always implemented for:
@@ -391,7 +391,7 @@ impl<'f> VaList<'f> {
/// are no more variable arguments, is unsound.
#[inline] // Avoid codegen when not used to help backends that don't support VaList.
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
pub const unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
pub const unsafe fn next_arg<T: VaArgSafe>(&mut self) -> T {
// SAFETY: the caller must uphold the safety contract for `va_arg`.
unsafe { va_arg(self) }
}
@@ -17,7 +17,7 @@ defined in Rust. They may be called both from within Rust and via FFI.
pub unsafe extern "C" fn add(n: usize, mut args: ...) -> usize {
let mut sum = 0;
for _ in 0..n {
sum += args.arg::<usize>();
sum += args.next_arg::<usize>();
}
sum
}
+1 -1
View File
@@ -4,7 +4,7 @@
fn read_too_many() {
unsafe extern "C" fn variadic(mut ap: ...) {
ap.arg::<i32>();
ap.next_arg::<i32>();
}
unsafe { variadic() };
+1 -1
View File
@@ -7,7 +7,7 @@ LL | unsafe { va_arg(self) }
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: stack backtrace:
0: std::ffi::VaList::<'_>::arg
0: std::ffi::VaList::<'_>::next_arg
at RUSTLIB/core/src/ffi/va_list.rs:LL:CC
1: read_too_many::variadic
at tests/fail/c-variadic.rs:LL:CC
@@ -13,8 +13,8 @@
fn main() {
unsafe extern "C" fn variadic(mut ap: ...) {
ap.arg::<i32>();
ap.arg::<i32>();
ap.next_arg::<i32>();
ap.next_arg::<i32>();
}
unsafe { variadic(0i32, (), 1i32) }
+11 -11
View File
@@ -11,7 +11,7 @@ fn ignores_arguments() {
fn echo() {
unsafe extern "C" fn variadic(mut ap: ...) -> i32 {
ap.arg()
ap.next_arg()
}
assert_eq!(unsafe { variadic(1) }, 1);
@@ -20,7 +20,7 @@ fn echo() {
fn forward_by_val() {
unsafe fn helper(mut ap: VaList) -> i32 {
ap.arg()
ap.next_arg()
}
unsafe extern "C" fn variadic(ap: ...) -> i32 {
@@ -33,7 +33,7 @@ unsafe fn helper(mut ap: VaList) -> i32 {
fn forward_by_ref() {
unsafe fn helper(ap: &mut VaList) -> i32 {
ap.arg()
ap.next_arg()
}
unsafe extern "C" fn variadic(mut ap: ...) -> i32 {
@@ -47,7 +47,7 @@ unsafe fn helper(ap: &mut VaList) -> i32 {
#[allow(improper_ctypes_definitions)]
fn nested() {
unsafe fn helper(mut ap1: VaList, mut ap2: VaList) -> (i32, i32) {
(ap1.arg(), ap2.arg())
(ap1.next_arg(), ap2.next_arg())
}
unsafe extern "C" fn variadic2(ap1: VaList, ap2: ...) -> (i32, i32) {
@@ -83,13 +83,13 @@ unsafe fn compare_c_str(ptr: *const c_char, val: &str) -> bool {
}
}
continue_if!(ap.arg::<c_double>().floor() == 3.14f64.floor());
continue_if!(ap.arg::<c_long>() == 12);
continue_if!(ap.arg::<c_int>() == 'a' as c_int);
continue_if!(ap.arg::<c_double>().floor() == 6.18f64.floor());
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Hello"));
continue_if!(ap.arg::<c_int>() == 42);
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "World"));
continue_if!(ap.next_arg::<c_double>().floor() == 3.14f64.floor());
continue_if!(ap.next_arg::<c_long>() == 12);
continue_if!(ap.next_arg::<c_int>() == 'a' as c_int);
continue_if!(ap.next_arg::<c_double>().floor() == 6.18f64.floor());
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), "Hello"));
continue_if!(ap.next_arg::<c_int>() == 42);
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), "World"));
}
unsafe {
+2 -2
View File
@@ -18,8 +18,8 @@
// CHECK: vadd.f64
// CHECK: vldr
// CHECK: vadd.f64
let b = args.arg::<f64>();
let c = args.arg::<f64>();
let b = args.next_arg::<f64>();
let c = args.next_arg::<f64>();
a + b + c
// CHECK: add sp, sp
+2 -2
View File
@@ -11,8 +11,8 @@
// CHECK: call void @llvm.lifetime.start.p0({{(i64 [0-9]+, )?}}ptr nonnull %args)
// CHECK: call void @llvm.va_start.p0(ptr nonnull %args)
let b = args.arg::<f64>();
let c = args.arg::<f64>();
let b = args.next_arg::<f64>();
let c = args.next_arg::<f64>();
a + b + c
+4 -4
View File
@@ -8,22 +8,22 @@
#[inline(always)]
unsafe extern "C" fn inline_always(mut ap: ...) -> u32 {
ap.arg::<u32>()
ap.next_arg::<u32>()
}
#[inline]
unsafe extern "C" fn inline(mut ap: ...) -> u32 {
ap.arg::<u32>()
ap.next_arg::<u32>()
}
#[inline(never)]
unsafe extern "C" fn inline_never(mut ap: ...) -> u32 {
ap.arg::<u32>()
ap.next_arg::<u32>()
}
#[cold]
unsafe extern "C" fn cold(mut ap: ...) -> u32 {
ap.arg::<u32>()
ap.next_arg::<u32>()
}
#[unsafe(no_mangle)]
+1 -1
View File
@@ -28,7 +28,7 @@
// CHECK: call void @llvm.va_start
let mut sum = 0;
for _ in 0..n {
sum += ap.arg::<i32>();
sum += ap.next_arg::<i32>();
}
sum
// CHECK: call void @llvm.va_end
+1 -1
View File
@@ -70,7 +70,7 @@ pub unsafe fn not_inlined_c_variadic() {
let mut s = 0;
let mut i = 0;
while i != n {
s += vs.arg::<u32>();
s += vs.next_arg::<u32>();
i += 1;
}
s
+1 -1
View File
@@ -9,7 +9,7 @@
}
pub unsafe extern "C" fn bar(_: i32, mut ap: ...) -> usize {
ap.arg::<usize>()
ap.next_arg::<usize>()
}
fn main() {}
+2 -1
View File
@@ -11,7 +11,8 @@ extern "C" {
unsafe fn foo(x: i32, va1: ...);
}
unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::<usize>() }
unsafe extern "C" fn bar(_: i32, mut va2: ...)
-> usize { va2.next_arg::<usize>() }
fn main() {
fn g1(_: extern "C" fn(_: u8, va: ...)) { }
+13 -5
View File
@@ -9,7 +9,7 @@
}
pub unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize {
va2.arg::<usize>()
va2.next_arg::<usize>()
}
fn main() {
@@ -21,9 +21,17 @@ fn g4(_: extern "C" fn(u8, _: ...)) {}
fn g5(_: extern "C" fn(va: ...)) {}
fn g6(_: extern "C" fn(_: ...)) {}
_ = { unsafe extern "C" fn f1(_: u8, va: ...) {} };
_ = { unsafe extern "C" fn f2(_: u8, _: ...) {} };
_ = {
unsafe extern "C" fn f1(_: u8, va: ...) {}
};
_ = {
unsafe extern "C" fn f2(_: u8, _: ...) {}
};
_ = { unsafe extern "C" fn f5(va: ...) {} };
_ = { unsafe extern "C" fn f6(_: ...) {} };
_ = {
unsafe extern "C" fn f5(va: ...) {}
};
_ = {
unsafe extern "C" fn f6(_: ...) {}
};
}
@@ -17,59 +17,59 @@ unsafe fn compare_c_str(ptr: *const c_char, val: &CStr) -> bool {
#[unsafe(no_mangle)]
pub unsafe extern "C" fn check_list_0(mut ap: VaList) -> usize {
continue_if!(ap.arg::<c_longlong>() == 1);
continue_if!(ap.arg::<c_int>() == 2);
continue_if!(ap.arg::<c_longlong>() == 3);
continue_if!(ap.next_arg::<c_longlong>() == 1);
continue_if!(ap.next_arg::<c_int>() == 2);
continue_if!(ap.next_arg::<c_longlong>() == 3);
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn check_list_1(mut ap: VaList) -> usize {
continue_if!(ap.arg::<c_int>() == -1);
continue_if!(ap.arg::<c_int>() == 'A' as c_int);
continue_if!(ap.arg::<c_int>() == '4' as c_int);
continue_if!(ap.arg::<c_int>() == ';' as c_int);
continue_if!(ap.arg::<c_int>() == 0x32);
continue_if!(ap.arg::<i32>() == 0x10000001);
continue_if!(compare_c_str(ap.arg::<*const c_char>(), c"Valid!"));
continue_if!(ap.next_arg::<c_int>() == -1);
continue_if!(ap.next_arg::<c_int>() == 'A' as c_int);
continue_if!(ap.next_arg::<c_int>() == '4' as c_int);
continue_if!(ap.next_arg::<c_int>() == ';' as c_int);
continue_if!(ap.next_arg::<c_int>() == 0x32);
continue_if!(ap.next_arg::<i32>() == 0x10000001);
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), c"Valid!"));
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn check_list_2(mut ap: VaList) -> usize {
continue_if!(ap.arg::<c_double>() == 3.14);
continue_if!(ap.arg::<c_long>() == 12);
continue_if!(ap.arg::<c_int>() == 'a' as c_int);
continue_if!(ap.arg::<c_double>() == 6.28);
continue_if!(compare_c_str(ap.arg::<*const c_char>(), c"Hello"));
continue_if!(ap.arg::<c_int>() == 42);
continue_if!(compare_c_str(ap.arg::<*const c_char>(), c"World"));
continue_if!(ap.next_arg::<c_double>() == 3.14);
continue_if!(ap.next_arg::<c_long>() == 12);
continue_if!(ap.next_arg::<c_int>() == 'a' as c_int);
continue_if!(ap.next_arg::<c_double>() == 6.28);
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), c"Hello"));
continue_if!(ap.next_arg::<c_int>() == 42);
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), c"World"));
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn check_list_copy_0(mut ap: VaList) -> usize {
continue_if!(ap.arg::<c_double>() == 6.28);
continue_if!(ap.arg::<c_int>() == 16);
continue_if!(ap.arg::<c_int>() == 'A' as c_int);
continue_if!(compare_c_str(ap.arg::<*const c_char>(), c"Skip Me!"));
continue_if!(ap.next_arg::<c_double>() == 6.28);
continue_if!(ap.next_arg::<c_int>() == 16);
continue_if!(ap.next_arg::<c_int>() == 'A' as c_int);
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), c"Skip Me!"));
let mut ap = ap.clone();
if compare_c_str(ap.arg::<*const c_char>(), c"Correct") { 0 } else { 0xff }
if compare_c_str(ap.next_arg::<*const c_char>(), c"Correct") { 0 } else { 0xff }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn check_varargs_0(_: c_int, mut ap: ...) -> usize {
continue_if!(ap.arg::<c_int>() == 42);
continue_if!(compare_c_str(ap.arg::<*const c_char>(), c"Hello, World!"));
continue_if!(ap.next_arg::<c_int>() == 42);
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), c"Hello, World!"));
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn check_varargs_1(_: c_int, mut ap: ...) -> usize {
continue_if!(ap.arg::<c_double>() == 3.14);
continue_if!(ap.arg::<c_long>() == 12);
continue_if!(ap.arg::<c_int>() == 'A' as c_int);
continue_if!(ap.arg::<c_longlong>() == 1);
continue_if!(ap.next_arg::<c_double>() == 3.14);
continue_if!(ap.next_arg::<c_long>() == 12);
continue_if!(ap.next_arg::<c_int>() == 'A' as c_int);
continue_if!(ap.next_arg::<c_longlong>() == 1);
0
}
@@ -80,65 +80,65 @@ unsafe fn compare_c_str(ptr: *const c_char, val: &CStr) -> bool {
#[unsafe(no_mangle)]
pub unsafe extern "C" fn check_varargs_3(_: c_int, mut ap: ...) -> usize {
continue_if!(ap.arg::<c_int>() == 1);
continue_if!(ap.arg::<c_int>() == 2);
continue_if!(ap.arg::<c_int>() == 3);
continue_if!(ap.arg::<c_int>() == 4);
continue_if!(ap.arg::<c_int>() == 5);
continue_if!(ap.arg::<c_int>() == 6);
continue_if!(ap.arg::<c_int>() == 7);
continue_if!(ap.arg::<c_int>() == 8);
continue_if!(ap.arg::<c_int>() == 9);
continue_if!(ap.arg::<c_int>() == 10);
continue_if!(ap.next_arg::<c_int>() == 1);
continue_if!(ap.next_arg::<c_int>() == 2);
continue_if!(ap.next_arg::<c_int>() == 3);
continue_if!(ap.next_arg::<c_int>() == 4);
continue_if!(ap.next_arg::<c_int>() == 5);
continue_if!(ap.next_arg::<c_int>() == 6);
continue_if!(ap.next_arg::<c_int>() == 7);
continue_if!(ap.next_arg::<c_int>() == 8);
continue_if!(ap.next_arg::<c_int>() == 9);
continue_if!(ap.next_arg::<c_int>() == 10);
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn check_varargs_4(_: c_double, mut ap: ...) -> usize {
continue_if!(ap.arg::<c_double>() == 1.0);
continue_if!(ap.arg::<c_double>() == 2.0);
continue_if!(ap.arg::<c_double>() == 3.0);
continue_if!(ap.arg::<c_double>() == 4.0);
continue_if!(ap.arg::<c_double>() == 5.0);
continue_if!(ap.arg::<c_double>() == 6.0);
continue_if!(ap.arg::<c_double>() == 7.0);
continue_if!(ap.arg::<c_double>() == 8.0);
continue_if!(ap.arg::<c_double>() == 9.0);
continue_if!(ap.arg::<c_double>() == 10.0);
continue_if!(ap.arg::<c_double>() == 11.0);
continue_if!(ap.arg::<c_double>() == 12.0);
continue_if!(ap.arg::<c_double>() == 13.0);
continue_if!(ap.next_arg::<c_double>() == 1.0);
continue_if!(ap.next_arg::<c_double>() == 2.0);
continue_if!(ap.next_arg::<c_double>() == 3.0);
continue_if!(ap.next_arg::<c_double>() == 4.0);
continue_if!(ap.next_arg::<c_double>() == 5.0);
continue_if!(ap.next_arg::<c_double>() == 6.0);
continue_if!(ap.next_arg::<c_double>() == 7.0);
continue_if!(ap.next_arg::<c_double>() == 8.0);
continue_if!(ap.next_arg::<c_double>() == 9.0);
continue_if!(ap.next_arg::<c_double>() == 10.0);
continue_if!(ap.next_arg::<c_double>() == 11.0);
continue_if!(ap.next_arg::<c_double>() == 12.0);
continue_if!(ap.next_arg::<c_double>() == 13.0);
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn check_varargs_5(_: c_int, mut ap: ...) -> usize {
continue_if!(ap.arg::<c_double>() == 1.0);
continue_if!(ap.arg::<c_int>() == 1);
continue_if!(ap.arg::<c_double>() == 2.0);
continue_if!(ap.arg::<c_int>() == 2);
continue_if!(ap.arg::<c_double>() == 3.0);
continue_if!(ap.arg::<c_int>() == 3);
continue_if!(ap.arg::<c_double>() == 4.0);
continue_if!(ap.arg::<c_int>() == 4);
continue_if!(ap.arg::<c_int>() == 5);
continue_if!(ap.arg::<c_double>() == 5.0);
continue_if!(ap.arg::<c_int>() == 6);
continue_if!(ap.arg::<c_double>() == 6.0);
continue_if!(ap.arg::<c_int>() == 7);
continue_if!(ap.arg::<c_double>() == 7.0);
continue_if!(ap.arg::<c_int>() == 8);
continue_if!(ap.arg::<c_double>() == 8.0);
continue_if!(ap.arg::<c_int>() == 9);
continue_if!(ap.arg::<c_double>() == 9.0);
continue_if!(ap.arg::<c_int>() == 10);
continue_if!(ap.arg::<c_double>() == 10.0);
continue_if!(ap.arg::<c_int>() == 11);
continue_if!(ap.arg::<c_double>() == 11.0);
continue_if!(ap.arg::<c_int>() == 12);
continue_if!(ap.arg::<c_double>() == 12.0);
continue_if!(ap.arg::<c_int>() == 13);
continue_if!(ap.arg::<c_double>() == 13.0);
continue_if!(ap.next_arg::<c_double>() == 1.0);
continue_if!(ap.next_arg::<c_int>() == 1);
continue_if!(ap.next_arg::<c_double>() == 2.0);
continue_if!(ap.next_arg::<c_int>() == 2);
continue_if!(ap.next_arg::<c_double>() == 3.0);
continue_if!(ap.next_arg::<c_int>() == 3);
continue_if!(ap.next_arg::<c_double>() == 4.0);
continue_if!(ap.next_arg::<c_int>() == 4);
continue_if!(ap.next_arg::<c_int>() == 5);
continue_if!(ap.next_arg::<c_double>() == 5.0);
continue_if!(ap.next_arg::<c_int>() == 6);
continue_if!(ap.next_arg::<c_double>() == 6.0);
continue_if!(ap.next_arg::<c_int>() == 7);
continue_if!(ap.next_arg::<c_double>() == 7.0);
continue_if!(ap.next_arg::<c_int>() == 8);
continue_if!(ap.next_arg::<c_double>() == 8.0);
continue_if!(ap.next_arg::<c_int>() == 9);
continue_if!(ap.next_arg::<c_double>() == 9.0);
continue_if!(ap.next_arg::<c_int>() == 10);
continue_if!(ap.next_arg::<c_double>() == 10.0);
continue_if!(ap.next_arg::<c_int>() == 11);
continue_if!(ap.next_arg::<c_double>() == 11.0);
continue_if!(ap.next_arg::<c_int>() == 12);
continue_if!(ap.next_arg::<c_double>() == 12.0);
continue_if!(ap.next_arg::<c_int>() == 13);
continue_if!(ap.next_arg::<c_double>() == 13.0);
0
}
+6 -6
View File
@@ -28,20 +28,20 @@
// Advance one pair in the copy before checking
let mut ap2 = ap.clone();
let _ = ap2.arg::<u64>();
let _ = ap2.arg::<f64>();
let _ = ap2.next_arg::<u64>();
let _ = ap2.next_arg::<f64>();
assert_eq!(rust_valist_interesting_average(2, ap2) as i64, 50);
// Advance one pair in the original
let _ = ap.arg::<u64>();
let _ = ap.arg::<f64>();
let _ = ap.next_arg::<u64>();
let _ = ap.next_arg::<f64>();
let ap2 = ap.clone();
assert_eq!(rust_valist_interesting_average(2, ap2) as i64, 50);
let mut ap2 = ap.clone();
let _ = ap2.arg::<u64>();
let _ = ap2.arg::<f64>();
let _ = ap2.next_arg::<u64>();
let _ = ap2.next_arg::<f64>();
assert_eq!(rust_valist_interesting_average(2, ap2) as i64, 70);
}
+5 -5
View File
@@ -13,12 +13,12 @@ fn main() {
unsafe extern "C" fn variadic(mut ap1: ...) {
let mut ap2 = ap1.clone();
assert_eq!(ap1.arg::<i32>(), 1);
assert_eq!(ap2.arg::<i32>(), 1);
assert_eq!(ap1.next_arg::<i32>(), 1);
assert_eq!(ap2.next_arg::<i32>(), 1);
assert_eq!(ap2.arg::<i32>(), 2);
assert_eq!(ap1.arg::<i32>(), 2);
assert_eq!(ap2.next_arg::<i32>(), 2);
assert_eq!(ap1.next_arg::<i32>(), 2);
drop(ap1);
assert_eq!(ap2.arg::<i32>(), 3);
assert_eq!(ap2.next_arg::<i32>(), 3);
}
+5 -5
View File
@@ -7,23 +7,23 @@
impl S {
unsafe extern "C" fn associated_function(mut ap: ...) -> i32 {
unsafe { ap.arg() }
unsafe { ap.next_arg() }
}
unsafe extern "C" fn method_owned(self, mut ap: ...) -> i32 {
self.0 + unsafe { ap.arg::<i32>() }
self.0 + unsafe { ap.next_arg::<i32>() }
}
unsafe extern "C" fn method_ref(&self, mut ap: ...) -> i32 {
self.0 + unsafe { ap.arg::<i32>() }
self.0 + unsafe { ap.next_arg::<i32>() }
}
unsafe extern "C" fn method_mut(&mut self, mut ap: ...) -> i32 {
self.0 + unsafe { ap.arg::<i32>() }
self.0 + unsafe { ap.next_arg::<i32>() }
}
unsafe extern "C" fn fat_pointer(self: Box<Self>, mut ap: ...) -> i32 {
self.0 + unsafe { ap.arg::<i32>() }
self.0 + unsafe { ap.next_arg::<i32>() }
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ trait Trait {
fn get(&self) -> u64;
unsafe extern "C" fn dyn_method_ref(&self, mut ap: ...) -> u64 {
self.get() + unsafe { ap.arg::<u64>() }
self.get() + unsafe { ap.next_arg::<u64>() }
}
}
+3 -3
View File
@@ -10,11 +10,11 @@
#[allow(improper_ctypes_definitions)]
const unsafe extern "C" fn variadic<T: VaArgSafe>(mut ap: ...) -> (T, T) {
let x = ap.arg::<T>();
let x = ap.next_arg::<T>();
// Intersperse a small type to test alignment logic. A `u32` (i.e. `c_uint`) is the smallest
// type that implements `VaArgSafe`: smaller types would automatically be promoted.
assert!(ap.arg::<u32>() == 0xAAAA_AAAA);
let y = ap.arg::<T>();
assert!(ap.next_arg::<u32>() == 0xAAAA_AAAA);
let y = ap.next_arg::<T>();
(x, y)
}
@@ -25,8 +25,8 @@ fn main() {
//
// #[unsafe(no_mangle)]
// unsafe extern "C" fn variadic(a: f64, mut args: ...) -> f64 {
// let b = args.arg::<f64>();
// let c = args.arg::<f64>();
// let b = args.next_arg::<f64>();
// let c = args.next_arg::<f64>();
//
// a + b + c
// }
@@ -24,8 +24,8 @@ fn main() {
//
// #[unsafe(no_mangle)]
// unsafe extern "C" fn variadic(a: u32, mut args: ...) -> u32 {
// let b = args.arg::<u32>();
// let c = args.arg::<u32>();
// let b = args.next_arg::<u32>();
// let c = args.next_arg::<u32>();
//
// a + b + c
// }
+7 -7
View File
@@ -7,11 +7,11 @@
impl Struct {
unsafe extern "C" fn associated_function(mut ap: ...) -> i32 {
unsafe { ap.arg() }
unsafe { ap.next_arg() }
}
unsafe extern "C" fn method(&self, mut ap: ...) -> i32 {
self.0 + unsafe { ap.arg::<i32>() }
self.0 + unsafe { ap.next_arg::<i32>() }
}
}
@@ -19,23 +19,23 @@ trait Trait: Sized {
fn get(&self) -> i32;
unsafe extern "C" fn trait_associated_function(mut ap: ...) -> i32 {
unsafe { ap.arg() }
unsafe { ap.next_arg() }
}
unsafe extern "C" fn trait_method_owned(self, mut ap: ...) -> i32 {
self.get() + unsafe { ap.arg::<i32>() }
self.get() + unsafe { ap.next_arg::<i32>() }
}
unsafe extern "C" fn trait_method_ref(&self, mut ap: ...) -> i32 {
self.get() + unsafe { ap.arg::<i32>() }
self.get() + unsafe { ap.next_arg::<i32>() }
}
unsafe extern "C" fn trait_method_mut(&mut self, mut ap: ...) -> i32 {
self.get() + unsafe { ap.arg::<i32>() }
self.get() + unsafe { ap.next_arg::<i32>() }
}
unsafe extern "C" fn trait_fat_pointer(self: Box<Self>, mut ap: ...) -> i32 {
self.get() + unsafe { ap.arg::<i32>() }
self.get() + unsafe { ap.next_arg::<i32>() }
}
}
+3 -3
View File
@@ -4,16 +4,16 @@
// In rust (and C23 and above) `...` can be the only argument.
unsafe extern "C" fn only_dot_dot_dot(mut ap: ...) -> i32 {
unsafe { ap.arg() }
unsafe { ap.next_arg() }
}
unsafe extern "C-unwind" fn abi_c_unwind(mut ap: ...) -> i32 {
unsafe { ap.arg() }
unsafe { ap.next_arg() }
}
#[allow(improper_ctypes_definitions)]
unsafe extern "C" fn mix_int_float(mut ap: ...) -> (i64, f64, *const i32, f64) {
(ap.arg(), ap.arg(), ap.arg(), ap.arg())
(ap.next_arg(), ap.next_arg(), ap.next_arg(), ap.next_arg())
}
fn main() {
@@ -13,7 +13,7 @@
let mut i = N;
while i > 0 {
i -= 1;
let _ = ap.arg::<i32>();
let _ = ap.next_arg::<i32>();
}
}
@@ -34,7 +34,7 @@ unsafe fn read_too_many() {
}
const unsafe extern "C" fn read_as<T: core::ffi::VaArgSafe>(mut ap: ...) -> T {
ap.arg::<T>()
ap.next_arg::<T>()
}
unsafe fn read_cast() {
@@ -72,7 +72,7 @@ fn use_after_free() {
unsafe {
let ap = helper(1, 2, 3);
let mut ap = std::mem::transmute::<_, VaList>(ap);
ap.arg::<i32>();
ap.next_arg::<i32>();
//~^ ERROR memory access failed: ALLOC0 has been freed, so this pointer is dangling [E0080]
}
};
@@ -82,12 +82,12 @@ fn manual_copy_drop() {
const unsafe extern "C" fn helper(ap: ...) {
// A copy created using Clone is valid, and can be used to read arguments.
let mut copy = ap.clone();
assert!(copy.arg::<i32>() == 1i32);
assert!(copy.next_arg::<i32>() == 1i32);
let mut copy: VaList = unsafe { std::mem::transmute_copy(&ap) };
// Using the copy is actually fine.
let _ = copy.arg::<i32>();
let _ = copy.next_arg::<i32>();
drop(copy);
// But then using the original is UB.
@@ -103,7 +103,7 @@ fn manual_copy_forget() {
let mut copy: VaList = unsafe { std::mem::transmute_copy(&ap) };
// Using the copy is actually fine.
let _ = copy.arg::<i32>();
let _ = copy.next_arg::<i32>();
std::mem::forget(copy);
// The read (via `copy`) deallocated the original allocation.
@@ -119,8 +119,8 @@ fn manual_copy_read() {
let mut copy: VaList = unsafe { std::mem::transmute_copy(&ap) };
// Reading from `ap` after reading from `copy` is UB.
let _ = copy.arg::<i32>();
let _ = ap.arg::<i32>();
let _ = copy.next_arg::<i32>();
let _ = ap.next_arg::<i32>();
}
const { unsafe { helper(1, 2, 3) } };
@@ -7,9 +7,9 @@ LL | const { read_n::<1>() }
note: inside `read_n::<1>`
--> $DIR/c-variadic-fail.rs:16:17
|
LL | let _ = ap.arg::<i32>();
| ^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::arg::<i32>`
LL | let _ = ap.next_arg::<i32>();
| ^^^^^^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::next_arg::<i32>`
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
note: erroneous constant encountered
@@ -35,9 +35,9 @@ LL | const { read_n::<2>(1) }
note: inside `read_n::<2>`
--> $DIR/c-variadic-fail.rs:16:17
|
LL | let _ = ap.arg::<i32>();
| ^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::arg::<i32>`
LL | let _ = ap.next_arg::<i32>();
| ^^^^^^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::next_arg::<i32>`
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
note: erroneous constant encountered
@@ -63,9 +63,9 @@ LL | const { read_as::<u32>(1i32) };
note: inside `read_as::<u32>`
--> $DIR/c-variadic-fail.rs:37:5
|
LL | ap.arg::<T>()
| ^^^^^^^^^^^^^
note: inside `VaList::<'_>::arg::<u32>`
LL | ap.next_arg::<T>()
| ^^^^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::next_arg::<u32>`
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
note: erroneous constant encountered
@@ -91,9 +91,9 @@ LL | const { read_as::<i32>(1u32) };
note: inside `read_as::<i32>`
--> $DIR/c-variadic-fail.rs:37:5
|
LL | ap.arg::<T>()
| ^^^^^^^^^^^^^
note: inside `VaList::<'_>::arg::<i32>`
LL | ap.next_arg::<T>()
| ^^^^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::next_arg::<i32>`
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
note: erroneous constant encountered
@@ -119,9 +119,9 @@ LL | const { read_as::<i32>(1u64) };
note: inside `read_as::<i32>`
--> $DIR/c-variadic-fail.rs:37:5
|
LL | ap.arg::<T>()
| ^^^^^^^^^^^^^
note: inside `VaList::<'_>::arg::<i32>`
LL | ap.next_arg::<T>()
| ^^^^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::next_arg::<i32>`
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
note: erroneous constant encountered
@@ -147,9 +147,9 @@ LL | const { read_as::<f64>(1i32) };
note: inside `read_as::<f64>`
--> $DIR/c-variadic-fail.rs:37:5
|
LL | ap.arg::<T>()
| ^^^^^^^^^^^^^
note: inside `VaList::<'_>::arg::<f64>`
LL | ap.next_arg::<T>()
| ^^^^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::next_arg::<f64>`
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
note: erroneous constant encountered
@@ -175,9 +175,9 @@ LL | const { read_as::<*const u8>(1i32) };
note: inside `read_as::<*const u8>`
--> $DIR/c-variadic-fail.rs:37:5
|
LL | ap.arg::<T>()
| ^^^^^^^^^^^^^
note: inside `VaList::<'_>::arg::<*const u8>`
LL | ap.next_arg::<T>()
| ^^^^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::next_arg::<*const u8>`
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
note: erroneous constant encountered
@@ -197,10 +197,10 @@ LL | const { read_as::<*const u8>(1i32) };
error[E0080]: memory access failed: ALLOC0 has been freed, so this pointer is dangling
--> $DIR/c-variadic-fail.rs:75:13
|
LL | ap.arg::<i32>();
| ^^^^^^^^^^^^^^^ evaluation of `use_after_free::{constant#0}` failed inside this call
LL | ap.next_arg::<i32>();
| ^^^^^^^^^^^^^^^^^^^^ evaluation of `use_after_free::{constant#0}` failed inside this call
|
note: inside `VaList::<'_>::arg::<i32>`
note: inside `VaList::<'_>::next_arg::<i32>`
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
note: erroneous constant encountered
@@ -300,9 +300,9 @@ LL | const { unsafe { helper(1, 2, 3) } };
note: inside `manual_copy_read::helper`
--> $DIR/c-variadic-fail.rs:123:17
|
LL | let _ = ap.arg::<i32>();
| ^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::arg::<i32>`
LL | let _ = ap.next_arg::<i32>();
| ^^^^^^^^^^^^^^^^^^^^
note: inside `VaList::<'_>::next_arg::<i32>`
--> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL
note: erroneous constant encountered
+11 -11
View File
@@ -21,7 +21,7 @@ fn ignores_arguments() {
fn echo() {
const unsafe extern "C" fn variadic(mut ap: ...) -> i32 {
ap.arg()
ap.next_arg()
}
assert_eq!(unsafe { variadic(1) }, 1);
@@ -35,7 +35,7 @@ fn echo() {
fn forward_by_val() {
const unsafe fn helper(mut ap: VaList) -> i32 {
ap.arg()
ap.next_arg()
}
const unsafe extern "C" fn variadic(ap: ...) -> i32 {
@@ -53,7 +53,7 @@ fn forward_by_val() {
fn forward_by_ref() {
const unsafe fn helper(ap: &mut VaList) -> i32 {
ap.arg()
ap.next_arg()
}
const unsafe extern "C" fn variadic(mut ap: ...) -> i32 {
@@ -72,7 +72,7 @@ fn forward_by_ref() {
#[allow(improper_ctypes_definitions)]
fn nested() {
const unsafe fn helper(mut ap1: VaList, mut ap2: VaList) -> (i32, i32) {
(ap1.arg(), ap2.arg())
(ap1.next_arg(), ap2.next_arg())
}
const unsafe extern "C" fn variadic2(ap1: VaList, ap2: ...) -> (i32, i32) {
@@ -112,13 +112,13 @@ macro_rules! continue_if {
}
}
continue_if!(ap.arg::<c_double>().floor() == 3.14f64.floor());
continue_if!(ap.arg::<c_long>() == 12);
continue_if!(ap.arg::<c_int>() == 'a' as c_int);
continue_if!(ap.arg::<c_double>().floor() == 6.18f64.floor());
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Hello"));
continue_if!(ap.arg::<c_int>() == 42);
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "World"));
continue_if!(ap.next_arg::<c_double>().floor() == 3.14f64.floor());
continue_if!(ap.next_arg::<c_long>() == 12);
continue_if!(ap.next_arg::<c_int>() == 'a' as c_int);
continue_if!(ap.next_arg::<c_double>().floor() == 6.18f64.floor());
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), "Hello"));
continue_if!(ap.next_arg::<c_int>() == 42);
continue_if!(compare_c_str(ap.next_arg::<*const c_char>(), "World"));
}
unsafe {
+1 -1
View File
@@ -3,7 +3,7 @@
#![allow(unused)]
unsafe extern "C" fn foo(mut ap: ...) -> u32 {
ap.arg::<u32>()
ap.next_arg::<u32>()
}
extern "C" fn bar() -> u32 {
+1 -1
View File
@@ -8,7 +8,7 @@
trait Trait {
unsafe extern "C" fn foo(x: i32, y: i32, mut ap: ...) -> i32 {
x + y + ap.arg::<i32>() + ap.arg::<i32>()
x + y + ap.next_arg::<i32>() + ap.next_arg::<i32>()
}
}