mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
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:
@@ -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
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
fn read_too_many() {
|
||||
unsafe extern "C" fn variadic(mut ap: ...) {
|
||||
ap.arg::<i32>();
|
||||
ap.next_arg::<i32>();
|
||||
}
|
||||
|
||||
unsafe { variadic() };
|
||||
|
||||
@@ -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,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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn bar(_: i32, mut ap: ...) -> usize {
|
||||
ap.arg::<usize>()
|
||||
ap.next_arg::<usize>()
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -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: ...)) { }
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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>() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user