Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions cpp2rust/converter/models/converter_refcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
23 changes: 12 additions & 11 deletions tests/unit/offsetof.cpp
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
// no-compile: refcount
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

struct Layout {
uint8_t a;
uint32_t b;
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) {
assert(offsetof(struct Layout, a) == 0);
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;
}
112 changes: 112 additions & 0 deletions tests/unit/out/refcount/offsetof.rs
Original file line number Diff line number Diff line change
@@ -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<u8>,
pub b: Value<u32>,
pub c: Value<u16>,
}
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(<u8>::from_bytes(&buf[0..1]))),
b: Rc::new(RefCell::new(<u32>::from_bytes(&buf[4..8]))),
c: Rc::new(RefCell::new(<u16>::from_bytes(&buf[8..10]))),
}
}
}
#[derive()]
pub struct Frame {
pub tag: Value<u16>,
pub body: Value<Box<[u8]>>,
}
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: <Value<u16>>::default(),
body: Rc::new(RefCell::new(
(0..64).map(|_| <u8>::default()).collect::<Box<[u8]>>(),
)),
}
}
}
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(<u16>::from_bytes(&buf[0..2]))),
body: Rc::new(RefCell::new(<Box<[u8]>>::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<Layout> = Rc::new(RefCell::new(Layout {
a: Rc::new(RefCell::new(0_u8)),
b: Rc::new(RefCell::new(<u32>::default())),
c: Rc::new(RefCell::new(<u16>::default())),
}));
(*(*v.borrow()).b.borrow_mut()) = 3735928559_u32;
let base: Value<Ptr<u8>> = Rc::new(RefCell::new((v.as_pointer()).reinterpret_cast::<u8>()));
let bp: Value<Ptr<u32>> = Rc::new(RefCell::new(
((*base.borrow()).offset((4_usize) as isize)).reinterpret_cast::<u32>(),
));
assert!((((*bp.borrow()).read()) == 3735928559_u32));
((*base.borrow()).offset((4_usize) as isize))
.reinterpret_cast::<u32>()
.write(305419896_u32);
assert!(((*(*v.borrow()).b.borrow()) == 305419896_u32));
let text: Value<Ptr<u8>> = Rc::new(RefCell::new(Ptr::from_string_literal(b"example-body")));
let len: Value<usize> = Rc::new(RefCell::new(
((*text.borrow()).to_string_iterator().count()).wrapping_add(1_usize),
));
let total: Value<usize> = 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;
}
28 changes: 18 additions & 10 deletions tests/unit/out/unsafe/offsetof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
Expand All @@ -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;
}
Loading