diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 4b092ee02..aa13f6639 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -3573,6 +3573,14 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) { StrCat(GetUnsafeTypeAsString(qual_type)); PushBrace brace(*this); + if (record->isUnion()) { + auto *field = expr->getInitializedFieldInUnion(); + assert(field && expr->getNumInits() == 1); + StrCat(GetNamedDeclAsString(field), token::kColon); + ConvertFieldInit(field, expr->getInit(0)); + SetFreshType(qual_type); + return false; + } int i = 0; for (const auto *field : record->fields()) { StrCat(GetNamedDeclAsString(field), token::kColon); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index ba70ca8b2..11d44dc09 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1908,6 +1908,21 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { return false; } + if (record->isUnion()) { + auto *field = expr->getInitializedFieldInUnion(); + assert(field && expr->getNumInits() == 1); + PushConversionKind push(*this, ConversionKind::Unboxed); + auto name = GetUnsafeTypeAsString(qual_type); + StrCat(std::format("{{ let __u: Value<{}> = Rc::new(RefCell::new({}));", + name, GetDefaultAsString(qual_type))); + StrCat(std::format("{}::{}(__u.as_pointer()).write(", name, + GetNamedDeclAsString(field))); + ConvertVarInit(field->getType(), expr->getInit(0)); + StrCat("); Rc::try_unwrap(__u).ok().unwrap().into_inner() }"); + computed_expr_type_ = ComputedExprType::FreshValue; + return false; + } + StrCat(GetUnsafeTypeAsString(qual_type)); { PushBrace brace(*this); diff --git a/tests/unit/out/refcount/union_basic.rs b/tests/unit/out/refcount/union_basic.rs index 4d60b4896..b35da820c 100644 --- a/tests/unit/out/refcount/union_basic.rs +++ b/tests/unit/out/refcount/union_basic.rs @@ -93,6 +93,18 @@ fn main_0() -> i32 { assert!(((basic::i(ru.clone()).read()) == 1065353216)); assert!(((pf.read()) == 1_f32)); assert!((((*buf.borrow())[(3) as usize] as i32) == 63)); + let braced: Value = Rc::new(RefCell::new({ + let __u: Value = Rc::new(RefCell::new(::default())); + basic::i(__u.as_pointer()).write(5); + Rc::try_unwrap(__u).ok().unwrap().into_inner() + })); + assert!(((basic::i(braced.as_pointer()).read()) == 5)); + let copied: Value = Rc::new(RefCell::new({ + let __u: Value = Rc::new(RefCell::new(::default())); + basic::i(__u.as_pointer()).write(7); + Rc::try_unwrap(__u).ok().unwrap().into_inner() + })); + assert!(((basic::i(copied.as_pointer()).read()) == 7)); { let anon_0: Value = Rc::new(RefCell::new(::default())); anon_0::ai(anon_0.as_pointer()).write(11); diff --git a/tests/unit/out/unsafe/union_basic.rs b/tests/unit/out/unsafe/union_basic.rs index 999cd945e..91ddf5a39 100644 --- a/tests/unit/out/unsafe/union_basic.rs +++ b/tests/unit/out/unsafe/union_basic.rs @@ -69,6 +69,10 @@ unsafe fn main_0() -> i32 { assert!((((*ru).i) == (1065353216))); assert!(((*pf) == (1_f32))); assert!(((buf[(3) as usize] as i32) == (63))); + let mut braced: basic = basic { i: 5 }; + assert!(((braced.i) == (5))); + let mut copied: basic = basic { i: 7 }; + assert!(((copied.i) == (7))); { let mut anon_0: anon_0 = ::default(); anon_0.ai = 11; diff --git a/tests/unit/union_basic.cpp b/tests/unit/union_basic.cpp index db7eb652e..50103772e 100644 --- a/tests/unit/union_basic.cpp +++ b/tests/unit/union_basic.cpp @@ -38,6 +38,11 @@ int main(void) { assert(*pf == 1.0f); assert(buf[3] == 0x3F); + union basic braced{5}; + assert(braced.i == 5); + union basic copied = {7}; + assert(copied.i == 7); + { union { int ai;