From 48b7f5d881dc876268b8cd15b0f7f46988d40a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Gouveia?= Date: Fri, 19 Jun 2026 21:56:26 +0000 Subject: [PATCH 1/2] Add pre-commit tests --- tests/unit/empty_main.cpp | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/unit/empty_main.cpp diff --git a/tests/unit/empty_main.cpp b/tests/unit/empty_main.cpp new file mode 100644 index 00000000..cf0e2bd9 --- /dev/null +++ b/tests/unit/empty_main.cpp @@ -0,0 +1 @@ +int main(int, char **) { return 0; } From cd32680817c3b8583353d5c910e46fda4e570091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Gouveia?= Date: Sat, 20 Jun 2026 02:05:41 +0100 Subject: [PATCH 2/2] Fix translations for unnamed function parameters --- cpp2rust/converter/converter.cpp | 2 +- cpp2rust/converter/converter_lib.cpp | 10 ++++++- .../converter/models/converter_refcount.cpp | 5 ++++ tests/unit/out/refcount/empty_main.rs | 27 +++++++++++++++++++ tests/unit/out/unsafe/empty_main.rs | 21 +++++++++++++++ 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 tests/unit/out/refcount/empty_main.rs create mode 100644 tests/unit/out/unsafe/empty_main.rs diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 923d1bd8..dc985d8e 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -483,7 +483,7 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) { if ((hoisted_decls_.contains(decl) || !qual_type.isConstQualified()) && !qual_type->isReferenceType() && ((method_or_null == nullptr) || !method_or_null->isVirtual()) && - !IsGlobalVar(decl)) { + !IsGlobalVar(decl) && name != "_") { StrCat(keyword_mut_); } diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 3ba0ccc3..12c0bf69 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -481,7 +481,15 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) { } if (name.empty()) { - name = "self"; + auto *pdecl = llvm::dyn_cast(decl); + assert(pdecl && "Unexpected unnamed construct"); + + const auto *ctor = + llvm::dyn_cast(pdecl->getDeclContext()); + name = (pdecl->isExplicitObjectParameter() || + (ctor && ctor->isCopyOrMoveConstructor())) + ? "self" + : "_"; } return name; diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 0d895b28..7fb3bc9a 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -594,6 +594,11 @@ void ConverterRefCount::EmitFunctionPreamble(clang::FunctionDecl *decl) { for (auto *param : params) { if (!param->getType()->isReferenceType()) { auto name = GetNamedDeclAsString(param); + // Skip emitting the preamble for unnamed parameters + if (name == "_") { + continue; + } + auto type = ToString(param->getType()); auto init = name; diff --git a/tests/unit/out/refcount/empty_main.rs b/tests/unit/out/refcount/empty_main.rs new file mode 100644 index 00000000..4e280a57 --- /dev/null +++ b/tests/unit/out/refcount/empty_main.rs @@ -0,0 +1,27 @@ +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}; + +pub fn main() { + let argv: Vec>> = ::std::env::args() + .map(|x| Rc::new(RefCell::new(x.as_bytes().to_vec()))) + .collect(); + let mut argv: Value>> = Rc::new(RefCell::new( + argv.iter() + .map(|x| { + x.borrow_mut().push(0); + x.as_pointer() + }) + .collect(), + )); + (*argv.borrow_mut()).push(Ptr::null()); + ::std::process::exit(main_0(::std::env::args().len() as i32, argv.as_pointer())); +} +fn main_0(_: i32, _: Ptr>) -> i32 { + return 0; +} diff --git a/tests/unit/out/unsafe/empty_main.rs b/tests/unit/out/unsafe/empty_main.rs new file mode 100644 index 00000000..97b40abf --- /dev/null +++ b/tests/unit/out/unsafe/empty_main.rs @@ -0,0 +1,21 @@ +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; + +pub fn main() { + let mut args: Vec> = std::env::args() + .map(|arg| arg.as_bytes().to_vec()) + .collect(); + args.iter_mut().for_each(|v| v.push(0)); + let mut argv: Vec<*mut u8> = args.iter().map(|arg| arg.as_ptr() as *mut u8).collect(); + argv.push(::std::ptr::null_mut()); + unsafe { ::std::process::exit(main_0((argv.len() - 1) as i32, argv.as_mut_ptr()) as i32) } +} +unsafe fn main_0(_: i32, _: *mut *mut u8) -> i32 { + return 0; +}