diff --git a/libcc2rs/src/compat.rs b/libcc2rs/src/compat.rs index 38873938..2729e810 100644 --- a/libcc2rs/src/compat.rs +++ b/libcc2rs/src/compat.rs @@ -1,7 +1,12 @@ // Copyright (c) 2022-present INESC-ID. // Distributed under the MIT license that can be found in the LICENSE file. +use std::cell::RefCell; use std::ffi::c_void; +use std::rc::Rc; + +use crate::rc::Ptr; +use crate::{AsPointer, Value}; unsafe extern "C" { #[cfg(target_os = "linux")] @@ -40,6 +45,14 @@ pub unsafe fn malloc_usable_size(ptr: *mut c_void) -> usize { /// # Safety /// /// Invokes the platform specific errno. -pub unsafe fn cpp2rust_errno() -> *mut i32 { +pub unsafe fn cpp2rust_errno_unsafe() -> *mut i32 { unsafe { platform_errno_location() } } + +thread_local! { + static ERRNO: Value = Rc::new(RefCell::new(0)); +} + +pub fn cpp2rust_errno() -> Ptr { + ERRNO.with(AsPointer::as_pointer) +} diff --git a/rules/errno/tgt_refcount.rs b/rules/errno/tgt_refcount.rs new file mode 100644 index 00000000..8220480e --- /dev/null +++ b/rules/errno/tgt_refcount.rs @@ -0,0 +1,8 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +use libcc2rs::*; + +fn f1() -> Ptr { + libcc2rs::cpp2rust_errno() +} diff --git a/rules/errno/tgt_unsafe.rs b/rules/errno/tgt_unsafe.rs index 57796bc2..1e2cc13f 100644 --- a/rules/errno/tgt_unsafe.rs +++ b/rules/errno/tgt_unsafe.rs @@ -2,5 +2,5 @@ // Distributed under the MIT license that can be found in the LICENSE file. unsafe fn f1() -> *mut i32 { - libcc2rs::cpp2rust_errno() + libcc2rs::cpp2rust_errno_unsafe() } diff --git a/rules/src/modules.rs b/rules/src/modules.rs index 53112eed..e873ed19 100644 --- a/rules/src/modules.rs +++ b/rules/src/modules.rs @@ -40,6 +40,8 @@ pub mod deque_tgt_refcount; pub mod deque_tgt_unsafe; #[path = r#"../dirent/tgt_unsafe.rs"#] pub mod dirent_tgt_unsafe; +#[path = r#"../errno/tgt_refcount.rs"#] +pub mod errno_tgt_refcount; #[path = r#"../errno/tgt_unsafe.rs"#] pub mod errno_tgt_unsafe; #[path = r#"../eventfd/tgt_unsafe.rs"#] diff --git a/tests/unit/errno.c b/tests/unit/errno.c index 8a0be0bf..9f9f0e3f 100644 --- a/tests/unit/errno.c +++ b/tests/unit/errno.c @@ -1,4 +1,4 @@ -// no-compile: refcount +// panic: refcount #include #include #include diff --git a/tests/unit/out/refcount/errno.rs b/tests/unit/out/refcount/errno.rs new file mode 100644 index 00000000..653f5b96 --- /dev/null +++ b/tests/unit/out/refcount/errno.rs @@ -0,0 +1,60 @@ +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}; +pub fn test_errno_0() { + libcc2rs::cpp2rust_errno().write(0); + assert!(((((libcc2rs::cpp2rust_errno().read()) == 0) as i32) != 0)); + libcc2rs::cpp2rust_errno().write(42); + assert!(((((libcc2rs::cpp2rust_errno().read()) == 42) as i32) != 0)); + let saved: Value = Rc::new(RefCell::new((libcc2rs::cpp2rust_errno().read()))); + assert!(((((*saved.borrow()) == 42) as i32) != 0)); + libcc2rs::cpp2rust_errno().write(0); +} +pub fn test_errno_preserved_across_strdup_1() { + libcc2rs::cpp2rust_errno().write(99); + let d: Value> = Rc::new(RefCell::new(libcc2rs::strdup_refcount( + Ptr::from_string_literal(b"hello"), + ))); + assert!((((!((*d.borrow()).is_null())) as i32) != 0)); + assert!(((((libcc2rs::cpp2rust_errno().read()) == 99) as i32) != 0)); + libcc2rs::free_refcount(((*d.borrow()).clone() as Ptr).to_any()); + libcc2rs::cpp2rust_errno().write(0); +} +pub fn test_errno_from_fseek_2() { + libcc2rs::cpp2rust_errno().write(0); + let r: Value = Rc::new(RefCell::new( + if (match 0 { + 0 => libcc2rs::cin().with_mut(|__v: &mut ::std::fs::File| { + __v.seek(std::io::SeekFrom::Start(0_i64 as u64)) + }), + 1 => libcc2rs::cin() + .with_mut(|__v: &mut ::std::fs::File| __v.seek(std::io::SeekFrom::Current(0_i64))), + 2 => libcc2rs::cin() + .with_mut(|__v: &mut ::std::fs::File| __v.seek(std::io::SeekFrom::End(0_i64))), + _ => Err(std::io::Error::other("unsupported whence for fseek.")), + }) + .is_ok() + { + 0 + } else { + -1 + }, + )); + assert!(((((*r.borrow()) == -1_i32) as i32) != 0)); + assert!(((((libcc2rs::cpp2rust_errno().read()) == 29) as i32) != 0)); + libcc2rs::cpp2rust_errno().write(0); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + ({ test_errno_0() }); + ({ test_errno_preserved_across_strdup_1() }); + ({ test_errno_from_fseek_2() }); + return 0; +} diff --git a/tests/unit/out/unsafe/errno.rs b/tests/unit/out/unsafe/errno.rs index 5a5e67a0..0e36fbbb 100644 --- a/tests/unit/out/unsafe/errno.rs +++ b/tests/unit/out/unsafe/errno.rs @@ -7,29 +7,29 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn test_errno_0() { - (*libcc2rs::cpp2rust_errno()) = 0; - assert!(((((*libcc2rs::cpp2rust_errno()) == (0)) as i32) != 0)); - (*libcc2rs::cpp2rust_errno()) = 42; - assert!(((((*libcc2rs::cpp2rust_errno()) == (42)) as i32) != 0)); - let mut saved: i32 = (*libcc2rs::cpp2rust_errno()); + (*libcc2rs::cpp2rust_errno_unsafe()) = 0; + assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (0)) as i32) != 0)); + (*libcc2rs::cpp2rust_errno_unsafe()) = 42; + assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (42)) as i32) != 0)); + let mut saved: i32 = (*libcc2rs::cpp2rust_errno_unsafe()); assert!(((((saved) == (42)) as i32) != 0)); - (*libcc2rs::cpp2rust_errno()) = 0; + (*libcc2rs::cpp2rust_errno_unsafe()) = 0; } pub unsafe fn test_errno_preserved_across_strdup_1() { - (*libcc2rs::cpp2rust_errno()) = 99; + (*libcc2rs::cpp2rust_errno_unsafe()) = 99; let mut d: *mut libc::c_char = libcc2rs::strdup_unsafe((c"hello".as_ptr().cast_mut()).cast_const()); assert!((((!((d).is_null())) as i32) != 0)); - assert!(((((*libcc2rs::cpp2rust_errno()) == (99)) as i32) != 0)); + assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (99)) as i32) != 0)); libcc2rs::free_unsafe((d as *mut libc::c_char as *mut ::libc::c_void)); - (*libcc2rs::cpp2rust_errno()) = 0; + (*libcc2rs::cpp2rust_errno_unsafe()) = 0; } pub unsafe fn test_errno_from_fseek_2() { - (*libcc2rs::cpp2rust_errno()) = 0; + (*libcc2rs::cpp2rust_errno_unsafe()) = 0; let mut r: i32 = libc::fseek(libcc2rs::stdin_unsafe(), 0_i64 as ::libc::c_long, 0); assert!(((((r) == (-1_i32)) as i32) != 0)); - assert!(((((*libcc2rs::cpp2rust_errno()) == (29)) as i32) != 0)); - (*libcc2rs::cpp2rust_errno()) = 0; + assert!(((((*libcc2rs::cpp2rust_errno_unsafe()) == (29)) as i32) != 0)); + (*libcc2rs::cpp2rust_errno_unsafe()) = 0; } pub fn main() { unsafe {