Skip to content

Commit a41899c

Browse files
authored
Handle array to pointer decay in union accessor (#211)
1 parent 4b1deff commit a41899c

9 files changed

Lines changed: 646 additions & 7 deletions

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -503,10 +503,13 @@ void ConverterRefCount::EmitRustUnion(clang::RecordDecl *decl) {
503503
{
504504
PushBrace impl_brace(*this);
505505
for (auto *field : decl->fields()) {
506+
PushConversionKind push(*this, ConversionKind::FullRefCount);
507+
std::string storage_ty = ToString(field->getType());
508+
Unwrap(storage_ty, "Value<", ">");
506509
StrCat(std::format(
507510
"pub fn {}(&self) -> Ptr<{}> {{ (self.__bytes.as_pointer() "
508511
"as Ptr<u8>).reinterpret_cast() }}",
509-
GetNamedDeclAsString(field), Mapper::Map(field->getType())));
512+
GetNamedDeclAsString(field), storage_ty));
510513
}
511514
}
512515

@@ -1499,6 +1502,7 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) {
14991502
}
15001503

15011504
void ConverterRefCount::ConvertUnionMemberAccessor(clang::MemberExpr *expr) {
1505+
auto member = expr->getMemberDecl();
15021506
std::string str;
15031507
{
15041508
Buffer buf(*this);
@@ -1509,15 +1513,24 @@ void ConverterRefCount::ConvertUnionMemberAccessor(clang::MemberExpr *expr) {
15091513
str += "()";
15101514

15111515
if (isAddrOf()) {
1512-
StrCat(str);
1516+
if (member->getType()->isArrayType()) {
1517+
PushConversionKind push(*this, ConversionKind::Unboxed);
1518+
StrCat(std::format(
1519+
"{}.reinterpret_cast::<{}>()", str,
1520+
ToString(
1521+
member->getType()->getAsArrayTypeUnsafe()->getElementType())));
1522+
} else {
1523+
StrCat(str);
1524+
}
15131525
computed_expr_type_ = ComputedExprType::Pointer;
15141526
return;
15151527
}
1528+
15161529
if (isLValue()) {
15171530
pending_deref_.set(str);
15181531
return;
15191532
}
1520-
StrCat(DerefPtrExpr(str, expr->getMemberDecl()->getType()));
1533+
StrCat(DerefPtrExpr(str, member->getType()));
15211534
}
15221535

15231536
bool ConverterRefCount::VisitMemberExpr(clang::MemberExpr *expr) {
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
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()]
10+
pub struct shape_a {
11+
pub code: Value<u16>,
12+
pub pad: Value<Box<[u8]>>,
13+
}
14+
impl Default for shape_a {
15+
fn default() -> Self {
16+
shape_a {
17+
code: <Value<u16>>::default(),
18+
pad: Rc::new(RefCell::new(
19+
(0..14).map(|_| <u8>::default()).collect::<Box<[u8]>>(),
20+
)),
21+
}
22+
}
23+
}
24+
impl ByteRepr for shape_a {
25+
fn byte_size() -> usize {
26+
16
27+
}
28+
fn to_bytes(&self, buf: &mut [u8]) {
29+
(*self.code.borrow()).to_bytes(&mut buf[0..2]);
30+
(*self.pad.borrow()).to_bytes(&mut buf[2..16]);
31+
}
32+
fn from_bytes(buf: &[u8]) -> Self {
33+
Self {
34+
code: Rc::new(RefCell::new(<u16>::from_bytes(&buf[0..2]))),
35+
pad: Rc::new(RefCell::new(<Box<[u8]>>::from_bytes(&buf[2..16]))),
36+
}
37+
}
38+
}
39+
#[derive()]
40+
pub struct shape_b {
41+
pub code: Value<u16>,
42+
pub lo: Value<u16>,
43+
pub mid: Value<u32>,
44+
pub fill: Value<Box<[u8]>>,
45+
pub tail: Value<u32>,
46+
}
47+
impl Default for shape_b {
48+
fn default() -> Self {
49+
shape_b {
50+
code: <Value<u16>>::default(),
51+
lo: <Value<u16>>::default(),
52+
mid: <Value<u32>>::default(),
53+
fill: Rc::new(RefCell::new(
54+
(0..16).map(|_| <u8>::default()).collect::<Box<[u8]>>(),
55+
)),
56+
tail: <Value<u32>>::default(),
57+
}
58+
}
59+
}
60+
impl ByteRepr for shape_b {
61+
fn byte_size() -> usize {
62+
28
63+
}
64+
fn to_bytes(&self, buf: &mut [u8]) {
65+
(*self.code.borrow()).to_bytes(&mut buf[0..2]);
66+
(*self.lo.borrow()).to_bytes(&mut buf[2..4]);
67+
(*self.mid.borrow()).to_bytes(&mut buf[4..8]);
68+
(*self.fill.borrow()).to_bytes(&mut buf[8..24]);
69+
(*self.tail.borrow()).to_bytes(&mut buf[24..28]);
70+
}
71+
fn from_bytes(buf: &[u8]) -> Self {
72+
Self {
73+
code: Rc::new(RefCell::new(<u16>::from_bytes(&buf[0..2]))),
74+
lo: Rc::new(RefCell::new(<u16>::from_bytes(&buf[2..4]))),
75+
mid: Rc::new(RefCell::new(<u32>::from_bytes(&buf[4..8]))),
76+
fill: Rc::new(RefCell::new(<Box<[u8]>>::from_bytes(&buf[8..24]))),
77+
tail: Rc::new(RefCell::new(<u32>::from_bytes(&buf[24..28]))),
78+
}
79+
}
80+
}
81+
pub struct anon_0 {
82+
__bytes: Value<Box<[u8]>>,
83+
}
84+
impl anon_0 {
85+
pub fn a(&self) -> Ptr<shape_a> {
86+
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
87+
}
88+
pub fn b(&self) -> Ptr<shape_b> {
89+
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
90+
}
91+
pub fn raw_(&self) -> Ptr<Box<[u8]>> {
92+
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
93+
}
94+
}
95+
impl Clone for anon_0 {
96+
fn clone(&self) -> Self {
97+
anon_0 {
98+
__bytes: Rc::new(RefCell::new(self.__bytes.borrow().clone())),
99+
}
100+
}
101+
}
102+
impl Default for anon_0 {
103+
fn default() -> Self {
104+
anon_0 {
105+
__bytes: Rc::new(RefCell::new(Box::from([0u8; 64]))),
106+
}
107+
}
108+
}
109+
impl ByteRepr for anon_0 {
110+
fn byte_size() -> usize {
111+
64
112+
}
113+
fn to_bytes(&self, buf: &mut [u8]) {
114+
buf.copy_from_slice(&self.__bytes.borrow());
115+
}
116+
fn from_bytes(buf: &[u8]) -> Self {
117+
anon_0 {
118+
__bytes: Rc::new(RefCell::new(Box::from(buf))),
119+
}
120+
}
121+
}
122+
#[derive(Default)]
123+
pub struct Container {
124+
pub len: Value<u32>,
125+
pub u: Value<anon_0>,
126+
}
127+
impl ByteRepr for Container {
128+
fn byte_size() -> usize {
129+
68
130+
}
131+
fn to_bytes(&self, buf: &mut [u8]) {
132+
(*self.len.borrow()).to_bytes(&mut buf[0..4]);
133+
(*self.u.borrow()).to_bytes(&mut buf[4..68]);
134+
}
135+
fn from_bytes(buf: &[u8]) -> Self {
136+
Self {
137+
len: Rc::new(RefCell::new(<u32>::from_bytes(&buf[0..4]))),
138+
u: Rc::new(RefCell::new(<anon_0>::from_bytes(&buf[4..68]))),
139+
}
140+
}
141+
}
142+
pub fn main() {
143+
std::process::exit(main_0());
144+
}
145+
fn main_0() -> i32 {
146+
let c: Value<Container> = <Value<Container>>::default();
147+
{
148+
((c.as_pointer()) as Ptr<Container>)
149+
.to_any()
150+
.memset((0) as u8, 68usize as usize);
151+
((c.as_pointer()) as Ptr<Container>).to_any().clone()
152+
};
153+
(*(*(*(*c.borrow()).u.borrow()).a().upgrade().deref())
154+
.code
155+
.borrow_mut()) = 10_u16;
156+
(*(*c.borrow()).len.borrow_mut()) = (28usize as u32);
157+
(*(*(((*(*c.borrow()).u.borrow()).a())
158+
.clone()
159+
.to_any()
160+
.cast::<shape_b>()
161+
.expect("ub:wrong type"))
162+
.upgrade()
163+
.deref())
164+
.tail
165+
.borrow_mut()) = 3735928559_u32;
166+
assert!(
167+
((((*(*(*(*c.borrow()).u.borrow()).b().upgrade().deref())
168+
.tail
169+
.borrow())
170+
== 3735928559_u32) as i32)
171+
!= 0)
172+
);
173+
assert!(
174+
(((((*(*(*(*c.borrow()).u.borrow()).b().upgrade().deref())
175+
.code
176+
.borrow()) as i32)
177+
== 10) as i32)
178+
!= 0)
179+
);
180+
(*(*(*(*c.borrow()).u.borrow()).b().upgrade().deref())
181+
.lo
182+
.borrow_mut()) = 8080_u16;
183+
assert!(
184+
((((((((*(*c.borrow()).u.borrow()).raw_().reinterpret_cast::<u8>())
185+
.to_strong()
186+
.as_pointer() as Ptr::<u8>)
187+
.offset((2) as isize)
188+
.read()) as i32)
189+
== 144) as i32)
190+
!= 0)
191+
);
192+
assert!(
193+
((((((((*(*c.borrow()).u.borrow()).raw_().reinterpret_cast::<u8>())
194+
.to_strong()
195+
.as_pointer() as Ptr::<u8>)
196+
.offset((3) as isize)
197+
.read()) as i32)
198+
== 31) as i32)
199+
!= 0)
200+
);
201+
return 0;
202+
}

0 commit comments

Comments
 (0)