diff options
-rw-r--r-- | src/parser.rs | 66 | ||||
-rw-r--r-- | tests/expectations/nsStyleAutoArray.rs | 23 | ||||
-rw-r--r-- | tests/expectations/template.rs | 26 | ||||
-rw-r--r-- | tests/headers/nsStyleAutoArray.hpp | 57 | ||||
-rw-r--r-- | tests/headers/template.hpp | 33 |
5 files changed, 195 insertions, 10 deletions
diff --git a/src/parser.rs b/src/parser.rs index 78f60709..26a03ed2 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -213,7 +213,7 @@ fn opaque_decl(ctx: &mut ClangParserCtx, decl: &Cursor) { ctx.current_module_mut().globals.push(name); } -fn fwd_decl<F:FnOnce(&mut ClangParserCtx)->()>(ctx: &mut ClangParserCtx, cursor: &Cursor, f: F) { +fn fwd_decl<F: FnOnce(&mut ClangParserCtx)->()>(ctx: &mut ClangParserCtx, cursor: &Cursor, f: F) { let def = cursor.definition(); if cursor == &def { f(ctx); @@ -568,10 +568,11 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, // NB: Overwritten in the case of non-integer bitfield let mut ty = conv_ty_resolving_typedefs(ctx, - &cursor.cur_type(), + &cursor_ty, cursor, is_class_typedef); + use std::cell::BorrowState; if let Some(child_ci) = ty.get_outermost_composite() { if let BorrowState::Unused = child_ci.borrow_state() { @@ -579,10 +580,12 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, let child_cursor = child_ci.parser_cursor.unwrap(); // TODO: This is lame, ideally we should use cursors. - // The problem this is trying to solve is - // tests/headers/inner_template_self.hpp. + // The problem this loop is trying to solve is + // tests/headers/inner_template_self.hpp, and templates with + // incomplete types. // - // The problem with this is that clang treats the *prev* + // The problem with this is that, in the first case (see the + // CXCursor_ClassDecl branch below) clang treats the *prev* // field as a Class Declaration instead of a Class Template, // so we have to check now for the name and the module id. // @@ -594,11 +597,44 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, // Also, there could be more complex cases, like a templated // type in an inner type declaration, that this is // completely unable to catch. - if child_cursor.kind() == CXCursor_ClassDecl && - child_ci.args.is_empty() && - child_ci.name == ci.name && - child_ci.module_id == ci.module_id { - child_ci.args = ci.args.clone(); + // + // In the second case (the CXCursor_ClassTemplate branch), + // we're not able to retrieve the template parameters of an + // incomplete type via the declaration or anything like + // that. We can inspect the AST and deduct them though, + // since there's a leading CXCursor_TemplateRef. + if child_ci.args.is_empty() { + // println!("child: {:?} {:?}, {:?}, {:?}", cursor.spelling(), + // type_to_str(cursor_ty.kind()), + // type_to_str(child_cursor.cur_type().kind()), + // kind_to_str(child_cursor.kind())); + match child_cursor.kind() { + CXCursor_ClassDecl => { + child_ci.args = ci.args.clone(); + } + CXCursor_ClassTemplate => { + let mut found_invalid_template_ref = false; + cursor.visit(|c, _| { + // println!("ichild: {:?} {:?}, {:?}", c.spelling(), + // kind_to_str(c.kind()), + // type_to_str(c.cur_type().kind())); + if c.kind() == CXCursor_TemplateRef && + c.cur_type().kind() == CXType_Invalid { + found_invalid_template_ref = true; + } + if found_invalid_template_ref && + c.kind() == CXCursor_TypeRef { + child_ci.args.push(TNamed(Rc::new(RefCell::new( + TypeInfo::new(c.spelling(), + ctx.current_module_id, + TVoid, + Layout::zero()))))); + } + CXChildVisit_Continue + }) + } + _ => {} + } } } } @@ -728,6 +764,13 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, let new_name = [&*ci.name, &*ci2.borrow().name].join("_").to_owned(); ci2.borrow_mut().name = new_name; + // This clear() is needed because of the speculation we do on + // incomplete types inside visit_composite() members. + // + // If this type ends up being complete, we're going to really + // parse them now, so we should reset them. + ci2.borrow_mut().args.clear(); + // Propagate template arguments and typedefs to inner structs ci2.borrow_mut().args.extend(ci.args.clone().into_iter()); ci2.borrow_mut().typedefs.extend(ci.typedefs.clone().into_iter()); @@ -998,6 +1041,9 @@ fn visit_top(cursor: &Cursor, fwd_decl(ctx, cursor, move |ctx_| { let decl = decl_name(ctx_, cursor); let ci = decl.compinfo(); + // This clear() is needed because of the speculation we do + // on incomplete types inside visit_composite() members. + ci.borrow_mut().args.clear(); cursor.visit(|c, p| { let mut ci_ = ci.borrow_mut(); visit_composite(c, p, ctx_, &mut ci_) diff --git a/tests/expectations/nsStyleAutoArray.rs b/tests/expectations/nsStyleAutoArray.rs new file mode 100644 index 00000000..28207639 --- /dev/null +++ b/tests/expectations/nsStyleAutoArray.rs @@ -0,0 +1,23 @@ +/* automatically generated by rust-bindgen */ + + +#![feature(const_fn)] +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Struct_nsTArray<T> { + pub mBuff: *mut T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Struct_nsStyleAutoArray<T> { + pub mFirstElement: T, + pub mOtherElements: Struct_nsTArray<T>, +} +#[repr(i32)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum nsStyleAutoArray_WithSingleInitialElement { + WITH_SINGLE_INITIAL_ELEMENT = 0, +} diff --git a/tests/expectations/template.rs b/tests/expectations/template.rs index 63f2d952..8f8d02c1 100644 --- a/tests/expectations/template.rs +++ b/tests/expectations/template.rs @@ -74,6 +74,32 @@ fn bindgen_test_layout_Struct_POD() { assert_eq!(::std::mem::size_of::<Struct_POD>() , 4usize); assert_eq!(::std::mem::align_of::<Struct_POD>() , 4usize); } +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Struct_NestedBase<T, U> { + pub buff: *mut T, + pub _phantom0: ::std::marker::PhantomData<U>, +} +/** + * <div rustbindgen replaces="NestedReplaced"></div> + */ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Struct_NestedReplaced<T> { + pub buff: *mut T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Struct_NestedContainer<T> { + pub c: T, + pub nested: Struct_NestedReplaced<T>, + pub inc: Struct_Incomplete<T>, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Struct_Incomplete<T> { + pub d: T, +} extern "C" { #[link_name = "_Z3bar3FooIiiE"] pub fn bar(foo: Struct_Foo<::std::os::raw::c_int, ::std::os::raw::c_int>); diff --git a/tests/headers/nsStyleAutoArray.hpp b/tests/headers/nsStyleAutoArray.hpp new file mode 100644 index 00000000..950152c0 --- /dev/null +++ b/tests/headers/nsStyleAutoArray.hpp @@ -0,0 +1,57 @@ + +template<typename T> +class nsTArray { + T* mBuff; +}; + +template<typename T> +class nsStyleAutoArray +{ +public: + // This constructor places a single element in mFirstElement. + enum WithSingleInitialElement { WITH_SINGLE_INITIAL_ELEMENT }; + explicit nsStyleAutoArray(WithSingleInitialElement) {} + nsStyleAutoArray(const nsStyleAutoArray& aOther) { *this = aOther; } + nsStyleAutoArray& operator=(const nsStyleAutoArray& aOther) { + mFirstElement = aOther.mFirstElement; + mOtherElements = aOther.mOtherElements; + return *this; + } + + bool operator==(const nsStyleAutoArray& aOther) const { + return Length() == aOther.Length() && + mFirstElement == aOther.mFirstElement && + mOtherElements == aOther.mOtherElements; + } + bool operator!=(const nsStyleAutoArray& aOther) const { + return !(*this == aOther); + } + + unsigned long Length() const { + return mOtherElements.Length() + 1; + } + const T& operator[](unsigned long aIndex) const { + return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1]; + } + T& operator[](unsigned long aIndex) { + return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1]; + } + + void EnsureLengthAtLeast(unsigned long aMinLen) { + if (aMinLen > 0) { + mOtherElements.EnsureLengthAtLeast(aMinLen - 1); + } + } + + void SetLengthNonZero(unsigned long aNewLen) { + mOtherElements.SetLength(aNewLen - 1); + } + + void TruncateLengthNonZero(unsigned long aNewLen) { + mOtherElements.TruncateLength(aNewLen - 1); + } + +private: + T mFirstElement; + nsTArray<T> mOtherElements; +}; diff --git a/tests/headers/template.hpp b/tests/headers/template.hpp index e53ecbc8..0fd8337d 100644 --- a/tests/headers/template.hpp +++ b/tests/headers/template.hpp @@ -55,3 +55,36 @@ class Opaque { class POD { Opaque<int> opaque_member; }; + +/** + * <div rustbindgen replaces="NestedReplaced"></div> + */ +template<typename T> +class Nested { + T* buff; +}; + +template<typename T, typename U> +class NestedBase { + T* buff; +}; + +template<typename T> +class NestedReplaced: public NestedBase<T, int> { +}; + +template<typename T> +class Incomplete; + +template<typename T> +class NestedContainer { + T c; +private: + NestedReplaced<T> nested; + Incomplete<T> inc; +}; + +template<typename T> +class Incomplete { + T d; +}; |