Skip to content

Commit 4b752bc

Browse files
committed
Translate offsetof
1 parent 7ee4a56 commit 4b752bc

4 files changed

Lines changed: 105 additions & 0 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3052,6 +3052,24 @@ bool Converter::VisitTypeTraitExpr(clang::TypeTraitExpr *expr) {
30523052
return false;
30533053
}
30543054

3055+
bool Converter::VisitOffsetOfExpr(clang::OffsetOfExpr *expr) {
3056+
std::string member_path;
3057+
for (unsigned i = 0; i < expr->getNumComponents(); ++i) {
3058+
const clang::OffsetOfNode &node = expr->getComponent(i);
3059+
ENSURE(node.getKind() == clang::OffsetOfNode::Field);
3060+
if (!member_path.empty()) {
3061+
member_path += '.';
3062+
}
3063+
member_path += GetNamedDeclAsString(node.getField());
3064+
}
3065+
StrCat(
3066+
std::format("::std::mem::offset_of!({}, {}) as u64",
3067+
GetUnsafeTypeAsString(expr->getTypeSourceInfo()->getType()),
3068+
member_path));
3069+
computed_expr_type_ = ComputedExprType::FreshValue;
3070+
return false;
3071+
}
3072+
30553073
bool Converter::VisitEnumDecl(clang::EnumDecl *decl) {
30563074
ENSURE(decl_ids_.insert(GetID(decl)).second);
30573075
if (Mapper::Contains(ctx_.getCanonicalTagType(decl))) {

cpp2rust/converter/converter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
349349

350350
virtual bool VisitTypeTraitExpr(clang::TypeTraitExpr *expr);
351351

352+
virtual bool VisitOffsetOfExpr(clang::OffsetOfExpr *expr);
353+
352354
virtual bool VisitEnumDecl(clang::EnumDecl *decl);
353355

354356
virtual void AddFromImpl(clang::EnumDecl *decl);

tests/unit/offsetof.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// no-compile: refcount
2+
#include <assert.h>
3+
#include <stddef.h>
4+
#include <stdint.h>
5+
6+
struct Layout {
7+
uint8_t a;
8+
uint32_t b;
9+
uint16_t c;
10+
};
11+
12+
struct Inner {
13+
uint16_t x;
14+
uint32_t y;
15+
};
16+
17+
struct Outer {
18+
uint8_t pad;
19+
struct Inner inner;
20+
};
21+
22+
int main(void) {
23+
assert(offsetof(struct Layout, a) == 0);
24+
assert(offsetof(struct Layout, b) == 4);
25+
assert(offsetof(struct Layout, c) == 8);
26+
27+
assert(offsetof(struct Outer, inner.y) == 8);
28+
29+
struct Layout v = {0};
30+
v.b = 0xDEADBEEF;
31+
unsigned char *base = (unsigned char *)&v;
32+
uint32_t *bp = (uint32_t *)(base + offsetof(struct Layout, b));
33+
assert(*bp == 0xDEADBEEF);
34+
35+
return 0;
36+
}

tests/unit/out/unsafe/offsetof.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
#[repr(C)]
10+
#[derive(Copy, Clone, Default)]
11+
pub struct Layout {
12+
pub a: u8,
13+
pub b: u32,
14+
pub c: u16,
15+
}
16+
#[repr(C)]
17+
#[derive(Copy, Clone, Default)]
18+
pub struct Inner {
19+
pub x: u16,
20+
pub y: u32,
21+
}
22+
#[repr(C)]
23+
#[derive(Copy, Clone, Default)]
24+
pub struct Outer {
25+
pub pad: u8,
26+
pub inner: Inner,
27+
}
28+
pub fn main() {
29+
unsafe {
30+
std::process::exit(main_0() as i32);
31+
}
32+
}
33+
unsafe fn main_0() -> i32 {
34+
assert!(((::std::mem::offset_of!(Layout, a) as u64) == (0_u64)));
35+
assert!(((::std::mem::offset_of!(Layout, b) as u64) == (4_u64)));
36+
assert!(((::std::mem::offset_of!(Layout, c) as u64) == (8_u64)));
37+
assert!(((::std::mem::offset_of!(Outer, inner.y) as u64) == (8_u64)));
38+
let mut v: Layout = Layout {
39+
a: 0_u8,
40+
b: 0_u32,
41+
c: 0_u16,
42+
};
43+
v.b = 3735928559_u32;
44+
let mut base: *mut u8 = ((&mut v as *mut Layout) as *mut u8);
45+
let mut bp: *mut u32 =
46+
((base.offset((::std::mem::offset_of!(Layout, b) as u64) as isize)) as *mut u32);
47+
assert!(((*bp) == (3735928559_u32)));
48+
return 0;
49+
}

0 commit comments

Comments
 (0)