diff --git a/libcc2rs/src/va_args.rs b/libcc2rs/src/va_args.rs index 9a4606f2..95693cbc 100644 --- a/libcc2rs/src/va_args.rs +++ b/libcc2rs/src/va_args.rs @@ -128,6 +128,15 @@ impl VaArgGet for crate::rc::Ptr { } } +impl VaArgGet for crate::rc::AnyPtr { + fn get(v: &VaArg) -> Self { + match v { + VaArg::Ptr(any) => any.clone(), + _ => panic!("VaArgGet: expected Ptr"), + } + } +} + impl From> for VaArg { fn from(v: crate::FnPtr) -> Self { VaArg::Ptr(v.to_any()) diff --git a/tests/unit/out/refcount/va_arg_void_ptr.rs b/tests/unit/out/refcount/va_arg_void_ptr.rs new file mode 100644 index 00000000..23b8ef71 --- /dev/null +++ b/tests/unit/out/refcount/va_arg_void_ptr.rs @@ -0,0 +1,128 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(Default)] +pub struct registry { + pub slot: Value, + pub level: Value, +} +impl Clone for registry { + fn clone(&self) -> Self { + Self { + slot: Rc::new(RefCell::new((*self.slot.borrow()).clone())), + level: Rc::new(RefCell::new((*self.level.borrow()).clone())), + } + } +} +impl ByteRepr for registry { + fn byte_size() -> usize { + 16 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.slot.borrow()).to_bytes(&mut buf[0..8]); + (*self.level.borrow()).to_bytes(&mut buf[8..16]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + slot: Rc::new(RefCell::new(::from_bytes(&buf[0..8]))), + level: Rc::new(RefCell::new(::from_bytes(&buf[8..16]))), + } + } +} +#[derive(Clone, Copy, PartialEq, Debug, Default)] +enum field { + #[default] + FIELD_SLOT = 0, + FIELD_LEVEL = 1, +} +impl From for field { + fn from(n: i32) -> field { + match n { + 0 => field::FIELD_SLOT, + 1 => field::FIELD_LEVEL, + _ => panic!("invalid field value: {}", n), + } + } +} +libcc2rs::impl_enum_inc_dec!(field); +impl ByteRepr for field { + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} +pub fn registry_update_0(r: Ptr, field: field, __args: &[VaArg]) -> i32 { + let r: Value> = Rc::new(RefCell::new(r)); + let field: Value = Rc::new(RefCell::new(field)); + let result: Value = Rc::new(RefCell::new(0)); + let ap: Value = Rc::new(RefCell::new(VaList::default())); + (*ap.borrow_mut()) = VaList::new(__args); + 'switch: { + let __match_cond = ((*field.borrow()) as u32); + match __match_cond { + __v if __v == ((field::FIELD_SLOT as i32) as u32) => { + (*(*(*r.borrow()).upgrade().deref()).slot.borrow_mut()) = + ((*ap.borrow_mut()).arg::()).clone(); + break 'switch; + } + __v if __v == ((field::FIELD_LEVEL as i32) as u32) => { + (*(*(*r.borrow()).upgrade().deref()).level.borrow_mut()) = + ((*ap.borrow_mut()).arg::()).clone(); + break 'switch; + } + _ => { + (*result.borrow_mut()) = 1; + break 'switch; + } + } + }; + return (*result.borrow()); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let r: Value = Rc::new(RefCell::new(registry { + slot: Rc::new(RefCell::new(AnyPtr::default())), + level: Rc::new(RefCell::new(0_i64)), + })); + let payload: Value = Rc::new(RefCell::new(7)); + assert!( + (((({ + registry_update_0( + (r.as_pointer()), + field::FIELD_SLOT, + &[(payload.as_pointer()).into()], + ) + }) == 0) as i32) + != 0) + ); + assert!( + (((({ registry_update_0((r.as_pointer()), field::FIELD_LEVEL, &[(5_i64).into(),]) }) == 0) + as i32) + != 0) + ); + assert!( + ((({ + let _lhs = (*(*r.borrow()).slot.borrow()).clone(); + _lhs == (payload.as_pointer()).to_any() + }) as i32) + != 0) + ); + assert!( + (((((*(*r.borrow()).slot.borrow()) + .reinterpret_cast::() + .read()) + == 7) as i32) + != 0) + ); + assert!(((((*(*r.borrow()).level.borrow()) == 5_i64) as i32) != 0)); + return 0; +} diff --git a/tests/unit/out/unsafe/va_arg_void_ptr.rs b/tests/unit/out/unsafe/va_arg_void_ptr.rs new file mode 100644 index 00000000..35bce556 --- /dev/null +++ b/tests/unit/out/unsafe/va_arg_void_ptr.rs @@ -0,0 +1,89 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct registry { + pub slot: *mut ::libc::c_void, + pub level: i64, +} +#[derive(Clone, Copy, PartialEq, Debug, Default)] +enum field { + #[default] + FIELD_SLOT = 0, + FIELD_LEVEL = 1, +} +impl From for field { + fn from(n: i32) -> field { + match n { + 0 => field::FIELD_SLOT, + 1 => field::FIELD_LEVEL, + _ => panic!("invalid field value: {}", n), + } + } +} +libcc2rs::impl_enum_inc_dec!(field); +pub unsafe fn registry_update_0(mut r: *mut registry, mut field: field, __args: &[VaArg]) -> i32 { + let mut result: i32 = 0; + let mut ap: VaList = VaList::default(); + ap = VaList::new(__args); + 'switch: { + let __match_cond = (field as u32); + match __match_cond { + __v if __v == ((field::FIELD_SLOT as i32) as u32) => { + (*r).slot = ap.arg::<*mut ::libc::c_void>(); + break 'switch; + } + __v if __v == ((field::FIELD_LEVEL as i32) as u32) => { + (*r).level = (ap.arg::()).clone(); + break 'switch; + } + _ => { + result = 1; + break 'switch; + } + } + }; + return result; +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut r: registry = registry { + slot: std::ptr::null_mut(), + level: 0_i64, + }; + let mut payload: i32 = 7; + assert!( + ((((unsafe { + registry_update_0( + (&mut r as *mut registry), + field::FIELD_SLOT, + &[(&mut payload as *mut i32).into()], + ) + }) == (0)) as i32) + != 0) + ); + assert!( + ((((unsafe { + registry_update_0( + (&mut r as *mut registry), + field::FIELD_LEVEL, + &[(5_i64).into()], + ) + }) == (0)) as i32) + != 0) + ); + assert!(((((r.slot) == ((&mut payload as *mut i32) as *mut ::libc::c_void)) as i32) != 0)); + assert!(((((*(r.slot as *mut i32)) == (7)) as i32) != 0)); + assert!(((((r.level) == (5_i64)) as i32) != 0)); + return 0; +} diff --git a/tests/unit/va_arg_void_ptr.c b/tests/unit/va_arg_void_ptr.c new file mode 100644 index 00000000..74baec86 --- /dev/null +++ b/tests/unit/va_arg_void_ptr.c @@ -0,0 +1,42 @@ +#include +#include + +struct registry { + void *slot; + long level; +}; + +enum field { + FIELD_SLOT, + FIELD_LEVEL, +}; + +static int registry_update(struct registry *r, enum field field, ...) { + int result = 0; + va_list ap; + va_start(ap, field); + switch (field) { + case FIELD_SLOT: + r->slot = va_arg(ap, void *); + break; + case FIELD_LEVEL: + r->level = va_arg(ap, long); + break; + default: + result = 1; + break; + } + va_end(ap); + return result; +} + +int main() { + struct registry r = {0, 0}; + int payload = 7; + assert(registry_update(&r, FIELD_SLOT, &payload) == 0); + assert(registry_update(&r, FIELD_LEVEL, 5L) == 0); + assert(r.slot == (void *)&payload); + assert(*(int *)r.slot == 7); + assert(r.level == 5); + return 0; +}