Skip to content

Commit af9c736

Browse files
committed
Generate unique names for unnamed template parameters
Fixes rust-lang#446
1 parent bdd034b commit af9c736

File tree

6 files changed

+70
-12
lines changed

6 files changed

+70
-12
lines changed

src/ir/comp.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -627,13 +627,15 @@ impl CompInfo {
627627
// Yes! You can arrive here with an empty template parameter
628628
// name! Awesome, isn't it?
629629
//
630-
// see tests/headers/empty_template_param_name.hpp
631-
if cur.spelling().is_empty() {
632-
return CXChildVisit_Continue;
633-
}
630+
// See tests/headers/empty_template_param_name.hpp
631+
let name = cur.spelling();
632+
let name = if name.is_empty() {
633+
format!("__anon_named_type_{}", ctx.allocate_anon_named_type_id())
634+
} else {
635+
name
636+
};
634637

635-
let param =
636-
Item::named_type(cur.spelling(), potential_id, ctx);
638+
let param = Item::named_type(name, potential_id, ctx);
637639
ci.template_args.push(param);
638640
}
639641
CXCursor_CXXBaseSpecifier => {

src/ir/context.rs

+31
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ pub struct BindgenContext<'ctx> {
141141

142142
/// Whether a bindgen complex was generated
143143
generated_bindegen_complex: Cell<bool>,
144+
145+
/// Counter for making our generated names for anonymous named types unique.
146+
anon_named_type_counter: usize,
144147
}
145148

146149
impl<'ctx> BindgenContext<'ctx> {
@@ -178,6 +181,7 @@ impl<'ctx> BindgenContext<'ctx> {
178181
translation_unit: translation_unit,
179182
options: options,
180183
generated_bindegen_complex: Cell::new(false),
184+
anon_named_type_counter: 0,
181185
};
182186

183187
me.add_item(root_module, None, None);
@@ -1145,6 +1149,33 @@ impl<'ctx> BindgenContext<'ctx> {
11451149
pub fn need_bindegen_complex_type(&self) -> bool {
11461150
self.generated_bindegen_complex.get()
11471151
}
1152+
1153+
/// We must generate a unique name for unnamed template parameters.
1154+
///
1155+
/// For example:
1156+
///
1157+
/// ```c++
1158+
/// template <typename> Foo { int x; };
1159+
/// ```
1160+
///
1161+
/// Must become something like this:
1162+
///
1163+
/// ```ignore
1164+
/// struct Foo<__anon_named_type_36> {
1165+
/// x: std::os::raw::c_int,
1166+
/// _phantom_0: PhantomData<__anon_named_type_36>,
1167+
/// }
1168+
/// ```
1169+
///
1170+
/// Ideally, this counter would only be locally unique within an Item's
1171+
/// direct siblings, parent, and children. However, we currently construct
1172+
/// these names at parse time, before each item has a local ID, and it isn't
1173+
/// clear that the extant local ID is unique enough for this purpose.
1174+
pub fn allocate_anon_named_type_id(&mut self) -> usize {
1175+
let id = self.anon_named_type_counter;
1176+
self.anon_named_type_counter += 1;
1177+
id
1178+
}
11481179
}
11491180

11501181
/// An iterator over whitelisted items.

tests/expectations/tests/bad-namespace-parenthood-inheritance.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ pub struct std_char_traits<_CharT> {
1111
pub _phantom_0: ::std::marker::PhantomData<_CharT>,
1212
}
1313
#[repr(C)]
14-
#[derive(Debug, Copy)]
15-
pub struct __gnu_cxx_char_traits {
14+
#[derive(Debug, Copy, Clone)]
15+
pub struct __gnu_cxx_char_traits<__bindgen_named_type_0> {
1616
pub _address: u8,
17-
}
18-
impl Clone for __gnu_cxx_char_traits {
19-
fn clone(&self) -> Self { *self }
17+
pub _phantom_0: ::std::marker::PhantomData<__bindgen_named_type_0>,
2018
}

tests/expectations/tests/empty_template_param_name.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
pub type __void_t = ::std::os::raw::c_void;
88
#[repr(C)]
99
#[derive(Debug, Copy, Clone)]
10-
pub struct __iterator_traits<_Iterator> {
10+
pub struct __iterator_traits<_Iterator, __bindgen_named_type_0> {
1111
pub _address: u8,
1212
pub _phantom_0: ::std::marker::PhantomData<_Iterator>,
13+
pub _phantom_1: ::std::marker::PhantomData<__bindgen_named_type_0>,
1314
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
pub mod root {
8+
#[allow(unused_imports)]
9+
use self::super::root;
10+
#[repr(C)]
11+
#[derive(Debug, Copy, Clone)]
12+
pub struct a<__bindgen_named_type_0> {
13+
pub _address: u8,
14+
pub _phantom_0: ::std::marker::PhantomData<__bindgen_named_type_0>,
15+
}
16+
pub type b<T> = root::a<T>;
17+
#[repr(C)]
18+
#[derive(Debug, Copy, Clone)]
19+
pub struct Rooted<T> {
20+
pub c: root::b<T>,
21+
}
22+
}
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// bindgen-flags: --enable-cxx-namespaces -- --std=c++14
2+
template <typename> struct a {};
3+
template <typename T> using b = a<T>;
4+
template <typename T> class Rooted { b<T> c; };

0 commit comments

Comments
 (0)