Skip to content

Commit 7e67e00

Browse files
authored
Translate access of union array members as Ptr<T> instead of Ptr<Box<[T]>> (#218)
1 parent 0497100 commit 7e67e00

10 files changed

Lines changed: 146 additions & 20 deletions

cpp2rust/converter/converter_lib.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,16 @@ bool IsInMainFile(const clang::Decl *decl) {
130130
return src_mgr.isInMainFile(src_mgr.getExpansionLoc(loc));
131131
}
132132

133+
bool IsUnionArrayMember(const clang::Expr *base) {
134+
if (auto *me =
135+
clang::dyn_cast<clang::MemberExpr>(base->IgnoreParenImpCasts())) {
136+
if (auto *fd = clang::dyn_cast<clang::FieldDecl>(me->getMemberDecl())) {
137+
return fd->getParent()->isUnion() && fd->getType()->isArrayType();
138+
}
139+
}
140+
return false;
141+
}
142+
133143
bool IsUserDefinedDecl(const clang::Decl *decl) {
134144
const auto &ctx = decl->getASTContext();
135145
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
@@ -40,6 +40,8 @@ bool IsComparisonWithNullOp(const clang::BinaryOperator *expr);
4040

4141
bool IsInMainFile(const clang::Decl *decl);
4242

43+
bool IsUnionArrayMember(const clang::Expr *base);
44+
4345
bool IsUserDefinedDecl(const clang::Decl *decl);
4446

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

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ std::string ConverterRefCount::ConvertPtrType(clang::QualType type) {
378378
bool ConverterRefCount::VisitArraySubscriptExpr(
379379
clang::ArraySubscriptExpr *expr) {
380380
auto *base = expr->getBase();
381-
if (base->IgnoreCasts()->getType()->isPointerType()) {
381+
if (base->IgnoreCasts()->getType()->isPointerType() ||
382+
IsUnionArrayMember(base)) {
382383
ConvertPointerSubscript(expr);
383384
} else {
384385
if (!base->IgnoreCasts()->getType()->isArrayType()) {
@@ -504,13 +505,16 @@ void ConverterRefCount::EmitRustUnion(clang::RecordDecl *decl) {
504505
{
505506
PushBrace impl_brace(*this);
506507
for (auto *field : decl->fields()) {
507-
PushConversionKind push(*this, ConversionKind::FullRefCount);
508-
std::string storage_ty = ToString(field->getType());
509-
Unwrap(storage_ty, "Value<", ">");
508+
PushConversionKind push(*this, ConversionKind::Unboxed);
509+
auto ty =
510+
field->getType()->isArrayType()
511+
? ToString(
512+
field->getType()->getAsArrayTypeUnsafe()->getElementType())
513+
: ToString(field->getType());
510514
StrCat(std::format(
511515
"pub fn {}(&self) -> Ptr<{}> {{ (self.__bytes.as_pointer() "
512516
"as Ptr<u8>).reinterpret_cast() }}",
513-
GetNamedDeclAsString(field), storage_ty));
517+
GetNamedDeclAsString(field), ty));
514518
}
515519
}
516520

tests/unit/out/refcount/union_addrof_external.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl anon_0 {
5151
pub fn h(&self) -> Ptr<record> {
5252
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
5353
}
54-
pub fn raw_(&self) -> Ptr<Box<[u8]>> {
54+
pub fn raw_(&self) -> Ptr<u8> {
5555
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
5656
}
5757
}
@@ -187,12 +187,21 @@ fn main_0() -> i32 {
187187
!= 0)
188188
);
189189
assert!(
190-
((((((*(*c.borrow()).view.borrow()).raw_().read())[(0) as usize] as i32) == 2) as i32)
190+
(((((((*(*c.borrow()).view.borrow())
191+
.raw_()
192+
.reinterpret_cast::<u8>() as Ptr::<u8>)
193+
.offset((0) as isize)
194+
.read()) as i32)
195+
== 2) as i32)
191196
!= 0)
192197
);
193198
assert!(
194-
(((((((*(*c.borrow()).view.borrow()).raw_().read())[(3) as usize] as u8) as i32) == 80)
195-
as i32)
199+
((((((((*(*c.borrow()).view.borrow())
200+
.raw_()
201+
.reinterpret_cast::<u8>() as Ptr::<u8>)
202+
.offset((3) as isize)
203+
.read()) as u8) as i32)
204+
== 80) as i32)
196205
!= 0)
197206
);
198207
return 0;

tests/unit/out/refcount/union_cross_arm_cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl anon_0 {
8888
pub fn b(&self) -> Ptr<shape_b> {
8989
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
9090
}
91-
pub fn raw_(&self) -> Ptr<Box<[u8]>> {
91+
pub fn raw_(&self) -> Ptr<u8> {
9292
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
9393
}
9494
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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+
pub struct anon_0 {
10+
__bytes: Value<Box<[u8]>>,
11+
}
12+
impl anon_0 {
13+
pub fn bytes(&self) -> Ptr<u8> {
14+
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
15+
}
16+
pub fn aligner(&self) -> Ptr<AnyPtr> {
17+
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
18+
}
19+
}
20+
impl Clone for anon_0 {
21+
fn clone(&self) -> Self {
22+
anon_0 {
23+
__bytes: Rc::new(RefCell::new(self.__bytes.borrow().clone())),
24+
}
25+
}
26+
}
27+
impl Default for anon_0 {
28+
fn default() -> Self {
29+
anon_0 {
30+
__bytes: Rc::new(RefCell::new(Box::from([0u8; 8]))),
31+
}
32+
}
33+
}
34+
impl ByteRepr for anon_0 {
35+
fn byte_size() -> usize {
36+
8
37+
}
38+
fn to_bytes(&self, buf: &mut [u8]) {
39+
buf.copy_from_slice(&self.__bytes.borrow());
40+
}
41+
fn from_bytes(buf: &[u8]) -> Self {
42+
anon_0 {
43+
__bytes: Rc::new(RefCell::new(Box::from(buf))),
44+
}
45+
}
46+
}
47+
#[derive(Default)]
48+
pub struct node {
49+
pub next: Value<Ptr<node>>,
50+
pub x: Value<anon_0>,
51+
}
52+
impl ByteRepr for node {
53+
fn byte_size() -> usize {
54+
16
55+
}
56+
fn to_bytes(&self, buf: &mut [u8]) {
57+
(*self.next.borrow()).to_bytes(&mut buf[0..8]);
58+
(*self.x.borrow()).to_bytes(&mut buf[8..16]);
59+
}
60+
fn from_bytes(buf: &[u8]) -> Self {
61+
Self {
62+
next: Rc::new(RefCell::new(<Ptr<node>>::from_bytes(&buf[0..8]))),
63+
x: Rc::new(RefCell::new(<anon_0>::from_bytes(&buf[8..16]))),
64+
}
65+
}
66+
}
67+
pub fn main() {
68+
std::process::exit(main_0());
69+
}
70+
fn main_0() -> i32 {
71+
let n: Value<node> = <Value<node>>::default();
72+
(*(*n.borrow()).next.borrow_mut()) = Ptr::<node>::null();
73+
((*(*n.borrow()).x.borrow()).bytes().reinterpret_cast::<u8>() as Ptr<u8>)
74+
.offset((0) as isize)
75+
.write(171_u8);
76+
assert!(
77+
(((((((*(*n.borrow()).x.borrow()).bytes().reinterpret_cast::<u8>() as Ptr::<u8>)
78+
.offset((0) as isize)
79+
.read()) as i32)
80+
== 171) as i32)
81+
!= 0)
82+
);
83+
return 0;
84+
}

tests/unit/out/refcount/union_memset_memcpy.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl anon_0 {
8484
pub fn b(&self) -> Ptr<shape_b> {
8585
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
8686
}
87-
pub fn raw_(&self) -> Ptr<Box<[u8]>> {
87+
pub fn raw_(&self) -> Ptr<u8> {
8888
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
8989
}
9090
}
@@ -158,11 +158,21 @@ fn main_0() -> i32 {
158158
!= 0)
159159
);
160160
assert!(
161-
((((((*(*c.borrow()).view.borrow()).raw_().read())[(0) as usize] as i32) == 0) as i32)
161+
(((((((*(*c.borrow()).view.borrow())
162+
.raw_()
163+
.reinterpret_cast::<u8>() as Ptr::<u8>)
164+
.offset((0) as isize)
165+
.read()) as i32)
166+
== 0) as i32)
162167
!= 0)
163168
);
164169
assert!(
165-
((((((*(*c.borrow()).view.borrow()).raw_().read())[(255) as usize] as i32) == 0) as i32)
170+
(((((((*(*c.borrow()).view.borrow())
171+
.raw_()
172+
.reinterpret_cast::<u8>() as Ptr::<u8>)
173+
.offset((255) as isize)
174+
.read()) as i32)
175+
== 0) as i32)
166176
!= 0)
167177
);
168178
let src: Value<Box<[u8]>> = Rc::new(RefCell::new(Box::new([

tests/unit/out/refcount/union_nested.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl anon_0 {
4343
pub fn h(&self) -> Ptr<record> {
4444
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
4545
}
46-
pub fn raw_(&self) -> Ptr<Box<[u8]>> {
46+
pub fn raw_(&self) -> Ptr<u8> {
4747
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
4848
}
4949
}

tests/unit/out/refcount/union_struct_dual_use.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl anon_1 {
4040
pub fn inner(&self) -> Ptr<Inner> {
4141
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
4242
}
43-
pub fn raw_(&self) -> Ptr<Box<[u8]>> {
43+
pub fn raw_(&self) -> Ptr<u8> {
4444
(self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
4545
}
4646
}
@@ -114,13 +114,21 @@ fn main_0() -> i32 {
114114
!= 0)
115115
);
116116
assert!(
117-
(((((((*(*outer.borrow()).u.borrow()).raw_().read())[(0) as usize] as u8) as i32) == 3)
118-
as i32)
117+
((((((((*(*outer.borrow()).u.borrow())
118+
.raw_()
119+
.reinterpret_cast::<u8>() as Ptr::<u8>)
120+
.offset((0) as isize)
121+
.read()) as u8) as i32)
122+
== 3) as i32)
119123
!= 0)
120124
);
121125
assert!(
122-
(((((((*(*outer.borrow()).u.borrow()).raw_().read())[(4) as usize] as u8) as i32) == 4)
123-
as i32)
126+
((((((((*(*outer.borrow()).u.borrow())
127+
.raw_()
128+
.reinterpret_cast::<u8>() as Ptr::<u8>)
129+
.offset((4) as isize)
130+
.read()) as u8) as i32)
131+
== 4) as i32)
124132
!= 0)
125133
);
126134
return 0;

tests/unit/union_field_alignment.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// no-compile: refcount
21
#include <assert.h>
32
#include <stddef.h>
43
#include <stdint.h>

0 commit comments

Comments
 (0)