Skip to content

Commit d833f7f

Browse files
authored
Translate template packs (#323)
Their body is fully instantiated at every call site. In the AST, the names of all expanded arguments is `args` which is wrong in the translated code because arguments have to have different names. I added support in the converter to translate them as `args_1`, `args_2`, etc.
1 parent f532aa4 commit d833f7f

4 files changed

Lines changed: 104 additions & 0 deletions

File tree

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,16 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) {
528528
(ctor && ctor->isCopyOrMoveConstructor()))
529529
? "self"
530530
: "_";
531+
} else if (auto *pdecl = llvm::dyn_cast<clang::ParmVarDecl>(decl)) {
532+
// Expanded parameter packs share one name across the expansion
533+
if (auto *fn = llvm::dyn_cast_or_null<clang::FunctionDecl>(
534+
pdecl->getDeclContext());
535+
fn && llvm::count_if(fn->parameters(), [&](const auto *p) {
536+
return p->getName() == pdecl->getName();
537+
}) > 1) {
538+
name += '_';
539+
name += std::to_string(pdecl->getFunctionScopeIndex());
540+
}
531541
}
532542

533543
return name;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
pub fn sum_0(args_0: i32, args_1: i32, args_2: i32) -> i32 {
10+
let args_0: Value<i32> = Rc::new(RefCell::new(args_0));
11+
let args_1: Value<i32> = Rc::new(RefCell::new(args_1));
12+
let args_2: Value<i32> = Rc::new(RefCell::new(args_2));
13+
return ((*args_0.borrow()) + ((*args_1.borrow()) + ((*args_2.borrow()) + 0)));
14+
}
15+
pub fn sum_1(args_0: i32, args_1: i32) -> i32 {
16+
let args_0: Value<i32> = Rc::new(RefCell::new(args_0));
17+
let args_1: Value<i32> = Rc::new(RefCell::new(args_1));
18+
return ((*args_0.borrow()) + ((*args_1.borrow()) + 0));
19+
}
20+
pub fn sum_2(args: i32) -> i32 {
21+
let args: Value<i32> = Rc::new(RefCell::new(args));
22+
return ((*args.borrow()) + 0);
23+
}
24+
pub fn first_3(x: i32, args_1: i32, args_2: i32) -> i32 {
25+
let x: Value<i32> = Rc::new(RefCell::new(x));
26+
let args_1: Value<i32> = Rc::new(RefCell::new(args_1));
27+
let args_2: Value<i32> = Rc::new(RefCell::new(args_2));
28+
return ((*x.borrow()) + ({ sum_1((*args_1.borrow()), (*args_2.borrow())) }));
29+
}
30+
pub fn first_4(x: i32, args: i32) -> i32 {
31+
let x: Value<i32> = Rc::new(RefCell::new(x));
32+
let args: Value<i32> = Rc::new(RefCell::new(args));
33+
return ((*x.borrow()) + ({ sum_2((*args.borrow())) }));
34+
}
35+
pub fn main() {
36+
std::process::exit(main_0());
37+
}
38+
fn main_0() -> i32 {
39+
assert!((({ sum_0(1, 2, 3,) }) == 6));
40+
assert!((({ sum_1(4, 5,) }) == 9));
41+
assert!((({ first_3(10, 1, 2,) }) == 13));
42+
assert!((({ first_4(10, 0,) }) == 10));
43+
return 0;
44+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
pub unsafe fn sum_0(mut args_0: i32, mut args_1: i32, mut args_2: i32) -> i32 {
10+
return ((args_0) + ((args_1) + ((args_2) + (0))));
11+
}
12+
pub unsafe fn sum_1(mut args_0: i32, mut args_1: i32) -> i32 {
13+
return ((args_0) + ((args_1) + (0)));
14+
}
15+
pub unsafe fn sum_2(mut args: i32) -> i32 {
16+
return ((args) + (0));
17+
}
18+
pub unsafe fn first_3(mut x: i32, mut args_1: i32, mut args_2: i32) -> i32 {
19+
return ((x) + (unsafe { sum_1(args_1, args_2) }));
20+
}
21+
pub unsafe fn first_4(mut x: i32, mut args: i32) -> i32 {
22+
return ((x) + (unsafe { sum_2(args) }));
23+
}
24+
pub fn main() {
25+
unsafe {
26+
std::process::exit(main_0() as i32);
27+
}
28+
}
29+
unsafe fn main_0() -> i32 {
30+
assert!(((unsafe { sum_0(1, 2, 3,) }) == (6)));
31+
assert!(((unsafe { sum_1(4, 5,) }) == (9)));
32+
assert!(((unsafe { first_3(10, 1, 2,) }) == (13)));
33+
assert!(((unsafe { first_4(10, 0,) }) == (10)));
34+
return 0;
35+
}

‎tests/unit/template_pack.cpp‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <cassert>
2+
3+
template <typename... Args> int sum(Args... args) { return (args + ... + 0); }
4+
5+
template <typename T, typename... Args> T first(T x, Args... args) {
6+
return x + sum(args...);
7+
}
8+
9+
int main() {
10+
assert(sum(1, 2, 3) == 6);
11+
assert(sum(4, 5) == 9);
12+
assert(first(10, 1, 2) == 13);
13+
assert(first(10, 0) == 10);
14+
return 0;
15+
}

0 commit comments

Comments
 (0)