Skip to content

Commit 72bb583

Browse files
authored
Fix list initializers for unions (#514)
1 parent f19aca1 commit 72bb583

5 files changed

Lines changed: 44 additions & 0 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3573,6 +3573,14 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) {
35733573

35743574
StrCat(GetUnsafeTypeAsString(qual_type));
35753575
PushBrace brace(*this);
3576+
if (record->isUnion()) {
3577+
auto *field = expr->getInitializedFieldInUnion();
3578+
assert(field && expr->getNumInits() == 1);
3579+
StrCat(GetNamedDeclAsString(field), token::kColon);
3580+
ConvertFieldInit(field, expr->getInit(0));
3581+
SetFreshType(qual_type);
3582+
return false;
3583+
}
35763584
int i = 0;
35773585
for (const auto *field : record->fields()) {
35783586
StrCat(GetNamedDeclAsString(field), token::kColon);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,6 +1908,21 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) {
19081908
return false;
19091909
}
19101910

1911+
if (record->isUnion()) {
1912+
auto *field = expr->getInitializedFieldInUnion();
1913+
assert(field && expr->getNumInits() == 1);
1914+
PushConversionKind push(*this, ConversionKind::Unboxed);
1915+
auto name = GetUnsafeTypeAsString(qual_type);
1916+
StrCat(std::format("{{ let __u: Value<{}> = Rc::new(RefCell::new({}));",
1917+
name, GetDefaultAsString(qual_type)));
1918+
StrCat(std::format("{}::{}(__u.as_pointer()).write(", name,
1919+
GetNamedDeclAsString(field)));
1920+
ConvertVarInit(field->getType(), expr->getInit(0));
1921+
StrCat("); Rc::try_unwrap(__u).ok().unwrap().into_inner() }");
1922+
computed_expr_type_ = ComputedExprType::FreshValue;
1923+
return false;
1924+
}
1925+
19111926
StrCat(GetUnsafeTypeAsString(qual_type));
19121927
{
19131928
PushBrace brace(*this);

‎tests/unit/out/refcount/union_basic.rs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,18 @@ fn main_0() -> i32 {
9393
assert!(((basic::i(ru.clone()).read()) == 1065353216));
9494
assert!(((pf.read()) == 1_f32));
9595
assert!((((*buf.borrow())[(3) as usize] as i32) == 63));
96+
let braced: Value<basic> = Rc::new(RefCell::new({
97+
let __u: Value<basic> = Rc::new(RefCell::new(<basic>::default()));
98+
basic::i(__u.as_pointer()).write(5);
99+
Rc::try_unwrap(__u).ok().unwrap().into_inner()
100+
}));
101+
assert!(((basic::i(braced.as_pointer()).read()) == 5));
102+
let copied: Value<basic> = Rc::new(RefCell::new({
103+
let __u: Value<basic> = Rc::new(RefCell::new(<basic>::default()));
104+
basic::i(__u.as_pointer()).write(7);
105+
Rc::try_unwrap(__u).ok().unwrap().into_inner()
106+
}));
107+
assert!(((basic::i(copied.as_pointer()).read()) == 7));
96108
{
97109
let anon_0: Value<anon_0> = Rc::new(RefCell::new(<anon_0>::default()));
98110
anon_0::ai(anon_0.as_pointer()).write(11);

‎tests/unit/out/unsafe/union_basic.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ unsafe fn main_0() -> i32 {
6969
assert!((((*ru).i) == (1065353216)));
7070
assert!(((*pf) == (1_f32)));
7171
assert!(((buf[(3) as usize] as i32) == (63)));
72+
let mut braced: basic = basic { i: 5 };
73+
assert!(((braced.i) == (5)));
74+
let mut copied: basic = basic { i: 7 };
75+
assert!(((copied.i) == (7)));
7276
{
7377
let mut anon_0: anon_0 = <anon_0>::default();
7478
anon_0.ai = 11;

‎tests/unit/union_basic.cpp‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ int main(void) {
3838
assert(*pf == 1.0f);
3939
assert(buf[3] == 0x3F);
4040

41+
union basic braced{5};
42+
assert(braced.i == 5);
43+
union basic copied = {7};
44+
assert(copied.i == 7);
45+
4146
{
4247
union {
4348
int ai;

0 commit comments

Comments
 (0)