From c7275f17f504485f547ad597512c07d24a8ebad5 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 3 Jun 2026 13:32:55 +0100 Subject: [PATCH 1/3] Fix char array initialiation through init list --- cpp2rust/converter/converter.cpp | 8 ++++++++ tests/unit/string_literals.cpp | 4 ++++ tests/unit/string_literals_c.c | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index f6659976..b835d3fc 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -2758,6 +2758,14 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) { StrCat(token::kComma); } } else { + if (expr->getNumInits() == 1 && qual_type->isArrayType() && + qual_type->getArrayElementTypeNoTypeQual()->isCharType() && + clang::isa( + expr->getInit(0)->IgnoreParenImpCasts())) { + auto *init = expr->getInit(0); + ConvertVarInit(init->getType(), init); + return false; + } PushBracket bracket(*this); for (auto *init : expr->inits()) { ConvertVarInit(init->getType(), init); diff --git a/tests/unit/string_literals.cpp b/tests/unit/string_literals.cpp index 33baffeb..c7fb8b4e 100644 --- a/tests/unit/string_literals.cpp +++ b/tests/unit/string_literals.cpp @@ -22,5 +22,9 @@ int main() { foo_const(""); foo_const(immutable_empty); foo_const(immutable_empty_arr); + + const char inited_through_init_list[] = { "papanasi cu smantana" }; + foo_const(inited_through_init_list); + return 0; } diff --git a/tests/unit/string_literals_c.c b/tests/unit/string_literals_c.c index d72fcbbf..25e57e8c 100644 --- a/tests/unit/string_literals_c.c +++ b/tests/unit/string_literals_c.c @@ -31,5 +31,9 @@ int main() { foo_const(immutable_empty); foo_const(mutable_empty_arr); foo_const(immutable_empty_arr); + + const char inited_through_init_list[] = { "papanasi cu smantana" }; + foo_const(inited_through_init_list); + return 0; } From bf1abb1013b7ace5bb8a04ab2590d8c9bd836cb6 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 3 Jun 2026 15:42:49 +0100 Subject: [PATCH 2/3] Update tests --- tests/unit/out/refcount/string_literals.rs | 7 +++++++ tests/unit/out/refcount/string_literals_c.rs | 7 +++++++ tests/unit/out/unsafe/string_literals.rs | 5 +++++ tests/unit/out/unsafe/string_literals_c.rs | 5 +++++ tests/unit/string_literals.cpp | 2 +- tests/unit/string_literals_c.c | 2 +- 6 files changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/unit/out/refcount/string_literals.rs b/tests/unit/out/refcount/string_literals.rs index ffa32466..4cc09dbc 100644 --- a/tests/unit/out/refcount/string_literals.rs +++ b/tests/unit/out/refcount/string_literals.rs @@ -60,5 +60,12 @@ fn main_0() -> i32 { let _str: Ptr = (immutable_empty_arr.as_pointer() as Ptr); foo_const_1(_str) }); + let inited_through_init_list: Value> = Rc::new(RefCell::new(Box::<[u8]>::from( + b"papanasi cu smantana\0".as_slice(), + ))); + ({ + let _str: Ptr = (inited_through_init_list.as_pointer() as Ptr); + foo_const_1(_str) + }); return 0; } diff --git a/tests/unit/out/refcount/string_literals_c.rs b/tests/unit/out/refcount/string_literals_c.rs index 9900b0c9..4706b590 100644 --- a/tests/unit/out/refcount/string_literals_c.rs +++ b/tests/unit/out/refcount/string_literals_c.rs @@ -91,5 +91,12 @@ fn main_0() -> i32 { let _str: Ptr = (immutable_empty_arr.as_pointer() as Ptr); foo_const_1(_str) }); + let inited_through_init_list: Value> = Rc::new(RefCell::new(Box::<[u8]>::from( + b"papanasi cu smantana\0".as_slice(), + ))); + ({ + let _str: Ptr = (inited_through_init_list.as_pointer() as Ptr); + foo_const_1(_str) + }); return 0; } diff --git a/tests/unit/out/unsafe/string_literals.rs b/tests/unit/out/unsafe/string_literals.rs index 4ee5d517..4d565613 100644 --- a/tests/unit/out/unsafe/string_literals.rs +++ b/tests/unit/out/unsafe/string_literals.rs @@ -49,5 +49,10 @@ unsafe fn main_0() -> i32 { let _str: *const u8 = immutable_empty_arr.as_ptr(); foo_const_1(_str) }); + let inited_through_init_list: [u8; 21] = *b"papanasi cu smantana\0"; + (unsafe { + let _str: *const u8 = inited_through_init_list.as_ptr(); + foo_const_1(_str) + }); return 0; } diff --git a/tests/unit/out/unsafe/string_literals_c.rs b/tests/unit/out/unsafe/string_literals_c.rs index e3b974b3..5d175c15 100644 --- a/tests/unit/out/unsafe/string_literals_c.rs +++ b/tests/unit/out/unsafe/string_literals_c.rs @@ -84,5 +84,10 @@ unsafe fn main_0() -> i32 { let _str: *const u8 = immutable_empty_arr.as_ptr(); foo_const_1(_str) }); + let inited_through_init_list: [u8; 21] = *b"papanasi cu smantana\0"; + (unsafe { + let _str: *const u8 = inited_through_init_list.as_ptr(); + foo_const_1(_str) + }); return 0; } diff --git a/tests/unit/string_literals.cpp b/tests/unit/string_literals.cpp index c7fb8b4e..6d302291 100644 --- a/tests/unit/string_literals.cpp +++ b/tests/unit/string_literals.cpp @@ -23,7 +23,7 @@ int main() { foo_const(immutable_empty); foo_const(immutable_empty_arr); - const char inited_through_init_list[] = { "papanasi cu smantana" }; + const char inited_through_init_list[] = {"papanasi cu smantana"}; foo_const(inited_through_init_list); return 0; diff --git a/tests/unit/string_literals_c.c b/tests/unit/string_literals_c.c index 25e57e8c..ca9f851c 100644 --- a/tests/unit/string_literals_c.c +++ b/tests/unit/string_literals_c.c @@ -32,7 +32,7 @@ int main() { foo_const(mutable_empty_arr); foo_const(immutable_empty_arr); - const char inited_through_init_list[] = { "papanasi cu smantana" }; + const char inited_through_init_list[] = {"papanasi cu smantana"}; foo_const(inited_through_init_list); return 0; From 5a610c88a4c358c4152abaf34ba1976f3db23a84 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 3 Jun 2026 15:43:00 +0100 Subject: [PATCH 3/3] Apply fix to refcount --- cpp2rust/converter/converter.cpp | 8 ++------ cpp2rust/converter/converter_lib.cpp | 8 ++++++++ cpp2rust/converter/converter_lib.h | 2 ++ cpp2rust/converter/models/converter_refcount.cpp | 6 ++++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index b835d3fc..edc771e4 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -2758,12 +2758,8 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) { StrCat(token::kComma); } } else { - if (expr->getNumInits() == 1 && qual_type->isArrayType() && - qual_type->getArrayElementTypeNoTypeQual()->isCharType() && - clang::isa( - expr->getInit(0)->IgnoreParenImpCasts())) { - auto *init = expr->getInit(0); - ConvertVarInit(init->getType(), init); + if (IsInitExprOfStringLiteral(expr)) { + Convert(expr->getInit(0)->IgnoreParenImpCasts()); return false; } PushBracket bracket(*this); diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 1999c8df..38d6170a 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -255,6 +255,14 @@ bool IsAsciiStringLiteral(const clang::StringLiteral *str) { return true; } +bool IsInitExprOfStringLiteral(const clang::InitListExpr *expr) { + auto type = expr->getType(); + return expr->getNumInits() == 1 && type->isArrayType() && + type->getArrayElementTypeNoTypeQual()->isCharType() && + clang::isa( + expr->getInit(0)->IgnoreParenImpCasts()); +} + std::vector GetTemplateInstantiatedCtors(clang::CXXRecordDecl *decl) { std::vector out; diff --git a/cpp2rust/converter/converter_lib.h b/cpp2rust/converter/converter_lib.h index 6e3bc559..bcd6e50c 100644 --- a/cpp2rust/converter/converter_lib.h +++ b/cpp2rust/converter/converter_lib.h @@ -67,6 +67,8 @@ bool IsCallToOstream(clang::CallExpr *expr); bool IsAsciiStringLiteral(const clang::StringLiteral *str); +bool IsInitExprOfStringLiteral(const clang::InitListExpr *expr); + std::vector GetTemplateInstantiatedCtors(clang::CXXRecordDecl *decl); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index d7af2500..4dff7a28 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1397,6 +1397,12 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { return false; } + if (IsInitExprOfStringLiteral(expr)) { + Convert(expr->getInit(0)->IgnoreParenImpCasts()); + computed_expr_type_ = ComputedExprType::FreshValue; + return false; + } + auto conv = getConversionKind(); // 2D arrays are FullRefCount'ed on the second level as well. PushConversionKind push(