From c9bac6ed47b8c581f714ce12fada8db179415b6f Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 11 May 2026 16:38:32 +0100 Subject: [PATCH 1/4] Allow non-extern global variables without initializer --- cpp2rust/converter/converter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 655a6020..042f5994 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -381,7 +381,8 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) { if (decl->isFileVarDecl()) { name = ReplaceAll(Mapper::ToString(decl), "::", "_"); - if ((decl->isExternallyDeclarable() && !decl->hasInit()) || + if (decl->isThisDeclarationADefinition() == + clang::VarDecl::DeclarationOnly || !globals_.insert(name).second) { return false; } From db1b393bf21134d919444ad3694748518d5b02d3 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 11 May 2026 16:45:13 +0100 Subject: [PATCH 2/4] Add global_without_initializer test --- tests/unit/global_without_initializer.cpp | 17 ++++++++ .../refcount/global_without_initializer.rs | 39 +++++++++++++++++++ .../out/unsafe/global_without_initializer.rs | 27 +++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 tests/unit/global_without_initializer.cpp create mode 100644 tests/unit/out/refcount/global_without_initializer.rs create mode 100644 tests/unit/out/unsafe/global_without_initializer.rs diff --git a/tests/unit/global_without_initializer.cpp b/tests/unit/global_without_initializer.cpp new file mode 100644 index 00000000..c3e36ba7 --- /dev/null +++ b/tests/unit/global_without_initializer.cpp @@ -0,0 +1,17 @@ +#include +#include + +struct S { + int a; +}; + +S *s; +FILE *file; +size_t size; + +int main() { + assert(s == nullptr); + assert(file == nullptr); + assert(size == 0); + return 0; +}; diff --git a/tests/unit/out/refcount/global_without_initializer.rs b/tests/unit/out/refcount/global_without_initializer.rs new file mode 100644 index 00000000..3afb964a --- /dev/null +++ b/tests/unit/out/refcount/global_without_initializer.rs @@ -0,0 +1,39 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(Default)] +pub struct S { + pub a: Value, +} +impl Clone for S { + fn clone(&self) -> Self { + let mut this = Self { + a: Rc::new(RefCell::new((*self.a.borrow()))), + }; + this + } +} +impl ByteRepr for S {} +thread_local!( + pub static s: Value> = Rc::new(RefCell::new(Ptr::::null())); +); +thread_local!( + pub static file: Value> = Rc::new(RefCell::new(Ptr::<_IO_FILE>::null())); +); +thread_local!( + pub static size: Value = >::default(); +); +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + assert!((*s.with(Value::clone).borrow()).is_null()); + assert!((*file.with(Value::clone).borrow()).is_null()); + assert!(((*size.with(Value::clone).borrow()) == 0_u64)); + return 0; +} diff --git a/tests/unit/out/unsafe/global_without_initializer.rs b/tests/unit/out/unsafe/global_without_initializer.rs new file mode 100644 index 00000000..57c51700 --- /dev/null +++ b/tests/unit/out/unsafe/global_without_initializer.rs @@ -0,0 +1,27 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct S { + pub a: i32, +} +pub static mut s: *mut S = std::ptr::null_mut(); +pub static mut file: *mut ::std::fs::File = std::ptr::null_mut(); +pub static mut size: u64 = 0_u64; +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + assert!((s).is_null()); + assert!((file).is_null()); + assert!(((size) == (0_u64))); + return 0; +} From da766e2c2807abe253023e96bde9d65bd73d0cb8 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 11 May 2026 16:55:24 +0100 Subject: [PATCH 3/4] Use ConvertPointeeType instead of GetUnsafeTypeAsString --- cpp2rust/converter/models/converter_refcount.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 44eb4cc0..050f887b 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1635,8 +1635,8 @@ std::string ConverterRefCount::GetDefaultAsString(clang::QualType qual_type) { if (pointee_type->isVoidType()) { ret = "AnyPtr::default()"; } else { - ret = std::format("Ptr::<{}>::null()", - GetUnsafeTypeAsString(pointee_type)); + PushConversionKind push(*this, ConversionKind::Unboxed); + ret = std::format("Ptr::<{}>::null()", ConvertPointeeType(qual_type)); } } } else if (auto *array_type = @@ -2240,6 +2240,7 @@ std::string ConverterRefCount::ConvertMappedMethodCall( } std::string ConverterRefCount::ConvertPointeeType(clang::QualType ptr_type) { + assert(!ptr_type.isNull() && ptr_type->isPointerType()); if (ptr_type->getPointeeType()->isIntegerType()) { return ToString(ptr_type->getPointeeType()); } @@ -2247,7 +2248,6 @@ std::string ConverterRefCount::ConvertPointeeType(clang::QualType ptr_type) { // Pointee of a pointer to incomplete type is an incomplete type that does // not have a translation rule. Hence ToString(ptr_type->getPointeeType()) is // not enough - assert(ptr_type->isPointerType()); auto str = ToString(ptr_type); Unwrap(str, "Ptr<", ">"); return str; From 5dad08dcbae01e405c0a87c3fdc4f0dba261ca05 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 11 May 2026 16:55:34 +0100 Subject: [PATCH 4/4] Update tests --- tests/unit/out/refcount/global_without_initializer.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit/out/refcount/global_without_initializer.rs b/tests/unit/out/refcount/global_without_initializer.rs index 3afb964a..52ae0d1e 100644 --- a/tests/unit/out/refcount/global_without_initializer.rs +++ b/tests/unit/out/refcount/global_without_initializer.rs @@ -23,7 +23,8 @@ thread_local!( pub static s: Value> = Rc::new(RefCell::new(Ptr::::null())); ); thread_local!( - pub static file: Value> = Rc::new(RefCell::new(Ptr::<_IO_FILE>::null())); + pub static file: Value> = + Rc::new(RefCell::new(Ptr::<::std::fs::File>::null())); ); thread_local!( pub static size: Value = >::default();