Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3476,7 +3476,7 @@ std::string Converter::GetRecordName(const clang::NamedDecl *decl) const {
if (auto it = inner_structs_.find(ID); it != inner_structs_.end()) {
return it->second;
}
return ReplaceAll(Mapper::ToString(decl), "::", "_");
return Mapper::ToRustName(Mapper::ToString(Mapper::GetTypeForDecl(decl)));
}

std::vector<const char *>
Expand Down
34 changes: 32 additions & 2 deletions cpp2rust/converter/mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,9 +723,30 @@ bool ParamIsPointer(const clang::Expr *expr, unsigned index) {
return GetParamInfo(expr, index).is_pointer();
}

clang::QualType GetTypeForDecl(const clang::NamedDecl *decl) {
if (const auto *spec =
llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
llvm::ArrayRef<clang::TemplateArgument> args =
spec->getTemplateArgs().asArray();
llvm::SmallVector<clang::TemplateArgument, 4> canon(args.begin(),
args.end());
ctx_->canonicalizeTemplateArguments(canon);

return ctx_->getTemplateSpecializationType(
clang::ElaboratedTypeKeyword::None,
clang::TemplateName(spec->getSpecializedTemplate()), args, canon);
}

const auto *rdecl = llvm::dyn_cast<clang::TagDecl>(decl);
assert(rdecl && "Unsupported decl type");

return ctx_->getTagType(clang::ElaboratedTypeKeyword::None,
rdecl->getQualifier(), rdecl, /*OwnsTag*/ false);
}

void AddRuleForUserDefinedType(clang::NamedDecl *decl) {
auto cpp_name = ToString(decl);
auto rs_name = ReplaceAll(cpp_name, "::", "_");
auto cpp_name = ToString(GetTypeForDecl(decl));
auto rs_name = ToRustName(cpp_name);

AddTypeRule(cpp_name, TranslationRule::TypeRule::Plain(rs_name));

Expand Down Expand Up @@ -767,6 +788,15 @@ void AddRuleForUserDefinedType(clang::NamedDecl *decl) {
}
}

std::string ToRustName(std::string name) {
size_t pos = 0;
while ((pos = name.find_first_of("<>, ", pos)) != std::string::npos) {
name[pos] = '_';
++pos;
}
return ReplaceAll(name, "::", "_");
}

std::string ToString(clang::QualType qual_type, ScalarSugar sugar) {
assert(ctx_);

Expand Down
2 changes: 2 additions & 0 deletions cpp2rust/converter/mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ enum class ScalarSugar {
kPreserve,
};

clang::QualType GetTypeForDecl(const clang::NamedDecl *decl);
std::string ToString(clang::QualType qual_type,
ScalarSugar sugar = ScalarSugar::kDesugar);
std::string ToString(const clang::Expr *expr);
std::string ToString(const clang::NamedDecl *decl);
std::string ToRustName(std::string name);

void LoadTranslationRules(Model model, clang::ASTContext &ctx,
const std::string &rules_dir);
Expand Down
43 changes: 43 additions & 0 deletions tests/unit/class_templates.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <cassert>
#include <vector>

template <typename T> class MyContainer {
std::vector<T> vec;

public:
using value_type = T;
using reference = T &;
using const_reference = const T &;
using size_type = std::size_t;

bool empty() const { return vec.empty(); }
size_type size() const { return vec.size(); }
const_reference back() const { return vec.back(); }
reference back() { return vec.back(); }
void pop_back() { return vec.pop_back(); }
void push_back(const_reference item) { vec.push_back(item); }
};

int main() {
MyContainer<int> imc;
assert(imc.empty());
imc.push_back(1);
assert(imc.size() == 1 && imc.back() == 1);
imc.pop_back();
assert(imc.empty());

MyContainer<char> cmc;
assert(cmc.empty());
cmc.push_back('a');
assert(cmc.size() == 1 && cmc.back() == 'a');
cmc.pop_back();
assert(cmc.empty());

MyContainer<float> fmc;
assert(fmc.empty());
fmc.push_back(1.0);
assert(fmc.size() == 1 && fmc.back() == 1.0);
fmc.pop_back();
assert(fmc.empty());
return 0;
}
160 changes: 160 additions & 0 deletions tests/unit/out/refcount/class_templates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
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};
#[derive(Default)]
pub struct MyContainer_int_ {
vec_: Value<Vec<i32>>,
}
impl MyContainer_int_ {
pub fn empty(&self) -> bool {
return (*self.vec_.borrow()).is_empty();
}
pub fn size(&self) -> usize {
return (*self.vec_.borrow()).len();
}
pub fn back_const(&self) -> Ptr<i32> {
return (self.vec_.as_pointer() as Ptr<i32>).to_last();
}
pub fn back(&self) -> Ptr<i32> {
return (self.vec_.as_pointer() as Ptr<i32>).to_last();
}
pub fn pop_back(&self) {
(*self.vec_.borrow_mut()).pop();
return;
}
pub fn push_back(&self, item: Ptr<i32>) {
{
let a0_clone = (item.read()).clone();
(*self.vec_.borrow_mut()).push(a0_clone)
};
}
}
impl Clone for MyContainer_int_ {
fn clone(&self) -> Self {
let mut this = Self {
vec_: Rc::new(RefCell::new((*self.vec_.borrow()).clone())),
};
this
}
}
impl ByteRepr for MyContainer_int_ {}
#[derive(Default)]
pub struct MyContainer_char_ {
vec_: Value<Vec<u8>>,
}
impl MyContainer_char_ {
pub fn empty(&self) -> bool {
return (*self.vec_.borrow()).is_empty();
}
pub fn size(&self) -> usize {
return (*self.vec_.borrow()).len();
}
pub fn back_const(&self) -> Ptr<u8> {
return (self.vec_.as_pointer() as Ptr<u8>).to_last();
}
pub fn back(&self) -> Ptr<u8> {
return (self.vec_.as_pointer() as Ptr<u8>).to_last();
}
pub fn pop_back(&self) {
(*self.vec_.borrow_mut()).pop();
return;
}
pub fn push_back(&self, item: Ptr<u8>) {
{
let a0_clone = (item.read()).clone();
(*self.vec_.borrow_mut()).push(a0_clone)
};
}
}
impl Clone for MyContainer_char_ {
fn clone(&self) -> Self {
let mut this = Self {
vec_: Rc::new(RefCell::new((*self.vec_.borrow()).clone())),
};
this
}
}
impl ByteRepr for MyContainer_char_ {}
#[derive(Default)]
pub struct MyContainer_float_ {
vec_: Value<Vec<f32>>,
}
impl MyContainer_float_ {
pub fn empty(&self) -> bool {
return (*self.vec_.borrow()).is_empty();
}
pub fn size(&self) -> usize {
return (*self.vec_.borrow()).len();
}
pub fn back_const(&self) -> Ptr<f32> {
return (self.vec_.as_pointer() as Ptr<f32>).to_last();
}
pub fn back(&self) -> Ptr<f32> {
return (self.vec_.as_pointer() as Ptr<f32>).to_last();
}
pub fn pop_back(&self) {
(*self.vec_.borrow_mut()).pop();
return;
}
pub fn push_back(&self, item: Ptr<f32>) {
{
let a0_clone = (item.read()).clone();
(*self.vec_.borrow_mut()).push(a0_clone)
};
}
}
impl Clone for MyContainer_float_ {
fn clone(&self) -> Self {
let mut this = Self {
vec_: Rc::new(RefCell::new((*self.vec_.borrow()).clone())),
};
this
}
}
impl ByteRepr for MyContainer_float_ {}
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
let imc: Value<MyContainer_int_> = Rc::new(RefCell::new(<MyContainer_int_>::default()));
assert!(({ (*imc.borrow()).empty() }));
({
let _item: Value<i32> = Rc::new(RefCell::new(1));
(*imc.borrow()).push_back(_item.as_pointer())
});
assert!(
(({ (*imc.borrow()).size() }) == 1_usize) && ((({ (*imc.borrow()).back() }).read()) == 1)
);
({ (*imc.borrow()).pop_back() });
assert!(({ (*imc.borrow()).empty() }));
let cmc: Value<MyContainer_char_> = Rc::new(RefCell::new(<MyContainer_char_>::default()));
assert!(({ (*cmc.borrow()).empty() }));
({
let _item: Value<u8> = Rc::new(RefCell::new(('a' as u8)));
(*cmc.borrow()).push_back(_item.as_pointer())
});
assert!(
(({ (*cmc.borrow()).size() }) == 1_usize)
&& (((({ (*cmc.borrow()).back() }).read()) as i32) == (('a' as u8) as i32))
);
({ (*cmc.borrow()).pop_back() });
assert!(({ (*cmc.borrow()).empty() }));
let fmc: Value<MyContainer_float_> = Rc::new(RefCell::new(<MyContainer_float_>::default()));
assert!(({ (*fmc.borrow()).empty() }));
({
let _item: Value<f32> = Rc::new(RefCell::new((1.0E+0 as f32)));
(*fmc.borrow()).push_back(_item.as_pointer())
});
assert!(
(({ (*fmc.borrow()).size() }) == 1_usize)
&& (((({ (*fmc.borrow()).back() }).read()) as f64) == 1.0E+0)
);
({ (*fmc.borrow()).pop_back() });
assert!(({ (*fmc.borrow()).empty() }));
return 0;
}
Loading
Loading