diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 483c7fdb..a346cb0d 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -417,6 +417,14 @@ bool ConverterRefCount::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) { return false; } +bool ConverterRefCount::VisitOffsetOfExpr(clang::OffsetOfExpr *expr) { + clang::Expr::EvalResult result; + ENSURE(expr->EvaluateAsInt(result, ctx_)); + StrCat(std::format("{}_usize", result.Val.getInt().getZExtValue())); + computed_expr_type_ = ComputedExprType::FreshValue; + return false; +} + void ConverterRefCount::ConvertOrdAndPartialOrdTraits( const clang::CXXRecordDecl *decl, const clang::FunctionDecl *op) { std::string first_branch, second_branch, first_return, second_return; diff --git a/cpp2rust/converter/models/converter_refcount.h b/cpp2rust/converter/models/converter_refcount.h index e58853e1..4b29299b 100644 --- a/cpp2rust/converter/models/converter_refcount.h +++ b/cpp2rust/converter/models/converter_refcount.h @@ -28,6 +28,8 @@ class ConverterRefCount final : public Converter { bool VisitCXXRecordDecl(clang::CXXRecordDecl *decl) override; + bool VisitOffsetOfExpr(clang::OffsetOfExpr *expr) override; + void EmitRustUnion(clang::RecordDecl *decl) override; bool EmitsReprCForRecords() const override { return false; } diff --git a/tests/unit/offsetof.cpp b/tests/unit/offsetof.cpp index 16b99134..f4e9309b 100644 --- a/tests/unit/offsetof.cpp +++ b/tests/unit/offsetof.cpp @@ -1,7 +1,7 @@ -// no-compile: refcount #include #include #include +#include struct Layout { uint8_t a; @@ -9,14 +9,9 @@ struct Layout { uint16_t c; }; -struct Inner { - uint16_t x; - uint32_t y; -}; - -struct Outer { - uint8_t pad; - struct Inner inner; +struct Frame { + uint16_t tag; + char body[64]; }; int main(void) { @@ -24,13 +19,19 @@ int main(void) { assert(offsetof(struct Layout, b) == 4); assert(offsetof(struct Layout, c) == 8); - assert(offsetof(struct Outer, inner.y) == 8); - struct Layout v = {0}; v.b = 0xDEADBEEF; unsigned char *base = (unsigned char *)&v; uint32_t *bp = (uint32_t *)(base + offsetof(struct Layout, b)); assert(*bp == 0xDEADBEEF); + *(uint32_t *)(base + offsetof(struct Layout, b)) = 0x12345678; + assert(v.b == 0x12345678); + + const char *text = "example-body"; + size_t len = strlen(text) + 1; + size_t total = offsetof(struct Frame, body) + len; + assert(total == 2 + len); + return 0; } diff --git a/tests/unit/out/refcount/offsetof.rs b/tests/unit/out/refcount/offsetof.rs new file mode 100644 index 00000000..ffb50b8b --- /dev/null +++ b/tests/unit/out/refcount/offsetof.rs @@ -0,0 +1,112 @@ +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 Layout { + pub a: Value, + pub b: Value, + pub c: Value, +} +impl Clone for Layout { + fn clone(&self) -> Self { + let mut this = Self { + a: Rc::new(RefCell::new((*self.a.borrow()))), + b: Rc::new(RefCell::new((*self.b.borrow()))), + c: Rc::new(RefCell::new((*self.c.borrow()))), + }; + this + } +} +impl ByteRepr for Layout { + fn byte_size() -> usize { + 12 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.a.borrow()).to_bytes(&mut buf[0..1]); + (*self.b.borrow()).to_bytes(&mut buf[4..8]); + (*self.c.borrow()).to_bytes(&mut buf[8..10]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + a: Rc::new(RefCell::new(::from_bytes(&buf[0..1]))), + b: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + c: Rc::new(RefCell::new(::from_bytes(&buf[8..10]))), + } + } +} +#[derive()] +pub struct Frame { + pub tag: Value, + pub body: Value>, +} +impl Clone for Frame { + fn clone(&self) -> Self { + let mut this = Self { + tag: Rc::new(RefCell::new((*self.tag.borrow()))), + body: Rc::new(RefCell::new((*self.body.borrow()).clone())), + }; + this + } +} +impl Default for Frame { + fn default() -> Self { + Frame { + tag: >::default(), + body: Rc::new(RefCell::new( + (0..64).map(|_| ::default()).collect::>(), + )), + } + } +} +impl ByteRepr for Frame { + fn byte_size() -> usize { + 66 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.tag.borrow()).to_bytes(&mut buf[0..2]); + (*self.body.borrow()).to_bytes(&mut buf[2..66]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + tag: Rc::new(RefCell::new(::from_bytes(&buf[0..2]))), + body: Rc::new(RefCell::new(>::from_bytes(&buf[2..66]))), + } + } +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + assert!((0_usize == 0_usize)); + assert!((4_usize == 4_usize)); + assert!((8_usize == 8_usize)); + let v: Value = Rc::new(RefCell::new(Layout { + a: Rc::new(RefCell::new(0_u8)), + b: Rc::new(RefCell::new(::default())), + c: Rc::new(RefCell::new(::default())), + })); + (*(*v.borrow()).b.borrow_mut()) = 3735928559_u32; + let base: Value> = Rc::new(RefCell::new((v.as_pointer()).reinterpret_cast::())); + let bp: Value> = Rc::new(RefCell::new( + ((*base.borrow()).offset((4_usize) as isize)).reinterpret_cast::(), + )); + assert!((((*bp.borrow()).read()) == 3735928559_u32)); + ((*base.borrow()).offset((4_usize) as isize)) + .reinterpret_cast::() + .write(305419896_u32); + assert!(((*(*v.borrow()).b.borrow()) == 305419896_u32)); + let text: Value> = Rc::new(RefCell::new(Ptr::from_string_literal(b"example-body"))); + let len: Value = Rc::new(RefCell::new( + ((*text.borrow()).to_string_iterator().count()).wrapping_add(1_usize), + )); + let total: Value = Rc::new(RefCell::new( + ((2_usize as u64).wrapping_add(((*len.borrow()) as u64)) as usize), + )); + assert!(((*total.borrow()) == (2_usize).wrapping_add((*len.borrow())))); + return 0; +} diff --git a/tests/unit/out/unsafe/offsetof.rs b/tests/unit/out/unsafe/offsetof.rs index 1562f269..560e0415 100644 --- a/tests/unit/out/unsafe/offsetof.rs +++ b/tests/unit/out/unsafe/offsetof.rs @@ -14,16 +14,18 @@ pub struct Layout { pub c: u16, } #[repr(C)] -#[derive(Copy, Clone, Default)] -pub struct Inner { - pub x: u16, - pub y: u32, +#[derive(Copy, Clone)] +pub struct Frame { + pub tag: u16, + pub body: [libc::c_char; 64], } -#[repr(C)] -#[derive(Copy, Clone, Default)] -pub struct Outer { - pub pad: u8, - pub inner: Inner, +impl Default for Frame { + fn default() -> Self { + Frame { + tag: 0_u16, + body: [(0 as libc::c_char); 64], + } + } } pub fn main() { unsafe { @@ -34,7 +36,6 @@ unsafe fn main_0() -> i32 { assert!(((::std::mem::offset_of!(Layout, a)) == (0_usize))); assert!(((::std::mem::offset_of!(Layout, b)) == (4_usize))); assert!(((::std::mem::offset_of!(Layout, c)) == (8_usize))); - assert!(((::std::mem::offset_of!(Outer, inner.y)) == (8_usize))); let mut v: Layout = Layout { a: 0_u8, b: 0_u32, @@ -45,5 +46,12 @@ unsafe fn main_0() -> i32 { let mut bp: *mut u32 = ((base.offset((::std::mem::offset_of!(Layout, b)) as isize)) as *mut u32); assert!(((*bp) == (3735928559_u32))); + (*((base.offset((::std::mem::offset_of!(Layout, b)) as isize)) as *mut u32)) = 305419896_u32; + assert!(((v.b) == (305419896_u32))); + let mut text: *const libc::c_char = c"example-body".as_ptr(); + let mut len: usize = (libc::strlen(text)).wrapping_add(1_usize); + let mut total: usize = + ((::std::mem::offset_of!(Frame, body) as u64).wrapping_add((len as u64)) as usize); + assert!(((total) == ((2_usize).wrapping_add(len)))); return 0; }