From 94919feaecae5870e109fa42d221f4b6cb479d22 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sun, 20 Sep 2026 10:26:24 +0100 Subject: [PATCH 1/2] Default initialize reamaining fields in small initializer list --- .../converter/models/converter_refcount.cpp | 6 +- tests/unit/new_struct.cpp | 17 +++++ tests/unit/out/refcount/new_struct.rs | 63 +++++++++++++++++++ tests/unit/out/unsafe/new_struct.rs | 24 +++++++ 4 files changed, 109 insertions(+), 1 deletion(-) diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index f2247a35d..89ac13e2f 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1636,7 +1636,11 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { PushConversionKind push(*this, ConversionKind::FullRefCount); for (const auto *field : record->fields()) { StrCat(GetNamedDeclAsString(field), token::kColon); - ConvertVarInit(field->getType(), expr->getInit(i++)); + if (i < expr->getNumInits()) { + ConvertVarInit(field->getType(), expr->getInit(i++)); + } else { + StrCat(GetDefaultAsString(field->getType())); + } StrCat(token::kComma); } } diff --git a/tests/unit/new_struct.cpp b/tests/unit/new_struct.cpp index 3a4c03247..e98e61160 100644 --- a/tests/unit/new_struct.cpp +++ b/tests/unit/new_struct.cpp @@ -4,10 +4,27 @@ struct Pair { int x, y; }; +struct Triple { + int a; + int b; + Pair p; +}; + int main() { Pair *p = new Pair{1, 2}; int out = p->x + p->y; delete p; assert(out == 3); + + Triple t{1}; + assert(t.a == 1); + assert(t.b == 0); + assert(t.p.x == 0 && t.p.y == 0); + + Triple *q = new Triple{2, 3}; + assert(q->a == 2); + assert(q->b == 3); + assert(q->p.x == 0 && q->p.y == 0); + delete q; return 0; } diff --git a/tests/unit/out/refcount/new_struct.rs b/tests/unit/out/refcount/new_struct.rs index 85b039dbd..bb27e89ba 100644 --- a/tests/unit/out/refcount/new_struct.rs +++ b/tests/unit/out/refcount/new_struct.rs @@ -36,6 +36,40 @@ impl ByteRepr for Pair { } } } +#[derive(Default)] +pub struct Triple { + pub a: Value, + pub b: Value, + pub p: Value, +} +impl Clone for Triple { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + a: Rc::new(RefCell::new((*self.a.borrow()))), + b: Rc::new(RefCell::new((*self.b.borrow()))), + p: Rc::new(RefCell::new((*self.p.borrow()).clone())), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for Triple { + fn byte_size() -> usize { + 16 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.a.borrow()).to_bytes(&mut buf[0..4]); + (*self.b.borrow()).to_bytes(&mut buf[4..8]); + (*self.p.borrow()).to_bytes(&mut buf[8..16]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + a: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + b: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + p: Rc::new(RefCell::new(::from_bytes(&buf[8..16]))), + } + } +} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -51,6 +85,35 @@ fn main_0() -> i32 { })); (*p.borrow()).delete(); assert!(((*out.borrow()) == 3)); + let t: Value = Rc::new(RefCell::new(Triple { + a: Rc::new(RefCell::new(1)), + b: Rc::new(RefCell::new(::default())), + p: Rc::new(RefCell::new(Pair { + x: Rc::new(RefCell::new(::default())), + y: Rc::new(RefCell::new(::default())), + })), + })); + assert!(((*(*t.borrow()).a.borrow()) == 1)); + assert!(((*(*t.borrow()).b.borrow()) == 0)); + assert!( + ((*(*(*t.borrow()).p.borrow()).x.borrow()) == 0) + && ((*(*(*t.borrow()).p.borrow()).y.borrow()) == 0) + ); + let q: Value> = Rc::new(RefCell::new(Ptr::alloc(Triple { + a: Rc::new(RefCell::new(2)), + b: Rc::new(RefCell::new(3)), + p: Rc::new(RefCell::new(Pair { + x: Rc::new(RefCell::new(::default())), + y: Rc::new(RefCell::new(::default())), + })), + }))); + assert!(((*(*(*q.borrow()).upgrade().deref()).a.borrow()) == 2)); + assert!(((*(*(*q.borrow()).upgrade().deref()).b.borrow()) == 3)); + assert!( + ((*(*(*(*q.borrow()).upgrade().deref()).p.borrow()).x.borrow()) == 0) + && ((*(*(*(*q.borrow()).upgrade().deref()).p.borrow()).y.borrow()) == 0) + ); + (*q.borrow()).delete(); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/new_struct.rs b/tests/unit/out/unsafe/new_struct.rs index 9228459fd..ccf4e4f82 100644 --- a/tests/unit/out/unsafe/new_struct.rs +++ b/tests/unit/out/unsafe/new_struct.rs @@ -12,6 +12,13 @@ pub struct Pair { pub x: i32, pub y: i32, } +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct Triple { + pub a: i32, + pub b: i32, + pub p: Pair, +} pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -23,6 +30,23 @@ unsafe fn main_0() -> i32 { let mut out: i32 = (((*p).x) + ((*p).y)); ::std::mem::drop(Box::from_raw(p)); assert!(((out) == (3))); + let mut t: Triple = Triple { + a: 1, + b: 0_i32, + p: Pair { x: 0_i32, y: 0_i32 }, + }; + assert!(((t.a) == (1))); + assert!(((t.b) == (0))); + assert!(((t.p.x) == (0)) && ((t.p.y) == (0))); + let mut q: *mut Triple = (Box::leak(Box::new(Triple { + a: 2, + b: 3, + p: Pair { x: 0_i32, y: 0_i32 }, + })) as *mut Triple); + assert!((((*q).a) == (2))); + assert!((((*q).b) == (3))); + assert!((((*q).p.x) == (0)) && (((*q).p.y) == (0))); + ::std::mem::drop(Box::from_raw(q)); return 0; } pub unsafe fn __cpp2rust_init_globals() {} From 189fc9b830ccc95f00ce41495f105c54c7459782 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sun, 20 Sep 2026 10:34:19 +0100 Subject: [PATCH 2/2] Use unsigned --- cpp2rust/converter/models/converter_refcount.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 89ac13e2f..c25ea3b02 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1632,7 +1632,7 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { StrCat(GetUnsafeTypeAsString(qual_type)); { PushBrace brace(*this); - int i = 0; + unsigned i = 0; PushConversionKind push(*this, ConversionKind::FullRefCount); for (const auto *field : record->fields()) { StrCat(GetNamedDeclAsString(field), token::kColon);