Skip to content

Commit 2012814

Browse files
authored
Fix translation of out-of-line template static methods (#393)
1 parent 676a76a commit 2012814

4 files changed

Lines changed: 145 additions & 2 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,8 @@ bool Converter::VisitCXXMethodDecl(clang::CXXMethodDecl *decl) {
10541054
if (!ShouldConvertMethod(decl)) {
10551055
return false;
10561056
}
1057-
if (!decl->isPureVirtual() && !decl->hasBody()) {
1057+
if (decl->getDescribedFunctionTemplate() || decl->isDependentContext() ||
1058+
(!decl->isPureVirtual() && !decl->hasBody())) {
10581059
return false;
10591060
}
10601061
if (!decl_ids_.insert(GetMethodID(decl)).second) {
@@ -1065,7 +1066,7 @@ bool Converter::VisitCXXMethodDecl(clang::CXXMethodDecl *decl) {
10651066
if (decl->isOutOfLine() && !decl->overridden_methods().empty()) {
10661067
return false;
10671068
}
1068-
if (decl->isOutOfLine()) {
1069+
if (decl->isOutOfLine() && !decl->isTemplateInstantiation()) {
10691070
return ConvertOutOfLineMethod(decl);
10701071
}
10711072
return ConvertCXXMethodDecl(decl);

‎tests/unit/class_templates.cpp‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,25 @@ template <typename T> class MyContainer {
1818
void push_back(const_reference item) { vec.push_back(item); }
1919
};
2020

21+
template <typename T> struct Boxed {
22+
T value;
23+
static T twice(T v);
24+
T plus(T other) const;
25+
};
26+
27+
template <typename T> T Boxed<T>::twice(T v) { return v + v; }
28+
29+
template <typename T> T Boxed<T>::plus(T other) const { return value + other; }
30+
2131
int main() {
32+
assert(Boxed<int>::twice(3) == 6);
33+
Boxed<int> bi{4};
34+
assert(bi.plus(5) == 9);
35+
36+
assert(Boxed<long>::twice(10) == 20);
37+
Boxed<long> bl{7};
38+
assert(bl.plus(1) == 8);
39+
2240
MyContainer<int> imc;
2341
assert(imc.empty());
2442
imc.push_back(1);

‎tests/unit/out/refcount/class_templates.rs‎

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,85 @@ impl ByteRepr for MyContainer_float_ {
8484
}
8585
}
8686
}
87+
#[derive(Default)]
88+
pub struct Boxed_int_ {
89+
pub value: Value<i32>,
90+
}
91+
impl Boxed_int_ {
92+
pub fn twice(v: i32) -> i32 {
93+
let v: Value<i32> = Rc::new(RefCell::new(v));
94+
return ((*v.borrow()) + (*v.borrow()));
95+
}
96+
}
97+
impl Clone for Boxed_int_ {
98+
fn clone(&self) -> Self {
99+
let __this: Value<Boxed_int_> = Rc::new(RefCell::new(Self {
100+
value: Rc::new(RefCell::new((*self.value.borrow()))),
101+
}));
102+
let this: Ptr<Boxed_int_> = __this.as_pointer();
103+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
104+
}
105+
}
106+
impl ByteRepr for Boxed_int_ {
107+
fn byte_size() -> usize {
108+
4
109+
}
110+
fn to_bytes(&self, buf: &mut [u8]) {
111+
(*self.value.borrow()).to_bytes(&mut buf[0..4]);
112+
}
113+
fn from_bytes(buf: &[u8]) -> Self {
114+
Self {
115+
value: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
116+
}
117+
}
118+
}
119+
#[derive(Default)]
120+
pub struct Boxed_long_ {
121+
pub value: Value<i64>,
122+
}
123+
impl Boxed_long_ {
124+
pub fn twice(v: i64) -> i64 {
125+
let v: Value<i64> = Rc::new(RefCell::new(v));
126+
return ((*v.borrow()) + (*v.borrow()));
127+
}
128+
}
129+
impl Clone for Boxed_long_ {
130+
fn clone(&self) -> Self {
131+
let __this: Value<Boxed_long_> = Rc::new(RefCell::new(Self {
132+
value: Rc::new(RefCell::new((*self.value.borrow()))),
133+
}));
134+
let this: Ptr<Boxed_long_> = __this.as_pointer();
135+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
136+
}
137+
}
138+
impl ByteRepr for Boxed_long_ {
139+
fn byte_size() -> usize {
140+
8
141+
}
142+
fn to_bytes(&self, buf: &mut [u8]) {
143+
(*self.value.borrow()).to_bytes(&mut buf[0..8]);
144+
}
145+
fn from_bytes(buf: &[u8]) -> Self {
146+
Self {
147+
value: Rc::new(RefCell::new(<i64>::from_bytes(&buf[0..8]))),
148+
}
149+
}
150+
}
87151
pub fn main() {
88152
__cpp2rust_init_globals();
89153
std::process::exit(main_0());
90154
}
91155
fn main_0() -> i32 {
156+
assert!((({ Boxed_int_::twice(3,) }) == 6));
157+
let bi: Value<Boxed_int_> = Rc::new(RefCell::new(Boxed_int_ {
158+
value: Rc::new(RefCell::new(4)),
159+
}));
160+
assert!((({ Boxed_int_Impl::plus(&bi.as_pointer(), 5,) }) == 9));
161+
assert!((({ Boxed_long_::twice(10_i64,) }) == 20_i64));
162+
let bl: Value<Boxed_long_> = Rc::new(RefCell::new(Boxed_long_ {
163+
value: Rc::new(RefCell::new(7_i64)),
164+
}));
165+
assert!((({ Boxed_long_Impl::plus(&bl.as_pointer(), 1_i64,) }) == 8_i64));
92166
let imc: Value<MyContainer_int_> = Rc::new(RefCell::new(<MyContainer_int_>::default()));
93167
assert!(({ MyContainer_int_Impl::empty(&imc.as_pointer(),) }));
94168
({
@@ -128,6 +202,24 @@ fn main_0() -> i32 {
128202
assert!(({ MyContainer_float_Impl::empty(&fmc.as_pointer(),) }));
129203
return 0;
130204
}
205+
pub trait Boxed_int_Impl {
206+
fn plus(&self, other: i32) -> i32;
207+
}
208+
impl Boxed_int_Impl for Ptr<Boxed_int_> {
209+
fn plus(&self, other: i32) -> i32 {
210+
let other: Value<i32> = Rc::new(RefCell::new(other));
211+
return ((*(*(*self).upgrade().deref()).value.borrow()) + (*other.borrow()));
212+
}
213+
}
214+
pub trait Boxed_long_Impl {
215+
fn plus(&self, other: i64) -> i64;
216+
}
217+
impl Boxed_long_Impl for Ptr<Boxed_long_> {
218+
fn plus(&self, other: i64) -> i64 {
219+
let other: Value<i64> = Rc::new(RefCell::new(other));
220+
return ((*(*(*self).upgrade().deref()).value.borrow()) + (*other.borrow()));
221+
}
222+
}
131223
pub trait MyContainer_char_Impl {
132224
fn empty(&self) -> bool;
133225
fn size(&self) -> usize;

‎tests/unit/out/unsafe/class_templates.rs‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,45 @@ impl MyContainer_float_ {
8484
};
8585
}
8686
}
87+
#[repr(C)]
88+
#[derive(Copy, Clone, Default)]
89+
pub struct Boxed_int_ {
90+
pub value: i32,
91+
}
92+
impl Boxed_int_ {
93+
pub unsafe fn twice(mut v: i32) -> i32 {
94+
return ((v) + (v));
95+
}
96+
pub unsafe fn plus(&self, mut other: i32) -> i32 {
97+
return ((self.value) + (other));
98+
}
99+
}
100+
#[repr(C)]
101+
#[derive(Copy, Clone, Default)]
102+
pub struct Boxed_long_ {
103+
pub value: i64,
104+
}
105+
impl Boxed_long_ {
106+
pub unsafe fn twice(mut v: i64) -> i64 {
107+
return ((v) + (v));
108+
}
109+
pub unsafe fn plus(&self, mut other: i64) -> i64 {
110+
return ((self.value) + (other));
111+
}
112+
}
87113
pub fn main() {
88114
unsafe {
89115
__cpp2rust_init_globals();
90116
std::process::exit(main_0() as i32);
91117
}
92118
}
93119
unsafe fn main_0() -> i32 {
120+
assert!(((unsafe { Boxed_int_::twice(3,) }) == (6)));
121+
let mut bi: Boxed_int_ = Boxed_int_ { value: 4 };
122+
assert!(((unsafe { Boxed_int_::plus(&bi, 5,) }) == (9)));
123+
assert!(((unsafe { Boxed_long_::twice(10_i64,) }) == (20_i64)));
124+
let mut bl: Boxed_long_ = Boxed_long_ { value: 7_i64 };
125+
assert!(((unsafe { Boxed_long_::plus(&bl, 1_i64,) }) == (8_i64)));
94126
let mut imc: MyContainer_int_ = <MyContainer_int_>::default();
95127
assert!((unsafe { MyContainer_int_::empty(&imc,) }));
96128
(unsafe {

0 commit comments

Comments
 (0)