mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
79 lines
2.3 KiB
Rust
79 lines
2.3 KiB
Rust
//@ run-pass
|
|
//@ ignore-backends: gcc
|
|
#![feature(c_variadic, const_c_variadic, const_destruct, const_raw_ptr_comparison)]
|
|
|
|
use std::ffi::*;
|
|
|
|
// In rustc we implement `va_arg` for the callee reading from a VaList, but still rely on LLVM
|
|
// for exactly how to pass c-variadic arguments and for constructing the VaList. Here we test
|
|
// that the rustc implementation works with what LLVM gives us.
|
|
|
|
#[allow(improper_ctypes_definitions)]
|
|
const unsafe extern "C" fn variadic<T: VaArgSafe>(mut ap: ...) -> (T, T) {
|
|
let x = ap.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>();
|
|
|
|
(x, y)
|
|
}
|
|
|
|
macro_rules! roundtrip {
|
|
($ty:ty, $a:expr, $b:expr) => {
|
|
const {
|
|
let a: $ty = $a;
|
|
let b: $ty = $b;
|
|
let (x, y) = variadic::<$ty>(a, 0xAAAA_AAAAu32, b);
|
|
assert!(a == x);
|
|
assert!(b == y);
|
|
}
|
|
|
|
let a: $ty = $a;
|
|
let b: $ty = $b;
|
|
assert_eq!(variadic::<$ty>(a, 0xAAAA_AAAAu32, b), (a, b))
|
|
};
|
|
}
|
|
|
|
macro_rules! roundtrip_ptr {
|
|
($ty:ty, $a:expr, $b:expr) => {
|
|
const {
|
|
let a: $ty = $a;
|
|
let b: $ty = $b;
|
|
let (x, y) = variadic::<$ty>(a, 0xAAAA_AAAAu32, b);
|
|
assert!(a.guaranteed_eq(x).unwrap());
|
|
assert!(b.guaranteed_eq(y).unwrap());
|
|
}
|
|
|
|
let a: $ty = $a;
|
|
let b: $ty = $b;
|
|
assert_eq!(variadic::<$ty>(a, 0xAAAA_AAAAu32, b), (a, b))
|
|
};
|
|
}
|
|
|
|
fn main() {
|
|
unsafe {
|
|
roundtrip!(i32, -1, -2);
|
|
roundtrip!(i64, -1, -2);
|
|
roundtrip!(isize, -1, -2);
|
|
roundtrip!(c_int, -1, -2);
|
|
roundtrip!(c_long, -1, -2);
|
|
roundtrip!(c_longlong, -1, -2);
|
|
|
|
roundtrip!(u32, 1, 2);
|
|
roundtrip!(u64, 1, 2);
|
|
roundtrip!(usize, 1, 2);
|
|
roundtrip!(c_uint, 1, 2);
|
|
roundtrip!(c_ulong, 1, 2);
|
|
roundtrip!(c_ulonglong, 1, 2);
|
|
|
|
roundtrip!(f64, 3.14, 6.28);
|
|
roundtrip!(c_double, 3.14, 6.28);
|
|
|
|
static mut A: u32 = 1u32;
|
|
static mut B: u32 = 2u32;
|
|
roundtrip_ptr!(*const u32, &raw const A, &raw const B);
|
|
roundtrip_ptr!(*mut u32, &raw mut A, &raw mut B);
|
|
}
|
|
}
|