Skip to content

Commit bf89150

Browse files
authored
Fix lambdas that receive pack captures (#500)
1 parent 36a88cf commit bf89150

4 files changed

Lines changed: 249 additions & 1 deletion

File tree

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,22 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) {
10051005
name += '_';
10061006
name += std::to_string(pdecl->getFunctionScopeIndex());
10071007
}
1008+
} else if (auto *var = llvm::dyn_cast<clang::VarDecl>(decl);
1009+
var && var->isInitCapture()) {
1010+
auto lambda =
1011+
llvm::cast<clang::CXXMethodDecl>(var->getDeclContext())->getParent();
1012+
if (llvm::count_if(lambda->captures(), [&](const clang::LambdaCapture &c) {
1013+
return c.capturesVariable() &&
1014+
c.getCapturedVar()->getName() == var->getName();
1015+
}) > 1) {
1016+
auto captures = lambda->captures();
1017+
auto it = llvm::find_if(captures, [&](const clang::LambdaCapture &c) {
1018+
return c.capturesVariable() && c.getCapturedVar() == var;
1019+
});
1020+
assert(it != captures.end());
1021+
name += '_';
1022+
name += std::to_string(it - captures.begin());
1023+
}
10081024
}
10091025

10101026
return name;

‎tests/unit/lambda_pack_capture.cpp‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// ADDITIONAL_COMPILE_FLAGS: -std=c++23
2-
// no-compile
32
#include <assert.h>
43

54
int sum() { return 0; }
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
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() -> i32 {
10+
return 0;
11+
}
12+
pub fn sum_1(mut t: i32, mut u_1: i32, mut u_2: i32) -> i32 {
13+
return (t + ({ sum_2(u_1, u_2) }));
14+
}
15+
pub fn sum_2(mut t: i32, mut u: i32) -> i32 {
16+
return (t + ({ sum_3(u) }));
17+
}
18+
pub fn sum_3(mut t: i32) -> i32 {
19+
return (t + ({ sum_0() }));
20+
}
21+
pub fn by_value_4() -> i32 {
22+
let f: Value<FnPtr<fn() -> i32>> =
23+
Rc::new(RefCell::new(FnPtr::<fn() -> i32>::new(|| -> i32 {
24+
{
25+
return ({ sum_0() });
26+
}
27+
})));
28+
();
29+
return ({ (*f.borrow()).call() }).clone();
30+
}
31+
pub fn by_value_5(t_0: i32, t_1: i32, t_2: i32) -> i32 {
32+
let t_0: Value<i32> = Rc::new(RefCell::new(t_0));
33+
let t_1: Value<i32> = Rc::new(RefCell::new(t_1));
34+
let t_2: Value<i32> = Rc::new(RefCell::new(t_2));
35+
let f: Value<FnPtr<fn() -> i32>> = Rc::new(RefCell::new(lambda!(
36+
{
37+
let t_0: Value<i32> = Rc::new(RefCell::new((*t_0.borrow())));
38+
let t_1: Value<i32> = Rc::new(RefCell::new((*t_1.borrow())));
39+
let t_2: Value<i32> = Rc::new(RefCell::new((*t_2.borrow())));
40+
},
41+
|| -> i32 {
42+
return ({ sum_1((*t_0.borrow()), (*t_1.borrow()), (*t_2.borrow())) });
43+
}
44+
)));
45+
{
46+
(*t_0.borrow_mut()) = 0;
47+
{
48+
(*t_1.borrow_mut()) = 0;
49+
(*t_2.borrow_mut()) = 0
50+
}
51+
};
52+
return ({ (*f.borrow()).call() }).clone();
53+
}
54+
pub fn by_ref_6(t_0: i32, t_1: i32, t_2: i32) -> i32 {
55+
let t_0: Value<i32> = Rc::new(RefCell::new(t_0));
56+
let t_1: Value<i32> = Rc::new(RefCell::new(t_1));
57+
let t_2: Value<i32> = Rc::new(RefCell::new(t_2));
58+
let f: Value<FnPtr<fn()>> = Rc::new(RefCell::new(lambda!(
59+
{
60+
let t_0: Ptr<i32> = t_0.as_pointer();
61+
let t_1: Ptr<i32> = t_1.as_pointer();
62+
let t_2: Ptr<i32> = t_2.as_pointer();
63+
},
64+
|| {
65+
{
66+
{
67+
t_0.with_mut(|__v| *__v = *__v * 2)
68+
};
69+
{
70+
{
71+
t_1.with_mut(|__v| *__v = *__v * 2)
72+
};
73+
{ t_2.with_mut(|__v| *__v = *__v * 2) }
74+
}
75+
};
76+
}
77+
)));
78+
({ (*f.borrow()).call() });
79+
return ({ sum_1((*t_0.borrow()), (*t_1.borrow()), (*t_2.borrow())) });
80+
}
81+
pub fn init_pack_7(mut t_0: i32, mut t_1: i32, mut t_2: i32) -> i32 {
82+
let f: Value<FnPtr<fn() -> i32>> = Rc::new(RefCell::new(lambda!(
83+
{
84+
let xs_0: Value<i32> = Rc::new(RefCell::new((t_0 + 1)));
85+
let xs_1: Value<i32> = Rc::new(RefCell::new((t_1 + 1)));
86+
let xs_2: Value<i32> = Rc::new(RefCell::new((t_2 + 1)));
87+
},
88+
|| -> i32 {
89+
return ({ sum_1((*xs_0.borrow()), (*xs_1.borrow()), (*xs_2.borrow())) });
90+
}
91+
)));
92+
return ({ (*f.borrow()).call() }).clone();
93+
}
94+
pub fn implicit_8(t_0: i32, t_1: i32) -> i32 {
95+
let t_0: Value<i32> = Rc::new(RefCell::new(t_0));
96+
let t_1: Value<i32> = Rc::new(RefCell::new(t_1));
97+
return ({
98+
lambda!(
99+
{
100+
let t_0: Value<i32> = Rc::new(RefCell::new((*t_0.borrow())));
101+
let t_1: Value<i32> = Rc::new(RefCell::new((*t_1.borrow())));
102+
},
103+
|| -> i32 {
104+
return ({ sum_2((*t_0.borrow()), (*t_1.borrow())) });
105+
}
106+
)
107+
.call()
108+
});
109+
}
110+
pub fn main() {
111+
__cpp2rust_init_globals();
112+
std::process::exit(main_0());
113+
}
114+
fn main_0() -> i32 {
115+
assert!((({ by_value_4() }) == 0));
116+
assert!((({ by_value_5(1, 2, 3,) }) == 6));
117+
assert!((({ by_ref_6(1, 2, 3,) }) == 12));
118+
assert!((({ init_pack_7(1, 2, 3,) }) == 9));
119+
assert!((({ implicit_8(4, 5,) }) == 9));
120+
return 0;
121+
}
122+
pub fn __cpp2rust_init_globals() {}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
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() -> i32 {
10+
return 0;
11+
}
12+
pub unsafe fn sum_1(mut t: i32, mut u_1: i32, mut u_2: i32) -> i32 {
13+
return ((t) + (unsafe { sum_2(u_1, u_2) }));
14+
}
15+
pub unsafe fn sum_2(mut t: i32, mut u: i32) -> i32 {
16+
return ((t) + (unsafe { sum_3(u) }));
17+
}
18+
pub unsafe fn sum_3(mut t: i32) -> i32 {
19+
return ((t) + (unsafe { sum_0() }));
20+
}
21+
pub unsafe fn by_value_4() -> i32 {
22+
let mut f: FnPtr<fn() -> i32> = FnPtr::<fn() -> i32>::new(|| -> i32 {
23+
unsafe {
24+
return (unsafe { sum_0() });
25+
}
26+
});
27+
();
28+
return (unsafe { f.call() });
29+
}
30+
pub unsafe fn by_value_5(mut t_0: i32, mut t_1: i32, mut t_2: i32) -> i32 {
31+
let mut f: FnPtr<fn() -> i32> = lambda_unsafe!(
32+
{
33+
let t_0: i32 = t_0;
34+
let t_1: i32 = t_1;
35+
let t_2: i32 = t_2;
36+
},
37+
|| -> i32 {
38+
return (unsafe { sum_1(t_0, t_1, t_2) });
39+
}
40+
);
41+
{
42+
t_0 = 0;
43+
{
44+
t_1 = 0;
45+
t_2 = 0
46+
}
47+
};
48+
return (unsafe { f.call() });
49+
}
50+
pub unsafe fn by_ref_6(mut t_0: i32, mut t_1: i32, mut t_2: i32) -> i32 {
51+
let mut f: FnPtr<fn()> = lambda_unsafe!(
52+
{
53+
let t_0: *mut i32 = &mut t_0;
54+
let t_1: *mut i32 = &mut t_1;
55+
let t_2: *mut i32 = &mut t_2;
56+
},
57+
|| {
58+
{
59+
(*t_0) *= 2;
60+
{
61+
(*t_1) *= 2;
62+
(*t_2) *= 2
63+
}
64+
};
65+
}
66+
);
67+
(unsafe { f.call() });
68+
return (unsafe { sum_1(t_0, t_1, t_2) });
69+
}
70+
pub unsafe fn init_pack_7(mut t_0: i32, mut t_1: i32, mut t_2: i32) -> i32 {
71+
let mut f: FnPtr<fn() -> i32> = lambda_unsafe!(
72+
{
73+
let xs_0: i32 = ((t_0) + (1));
74+
let xs_1: i32 = ((t_1) + (1));
75+
let xs_2: i32 = ((t_2) + (1));
76+
},
77+
|| -> i32 {
78+
return (unsafe { sum_1(xs_0, xs_1, xs_2) });
79+
}
80+
);
81+
return (unsafe { f.call() });
82+
}
83+
pub unsafe fn implicit_8(mut t_0: i32, mut t_1: i32) -> i32 {
84+
return (unsafe {
85+
lambda_unsafe!(
86+
{
87+
let t_0: i32 = t_0;
88+
let t_1: i32 = t_1;
89+
},
90+
|| -> i32 {
91+
return (unsafe { sum_2(t_0, t_1) });
92+
}
93+
)
94+
.call()
95+
});
96+
}
97+
pub fn main() {
98+
unsafe {
99+
__cpp2rust_init_globals();
100+
std::process::exit(main_0() as i32);
101+
}
102+
}
103+
unsafe fn main_0() -> i32 {
104+
assert!(((unsafe { by_value_4() }) == (0)));
105+
assert!(((unsafe { by_value_5(1, 2, 3,) }) == (6)));
106+
assert!(((unsafe { by_ref_6(1, 2, 3,) }) == (12)));
107+
assert!(((unsafe { init_pack_7(1, 2, 3,) }) == (9)));
108+
assert!(((unsafe { implicit_8(4, 5,) }) == (9)));
109+
return 0;
110+
}
111+
pub unsafe fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)