diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2017-03-10 10:46:50 -0800 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2017-03-10 13:53:17 -0800 |
commit | 414442638a913bf5d924f9b16b2ae417cde5840b (patch) | |
tree | 1077c528aaaea889a6a038fe50ab063c5f5bb041 | |
parent | 1320efeb79d373acb8dd92fb2722732c251497d8 (diff) |
Allow anonymous template types
We have various assertions that the only way that some template parameter
related methods will return `None` is if the template definition is marked
opaque. These assertions fail in the presence of test cases with unnamed
template types, because we never save an IR item for the template type, and
subsequently think that the template definition has no template parameters. The
assertions are in fact sound and correct, so it doesn't make sense to remove
them. Instead it is more correct to save IR items for the anonymous template
types and simply let the template usage analysis prevent them from getting
codegen'd.
Fixes #574
-rw-r--r-- | src/ir/comp.rs | 8 | ||||
-rw-r--r-- | src/ir/item.rs | 16 | ||||
-rw-r--r-- | src/ir/ty.rs | 14 | ||||
-rw-r--r-- | tests/expectations/tests/anonymous-template-types.rs | 33 | ||||
-rw-r--r-- | tests/expectations/tests/bad-namespace-parenthood-inheritance.rs | 10 | ||||
-rw-r--r-- | tests/expectations/tests/issue-358.rs | 5 | ||||
-rw-r--r-- | tests/expectations/tests/issue-544-stylo-creduce.rs | 5 | ||||
-rw-r--r-- | tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs | 2 | ||||
-rw-r--r-- | tests/expectations/tests/issue-574-assertion-failure-in-codegen.rs | 38 | ||||
-rw-r--r-- | tests/headers/anonymous-template-types.hpp | 24 | ||||
-rw-r--r-- | tests/headers/issue-574-assertion-failure-in-codegen.hpp | 6 |
11 files changed, 129 insertions, 32 deletions
diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 814204c2..9a6548a7 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -597,14 +597,6 @@ impl CompInfo { ci.packed = true; } CXCursor_TemplateTypeParameter => { - // Yes! You can arrive here with an empty template parameter - // name! Awesome, isn't it? - // - // see tests/headers/empty_template_param_name.hpp - if cur.spelling().is_empty() { - return CXChildVisit_Continue; - } - let param = Item::named_type(None, cur, ctx) .expect("Item::named_type should't fail when pointing \ at a TemplateTypeParameter"); diff --git a/src/ir/item.rs b/src/ir/item.rs index 93df9c77..89422e87 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -19,6 +19,7 @@ use std::collections::BTreeSet; use std::fmt::Write; use std::io; use std::iter; +use regex; /// A trait to get the canonical name from an item. /// @@ -1313,8 +1314,19 @@ impl ClangItemParser for Item { fn is_template_with_spelling(refd: &clang::Cursor, spelling: &str) -> bool { - refd.kind() == clang_sys::CXCursor_TemplateTypeParameter && - refd.spelling() == spelling + lazy_static! { + static ref ANON_TYPE_PARAM_RE: regex::Regex = + regex::Regex::new(r"^type\-parameter\-\d+\-\d+$").unwrap(); + } + + if refd.kind() != clang_sys::CXCursor_TemplateTypeParameter { + return false; + } + + let refd_spelling = refd.spelling(); + refd_spelling == spelling || + // Allow for anonymous template parameters. + (refd_spelling.is_empty() && ANON_TYPE_PARAM_RE.is_match(spelling.as_ref())) } let definition = if is_template_with_spelling(&location, diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 6c8e7363..54925696 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -292,8 +292,12 @@ impl Type { /// Creates a new named type, with name `name`. pub fn named(name: String) -> Self { - assert!(!name.is_empty()); - Self::new(Some(name), None, TypeKind::Named, false) + let name = if name.is_empty() { + None + } else { + Some(name) + }; + Self::new(name, None, TypeKind::Named, false) } /// Is this a floating point type? @@ -1127,12 +1131,6 @@ impl Type { ctx); } CXCursor_TemplateTypeParameter => { - // See the comment in src/ir/comp.rs - // about the same situation. - if cur.spelling().is_empty() { - return CXChildVisit_Continue; - } - let param = Item::named_type(None, cur, diff --git a/tests/expectations/tests/anonymous-template-types.rs b/tests/expectations/tests/anonymous-template-types.rs new file mode 100644 index 00000000..bb4be105 --- /dev/null +++ b/tests/expectations/tests/anonymous-template-types.rs @@ -0,0 +1,33 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo<T> { + pub t_member: T, +} +impl <T> Default for Foo<T> { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Bar { + pub member: ::std::os::raw::c_schar, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Quux<V> { + pub v_member: V, +} +impl <V> Default for Quux<V> { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct Lobo { + pub also_member: ::std::os::raw::c_schar, +} +pub type AliasWithAnonType = ::std::os::raw::c_schar; diff --git a/tests/expectations/tests/bad-namespace-parenthood-inheritance.rs b/tests/expectations/tests/bad-namespace-parenthood-inheritance.rs index 4074dd02..9ff4af1f 100644 --- a/tests/expectations/tests/bad-namespace-parenthood-inheritance.rs +++ b/tests/expectations/tests/bad-namespace-parenthood-inheritance.rs @@ -5,15 +5,15 @@ #[repr(C)] -#[derive(Debug, Default, Copy, Clone)] +#[derive(Debug, Copy, Clone)] pub struct std_char_traits { pub _address: u8, } +impl Default for std_char_traits { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} #[repr(C)] -#[derive(Debug, Default, Copy)] +#[derive(Debug, Default, Copy, Clone)] pub struct __gnu_cxx_char_traits { pub _address: u8, } -impl Clone for __gnu_cxx_char_traits { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/issue-358.rs b/tests/expectations/tests/issue-358.rs index e574bd01..d01ae800 100644 --- a/tests/expectations/tests/issue-358.rs +++ b/tests/expectations/tests/issue-358.rs @@ -13,13 +13,10 @@ impl Default for JS_PersistentRooted { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } #[repr(C)] -#[derive(Debug, Copy)] +#[derive(Debug, Copy, Clone)] pub struct a { pub b: *mut a, } -impl Clone for a { - fn clone(&self) -> Self { *self } -} impl Default for a { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } diff --git a/tests/expectations/tests/issue-544-stylo-creduce.rs b/tests/expectations/tests/issue-544-stylo-creduce.rs index 88cc0d87..fb543cba 100644 --- a/tests/expectations/tests/issue-544-stylo-creduce.rs +++ b/tests/expectations/tests/issue-544-stylo-creduce.rs @@ -5,10 +5,7 @@ #[repr(C)] -#[derive(Debug, Default, Copy)] +#[derive(Debug, Default, Copy, Clone)] pub struct a { pub _address: u8, } -impl Clone for a { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs b/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs index 6cf2ba16..c4ce5139 100644 --- a/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs +++ b/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs @@ -32,7 +32,7 @@ impl Default for JS_AutoIdVector { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } #[test] -fn __bindgen_test_layout_JS_Base_instantiation_16() { +fn __bindgen_test_layout_JS_Base_instantiation_20() { assert_eq!(::std::mem::size_of::<JS_Base>() , 1usize , concat ! ( "Size of template specialization: " , stringify ! ( JS_Base ) )); diff --git a/tests/expectations/tests/issue-574-assertion-failure-in-codegen.rs b/tests/expectations/tests/issue-574-assertion-failure-in-codegen.rs new file mode 100644 index 00000000..084cdb62 --- /dev/null +++ b/tests/expectations/tests/issue-574-assertion-failure-in-codegen.rs @@ -0,0 +1,38 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct a { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct _bindgen_ty_1 { + pub ar: a, +} +#[test] +fn bindgen_test_layout__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 1usize , concat ! ( + "Size of: " , stringify ! ( _bindgen_ty_1 ) )); + assert_eq! (::std::mem::align_of::<_bindgen_ty_1>() , 1usize , concat ! ( + "Alignment of " , stringify ! ( _bindgen_ty_1 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const _bindgen_ty_1 ) ) . ar as * const _ as + usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( _bindgen_ty_1 ) , "::" + , stringify ! ( ar ) )); +} +impl Clone for _bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +impl Default for _bindgen_ty_1 { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +extern "C" { + #[link_name = "AutoIdVector"] + pub static mut AutoIdVector: _bindgen_ty_1; +} diff --git a/tests/headers/anonymous-template-types.hpp b/tests/headers/anonymous-template-types.hpp new file mode 100644 index 00000000..9ada71a9 --- /dev/null +++ b/tests/headers/anonymous-template-types.hpp @@ -0,0 +1,24 @@ +// bindgen-flags: -- -std=c++14 + +template <typename T, typename> +struct Foo { + T t_member; +}; + +template <typename U, typename> +struct Bar { + char member; +}; + +template <typename, typename V> +struct Quux { + V v_member; +}; + +template <typename, typename W> +struct Lobo { + char also_member; +}; + +template <typename> +using AliasWithAnonType = char; diff --git a/tests/headers/issue-574-assertion-failure-in-codegen.hpp b/tests/headers/issue-574-assertion-failure-in-codegen.hpp new file mode 100644 index 00000000..b563b4ef --- /dev/null +++ b/tests/headers/issue-574-assertion-failure-in-codegen.hpp @@ -0,0 +1,6 @@ +// bindgen-flags: -- -std=c++14 + +template <class> class a {}; +class { + a<int> ar; +} AutoIdVector; |