-
Notifications
You must be signed in to change notification settings - Fork 13
Fix class template translations #195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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)); | ||
|
|
||
|
|
@@ -767,6 +788,16 @@ void AddRuleForUserDefinedType(clang::NamedDecl *decl) { | |
| } | ||
| } | ||
|
|
||
| std::string ToRustName(std::string name) { | ||
| size_t pos = 0; | ||
| std::string chars = "<>, "; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove this var to avoid allocations (inline in find_first_of) |
||
| while ((pos = name.find_first_of(chars, pos)) != std::string::npos) { | ||
| name.replace(pos, 1, 1, '_'); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. name[pos] = '_'; |
||
| ++pos; | ||
| } | ||
| return ReplaceAll(name, "::", "_"); | ||
| } | ||
|
|
||
| std::string ToString(clang::QualType qual_type, ScalarSugar sugar) { | ||
| assert(ctx_); | ||
|
|
||
|
|
||
| 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('a'); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1.0? |
||
| assert(fmc.size() == 1 && fmc.back() == 'a'); | ||
| fmc.pop_back(); | ||
| assert(fmc.empty()); | ||
| return 0; | ||
| } | ||
| 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((('a' as u8) as f32))); | ||
| (*fmc.borrow()).push_back(_item.as_pointer()) | ||
| }); | ||
| assert!( | ||
| (({ (*fmc.borrow()).size() }) == 1_usize) | ||
| && ((({ (*fmc.borrow()).back() }).read()) == ((('a' as u8) as i32) as f32)) | ||
| ); | ||
| ({ (*fmc.borrow()).pop_back() }); | ||
| assert!(({ (*fmc.borrow()).empty() })); | ||
| return 0; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe Mapper::ToString is a better place to do these replaces. We already have some similar replaces that we do to normalize the output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ToStringhandles converting a given C++ construct to its corresponding string representation, whereasToRustNameis responsible for transforming the string representation of an arbitrary C++ construct into a valid Rust name. Given this distinction, wouldn't it be clearer to keep these two functions separate?Additionally, this normalization is only required when we want to use the string representation of a given C++ construct as a Rust name. It is not required for the other uses of
ToString, such as obtaining the string representation of a construct in order to look up or insert a translation rule.