Skip to content

Commit b662443

Browse files
committed
Generate better opaque blobs in the face of non-type parameters
When instantiating templates whose definitions have non-type generic parameters, prefer the layout of the instantiation type to the garbage we get from the definition's layout. In general, an instantiation's layout will always be a better choice than the definition's layout, regardless of non-type parameters. Fixes #569
1 parent 72ab471 commit b662443

7 files changed

+148
-6
lines changed

src/codegen/mod.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,13 @@ impl CodeGenerator for Type {
561561
let layout = self.layout(ctx).unwrap_or_else(Layout::zero);
562562
BlobTyBuilder::new(layout).build()
563563
} else {
564-
inner_item.to_rust_ty(ctx)
564+
let inner_rust_ty = inner_item.to_rust_ty(ctx);
565+
if inner_rust_ty == aster::AstBuilder::new().ty().unit() {
566+
let layout = self.layout(ctx).unwrap_or_else(|| Layout::for_size(1));
567+
BlobTyBuilder::new(layout).build()
568+
} else {
569+
inner_rust_ty
570+
}
565571
};
566572

567573
{
@@ -2356,12 +2362,14 @@ impl ToRustTy for TemplateInstantiation {
23562362
let decl = self.template_definition();
23572363
let mut ty = decl.to_rust_ty(ctx).unwrap();
23582364

2359-
// If we gave up when making a type for the template definition,
2360-
// check if maybe we can make a better opaque blob for the
2361-
// instantiation.
23622365
if ty == aster::AstBuilder::new().ty().unit().unwrap() {
2366+
// If we gave up when making a type for the template definition,
2367+
// check if maybe we can make a better opaque blob for the
2368+
// instantiation. If not, at least don't use a zero-sized type.
23632369
if let Some(layout) = self_ty.layout(ctx) {
23642370
return BlobTyBuilder::new(layout).build();
2371+
} else {
2372+
return quote_ty!(ctx.ext_cx(), u8);
23652373
}
23662374
}
23672375

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
pub const ENUM_VARIANT_1: _bindgen_ty_1 = _bindgen_ty_1::ENUM_VARIANT_1;
8+
pub const ENUM_VARIANT_2: _bindgen_ty_1 = _bindgen_ty_1::ENUM_VARIANT_2;
9+
#[repr(u32)]
10+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
11+
pub enum _bindgen_ty_1 { ENUM_VARIANT_1 = 0, ENUM_VARIANT_2 = 1, }
12+
pub type JS_Alias = u8;
13+
#[repr(C)]
14+
pub struct JS_Base {
15+
pub f: JS_Alias,
16+
}
17+
impl Default for JS_Base {
18+
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
19+
}
20+
#[repr(C)]
21+
pub struct JS_AutoIdVector {
22+
pub _base: JS_Base,
23+
}
24+
#[test]
25+
fn bindgen_test_layout_JS_AutoIdVector() {
26+
assert_eq!(::std::mem::size_of::<JS_AutoIdVector>() , 1usize , concat ! (
27+
"Size of: " , stringify ! ( JS_AutoIdVector ) ));
28+
assert_eq! (::std::mem::align_of::<JS_AutoIdVector>() , 1usize , concat !
29+
( "Alignment of " , stringify ! ( JS_AutoIdVector ) ));
30+
}
31+
impl Default for JS_AutoIdVector {
32+
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
33+
}
34+
#[test]
35+
fn __bindgen_test_layout_JS_Base_instantiation_16() {
36+
assert_eq!(::std::mem::size_of::<JS_Base>() , 1usize , concat ! (
37+
"Size of template specialization: " , stringify ! ( JS_Base )
38+
));
39+
assert_eq!(::std::mem::align_of::<JS_Base>() , 1usize , concat ! (
40+
"Alignment of template specialization: " , stringify ! (
41+
JS_Base ) ));
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
pub type Array16 = u8;
8+
pub type ArrayInt4 = [u32; 4usize];
9+
#[repr(C)]
10+
pub struct UsesArray {
11+
pub array_char_16: [u8; 16usize],
12+
pub array_bool_8: [u8; 8usize],
13+
pub array_int_4: ArrayInt4,
14+
}
15+
#[test]
16+
fn bindgen_test_layout_UsesArray() {
17+
assert_eq!(::std::mem::size_of::<UsesArray>() , 40usize , concat ! (
18+
"Size of: " , stringify ! ( UsesArray ) ));
19+
assert_eq! (::std::mem::align_of::<UsesArray>() , 4usize , concat ! (
20+
"Alignment of " , stringify ! ( UsesArray ) ));
21+
assert_eq! (unsafe {
22+
& ( * ( 0 as * const UsesArray ) ) . array_char_16 as * const
23+
_ as usize } , 0usize , concat ! (
24+
"Alignment of field: " , stringify ! ( UsesArray ) , "::" ,
25+
stringify ! ( array_char_16 ) ));
26+
assert_eq! (unsafe {
27+
& ( * ( 0 as * const UsesArray ) ) . array_bool_8 as * const _
28+
as usize } , 16usize , concat ! (
29+
"Alignment of field: " , stringify ! ( UsesArray ) , "::" ,
30+
stringify ! ( array_bool_8 ) ));
31+
assert_eq! (unsafe {
32+
& ( * ( 0 as * const UsesArray ) ) . array_int_4 as * const _
33+
as usize } , 24usize , concat ! (
34+
"Alignment of field: " , stringify ! ( UsesArray ) , "::" ,
35+
stringify ! ( array_int_4 ) ));
36+
}
37+
impl Default for UsesArray {
38+
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
39+
}
40+
#[test]
41+
fn __bindgen_test_layout_Array_instantiation_18() {
42+
assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat ! (
43+
"Size of template specialization: " , stringify ! (
44+
[u32; 4usize] ) ));
45+
assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat ! (
46+
"Alignment of template specialization: " , stringify ! (
47+
[u32; 4usize] ) ));
48+
}

tests/expectations/tests/opaque_pointer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl Default for Opaque {
3535
#[repr(C)]
3636
#[derive(Debug, Copy)]
3737
pub struct WithOpaquePtr {
38-
pub whatever: *mut (),
38+
pub whatever: *mut u8,
3939
pub other: u32,
4040
pub t: OtherOpaque,
4141
}

tests/expectations/tests/type_alias_empty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
#![allow(non_snake_case)]
55

66

7-
pub type bool_constant = ();
7+
pub type bool_constant = u8;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// bindgen-flags: -- -std=c++14
2+
3+
// Generated by C-Reduce, cleaned up and given names for readability.
4+
5+
template <int, typename>
6+
struct HasNonTypeTemplateParam {
7+
// But doesn't use the non-type template param nor its type param...
8+
};
9+
10+
enum {
11+
ENUM_VARIANT_1,
12+
ENUM_VARIANT_2
13+
};
14+
15+
namespace JS {
16+
17+
template <typename T>
18+
using Alias = HasNonTypeTemplateParam<ENUM_VARIANT_1, T>;
19+
20+
template <typename U>
21+
class Base {
22+
Alias<U> f;
23+
};
24+
25+
class AutoIdVector : Base<int> {};
26+
27+
}

tests/headers/non-type-params.hpp

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// bindgen-flags: -- -std=c++14
2+
3+
template <typename T, unsigned int Capacity>
4+
struct Array {
5+
T elements[Capacity];
6+
};
7+
8+
template <typename T>
9+
using Array16 = Array<T, 16>;
10+
11+
using ArrayInt4 = Array<int, 4>;
12+
13+
struct UsesArray {
14+
Array16<char> array_char_16;
15+
Array<bool, 8> array_bool_8;
16+
ArrayInt4 array_int_4;
17+
};

0 commit comments

Comments
 (0)