Skip to content

Commit 236d65b

Browse files
authored
Merge branch 'master' into enum-subscript
2 parents 8a9145e + 707cad8 commit 236d65b

17 files changed

Lines changed: 546 additions & 35 deletions

cpp2rust/converter/converter.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,11 @@ bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
891891
}
892892
}
893893

894+
EmitRustStructOrUnion(decl);
895+
} else if (decl->isUnion()) {
896+
if (!record_decls_.MarkDefined(GetRecordName(decl))) {
897+
return false;
898+
}
894899
EmitRustStructOrUnion(decl);
895900
} else {
896901
// FIXME: improve error handling
@@ -2084,8 +2089,7 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
20842089
bool dest_pointee_const =
20852090
expr->getType()->getPointeeType().isConstQualified();
20862091
Convert(sub_expr);
2087-
if (clang::isa<clang::StringLiteral>(sub_expr) ||
2088-
clang::isa<clang::PredefinedExpr>(sub_expr)) {
2092+
if (IsStringLiteralExpr(sub_expr)) {
20892093
StrCat(".as_ptr()");
20902094
if (!dest_pointee_const) {
20912095
StrCat(".cast_mut()");

cpp2rust/converter/converter_lib.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ bool IsUnionArrayMember(const clang::Expr *base) {
140140
return false;
141141
}
142142

143+
bool IsStringLiteralExpr(const clang::Expr *expr) {
144+
const auto *stripped = expr->IgnoreParens()->IgnoreImplicit();
145+
return clang::isa<clang::StringLiteral>(stripped) ||
146+
clang::isa<clang::PredefinedExpr>(stripped);
147+
}
148+
143149
bool IsUserDefinedDecl(const clang::Decl *decl) {
144150
const auto &ctx = decl->getASTContext();
145151
const auto &src_mgr = ctx.getSourceManager();

cpp2rust/converter/converter_lib.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ bool IsInMainFile(const clang::Decl *decl);
4242

4343
bool IsUnionArrayMember(const clang::Expr *base);
4444

45+
bool IsStringLiteralExpr(const clang::Expr *expr);
46+
4547
bool IsUserDefinedDecl(const clang::Decl *decl);
4648

4749
bool RefersToUserDefinedDecl(const clang::Expr *expr);

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,14 @@ bool ConverterRefCount::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
417417
return false;
418418
}
419419

420+
bool ConverterRefCount::VisitOffsetOfExpr(clang::OffsetOfExpr *expr) {
421+
clang::Expr::EvalResult result;
422+
ENSURE(expr->EvaluateAsInt(result, ctx_));
423+
StrCat(std::format("{}_usize", result.Val.getInt().getZExtValue()));
424+
computed_expr_type_ = ComputedExprType::FreshValue;
425+
return false;
426+
}
427+
420428
void ConverterRefCount::ConvertOrdAndPartialOrdTraits(
421429
const clang::CXXRecordDecl *decl, const clang::FunctionDecl *op) {
422430
std::string first_branch, second_branch, first_return, second_return;
@@ -1170,6 +1178,8 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
11701178
->getPointeeType()
11711179
->getAsArrayTypeUnsafe()
11721180
->getElementType())));
1181+
} else if (IsStringLiteralExpr(sub_expr)) {
1182+
StrCat(std::format("{}.to_any()", ConvertFreshPointer(sub_expr)));
11731183
} else {
11741184
StrCat(std::format("({} as {}).to_any()", ConvertFreshPointer(sub_expr),
11751185
ToString(sub_expr->getType())));
@@ -1209,9 +1219,9 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
12091219
Convert(sub_expr);
12101220
return false;
12111221
}
1212-
if (clang::isa<clang::StringLiteral>(sub_expr) ||
1213-
clang::isa<clang::PredefinedExpr>(sub_expr)) {
1214-
StrCat(std::format("Ptr::from_string_literal({})", ToString(sub_expr)));
1222+
if (IsStringLiteralExpr(sub_expr)) {
1223+
StrCat(std::format("Ptr::from_string_literal({})",
1224+
ToString(sub_expr->IgnoreParens())));
12151225
return false;
12161226
} else {
12171227
// we need to write (var.as_pointer as Ptr<T>) because Rust isn't
@@ -1315,6 +1325,7 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
13151325
return false;
13161326
}
13171327
if (expr->getCastKind() == clang::CK_NullToPointer) {
1328+
PushConversionKind push(*this, ConversionKind::Unboxed);
13181329
StrCat(GetDefaultAsString(expr->getType()));
13191330
computed_expr_type_ = ComputedExprType::FreshPointer;
13201331
return false;
@@ -2230,10 +2241,16 @@ void ConverterRefCount::ConvertArraySubscript(clang::Expr *base,
22302241

22312242
{
22322243
PushParen paren(*this, is_inner_boxed);
2233-
StrCat(std::format("({} as {}).offset({})",
2234-
ToString(base->IgnoreImplicit()),
2235-
ConvertPtrType(base->IgnoreImplicit()->getType()),
2236-
ConvertSubscriptIndex(idx)));
2244+
if (IsStringLiteralExpr(base)) {
2245+
StrCat(std::format("Ptr::from_string_literal({}).offset({})",
2246+
ToString(base->IgnoreParens()->IgnoreImplicit()),
2247+
ConvertSubscriptIndex(idx)));
2248+
} else {
2249+
StrCat(std::format("({} as {}).offset({})",
2250+
ToString(base->IgnoreImplicit()),
2251+
ConvertPtrType(base->IgnoreImplicit()->getType()),
2252+
ConvertSubscriptIndex(idx)));
2253+
}
22372254

22382255
if (is_inner_boxed) {
22392256
StrCat(GetPointerDerefSuffix(type), ".as_pointer()");

cpp2rust/converter/models/converter_refcount.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class ConverterRefCount final : public Converter {
2828

2929
bool VisitCXXRecordDecl(clang::CXXRecordDecl *decl) override;
3030

31+
bool VisitOffsetOfExpr(clang::OffsetOfExpr *expr) override;
32+
3133
void EmitRustUnion(clang::RecordDecl *decl) override;
3234

3335
bool EmitsReprCForRecords() const override { return false; }

tests/unit/offsetof.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,37 @@
1-
// no-compile: refcount
21
#include <assert.h>
32
#include <stddef.h>
43
#include <stdint.h>
4+
#include <string.h>
55

66
struct Layout {
77
uint8_t a;
88
uint32_t b;
99
uint16_t c;
1010
};
1111

12-
struct Inner {
13-
uint16_t x;
14-
uint32_t y;
15-
};
16-
17-
struct Outer {
18-
uint8_t pad;
19-
struct Inner inner;
12+
struct Frame {
13+
uint16_t tag;
14+
char body[64];
2015
};
2116

2217
int main(void) {
2318
assert(offsetof(struct Layout, a) == 0);
2419
assert(offsetof(struct Layout, b) == 4);
2520
assert(offsetof(struct Layout, c) == 8);
2621

27-
assert(offsetof(struct Outer, inner.y) == 8);
28-
2922
struct Layout v = {0};
3023
v.b = 0xDEADBEEF;
3124
unsigned char *base = (unsigned char *)&v;
3225
uint32_t *bp = (uint32_t *)(base + offsetof(struct Layout, b));
3326
assert(*bp == 0xDEADBEEF);
3427

28+
*(uint32_t *)(base + offsetof(struct Layout, b)) = 0x12345678;
29+
assert(v.b == 0x12345678);
30+
31+
const char *text = "example-body";
32+
size_t len = strlen(text) + 1;
33+
size_t total = offsetof(struct Frame, body) + len;
34+
assert(total == 2 + len);
35+
3536
return 0;
3637
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
#[derive(Default)]
10+
pub struct Layout {
11+
pub a: Value<u8>,
12+
pub b: Value<u32>,
13+
pub c: Value<u16>,
14+
}
15+
impl Clone for Layout {
16+
fn clone(&self) -> Self {
17+
let mut this = Self {
18+
a: Rc::new(RefCell::new((*self.a.borrow()))),
19+
b: Rc::new(RefCell::new((*self.b.borrow()))),
20+
c: Rc::new(RefCell::new((*self.c.borrow()))),
21+
};
22+
this
23+
}
24+
}
25+
impl ByteRepr for Layout {
26+
fn byte_size() -> usize {
27+
12
28+
}
29+
fn to_bytes(&self, buf: &mut [u8]) {
30+
(*self.a.borrow()).to_bytes(&mut buf[0..1]);
31+
(*self.b.borrow()).to_bytes(&mut buf[4..8]);
32+
(*self.c.borrow()).to_bytes(&mut buf[8..10]);
33+
}
34+
fn from_bytes(buf: &[u8]) -> Self {
35+
Self {
36+
a: Rc::new(RefCell::new(<u8>::from_bytes(&buf[0..1]))),
37+
b: Rc::new(RefCell::new(<u32>::from_bytes(&buf[4..8]))),
38+
c: Rc::new(RefCell::new(<u16>::from_bytes(&buf[8..10]))),
39+
}
40+
}
41+
}
42+
#[derive()]
43+
pub struct Frame {
44+
pub tag: Value<u16>,
45+
pub body: Value<Box<[u8]>>,
46+
}
47+
impl Clone for Frame {
48+
fn clone(&self) -> Self {
49+
let mut this = Self {
50+
tag: Rc::new(RefCell::new((*self.tag.borrow()))),
51+
body: Rc::new(RefCell::new((*self.body.borrow()).clone())),
52+
};
53+
this
54+
}
55+
}
56+
impl Default for Frame {
57+
fn default() -> Self {
58+
Frame {
59+
tag: <Value<u16>>::default(),
60+
body: Rc::new(RefCell::new(
61+
(0..64).map(|_| <u8>::default()).collect::<Box<[u8]>>(),
62+
)),
63+
}
64+
}
65+
}
66+
impl ByteRepr for Frame {
67+
fn byte_size() -> usize {
68+
66
69+
}
70+
fn to_bytes(&self, buf: &mut [u8]) {
71+
(*self.tag.borrow()).to_bytes(&mut buf[0..2]);
72+
(*self.body.borrow()).to_bytes(&mut buf[2..66]);
73+
}
74+
fn from_bytes(buf: &[u8]) -> Self {
75+
Self {
76+
tag: Rc::new(RefCell::new(<u16>::from_bytes(&buf[0..2]))),
77+
body: Rc::new(RefCell::new(<Box<[u8]>>::from_bytes(&buf[2..66]))),
78+
}
79+
}
80+
}
81+
pub fn main() {
82+
std::process::exit(main_0());
83+
}
84+
fn main_0() -> i32 {
85+
assert!((0_usize == 0_usize));
86+
assert!((4_usize == 4_usize));
87+
assert!((8_usize == 8_usize));
88+
let v: Value<Layout> = Rc::new(RefCell::new(Layout {
89+
a: Rc::new(RefCell::new(0_u8)),
90+
b: Rc::new(RefCell::new(<u32>::default())),
91+
c: Rc::new(RefCell::new(<u16>::default())),
92+
}));
93+
(*(*v.borrow()).b.borrow_mut()) = 3735928559_u32;
94+
let base: Value<Ptr<u8>> = Rc::new(RefCell::new((v.as_pointer()).reinterpret_cast::<u8>()));
95+
let bp: Value<Ptr<u32>> = Rc::new(RefCell::new(
96+
((*base.borrow()).offset((4_usize) as isize)).reinterpret_cast::<u32>(),
97+
));
98+
assert!((((*bp.borrow()).read()) == 3735928559_u32));
99+
((*base.borrow()).offset((4_usize) as isize))
100+
.reinterpret_cast::<u32>()
101+
.write(305419896_u32);
102+
assert!(((*(*v.borrow()).b.borrow()) == 305419896_u32));
103+
let text: Value<Ptr<u8>> = Rc::new(RefCell::new(Ptr::from_string_literal(b"example-body")));
104+
let len: Value<usize> = Rc::new(RefCell::new(
105+
((*text.borrow()).to_string_iterator().count()).wrapping_add(1_usize),
106+
));
107+
let total: Value<usize> = Rc::new(RefCell::new(
108+
((2_usize as u64).wrapping_add(((*len.borrow()) as u64)) as usize),
109+
));
110+
assert!(((*total.borrow()) == (2_usize).wrapping_add((*len.borrow()))));
111+
return 0;
112+
}

tests/unit/out/refcount/ptr_cast_init.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,30 @@ fn main_0() -> i32 {
7474
let hp: Value<Ptr<header>> = Rc::new(RefCell::new((h.as_pointer())));
7575
let v: Value<Ptr<view>> = Rc::new(RefCell::new((*hp.borrow()).reinterpret_cast::<view>()));
7676
assert!(((((*(*(*v.borrow()).upgrade().deref()).tag.borrow()) == 7) as i32) != 0));
77+
let data: Value<Box<[u8]>> = Rc::new(RefCell::new(Box::from(*b"hi\0")));
78+
let vp: Value<AnyPtr> = Rc::new(RefCell::new(
79+
((data.as_pointer() as Ptr<u8>) as Ptr<u8>).to_any(),
80+
));
81+
let n: Value<i32> = Rc::new(RefCell::new(2));
82+
let sel: Value<Ptr<u8>> = Rc::new(RefCell::new(
83+
if ((((*n.borrow()) < 100) as i32) != 0) {
84+
(*vp.borrow()).clone()
85+
} else {
86+
(AnyPtr::default())
87+
}
88+
.reinterpret_cast::<u8>(),
89+
));
90+
assert!((((!((*sel.borrow()).is_null())) as i32) != 0));
91+
assert!(
92+
((((((*sel.borrow()).offset((0) as isize).read()) as i32) == ('h' as i32)) as i32) != 0)
93+
);
94+
(*n.borrow_mut()) = 200;
95+
(*sel.borrow_mut()) = if ((((*n.borrow()) < 100) as i32) != 0) {
96+
(*vp.borrow()).clone()
97+
} else {
98+
(AnyPtr::default())
99+
}
100+
.reinterpret_cast::<u8>();
101+
assert!(((((*sel.borrow()).is_null()) as i32) != 0));
77102
return 0;
78103
}

0 commit comments

Comments
 (0)