Skip to content

Commit 0dfb5ba

Browse files
authored
Fix translations for unnamed function parameters (#197)
The current implementation of `GetNamedDeclAsString` defaults to returning `self` whenever the declaration corresponds to an unnamed function parameter. This leads to incorrect translations such as the following: ```cpp int main(int, char**) { return 0; } ``` ```rust fn main_0(self: i32, self: Ptr<Ptr<u8>>) -> i32 { let self: Value<i32> = Rc::new(RefCell::new(self)); let self: Value<Ptr<Ptr<u8>>> = Rc::new(RefCell::new(self)); return 0; } ``` This patch addresses this issue by changing `GetNamedDeclAsString` to return `self` only when it is actually required, and `_` otherwise.
1 parent 3f4bcbf commit 0dfb5ba

6 files changed

Lines changed: 64 additions & 2 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) {
483483
if ((hoisted_decls_.contains(decl) || !qual_type.isConstQualified()) &&
484484
!qual_type->isReferenceType() &&
485485
((method_or_null == nullptr) || !method_or_null->isVirtual()) &&
486-
!IsGlobalVar(decl)) {
486+
!IsGlobalVar(decl) && name != "_") {
487487
StrCat(keyword_mut_);
488488
}
489489

cpp2rust/converter/converter_lib.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,15 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) {
481481
}
482482

483483
if (name.empty()) {
484-
name = "self";
484+
auto *pdecl = llvm::dyn_cast<clang::ParmVarDecl>(decl);
485+
assert(pdecl && "Unexpected unnamed construct");
486+
487+
const auto *ctor =
488+
llvm::dyn_cast<clang::CXXConstructorDecl>(pdecl->getDeclContext());
489+
name = (pdecl->isExplicitObjectParameter() ||
490+
(ctor && ctor->isCopyOrMoveConstructor()))
491+
? "self"
492+
: "_";
485493
}
486494

487495
return name;

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,11 @@ void ConverterRefCount::EmitFunctionPreamble(clang::FunctionDecl *decl) {
594594
for (auto *param : params) {
595595
if (!param->getType()->isReferenceType()) {
596596
auto name = GetNamedDeclAsString(param);
597+
// Skip emitting the preamble for unnamed parameters
598+
if (name == "_") {
599+
continue;
600+
}
601+
597602
auto type = ToString(param->getType());
598603
auto init = name;
599604

tests/unit/empty_main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int main(int, char **) { return 0; }
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
10+
pub fn main() {
11+
let argv: Vec<Value<Vec<u8>>> = ::std::env::args()
12+
.map(|x| Rc::new(RefCell::new(x.as_bytes().to_vec())))
13+
.collect();
14+
let mut argv: Value<Vec<Ptr<u8>>> = Rc::new(RefCell::new(
15+
argv.iter()
16+
.map(|x| {
17+
x.borrow_mut().push(0);
18+
x.as_pointer()
19+
})
20+
.collect(),
21+
));
22+
(*argv.borrow_mut()).push(Ptr::null());
23+
::std::process::exit(main_0(::std::env::args().len() as i32, argv.as_pointer()));
24+
}
25+
fn main_0(_: i32, _: Ptr<Ptr<u8>>) -> i32 {
26+
return 0;
27+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
10+
pub fn main() {
11+
let mut args: Vec<Vec<u8>> = std::env::args()
12+
.map(|arg| arg.as_bytes().to_vec())
13+
.collect();
14+
args.iter_mut().for_each(|v| v.push(0));
15+
let mut argv: Vec<*mut u8> = args.iter().map(|arg| arg.as_ptr() as *mut u8).collect();
16+
argv.push(::std::ptr::null_mut());
17+
unsafe { ::std::process::exit(main_0((argv.len() - 1) as i32, argv.as_mut_ptr()) as i32) }
18+
}
19+
unsafe fn main_0(_: i32, _: *mut *mut u8) -> i32 {
20+
return 0;
21+
}

0 commit comments

Comments
 (0)