mirror of
https://gitee.com/openharmony/third_party_rust_bindgen
synced 2024-12-14 18:49:41 +00:00
Completely rework templates
* Find each item's used template parameters when we begin the codegen phase * Add TemplateDeclaration::used_template_params() This method is available during the codegen phase, and uses the information gleaned by the `ir::named::UsedTemplateParameters` analysis. * Remove Item::{applicable_template_args,signature_contains_named_type} They are replaced by the template parameter usage analysis and TemplateDeclaration::used_template_params. * Parse and de-duplicate named template type parameters * Do not attempt to determine template parameter usage when not recursively whitelisting * Add a proper TemplateInstantiation type This makes it so that CompInfo is always either a compound type definition, or a template compound type definition, never an instantiation of a template. It also pulls out TypeKind::TemplateInstantiation(<inline stuff>) to a proper ir::TemplateInstantiation type, and TypeKind::TemplateInstantiation just wraps ir::TemplateInstantiation into TypeKind. * Allow template definitions to lack template parameters because of opaque template definitions * Detect and ignore cycles deriving Copy/Debug and whether a type has a vtable * Bail out early in the face of partial template specialization We don't support it, and shouldn't continue trying to parse a type from this cursor. * Do not consider inner type's parameter usage as our own parameter usage * Do not require a parent_id for template instantiations It is not necessary, and in fact was preventing us from creating template instantiations in some places, resulting in such nonsense as a generic template definition as a base for another type. * Only join if this is NOT a named template type or a template instantiation Otherwise, we'll always consider all of a template instantiation's arguments as used, when they should only be considered used if the template definition uses that template parameter. * Consider function return and parameter types as used Although we should not follow class method edges because we cannot create new monomorphizations of methods, code can create aliases of function pointers whose return or parameter types are template parameters, and those template parameters should be considered used. * Add the AsNamed trait for things which might be a named template type This sees through ResolvedTypeReferences to get at the final named type and its canonical item id. By using this in the named template parameter usage analysis, we ensure we don't have bugs where there are ResolvedTypeReferences in the usage sets rather than the canonical named item id, which could cause template parameters to be ignored accidentally. * Do not consider an inner var's template parameter usage as our own * Make the expectations' tests less noisy * Use opaque blobs for unknown template definition types When we don't know how to generate a Rust type from a template definition (eg because it uses non-type template parameters), then we should fall back to using the instantiation's layout to generate the opaque blob. * Implement CanDeriveDebug for TemplateInstantiation We need the template instantiation's layout to determine if we can derive debug for it when the instantiation's template definition has non-type parameters. * Stop thrashing malloc when unioning ItemSets in UsedTemplateParameters Previously, we were cloning an ItemSet, which requires a malloc for non-empty sets, when taking its union with our current id's set. Now, instead of doing that, we wrap each ItemSet in an Option, and take the set out of the hash map when modifying it. This allows us to side-step the borrow checker and HashMap's lack of an analog to `slice::split_at_mut` and mutate what is logically a value in the hash map while also using immutable references of values that are physically in the hash map. * Add some tests explicitly about template parameter usage * Updated test expectations now that we are inferring template parameter usage * Reinstate the layout tests for template instantiations * Generate opaque blobs for uses of partially specialized templates This adds `TypeKind::Opaque` which signifies that we do not understand anything about the given type and that we should just generate an opaque blob based on the type's layout. It explicitly uses the opaque type kind for partially specialized templates. * Add note about None vs Some([]) in TemplateDeclaration * Do not rely on TypeKind implementing PartialEq * Prefer assert_eq!(lhs, rhs) to assert!(lhs == rhs) * Expand some comments for ir::named::UsedTemplateParameters * Expand Item::is_opaque to consider TypeKind::Opaque * Use opaque types instead of panicking Use opaque types as our last resort when resolving type references after we have collected unresolved type references instead of panicking. * Find template definitions that don't want to be found * Recognize associated template types and make them opaque
This commit is contained in:
parent
17275f8700
commit
1c4332a1aa
48
src/clang.rs
48
src/clang.rs
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
use cexpr;
|
use cexpr;
|
||||||
use clang_sys::*;
|
use clang_sys::*;
|
||||||
|
use regex;
|
||||||
use std::{mem, ptr, slice};
|
use std::{mem, ptr, slice};
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -126,11 +127,11 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the number of template arguments used by this cursor's referent,
|
/// Return the number of template arguments used by this cursor's referent,
|
||||||
/// if the referent is either a template specialization or declaration.
|
/// if the referent is either a template instantiation. Returns `None`
|
||||||
/// Returns `None` otherwise.
|
/// otherwise.
|
||||||
///
|
///
|
||||||
/// NOTE: This may not return `Some` for some non-fully specialized
|
/// NOTE: This may not return `Some` for partial template specializations,
|
||||||
/// templates, see #193 and #194.
|
/// see #193 and #194.
|
||||||
pub fn num_template_args(&self) -> Option<u32> {
|
pub fn num_template_args(&self) -> Option<u32> {
|
||||||
// XXX: `clang_Type_getNumTemplateArguments` is sort of reliable, while
|
// XXX: `clang_Type_getNumTemplateArguments` is sort of reliable, while
|
||||||
// `clang_Cursor_getNumTemplateArguments` is totally unreliable.
|
// `clang_Cursor_getNumTemplateArguments` is totally unreliable.
|
||||||
@ -302,7 +303,11 @@ impl Cursor {
|
|||||||
x: clang_getCursorDefinition(self.x),
|
x: clang_getCursorDefinition(self.x),
|
||||||
};
|
};
|
||||||
|
|
||||||
if ret.is_valid() { Some(ret) } else { None }
|
if ret.is_valid() && ret.kind() != CXCursor_NoDeclFound {
|
||||||
|
Some(ret)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,8 +336,9 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given that this cursor points to a template specialization, get a cursor
|
/// Given that this cursor points to either a template specialization or a
|
||||||
/// pointing to the template definition that is being specialized.
|
/// template instantiation, get a cursor pointing to the template definition
|
||||||
|
/// that is being specialized.
|
||||||
pub fn specialized(&self) -> Option<Cursor> {
|
pub fn specialized(&self) -> Option<Cursor> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ret = Cursor {
|
let ret = Cursor {
|
||||||
@ -895,8 +901,8 @@ impl Type {
|
|||||||
self.is_valid() && self.kind() != CXType_Unexposed
|
self.is_valid() && self.kind() != CXType_Unexposed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this type a fully specialized template?
|
/// Is this type a fully instantiated template?
|
||||||
pub fn is_fully_specialized_template(&self) -> bool {
|
pub fn is_fully_instantiated_template(&self) -> bool {
|
||||||
// Yep, the spelling of this containing type-parameter is extremely
|
// Yep, the spelling of this containing type-parameter is extremely
|
||||||
// nasty... But can happen in <type_traits>. Unfortunately I couldn't
|
// nasty... But can happen in <type_traits>. Unfortunately I couldn't
|
||||||
// reduce it enough :(
|
// reduce it enough :(
|
||||||
@ -908,6 +914,30 @@ impl Type {
|
|||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is this type an associated template type? Eg `T::Associated` in
|
||||||
|
/// this example:
|
||||||
|
///
|
||||||
|
/// ```c++
|
||||||
|
/// template <typename T>
|
||||||
|
/// class Foo {
|
||||||
|
/// typename T::Associated member;
|
||||||
|
/// };
|
||||||
|
/// ```
|
||||||
|
pub fn is_associated_type(&self) -> bool {
|
||||||
|
// This is terrible :(
|
||||||
|
fn hacky_parse_associated_type<S: AsRef<str>>(spelling: S) -> bool {
|
||||||
|
lazy_static! {
|
||||||
|
static ref ASSOC_TYPE_RE: regex::Regex =
|
||||||
|
regex::Regex::new(r"typename type\-parameter\-\d+\-\d+::.+").unwrap();
|
||||||
|
}
|
||||||
|
ASSOC_TYPE_RE.is_match(spelling.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
self.kind() == CXType_Unexposed &&
|
||||||
|
(hacky_parse_associated_type(self.spelling()) ||
|
||||||
|
hacky_parse_associated_type(self.canonical_type().spelling()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `CanonicalTypeDeclaration` type exists as proof-by-construction that its
|
/// The `CanonicalTypeDeclaration` type exists as proof-by-construction that its
|
||||||
|
@ -2,8 +2,8 @@ mod helpers;
|
|||||||
mod struct_layout;
|
mod struct_layout;
|
||||||
|
|
||||||
use self::helpers::{BlobTyBuilder, attributes};
|
use self::helpers::{BlobTyBuilder, attributes};
|
||||||
|
use self::struct_layout::{StructLayoutTracker, bytes_from_bits_pow2};
|
||||||
use self::struct_layout::{align_to, bytes_from_bits};
|
use self::struct_layout::{align_to, bytes_from_bits};
|
||||||
use self::struct_layout::{bytes_from_bits_pow2, StructLayoutTracker};
|
|
||||||
use aster;
|
use aster;
|
||||||
|
|
||||||
use ir::annotations::FieldAccessorKind;
|
use ir::annotations::FieldAccessorKind;
|
||||||
@ -20,7 +20,8 @@ use ir::item_kind::ItemKind;
|
|||||||
use ir::layout::Layout;
|
use ir::layout::Layout;
|
||||||
use ir::module::Module;
|
use ir::module::Module;
|
||||||
use ir::objc::ObjCInterface;
|
use ir::objc::ObjCInterface;
|
||||||
use ir::ty::{Type, TypeKind};
|
use ir::template::{AsNamed, TemplateInstantiation};
|
||||||
|
use ir::ty::{TemplateDeclaration, Type, TypeKind};
|
||||||
use ir::var::Var;
|
use ir::var::Var;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
@ -137,11 +138,6 @@ impl<'a> CodegenResult<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_id(&mut self) -> usize {
|
|
||||||
self.codegen_id.set(self.codegen_id.get() + 1);
|
|
||||||
self.codegen_id.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn saw_union(&mut self) {
|
fn saw_union(&mut self) {
|
||||||
self.saw_union = true;
|
self.saw_union = true;
|
||||||
}
|
}
|
||||||
@ -522,19 +518,20 @@ impl CodeGenerator for Type {
|
|||||||
TypeKind::Pointer(..) |
|
TypeKind::Pointer(..) |
|
||||||
TypeKind::BlockPointer |
|
TypeKind::BlockPointer |
|
||||||
TypeKind::Reference(..) |
|
TypeKind::Reference(..) |
|
||||||
TypeKind::TemplateInstantiation(..) |
|
|
||||||
TypeKind::Function(..) |
|
TypeKind::Function(..) |
|
||||||
TypeKind::ResolvedTypeRef(..) |
|
TypeKind::ResolvedTypeRef(..) |
|
||||||
|
TypeKind::Opaque |
|
||||||
TypeKind::Named => {
|
TypeKind::Named => {
|
||||||
// These items don't need code generation, they only need to be
|
// These items don't need code generation, they only need to be
|
||||||
// converted to rust types in fields, arguments, and such.
|
// converted to rust types in fields, arguments, and such.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
TypeKind::TemplateInstantiation(ref inst) => {
|
||||||
|
inst.codegen(ctx, result, whitelisted_items, item)
|
||||||
|
}
|
||||||
TypeKind::Comp(ref ci) => {
|
TypeKind::Comp(ref ci) => {
|
||||||
ci.codegen(ctx, result, whitelisted_items, item)
|
ci.codegen(ctx, result, whitelisted_items, item)
|
||||||
}
|
}
|
||||||
// NB: The code below will pick the correct
|
|
||||||
// applicable_template_args.
|
|
||||||
TypeKind::TemplateAlias(inner, _) |
|
TypeKind::TemplateAlias(inner, _) |
|
||||||
TypeKind::Alias(inner) => {
|
TypeKind::Alias(inner) => {
|
||||||
let inner_item = ctx.resolve_item(inner);
|
let inner_item = ctx.resolve_item(inner);
|
||||||
@ -557,10 +554,9 @@ impl CodeGenerator for Type {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut applicable_template_args =
|
let mut used_template_params = item.used_template_params(ctx);
|
||||||
item.applicable_template_args(ctx);
|
|
||||||
let inner_rust_type = if item.is_opaque(ctx) {
|
let inner_rust_type = if item.is_opaque(ctx) {
|
||||||
applicable_template_args.clear();
|
used_template_params = None;
|
||||||
// Pray if there's no layout.
|
// Pray if there's no layout.
|
||||||
let layout = self.layout(ctx).unwrap_or_else(Layout::zero);
|
let layout = self.layout(ctx).unwrap_or_else(Layout::zero);
|
||||||
BlobTyBuilder::new(layout).build()
|
BlobTyBuilder::new(layout).build()
|
||||||
@ -603,7 +599,7 @@ impl CodeGenerator for Type {
|
|||||||
// https://github.com/rust-lang/rust/issues/26264
|
// https://github.com/rust-lang/rust/issues/26264
|
||||||
let simple_enum_path = match inner_rust_type.node {
|
let simple_enum_path = match inner_rust_type.node {
|
||||||
ast::TyKind::Path(None, ref p) => {
|
ast::TyKind::Path(None, ref p) => {
|
||||||
if applicable_template_args.is_empty() &&
|
if used_template_params.is_none() &&
|
||||||
inner_item.expect_type()
|
inner_item.expect_type()
|
||||||
.canonical_type(ctx)
|
.canonical_type(ctx)
|
||||||
.is_enum() &&
|
.is_enum() &&
|
||||||
@ -627,17 +623,21 @@ impl CodeGenerator for Type {
|
|||||||
typedef.use_().build(p).as_(rust_name)
|
typedef.use_().build(p).as_(rust_name)
|
||||||
} else {
|
} else {
|
||||||
let mut generics = typedef.type_(rust_name).generics();
|
let mut generics = typedef.type_(rust_name).generics();
|
||||||
for template_arg in applicable_template_args.iter() {
|
if let Some(ref params) = used_template_params {
|
||||||
let template_arg = ctx.resolve_type(*template_arg);
|
for template_param in params {
|
||||||
if template_arg.is_named() {
|
if let Some(id) =
|
||||||
if template_arg.is_invalid_named_type() {
|
template_param.as_named(ctx, &()) {
|
||||||
warn!("Item contained invalid template \
|
let template_param = ctx.resolve_type(id);
|
||||||
parameter: {:?}",
|
if template_param.is_invalid_named_type() {
|
||||||
item);
|
warn!("Item contained invalid template \
|
||||||
return;
|
parameter: {:?}",
|
||||||
|
item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
generics =
|
||||||
|
generics.ty_param_id(template_param.name()
|
||||||
|
.unwrap());
|
||||||
}
|
}
|
||||||
generics =
|
|
||||||
generics.ty_param_id(template_arg.name().unwrap());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
generics.build().build_ty(inner_rust_type)
|
generics.build().build_ty(inner_rust_type)
|
||||||
@ -768,7 +768,7 @@ impl<'a> Bitfield<'a> {
|
|||||||
let field_align = field_ty_layout.align;
|
let field_align = field_ty_layout.align;
|
||||||
|
|
||||||
if field_size_in_bits != 0 &&
|
if field_size_in_bits != 0 &&
|
||||||
(width == 0 || width as usize > unfilled_bits_in_last_unit) {
|
(width == 0 || width as usize > unfilled_bits_in_last_unit) {
|
||||||
field_size_in_bits = align_to(field_size_in_bits, field_align);
|
field_size_in_bits = align_to(field_size_in_bits, field_align);
|
||||||
// Push the new field.
|
// Push the new field.
|
||||||
let ty =
|
let ty =
|
||||||
@ -829,6 +829,53 @@ impl<'a> Bitfield<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CodeGenerator for TemplateInstantiation {
|
||||||
|
type Extra = Item;
|
||||||
|
|
||||||
|
fn codegen<'a>(&self,
|
||||||
|
ctx: &BindgenContext,
|
||||||
|
result: &mut CodegenResult<'a>,
|
||||||
|
_whitelisted_items: &ItemSet,
|
||||||
|
item: &Item) {
|
||||||
|
// Although uses of instantiations don't need code generation, and are
|
||||||
|
// just converted to rust types in fields, vars, etc, we take this
|
||||||
|
// opportunity to generate tests for their layout here.
|
||||||
|
|
||||||
|
let layout = item.kind().expect_type().layout(ctx);
|
||||||
|
|
||||||
|
if let Some(layout) = layout {
|
||||||
|
let size = layout.size;
|
||||||
|
let align = layout.align;
|
||||||
|
|
||||||
|
let name = item.canonical_name(ctx);
|
||||||
|
let fn_name = format!("__bindgen_test_layout_{}_instantiation_{}",
|
||||||
|
name,
|
||||||
|
item.id().as_usize());
|
||||||
|
let fn_name = ctx.rust_ident_raw(&fn_name);
|
||||||
|
|
||||||
|
let prefix = ctx.trait_prefix();
|
||||||
|
let ident = item.to_rust_ty(ctx);
|
||||||
|
let size_of_expr = quote_expr!(ctx.ext_cx(),
|
||||||
|
::$prefix::mem::size_of::<$ident>());
|
||||||
|
let align_of_expr = quote_expr!(ctx.ext_cx(),
|
||||||
|
::$prefix::mem::align_of::<$ident>());
|
||||||
|
|
||||||
|
let item = quote_item!(
|
||||||
|
ctx.ext_cx(),
|
||||||
|
#[test]
|
||||||
|
fn $fn_name() {
|
||||||
|
assert_eq!($size_of_expr, $size,
|
||||||
|
concat!("Size of template specialization: ", stringify!($ident)));
|
||||||
|
assert_eq!($align_of_expr, $align,
|
||||||
|
concat!("Alignment of template specialization: ", stringify!($ident)));
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
result.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CodeGenerator for CompInfo {
|
impl CodeGenerator for CompInfo {
|
||||||
type Extra = Item;
|
type Extra = Item;
|
||||||
|
|
||||||
@ -847,12 +894,11 @@ impl CodeGenerator for CompInfo {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let applicable_template_args = item.applicable_template_args(ctx);
|
let used_template_params = item.used_template_params(ctx);
|
||||||
|
|
||||||
// generate tuple struct if struct or union is a forward declaration,
|
// generate tuple struct if struct or union is a forward declaration,
|
||||||
// skip for now if template parameters are needed.
|
// skip for now if template parameters are needed.
|
||||||
if self.is_forward_declaration() &&
|
if self.is_forward_declaration() && used_template_params.is_none() {
|
||||||
applicable_template_args.is_empty() {
|
|
||||||
let struct_name = item.canonical_name(ctx);
|
let struct_name = item.canonical_name(ctx);
|
||||||
let struct_name = ctx.rust_ident_raw(&struct_name);
|
let struct_name = ctx.rust_ident_raw(&struct_name);
|
||||||
let tuple_struct = quote_item!(ctx.ext_cx(),
|
let tuple_struct = quote_item!(ctx.ext_cx(),
|
||||||
@ -865,35 +911,6 @@ impl CodeGenerator for CompInfo {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_template_specialization() {
|
|
||||||
let layout = item.kind().expect_type().layout(ctx);
|
|
||||||
|
|
||||||
if let Some(layout) = layout {
|
|
||||||
let fn_name = format!("__bindgen_test_layout_template_{}",
|
|
||||||
result.next_id());
|
|
||||||
let fn_name = ctx.rust_ident_raw(&fn_name);
|
|
||||||
let ident = item.to_rust_ty(ctx);
|
|
||||||
let prefix = ctx.trait_prefix();
|
|
||||||
let size_of_expr = quote_expr!(ctx.ext_cx(),
|
|
||||||
::$prefix::mem::size_of::<$ident>());
|
|
||||||
let align_of_expr = quote_expr!(ctx.ext_cx(),
|
|
||||||
::$prefix::mem::align_of::<$ident>());
|
|
||||||
let size = layout.size;
|
|
||||||
let align = layout.align;
|
|
||||||
let item = quote_item!(ctx.ext_cx(),
|
|
||||||
#[test]
|
|
||||||
fn $fn_name() {
|
|
||||||
assert_eq!($size_of_expr, $size,
|
|
||||||
concat!("Size of template specialization: ", stringify!($ident)));
|
|
||||||
assert_eq!($align_of_expr, $align,
|
|
||||||
concat!("Alignment of template specialization: ", stringify!($ident)));
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
result.push(item);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut attributes = vec![];
|
let mut attributes = vec![];
|
||||||
let mut needs_clone_impl = false;
|
let mut needs_clone_impl = false;
|
||||||
let mut needs_default_impl = false;
|
let mut needs_default_impl = false;
|
||||||
@ -923,7 +940,7 @@ impl CodeGenerator for CompInfo {
|
|||||||
if item.can_derive_copy(ctx, ()) &&
|
if item.can_derive_copy(ctx, ()) &&
|
||||||
!item.annotations().disallow_copy() {
|
!item.annotations().disallow_copy() {
|
||||||
derives.push("Copy");
|
derives.push("Copy");
|
||||||
if !applicable_template_args.is_empty() {
|
if used_template_params.is_some() {
|
||||||
// FIXME: This requires extra logic if you have a big array in a
|
// FIXME: This requires extra logic if you have a big array in a
|
||||||
// templated struct. The reason for this is that the magic:
|
// templated struct. The reason for this is that the magic:
|
||||||
// fn clone(&self) -> Self { *self }
|
// fn clone(&self) -> Self { *self }
|
||||||
@ -940,8 +957,6 @@ impl CodeGenerator for CompInfo {
|
|||||||
attributes.push(attributes::derives(&derives))
|
attributes.push(attributes::derives(&derives))
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut template_args_used =
|
|
||||||
vec![false; applicable_template_args.len()];
|
|
||||||
let canonical_name = item.canonical_name(ctx);
|
let canonical_name = item.canonical_name(ctx);
|
||||||
let builder = if is_union && ctx.options().unstable_rust {
|
let builder = if is_union && ctx.options().unstable_rust {
|
||||||
aster::AstBuilder::new()
|
aster::AstBuilder::new()
|
||||||
@ -1004,13 +1019,6 @@ impl CodeGenerator for CompInfo {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, ty_id) in applicable_template_args.iter().enumerate() {
|
|
||||||
let template_arg_ty = ctx.resolve_type(*ty_id);
|
|
||||||
if base_ty.signature_contains_named_type(ctx, template_arg_ty) {
|
|
||||||
template_args_used[i] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let inner = base.ty.to_rust_ty(ctx);
|
let inner = base.ty.to_rust_ty(ctx);
|
||||||
let field_name = if i == 0 {
|
let field_name = if i == 0 {
|
||||||
"_base".into()
|
"_base".into()
|
||||||
@ -1092,13 +1100,6 @@ impl CodeGenerator for CompInfo {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, ty_id) in applicable_template_args.iter().enumerate() {
|
|
||||||
let template_arg = ctx.resolve_type(*ty_id);
|
|
||||||
if field_ty.signature_contains_named_type(ctx, template_arg) {
|
|
||||||
template_args_used[i] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let ty = field.ty().to_rust_ty(ctx);
|
let ty = field.ty().to_rust_ty(ctx);
|
||||||
|
|
||||||
// NB: In unstable rust we use proper `union` types.
|
// NB: In unstable rust we use proper `union` types.
|
||||||
@ -1108,7 +1109,8 @@ impl CodeGenerator for CompInfo {
|
|||||||
} else {
|
} else {
|
||||||
quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
|
quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
|
||||||
}
|
}
|
||||||
} else if let Some(item) = field_ty.is_incomplete_array(ctx) {
|
} else if let Some(item) =
|
||||||
|
field_ty.is_incomplete_array(ctx) {
|
||||||
result.saw_incomplete_array();
|
result.saw_incomplete_array();
|
||||||
|
|
||||||
let inner = item.to_rust_ty(ctx);
|
let inner = item.to_rust_ty(ctx);
|
||||||
@ -1257,9 +1259,6 @@ impl CodeGenerator for CompInfo {
|
|||||||
if item.is_opaque(ctx) {
|
if item.is_opaque(ctx) {
|
||||||
fields.clear();
|
fields.clear();
|
||||||
methods.clear();
|
methods.clear();
|
||||||
for i in 0..template_args_used.len() {
|
|
||||||
template_args_used[i] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
Some(l) => {
|
Some(l) => {
|
||||||
@ -1276,7 +1275,9 @@ impl CodeGenerator for CompInfo {
|
|||||||
}
|
}
|
||||||
} else if !is_union && !self.is_unsized(ctx) {
|
} else if !is_union && !self.is_unsized(ctx) {
|
||||||
if let Some(padding_field) =
|
if let Some(padding_field) =
|
||||||
layout.and_then(|layout| struct_layout.pad_struct(&canonical_name, layout)) {
|
layout.and_then(|layout| {
|
||||||
|
struct_layout.pad_struct(&canonical_name, layout)
|
||||||
|
}) {
|
||||||
fields.push(padding_field);
|
fields.push(padding_field);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1299,33 +1300,15 @@ impl CodeGenerator for CompInfo {
|
|||||||
fields.push(field);
|
fields.push(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append any extra template arguments that nobody has used so far.
|
|
||||||
for (i, ty) in applicable_template_args.iter().enumerate() {
|
|
||||||
if !template_args_used[i] {
|
|
||||||
let name = ctx.resolve_type(*ty).name().unwrap();
|
|
||||||
let ident = ctx.rust_ident(name);
|
|
||||||
let prefix = ctx.trait_prefix();
|
|
||||||
let phantom = quote_ty!(ctx.ext_cx(),
|
|
||||||
::$prefix::marker::PhantomData<$ident>);
|
|
||||||
let field = StructFieldBuilder::named(format!("_phantom_{}",
|
|
||||||
i))
|
|
||||||
.pub_()
|
|
||||||
.build_ty(phantom);
|
|
||||||
fields.push(field)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let mut generics = aster::AstBuilder::new().generics();
|
let mut generics = aster::AstBuilder::new().generics();
|
||||||
for template_arg in applicable_template_args.iter() {
|
|
||||||
// Take into account that here only arrive named types, not
|
if let Some(ref params) = used_template_params {
|
||||||
// template specialisations that would need to be
|
for ty in params.iter() {
|
||||||
// instantiated.
|
let param = ctx.resolve_type(*ty);
|
||||||
//
|
let name = param.name().unwrap();
|
||||||
// TODO: Add template args from the parent, here and in
|
let ident = ctx.rust_ident(name);
|
||||||
// `to_rust_ty`!!
|
generics = generics.ty_param_id(ident);
|
||||||
let template_arg = ctx.resolve_type(*template_arg);
|
}
|
||||||
generics = generics.ty_param_id(template_arg.name().unwrap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let generics = generics.build();
|
let generics = generics.build();
|
||||||
@ -1353,7 +1336,7 @@ impl CodeGenerator for CompInfo {
|
|||||||
canonical_name);
|
canonical_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if applicable_template_args.is_empty() {
|
if used_template_params.is_none() {
|
||||||
for var in self.inner_vars() {
|
for var in self.inner_vars() {
|
||||||
ctx.resolve_item(*var)
|
ctx.resolve_item(*var)
|
||||||
.codegen(ctx, result, whitelisted_items, &());
|
.codegen(ctx, result, whitelisted_items, &());
|
||||||
@ -2193,16 +2176,54 @@ impl ToRustTy for Type {
|
|||||||
let path = item.namespace_aware_canonical_path(ctx);
|
let path = item.namespace_aware_canonical_path(ctx);
|
||||||
aster::AstBuilder::new().ty().path().ids(path).build()
|
aster::AstBuilder::new().ty().path().ids(path).build()
|
||||||
}
|
}
|
||||||
TypeKind::TemplateInstantiation(inner, ref template_args) => {
|
TypeKind::TemplateInstantiation(ref inst) => {
|
||||||
// PS: Sorry for the duplication here.
|
let decl = inst.template_definition();
|
||||||
let mut inner_ty = inner.to_rust_ty(ctx).unwrap();
|
let mut ty = decl.to_rust_ty(ctx).unwrap();
|
||||||
|
|
||||||
if let ast::TyKind::Path(_, ref mut path) = inner_ty.node {
|
// If we gave up when making a type for the template definition,
|
||||||
let template_args = template_args.iter()
|
// check if maybe we can make a better opaque blob for the
|
||||||
.map(|arg| arg.to_rust_ty(ctx))
|
// instantiation.
|
||||||
|
if ty == aster::AstBuilder::new().ty().unit().unwrap() {
|
||||||
|
if let Some(layout) = self.layout(ctx) {
|
||||||
|
ty = BlobTyBuilder::new(layout).build().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let decl_params = if let Some(params) =
|
||||||
|
decl.self_template_params(ctx) {
|
||||||
|
params
|
||||||
|
} else {
|
||||||
|
// This can happen if we generated an opaque type for a
|
||||||
|
// partial template specialization, in which case we just
|
||||||
|
// use the opaque type's layout. If we don't have a layout,
|
||||||
|
// we cross our fingers and hope for the best :-/
|
||||||
|
debug_assert!(ctx.resolve_type_through_type_refs(decl)
|
||||||
|
.is_opaque());
|
||||||
|
let layout = self.layout(ctx).unwrap_or(Layout::zero());
|
||||||
|
ty = BlobTyBuilder::new(layout).build().unwrap();
|
||||||
|
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: If the decl type is a template class/struct
|
||||||
|
// declaration's member template declaration, it could rely on
|
||||||
|
// generic template parameters from its outer template
|
||||||
|
// class/struct. When we emit bindings for it, it could require
|
||||||
|
// *more* type arguments than we have here, and we will need to
|
||||||
|
// reconstruct them somehow. We don't have any means of doing
|
||||||
|
// that reconstruction at this time.
|
||||||
|
|
||||||
|
if let ast::TyKind::Path(_, ref mut path) = ty.node {
|
||||||
|
let template_args = inst.template_arguments()
|
||||||
|
.iter()
|
||||||
|
.zip(decl_params.iter())
|
||||||
|
// Only pass type arguments for the type parameters that
|
||||||
|
// the decl uses.
|
||||||
|
.filter(|&(_, param)| ctx.uses_template_parameter(decl, *param))
|
||||||
|
.map(|(arg, _)| arg.to_rust_ty(ctx))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
path.segments.last_mut().unwrap().parameters = if
|
path.segments.last_mut().unwrap().parameters = if
|
||||||
template_args.is_empty() {
|
template_args.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -2216,18 +2237,19 @@ impl ToRustTy for Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
P(inner_ty)
|
P(ty)
|
||||||
}
|
}
|
||||||
TypeKind::ResolvedTypeRef(inner) => inner.to_rust_ty(ctx),
|
TypeKind::ResolvedTypeRef(inner) => inner.to_rust_ty(ctx),
|
||||||
TypeKind::TemplateAlias(inner, _) |
|
TypeKind::TemplateAlias(inner, _) |
|
||||||
TypeKind::Alias(inner) => {
|
TypeKind::Alias(inner) => {
|
||||||
let applicable_named_args = item.applicable_template_args(ctx)
|
let template_params = item.used_template_params(ctx)
|
||||||
|
.unwrap_or(vec![])
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|arg| ctx.resolve_type(*arg).is_named())
|
.filter(|param| param.is_named(ctx, &()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let spelling = self.name().expect("Unnamed alias?");
|
let spelling = self.name().expect("Unnamed alias?");
|
||||||
if item.is_opaque(ctx) && !applicable_named_args.is_empty() {
|
if item.is_opaque(ctx) && !template_params.is_empty() {
|
||||||
// Pray if there's no available layout.
|
// Pray if there's no available layout.
|
||||||
let layout = self.layout(ctx).unwrap_or_else(Layout::zero);
|
let layout = self.layout(ctx).unwrap_or_else(Layout::zero);
|
||||||
BlobTyBuilder::new(layout).build()
|
BlobTyBuilder::new(layout).build()
|
||||||
@ -2236,15 +2258,13 @@ impl ToRustTy for Type {
|
|||||||
inner) {
|
inner) {
|
||||||
ty
|
ty
|
||||||
} else {
|
} else {
|
||||||
utils::build_templated_path(item,
|
utils::build_templated_path(item, ctx, template_params)
|
||||||
ctx,
|
|
||||||
applicable_named_args)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeKind::Comp(ref info) => {
|
TypeKind::Comp(ref info) => {
|
||||||
let template_args = item.applicable_template_args(ctx);
|
let template_params = item.used_template_params(ctx);
|
||||||
if info.has_non_type_template_params() ||
|
if info.has_non_type_template_params() ||
|
||||||
(item.is_opaque(ctx) && !template_args.is_empty()) {
|
(item.is_opaque(ctx) && template_params.is_some()) {
|
||||||
return match self.layout(ctx) {
|
return match self.layout(ctx) {
|
||||||
Some(layout) => BlobTyBuilder::new(layout).build(),
|
Some(layout) => BlobTyBuilder::new(layout).build(),
|
||||||
None => {
|
None => {
|
||||||
@ -2256,7 +2276,13 @@ impl ToRustTy for Type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::build_templated_path(item, ctx, template_args)
|
utils::build_templated_path(item,
|
||||||
|
ctx,
|
||||||
|
template_params.unwrap_or(vec![]))
|
||||||
|
}
|
||||||
|
TypeKind::Opaque => {
|
||||||
|
BlobTyBuilder::new(self.layout(ctx).unwrap_or(Layout::zero()))
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
TypeKind::BlockPointer => {
|
TypeKind::BlockPointer => {
|
||||||
let void = raw_type(ctx, "c_void");
|
let void = raw_type(ctx, "c_void");
|
||||||
@ -2742,19 +2768,19 @@ mod utils {
|
|||||||
|
|
||||||
pub fn build_templated_path(item: &Item,
|
pub fn build_templated_path(item: &Item,
|
||||||
ctx: &BindgenContext,
|
ctx: &BindgenContext,
|
||||||
template_args: Vec<ItemId>)
|
template_params: Vec<ItemId>)
|
||||||
-> P<ast::Ty> {
|
-> P<ast::Ty> {
|
||||||
let path = item.namespace_aware_canonical_path(ctx);
|
let path = item.namespace_aware_canonical_path(ctx);
|
||||||
let builder = aster::AstBuilder::new().ty().path();
|
let builder = aster::AstBuilder::new().ty().path();
|
||||||
|
|
||||||
let template_args = template_args.iter()
|
let template_params = template_params.iter()
|
||||||
.map(|arg| arg.to_rust_ty(ctx))
|
.map(|param| param.to_rust_ty(ctx))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// XXX: I suck at aster.
|
// XXX: I suck at aster.
|
||||||
if path.len() == 1 {
|
if path.len() == 1 {
|
||||||
return builder.segment(&path[0])
|
return builder.segment(&path[0])
|
||||||
.with_tys(template_args)
|
.with_tys(template_params)
|
||||||
.build()
|
.build()
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@ -2765,7 +2791,7 @@ mod utils {
|
|||||||
builder = if i == path.len() - 2 {
|
builder = if i == path.len() - 2 {
|
||||||
// XXX Extra clone courtesy of the borrow checker.
|
// XXX Extra clone courtesy of the borrow checker.
|
||||||
builder.segment(&segment)
|
builder.segment(&segment)
|
||||||
.with_tys(template_args.clone())
|
.with_tys(template_params.clone())
|
||||||
.build()
|
.build()
|
||||||
} else {
|
} else {
|
||||||
builder.segment(&segment).build()
|
builder.segment(&segment).build()
|
||||||
|
@ -167,17 +167,20 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
|
|||||||
None => return None,
|
None => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let TypeKind::Array(inner, len) = *field_ty.canonical_type(self.ctx).kind() {
|
if let TypeKind::Array(inner, len) =
|
||||||
|
*field_ty.canonical_type(self.ctx).kind() {
|
||||||
// FIXME(emilio): As an _ultra_ hack, we correct the layout returned
|
// FIXME(emilio): As an _ultra_ hack, we correct the layout returned
|
||||||
// by arrays of structs that have a bigger alignment than what we
|
// by arrays of structs that have a bigger alignment than what we
|
||||||
// can support.
|
// can support.
|
||||||
//
|
//
|
||||||
// This means that the structs in the array are super-unsafe to
|
// This means that the structs in the array are super-unsafe to
|
||||||
// access, since they won't be properly aligned, but *shrug*.
|
// access, since they won't be properly aligned, but *shrug*.
|
||||||
if let Some(layout) = self.ctx.resolve_type(inner).layout(self.ctx) {
|
if let Some(layout) = self.ctx
|
||||||
|
.resolve_type(inner)
|
||||||
|
.layout(self.ctx) {
|
||||||
if layout.align > mem::size_of::<*mut ()>() {
|
if layout.align > mem::size_of::<*mut ()>() {
|
||||||
field_layout.size =
|
field_layout.size = align_to(layout.size, layout.align) *
|
||||||
align_to(layout.size, layout.align) * len;
|
len;
|
||||||
field_layout.align = mem::size_of::<*mut ()>();
|
field_layout.align = mem::size_of::<*mut ()>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,7 +200,8 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Otherwise the padding is useless.
|
// Otherwise the padding is useless.
|
||||||
let need_padding = padding_bytes >= field_layout.align || field_layout.align > mem::size_of::<*mut ()>();
|
let need_padding = padding_bytes >= field_layout.align ||
|
||||||
|
field_layout.align > mem::size_of::<*mut ()>();
|
||||||
|
|
||||||
self.latest_offset += padding_bytes;
|
self.latest_offset += padding_bytes;
|
||||||
|
|
||||||
@ -206,14 +210,16 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
|
|||||||
self.latest_offset);
|
self.latest_offset);
|
||||||
|
|
||||||
debug!("align field {} to {}/{} with {} padding bytes {:?}",
|
debug!("align field {} to {}/{} with {} padding bytes {:?}",
|
||||||
field_name,
|
field_name,
|
||||||
self.latest_offset,
|
self.latest_offset,
|
||||||
field_offset.unwrap_or(0) / 8,
|
field_offset.unwrap_or(0) / 8,
|
||||||
padding_bytes,
|
padding_bytes,
|
||||||
field_layout);
|
field_layout);
|
||||||
|
|
||||||
if need_padding && padding_bytes != 0 {
|
if need_padding && padding_bytes != 0 {
|
||||||
Some(Layout::new(padding_bytes, cmp::min(field_layout.align, mem::size_of::<*mut ()>())))
|
Some(Layout::new(padding_bytes,
|
||||||
|
cmp::min(field_layout.align,
|
||||||
|
mem::size_of::<*mut ()>())))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -221,7 +227,8 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
|
|||||||
|
|
||||||
self.latest_offset += field_layout.size;
|
self.latest_offset += field_layout.size;
|
||||||
self.latest_field_layout = Some(field_layout);
|
self.latest_field_layout = Some(field_layout);
|
||||||
self.max_field_align = cmp::max(self.max_field_align, field_layout.align);
|
self.max_field_align = cmp::max(self.max_field_align,
|
||||||
|
field_layout.align);
|
||||||
self.last_field_was_bitfield = false;
|
self.last_field_was_bitfield = false;
|
||||||
|
|
||||||
debug!("Offset: {}: {} -> {}",
|
debug!("Offset: {}: {} -> {}",
|
||||||
@ -232,11 +239,15 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
|
|||||||
padding_layout.map(|layout| self.padding_field(layout))
|
padding_layout.map(|layout| self.padding_field(layout))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pad_struct(&mut self, name: &str, layout: Layout) -> Option<ast::StructField> {
|
pub fn pad_struct(&mut self,
|
||||||
|
name: &str,
|
||||||
|
layout: Layout)
|
||||||
|
-> Option<ast::StructField> {
|
||||||
if layout.size < self.latest_offset {
|
if layout.size < self.latest_offset {
|
||||||
error!("Calculated wrong layout for {}, too more {} bytes",
|
error!("Calculated wrong layout for {}, too more {} bytes",
|
||||||
name, self.latest_offset - layout.size);
|
name,
|
||||||
return None
|
self.latest_offset - layout.size);
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let padding_bytes = layout.size - self.latest_offset;
|
let padding_bytes = layout.size - self.latest_offset;
|
||||||
@ -248,14 +259,14 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
|
|||||||
// regardless, because bitfields don't respect alignment as strictly as
|
// regardless, because bitfields don't respect alignment as strictly as
|
||||||
// other fields.
|
// other fields.
|
||||||
if padding_bytes > 0 &&
|
if padding_bytes > 0 &&
|
||||||
(padding_bytes >= layout.align ||
|
(padding_bytes >= layout.align ||
|
||||||
(self.last_field_was_bitfield &&
|
(self.last_field_was_bitfield &&
|
||||||
padding_bytes >= self.latest_field_layout.unwrap().align) ||
|
padding_bytes >= self.latest_field_layout.unwrap().align) ||
|
||||||
layout.align > mem::size_of::<*mut ()>()) {
|
layout.align > mem::size_of::<*mut ()>()) {
|
||||||
let layout = if self.comp.packed() {
|
let layout = if self.comp.packed() {
|
||||||
Layout::new(padding_bytes, 1)
|
Layout::new(padding_bytes, 1)
|
||||||
} else if self.last_field_was_bitfield ||
|
} else if self.last_field_was_bitfield ||
|
||||||
layout.align > mem::size_of::<*mut ()>() {
|
layout.align > mem::size_of::<*mut ()>() {
|
||||||
// We've already given up on alignment here.
|
// We've already given up on alignment here.
|
||||||
Layout::for_size(padding_bytes)
|
Layout::for_size(padding_bytes)
|
||||||
} else {
|
} else {
|
||||||
@ -316,12 +327,14 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
|
|||||||
|
|
||||||
// If it was, we may or may not need to align, depending on what the
|
// If it was, we may or may not need to align, depending on what the
|
||||||
// current field alignment and the bitfield size and alignment are.
|
// current field alignment and the bitfield size and alignment are.
|
||||||
debug!("align_to_bitfield? {}: {:?} {:?}", self.last_field_was_bitfield,
|
debug!("align_to_bitfield? {}: {:?} {:?}",
|
||||||
layout, new_field_layout);
|
self.last_field_was_bitfield,
|
||||||
|
layout,
|
||||||
|
new_field_layout);
|
||||||
|
|
||||||
if self.last_field_was_bitfield &&
|
if self.last_field_was_bitfield &&
|
||||||
new_field_layout.align <= layout.size % layout.align &&
|
new_field_layout.align <= layout.size % layout.align &&
|
||||||
new_field_layout.size <= layout.size % layout.align {
|
new_field_layout.size <= layout.size % layout.align {
|
||||||
// The new field will be coalesced into some of the remaining bits.
|
// The new field will be coalesced into some of the remaining bits.
|
||||||
//
|
//
|
||||||
// FIXME(emilio): I think this may not catch everything?
|
// FIXME(emilio): I think this may not catch everything?
|
||||||
|
181
src/ir/comp.rs
181
src/ir/comp.rs
@ -6,7 +6,7 @@ use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
|
|||||||
use super::item::Item;
|
use super::item::Item;
|
||||||
use super::layout::Layout;
|
use super::layout::Layout;
|
||||||
use super::traversal::{EdgeKind, Trace, Tracer};
|
use super::traversal::{EdgeKind, Trace, Tracer};
|
||||||
use super::ty::{TemplateDeclaration, Type};
|
use super::ty::TemplateDeclaration;
|
||||||
use clang;
|
use clang;
|
||||||
use parse::{ClangItemParser, ParseError};
|
use parse::{ClangItemParser, ParseError};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
@ -238,10 +238,11 @@ pub struct CompInfo {
|
|||||||
/// The members of this struct or union.
|
/// The members of this struct or union.
|
||||||
fields: Vec<Field>,
|
fields: Vec<Field>,
|
||||||
|
|
||||||
/// The template parameters of this class. These are non-concrete, and
|
/// The abstract template parameters of this class. These are NOT concrete
|
||||||
/// should always be a Type(TypeKind::Named(name)), but still they need to
|
/// template arguments, and should always be a
|
||||||
/// be registered with an unique type id in the context.
|
/// Type(TypeKind::Named(name)). For concrete template arguments, see the
|
||||||
template_args: Vec<ItemId>,
|
/// TypeKind::TemplateInstantiation.
|
||||||
|
template_params: Vec<ItemId>,
|
||||||
|
|
||||||
/// The method declarations inside this class, if in C++ mode.
|
/// The method declarations inside this class, if in C++ mode.
|
||||||
methods: Vec<Method>,
|
methods: Vec<Method>,
|
||||||
@ -252,9 +253,6 @@ pub struct CompInfo {
|
|||||||
/// Vector of classes this one inherits from.
|
/// Vector of classes this one inherits from.
|
||||||
base_members: Vec<Base>,
|
base_members: Vec<Base>,
|
||||||
|
|
||||||
/// The parent reference template if any.
|
|
||||||
ref_template: Option<ItemId>,
|
|
||||||
|
|
||||||
/// The inner types that were declared inside this class, in something like:
|
/// The inner types that were declared inside this class, in something like:
|
||||||
///
|
///
|
||||||
/// class Foo {
|
/// class Foo {
|
||||||
@ -320,11 +318,10 @@ impl CompInfo {
|
|||||||
CompInfo {
|
CompInfo {
|
||||||
kind: kind,
|
kind: kind,
|
||||||
fields: vec![],
|
fields: vec![],
|
||||||
template_args: vec![],
|
template_params: vec![],
|
||||||
methods: vec![],
|
methods: vec![],
|
||||||
constructors: vec![],
|
constructors: vec![],
|
||||||
base_members: vec![],
|
base_members: vec![],
|
||||||
ref_template: None,
|
|
||||||
inner_types: vec![],
|
inner_types: vec![],
|
||||||
inner_vars: vec![],
|
inner_vars: vec![],
|
||||||
has_vtable: false,
|
has_vtable: false,
|
||||||
@ -345,9 +342,7 @@ impl CompInfo {
|
|||||||
!self.has_vtable(ctx) && self.fields.is_empty() &&
|
!self.has_vtable(ctx) && self.fields.is_empty() &&
|
||||||
self.base_members.iter().all(|base| {
|
self.base_members.iter().all(|base| {
|
||||||
ctx.resolve_type(base.ty).canonical_type(ctx).is_unsized(ctx)
|
ctx.resolve_type(base.ty).canonical_type(ctx).is_unsized(ctx)
|
||||||
}) &&
|
})
|
||||||
self.ref_template
|
|
||||||
.map_or(true, |template| ctx.resolve_type(template).is_unsized(ctx))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does this compound type have a destructor?
|
/// Does this compound type have a destructor?
|
||||||
@ -364,16 +359,6 @@ impl CompInfo {
|
|||||||
match self.kind {
|
match self.kind {
|
||||||
CompKind::Union => false,
|
CompKind::Union => false,
|
||||||
CompKind::Struct => {
|
CompKind::Struct => {
|
||||||
// NB: We can't rely on a type with type parameters
|
|
||||||
// not having destructor.
|
|
||||||
//
|
|
||||||
// This is unfortunate, but...
|
|
||||||
self.ref_template.as_ref().map_or(false, |t| {
|
|
||||||
ctx.resolve_type(*t).has_destructor(ctx)
|
|
||||||
}) ||
|
|
||||||
self.template_args.iter().any(|t| {
|
|
||||||
ctx.resolve_type(*t).has_destructor(ctx)
|
|
||||||
}) ||
|
|
||||||
self.base_members.iter().any(|base| {
|
self.base_members.iter().any(|base| {
|
||||||
ctx.resolve_type(base.ty).has_destructor(ctx)
|
ctx.resolve_type(base.ty).has_destructor(ctx)
|
||||||
}) ||
|
}) ||
|
||||||
@ -389,16 +374,6 @@ impl CompInfo {
|
|||||||
has_destructor
|
has_destructor
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this type a template specialization?
|
|
||||||
pub fn is_template_specialization(&self) -> bool {
|
|
||||||
self.ref_template.is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the template declaration this specialization is specializing.
|
|
||||||
pub fn specialized_template(&self) -> Option<ItemId> {
|
|
||||||
self.ref_template
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compute the layout of this type.
|
/// Compute the layout of this type.
|
||||||
///
|
///
|
||||||
/// This is called as a fallback under some circumstances where LLVM doesn't
|
/// This is called as a fallback under some circumstances where LLVM doesn't
|
||||||
@ -411,7 +386,7 @@ impl CompInfo {
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
// We can't do better than clang here, sorry.
|
// We can't do better than clang here, sorry.
|
||||||
if self.kind == CompKind::Struct {
|
if self.kind == CompKind::Struct {
|
||||||
return None
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut max_size = 0;
|
let mut max_size = 0;
|
||||||
@ -434,12 +409,6 @@ impl CompInfo {
|
|||||||
&self.fields
|
&self.fields
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get this type's set of free template arguments. Empty if this is not a
|
|
||||||
/// template.
|
|
||||||
pub fn template_args(&self) -> &[ItemId] {
|
|
||||||
&self.template_args
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Does this type have any template parameters that aren't types
|
/// Does this type have any template parameters that aren't types
|
||||||
/// (e.g. int)?
|
/// (e.g. int)?
|
||||||
pub fn has_non_type_template_params(&self) -> bool {
|
pub fn has_non_type_template_params(&self) -> bool {
|
||||||
@ -452,9 +421,6 @@ impl CompInfo {
|
|||||||
self.base_members().iter().any(|base| {
|
self.base_members().iter().any(|base| {
|
||||||
ctx.resolve_type(base.ty)
|
ctx.resolve_type(base.ty)
|
||||||
.has_vtable(ctx)
|
.has_vtable(ctx)
|
||||||
}) ||
|
|
||||||
self.ref_template.map_or(false, |template| {
|
|
||||||
ctx.resolve_type(template).has_vtable(ctx)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,10 +451,9 @@ impl CompInfo {
|
|||||||
ctx: &mut BindgenContext)
|
ctx: &mut BindgenContext)
|
||||||
-> Result<Self, ParseError> {
|
-> Result<Self, ParseError> {
|
||||||
use clang_sys::*;
|
use clang_sys::*;
|
||||||
// Sigh... For class templates we want the location, for
|
assert!(ty.template_args().is_none(),
|
||||||
// specialisations, we want the declaration... So just try both.
|
"We handle template instantiations elsewhere");
|
||||||
//
|
|
||||||
// TODO: Yeah, this code reads really bad.
|
|
||||||
let mut cursor = ty.declaration();
|
let mut cursor = ty.declaration();
|
||||||
let mut kind = Self::kind_from_cursor(&cursor);
|
let mut kind = Self::kind_from_cursor(&cursor);
|
||||||
if kind.is_err() {
|
if kind.is_err() {
|
||||||
@ -510,35 +475,6 @@ impl CompInfo {
|
|||||||
CXCursor_ClassDecl => !cur.is_definition(),
|
CXCursor_ClassDecl => !cur.is_definition(),
|
||||||
_ => false,
|
_ => false,
|
||||||
});
|
});
|
||||||
ci.template_args = match ty.template_args() {
|
|
||||||
// In forward declarations and not specializations, etc, they are in
|
|
||||||
// the ast, we'll meet them in CXCursor_TemplateTypeParameter
|
|
||||||
None => vec![],
|
|
||||||
Some(arg_types) => {
|
|
||||||
let num_arg_types = arg_types.len();
|
|
||||||
let mut specialization = true;
|
|
||||||
|
|
||||||
let args = arg_types.filter(|t| t.kind() != CXType_Invalid)
|
|
||||||
.filter_map(|t| if t.spelling()
|
|
||||||
.starts_with("type-parameter") {
|
|
||||||
specialization = false;
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(Item::from_ty_or_ref(t, None, None, ctx))
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if specialization && args.len() != num_arg_types {
|
|
||||||
ci.has_non_type_template_params = true;
|
|
||||||
warn!("warning: Template parameter is not a type");
|
|
||||||
}
|
|
||||||
|
|
||||||
if specialization { args } else { vec![] }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ci.ref_template = cursor.specialized()
|
|
||||||
.and_then(|c| Item::parse(c, None, ctx).ok());
|
|
||||||
|
|
||||||
let mut maybe_anonymous_struct_field = None;
|
let mut maybe_anonymous_struct_field = None;
|
||||||
cursor.visit(|cur| {
|
cursor.visit(|cur| {
|
||||||
@ -576,7 +512,7 @@ impl CompInfo {
|
|||||||
|
|
||||||
let bit_width = cur.bit_width();
|
let bit_width = cur.bit_width();
|
||||||
let field_type = Item::from_ty_or_ref(cur.cur_type(),
|
let field_type = Item::from_ty_or_ref(cur.cur_type(),
|
||||||
Some(cur),
|
cur,
|
||||||
Some(potential_id),
|
Some(potential_id),
|
||||||
ctx);
|
ctx);
|
||||||
|
|
||||||
@ -616,6 +552,7 @@ impl CompInfo {
|
|||||||
}
|
}
|
||||||
CXCursor_EnumDecl |
|
CXCursor_EnumDecl |
|
||||||
CXCursor_TypeAliasDecl |
|
CXCursor_TypeAliasDecl |
|
||||||
|
CXCursor_TypeAliasTemplateDecl |
|
||||||
CXCursor_TypedefDecl |
|
CXCursor_TypedefDecl |
|
||||||
CXCursor_StructDecl |
|
CXCursor_StructDecl |
|
||||||
CXCursor_UnionDecl |
|
CXCursor_UnionDecl |
|
||||||
@ -668,9 +605,10 @@ impl CompInfo {
|
|||||||
return CXChildVisit_Continue;
|
return CXChildVisit_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let param =
|
let param = Item::named_type(None, cur, ctx)
|
||||||
Item::named_type(cur.spelling(), potential_id, ctx);
|
.expect("Item::named_type should't fail when pointing \
|
||||||
ci.template_args.push(param);
|
at a TemplateTypeParameter");
|
||||||
|
ci.template_params.push(param);
|
||||||
}
|
}
|
||||||
CXCursor_CXXBaseSpecifier => {
|
CXCursor_CXXBaseSpecifier => {
|
||||||
let is_virtual_base = cur.is_virtual_base();
|
let is_virtual_base = cur.is_virtual_base();
|
||||||
@ -682,10 +620,8 @@ impl CompInfo {
|
|||||||
BaseKind::Normal
|
BaseKind::Normal
|
||||||
};
|
};
|
||||||
|
|
||||||
let type_id = Item::from_ty_or_ref(cur.cur_type(),
|
let type_id =
|
||||||
Some(cur),
|
Item::from_ty_or_ref(cur.cur_type(), cur, None, ctx);
|
||||||
None,
|
|
||||||
ctx);
|
|
||||||
ci.base_members.push(Base {
|
ci.base_members.push(Base {
|
||||||
ty: type_id,
|
ty: type_id,
|
||||||
kind: kind,
|
kind: kind,
|
||||||
@ -711,7 +647,7 @@ impl CompInfo {
|
|||||||
// Methods of template functions not only use to be inlined,
|
// Methods of template functions not only use to be inlined,
|
||||||
// but also instantiated, and we wouldn't be able to call
|
// but also instantiated, and we wouldn't be able to call
|
||||||
// them, so just bail out.
|
// them, so just bail out.
|
||||||
if !ci.template_args.is_empty() {
|
if !ci.template_params.is_empty() {
|
||||||
return CXChildVisit_Continue;
|
return CXChildVisit_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -778,7 +714,7 @@ impl CompInfo {
|
|||||||
_ => {
|
_ => {
|
||||||
warn!("unhandled comp member `{}` (kind {:?}) in `{}` ({})",
|
warn!("unhandled comp member `{}` (kind {:?}) in `{}` ({})",
|
||||||
cur.spelling(),
|
cur.spelling(),
|
||||||
cur.kind(),
|
clang::kind_to_str(cur.kind()),
|
||||||
cursor.spelling(),
|
cursor.spelling(),
|
||||||
cur.location());
|
cur.location());
|
||||||
}
|
}
|
||||||
@ -816,25 +752,6 @@ impl CompInfo {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do any of the types that participate in this type's "signature" use the
|
|
||||||
/// named type `ty`?
|
|
||||||
///
|
|
||||||
/// See also documentation for `ir::Item::signature_contains_named_type`.
|
|
||||||
pub fn signature_contains_named_type(&self,
|
|
||||||
ctx: &BindgenContext,
|
|
||||||
ty: &Type)
|
|
||||||
-> bool {
|
|
||||||
// We don't generate these, so rather don't make the codegen step to
|
|
||||||
// think we got it covered.
|
|
||||||
if self.has_non_type_template_params() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
self.template_args.iter().any(|arg| {
|
|
||||||
ctx.resolve_type(*arg)
|
|
||||||
.signature_contains_named_type(ctx, ty)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the set of types that were declared within this compound type
|
/// Get the set of types that were declared within this compound type
|
||||||
/// (e.g. nested class definitions).
|
/// (e.g. nested class definitions).
|
||||||
pub fn inner_types(&self) -> &[ItemId] {
|
pub fn inner_types(&self) -> &[ItemId] {
|
||||||
@ -882,11 +799,13 @@ impl CompInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TemplateDeclaration for CompInfo {
|
impl TemplateDeclaration for CompInfo {
|
||||||
fn self_template_params(&self, _ctx: &BindgenContext) -> Option<Vec<ItemId>> {
|
fn self_template_params(&self,
|
||||||
if self.template_args.is_empty() {
|
_ctx: &BindgenContext)
|
||||||
|
-> Option<Vec<ItemId>> {
|
||||||
|
if self.template_params.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(self.template_args.clone())
|
Some(self.template_params.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -925,13 +844,9 @@ impl CanDeriveDebug for CompInfo {
|
|||||||
self.base_members
|
self.base_members
|
||||||
.iter()
|
.iter()
|
||||||
.all(|base| base.ty.can_derive_debug(ctx, ())) &&
|
.all(|base| base.ty.can_derive_debug(ctx, ())) &&
|
||||||
self.template_args
|
|
||||||
.iter()
|
|
||||||
.all(|id| id.can_derive_debug(ctx, ())) &&
|
|
||||||
self.fields
|
self.fields
|
||||||
.iter()
|
.iter()
|
||||||
.all(|f| f.can_derive_debug(ctx, ())) &&
|
.all(|f| f.can_derive_debug(ctx, ()))
|
||||||
self.ref_template.map_or(true, |id| id.can_derive_debug(ctx, ()))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.detect_derive_debug_cycle.set(false);
|
self.detect_derive_debug_cycle.set(false);
|
||||||
@ -961,7 +876,7 @@ impl CanDeriveDefault for CompInfo {
|
|||||||
|
|
||||||
return layout.unwrap_or_else(Layout::zero)
|
return layout.unwrap_or_else(Layout::zero)
|
||||||
.opaque()
|
.opaque()
|
||||||
.can_derive_debug(ctx, ());
|
.can_derive_default(ctx, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.detect_derive_default_cycle.set(true);
|
self.detect_derive_default_cycle.set(true);
|
||||||
@ -971,14 +886,9 @@ impl CanDeriveDefault for CompInfo {
|
|||||||
self.base_members
|
self.base_members
|
||||||
.iter()
|
.iter()
|
||||||
.all(|base| base.ty.can_derive_default(ctx, ())) &&
|
.all(|base| base.ty.can_derive_default(ctx, ())) &&
|
||||||
self.template_args
|
|
||||||
.iter()
|
|
||||||
.all(|id| id.can_derive_default(ctx, ())) &&
|
|
||||||
self.fields
|
self.fields
|
||||||
.iter()
|
.iter()
|
||||||
.all(|f| f.can_derive_default(ctx, ())) &&
|
.all(|f| f.can_derive_default(ctx, ()));
|
||||||
self.ref_template
|
|
||||||
.map_or(true, |id| id.can_derive_default(ctx, ()));
|
|
||||||
|
|
||||||
self.detect_derive_default_cycle.set(false);
|
self.detect_derive_default_cycle.set(false);
|
||||||
|
|
||||||
@ -1013,17 +923,12 @@ impl<'a> CanDeriveCopy<'a> for CompInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/rust-lang/rust/issues/36640
|
// https://github.com/rust-lang/rust/issues/36640
|
||||||
if !self.template_args.is_empty() || self.ref_template.is_some() ||
|
if !self.template_params.is_empty() ||
|
||||||
!item.applicable_template_args(ctx).is_empty() {
|
item.used_template_params(ctx).is_some() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// With template args, use a safe subset of the types,
|
|
||||||
// since copyability depends on the types itself.
|
|
||||||
self.ref_template
|
|
||||||
.as_ref()
|
|
||||||
.map_or(true, |t| t.can_derive_copy(ctx, ())) &&
|
|
||||||
self.base_members
|
self.base_members
|
||||||
.iter()
|
.iter()
|
||||||
.all(|base| base.ty.can_derive_copy(ctx, ())) &&
|
.all(|base| base.ty.can_derive_copy(ctx, ())) &&
|
||||||
@ -1044,25 +949,9 @@ impl Trace for CompInfo {
|
|||||||
fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item)
|
fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, item: &Item)
|
||||||
where T: Tracer,
|
where T: Tracer,
|
||||||
{
|
{
|
||||||
// TODO: We should properly distinguish template instantiations from
|
let params = item.all_template_params(context).unwrap_or(vec![]);
|
||||||
// template declarations at the type level. Why are some template
|
for p in params {
|
||||||
// instantiations represented here instead of as
|
tracer.visit_kind(p, EdgeKind::TemplateParameterDefinition);
|
||||||
// TypeKind::TemplateInstantiation?
|
|
||||||
if let Some(template) = self.specialized_template() {
|
|
||||||
// This is an instantiation of a template declaration with concrete
|
|
||||||
// template type arguments.
|
|
||||||
tracer.visit_kind(template, EdgeKind::TemplateDeclaration);
|
|
||||||
let args = item.applicable_template_args(context);
|
|
||||||
for a in args {
|
|
||||||
tracer.visit_kind(a, EdgeKind::TemplateArgument);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let params = item.applicable_template_args(context);
|
|
||||||
// This is a template declaration with abstract template type
|
|
||||||
// parameters.
|
|
||||||
for p in params {
|
|
||||||
tracer.visit_kind(p, EdgeKind::TemplateParameterDefinition);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for base in self.base_members() {
|
for base in self.base_members() {
|
||||||
|
@ -5,6 +5,8 @@ use super::int::IntKind;
|
|||||||
use super::item::{Item, ItemCanonicalPath, ItemSet};
|
use super::item::{Item, ItemCanonicalPath, ItemSet};
|
||||||
use super::item_kind::ItemKind;
|
use super::item_kind::ItemKind;
|
||||||
use super::module::{Module, ModuleKind};
|
use super::module::{Module, ModuleKind};
|
||||||
|
use super::named::{UsedTemplateParameters, analyze};
|
||||||
|
use super::template::TemplateInstantiation;
|
||||||
use super::traversal::{self, Edge, ItemTraversal};
|
use super::traversal::{self, Edge, ItemTraversal};
|
||||||
use super::ty::{FloatKind, TemplateDeclaration, Type, TypeKind};
|
use super::ty::{FloatKind, TemplateDeclaration, Type, TypeKind};
|
||||||
use BindgenOptions;
|
use BindgenOptions;
|
||||||
@ -102,6 +104,10 @@ pub struct BindgenContext<'ctx> {
|
|||||||
/// item ids during parsing.
|
/// item ids during parsing.
|
||||||
types: HashMap<TypeKey, ItemId>,
|
types: HashMap<TypeKey, ItemId>,
|
||||||
|
|
||||||
|
/// Maps from a cursor to the item id of the named template type parameter
|
||||||
|
/// for that cursor.
|
||||||
|
named_types: HashMap<clang::Cursor, ItemId>,
|
||||||
|
|
||||||
/// A cursor to module map. Similar reason than above.
|
/// A cursor to module map. Similar reason than above.
|
||||||
modules: HashMap<Cursor, ItemId>,
|
modules: HashMap<Cursor, ItemId>,
|
||||||
|
|
||||||
@ -149,6 +155,11 @@ pub struct BindgenContext<'ctx> {
|
|||||||
|
|
||||||
/// Whether a bindgen complex was generated
|
/// Whether a bindgen complex was generated
|
||||||
generated_bindegen_complex: Cell<bool>,
|
generated_bindegen_complex: Cell<bool>,
|
||||||
|
|
||||||
|
/// Map from an item's id to the set of template parameter items that it
|
||||||
|
/// uses. See `ir::named` for more details. Always `Some` during the codegen
|
||||||
|
/// phase.
|
||||||
|
used_template_parameters: Option<HashMap<ItemId, ItemSet>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A traversal of whitelisted items.
|
/// A traversal of whitelisted items.
|
||||||
@ -173,12 +184,13 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
&options.clang_args,
|
&options.clang_args,
|
||||||
&[],
|
&[],
|
||||||
parse_options)
|
parse_options)
|
||||||
.expect("TranslationUnit::parse");
|
.expect("TranslationUnit::parse failed");
|
||||||
|
|
||||||
let root_module = Self::build_root_module(ItemId(0));
|
let root_module = Self::build_root_module(ItemId(0));
|
||||||
let mut me = BindgenContext {
|
let mut me = BindgenContext {
|
||||||
items: Default::default(),
|
items: Default::default(),
|
||||||
types: Default::default(),
|
types: Default::default(),
|
||||||
|
named_types: Default::default(),
|
||||||
modules: Default::default(),
|
modules: Default::default(),
|
||||||
next_item_id: ItemId(1),
|
next_item_id: ItemId(1),
|
||||||
root_module: root_module.id(),
|
root_module: root_module.id(),
|
||||||
@ -193,6 +205,7 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
translation_unit: translation_unit,
|
translation_unit: translation_unit,
|
||||||
options: options,
|
options: options,
|
||||||
generated_bindegen_complex: Cell::new(false),
|
generated_bindegen_complex: Cell::new(false),
|
||||||
|
used_template_parameters: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
me.add_item(root_module, None, None);
|
me.add_item(root_module, None, None);
|
||||||
@ -238,7 +251,8 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
declaration,
|
declaration,
|
||||||
location);
|
location);
|
||||||
debug_assert!(declaration.is_some() || !item.kind().is_type() ||
|
debug_assert!(declaration.is_some() || !item.kind().is_type() ||
|
||||||
item.kind().expect_type().is_builtin_or_named(),
|
item.kind().expect_type().is_builtin_or_named() ||
|
||||||
|
item.kind().expect_type().is_opaque(),
|
||||||
"Adding a type without declaration?");
|
"Adding a type without declaration?");
|
||||||
|
|
||||||
let id = item.id();
|
let id = item.id();
|
||||||
@ -256,7 +270,8 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let old_item = self.items.insert(id, item);
|
let old_item = self.items.insert(id, item);
|
||||||
assert!(old_item.is_none(), "Inserted type twice?");
|
assert!(old_item.is_none(),
|
||||||
|
"should not have already associated an item with the given id");
|
||||||
|
|
||||||
// Unnamed items can have an USR, but they can't be referenced from
|
// Unnamed items can have an USR, but they can't be referenced from
|
||||||
// other sites explicitly and the USR can match if the unnamed items are
|
// other sites explicitly and the USR can match if the unnamed items are
|
||||||
@ -299,6 +314,35 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a new named template type parameter to this context's item set.
|
||||||
|
pub fn add_named_type(&mut self, item: Item, definition: clang::Cursor) {
|
||||||
|
debug!("BindgenContext::add_named_type: item = {:?}; definition = {:?}",
|
||||||
|
item,
|
||||||
|
definition);
|
||||||
|
|
||||||
|
assert!(item.expect_type().is_named(),
|
||||||
|
"Should directly be a named type, not a resolved reference or anything");
|
||||||
|
assert_eq!(definition.kind(),
|
||||||
|
clang_sys::CXCursor_TemplateTypeParameter);
|
||||||
|
|
||||||
|
let id = item.id();
|
||||||
|
let old_item = self.items.insert(id, item);
|
||||||
|
assert!(old_item.is_none(),
|
||||||
|
"should not have already associated an item with the given id");
|
||||||
|
|
||||||
|
let old_named_ty = self.named_types.insert(definition, id);
|
||||||
|
assert!(old_named_ty.is_none(),
|
||||||
|
"should not have already associated a named type with this id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the named type defined at the given cursor location, if we've
|
||||||
|
/// already added one.
|
||||||
|
pub fn get_named_type(&self, definition: &clang::Cursor) -> Option<ItemId> {
|
||||||
|
assert_eq!(definition.kind(),
|
||||||
|
clang_sys::CXCursor_TemplateTypeParameter);
|
||||||
|
self.named_types.get(definition).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Move all this syntax crap to other part of the code.
|
// TODO: Move all this syntax crap to other part of the code.
|
||||||
|
|
||||||
/// Given that we are in the codegen phase, get the syntex context.
|
/// Given that we are in the codegen phase, get the syntex context.
|
||||||
@ -352,7 +396,7 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
/// Gather all the unresolved type references.
|
/// Gather all the unresolved type references.
|
||||||
fn collect_typerefs
|
fn collect_typerefs
|
||||||
(&mut self)
|
(&mut self)
|
||||||
-> Vec<(ItemId, clang::Type, Option<clang::Cursor>, Option<ItemId>)> {
|
-> Vec<(ItemId, clang::Type, clang::Cursor, Option<ItemId>)> {
|
||||||
debug_assert!(!self.collected_typerefs);
|
debug_assert!(!self.collected_typerefs);
|
||||||
self.collected_typerefs = true;
|
self.collected_typerefs = true;
|
||||||
let mut typerefs = vec![];
|
let mut typerefs = vec![];
|
||||||
@ -423,7 +467,7 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
TypeKind::Comp(ref ci) if !ci.is_template_specialization() => {}
|
TypeKind::Comp(..) |
|
||||||
TypeKind::TemplateAlias(..) |
|
TypeKind::TemplateAlias(..) |
|
||||||
TypeKind::Alias(..) => {}
|
TypeKind::Alias(..) => {}
|
||||||
_ => continue,
|
_ => continue,
|
||||||
@ -529,6 +573,8 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
self.process_replacements();
|
self.process_replacements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.find_used_template_parameters();
|
||||||
|
|
||||||
let ret = cb(self);
|
let ret = cb(self);
|
||||||
self.gen_ctx = None;
|
self.gen_ctx = None;
|
||||||
ret
|
ret
|
||||||
@ -555,6 +601,45 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
traversal::all_edges)
|
traversal::all_edges)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_used_template_parameters(&mut self) {
|
||||||
|
if self.options.whitelist_recursively {
|
||||||
|
let used_params = analyze::<UsedTemplateParameters>(self);
|
||||||
|
self.used_template_parameters = Some(used_params);
|
||||||
|
} else {
|
||||||
|
// If you aren't recursively whitelisting, then we can't really make
|
||||||
|
// any sense of template parameter usage, and you're on your own.
|
||||||
|
let mut used_params = HashMap::new();
|
||||||
|
for id in self.whitelisted_items() {
|
||||||
|
used_params.entry(id)
|
||||||
|
.or_insert(id.self_template_params(self)
|
||||||
|
.map_or(Default::default(),
|
||||||
|
|params| params.into_iter().collect()));
|
||||||
|
}
|
||||||
|
self.used_template_parameters = Some(used_params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `true` if `item` uses the given `template_param`, `false`
|
||||||
|
/// otherwise.
|
||||||
|
///
|
||||||
|
/// This method may only be called during the codegen phase, because the
|
||||||
|
/// template usage information is only computed as we enter the codegen
|
||||||
|
/// phase.
|
||||||
|
pub fn uses_template_parameter(&self,
|
||||||
|
item: ItemId,
|
||||||
|
template_param: ItemId)
|
||||||
|
-> bool {
|
||||||
|
assert!(self.in_codegen_phase(),
|
||||||
|
"We only compute template parameter usage as we enter codegen");
|
||||||
|
|
||||||
|
self.used_template_parameters
|
||||||
|
.as_ref()
|
||||||
|
.expect("should have found template parameter usage if we're in codegen")
|
||||||
|
.get(&item)
|
||||||
|
.map(|items_used_params| items_used_params.contains(&template_param))
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
// This deserves a comment. Builtin types don't get a valid declaration, so
|
// This deserves a comment. Builtin types don't get a valid declaration, so
|
||||||
// we can't add it to the cursor->type map.
|
// we can't add it to the cursor->type map.
|
||||||
//
|
//
|
||||||
@ -613,6 +698,21 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolve the given `ItemId` into a `Type`, and keep doing so while we see
|
||||||
|
/// `ResolvedTypeRef`s to other items until we get to the final `Type`.
|
||||||
|
pub fn resolve_type_through_type_refs(&self, item_id: ItemId) -> &Type {
|
||||||
|
assert!(self.collected_typerefs());
|
||||||
|
|
||||||
|
let mut id = item_id;
|
||||||
|
loop {
|
||||||
|
let ty = self.resolve_type(id);
|
||||||
|
match *ty.kind() {
|
||||||
|
TypeKind::ResolvedTypeRef(next_id) => id = next_id,
|
||||||
|
_ => return ty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the current module.
|
/// Get the current module.
|
||||||
pub fn current_module(&self) -> ItemId {
|
pub fn current_module(&self) -> ItemId {
|
||||||
self.current_module
|
self.current_module
|
||||||
@ -753,7 +853,7 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
// template declaration as the parent. It is already parsed and
|
// template declaration as the parent. It is already parsed and
|
||||||
// has a known-resolvable `ItemId`.
|
// has a known-resolvable `ItemId`.
|
||||||
let ty = Item::from_ty_or_ref(child.cur_type(),
|
let ty = Item::from_ty_or_ref(child.cur_type(),
|
||||||
Some(*child),
|
*child,
|
||||||
Some(template),
|
Some(template),
|
||||||
self);
|
self);
|
||||||
args.push(ty);
|
args.push(ty);
|
||||||
@ -770,7 +870,7 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
// Do a happy little parse. See comment in the TypeRef
|
// Do a happy little parse. See comment in the TypeRef
|
||||||
// match arm about parent IDs.
|
// match arm about parent IDs.
|
||||||
let ty = Item::from_ty_or_ref(child.cur_type(),
|
let ty = Item::from_ty_or_ref(child.cur_type(),
|
||||||
Some(*child),
|
*child,
|
||||||
Some(template),
|
Some(template),
|
||||||
self);
|
self);
|
||||||
args.push(ty);
|
args.push(ty);
|
||||||
@ -792,9 +892,9 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
sub_args.reverse();
|
sub_args.reverse();
|
||||||
|
|
||||||
let sub_name = Some(template_decl_cursor.spelling());
|
let sub_name = Some(template_decl_cursor.spelling());
|
||||||
|
let sub_inst = TemplateInstantiation::new(template_decl_id, sub_args);
|
||||||
let sub_kind =
|
let sub_kind =
|
||||||
TypeKind::TemplateInstantiation(template_decl_id,
|
TypeKind::TemplateInstantiation(sub_inst);
|
||||||
sub_args);
|
|
||||||
let sub_ty = Type::new(sub_name,
|
let sub_ty = Type::new(sub_name,
|
||||||
template_decl_cursor.cur_type()
|
template_decl_cursor.cur_type()
|
||||||
.fallible_layout()
|
.fallible_layout()
|
||||||
@ -844,7 +944,8 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
args.reverse();
|
args.reverse();
|
||||||
let type_kind = TypeKind::TemplateInstantiation(template, args);
|
let type_kind = TypeKind::TemplateInstantiation(
|
||||||
|
TemplateInstantiation::new(template, args));
|
||||||
let name = ty.spelling();
|
let name = ty.spelling();
|
||||||
let name = if name.is_empty() { None } else { Some(name) };
|
let name = if name.is_empty() { None } else { Some(name) };
|
||||||
let ty = Type::new(name,
|
let ty = Type::new(name,
|
||||||
@ -863,9 +964,9 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
|
|
||||||
/// If we have already resolved the type for the given type declaration,
|
/// If we have already resolved the type for the given type declaration,
|
||||||
/// return its `ItemId`. Otherwise, return `None`.
|
/// return its `ItemId`. Otherwise, return `None`.
|
||||||
fn get_resolved_type(&self,
|
pub fn get_resolved_type(&self,
|
||||||
decl: &clang::CanonicalTypeDeclaration)
|
decl: &clang::CanonicalTypeDeclaration)
|
||||||
-> Option<ItemId> {
|
-> Option<ItemId> {
|
||||||
self.types
|
self.types
|
||||||
.get(&TypeKey::Declaration(*decl.cursor()))
|
.get(&TypeKey::Declaration(*decl.cursor()))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
@ -904,16 +1005,15 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
// of it, or
|
// of it, or
|
||||||
// * we have already parsed and resolved this type, and
|
// * we have already parsed and resolved this type, and
|
||||||
// there's nothing left to do.
|
// there's nothing left to do.
|
||||||
//
|
|
||||||
// Note that we only do the former if the `parent_id` exists,
|
|
||||||
// and we have a location for building the new arguments. The
|
|
||||||
// template argument names don't matter in the global context.
|
|
||||||
if decl.cursor().is_template_like() &&
|
if decl.cursor().is_template_like() &&
|
||||||
*ty != decl.cursor().cur_type() &&
|
*ty != decl.cursor().cur_type() &&
|
||||||
location.is_some() &&
|
location.is_some() {
|
||||||
parent_id.is_some() {
|
|
||||||
let location = location.unwrap();
|
let location = location.unwrap();
|
||||||
let parent_id = parent_id.unwrap();
|
|
||||||
|
// It is always safe to hang instantiations off of the root
|
||||||
|
// module. They use their template definition for naming,
|
||||||
|
// and don't need the parent for anything else.
|
||||||
|
let parent_id = self.root_module();
|
||||||
|
|
||||||
// For specialized type aliases, there's no way to get the
|
// For specialized type aliases, there's no way to get the
|
||||||
// template parameters as of this writing (for a struct
|
// template parameters as of this writing (for a struct
|
||||||
@ -947,17 +1047,20 @@ impl<'ctx> BindgenContext<'ctx> {
|
|||||||
self.build_builtin_ty(ty)
|
self.build_builtin_ty(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is unfortunately a lot of bloat, but is needed to properly track
|
/// Make a new item that is a resolved type reference to the `wrapped_id`.
|
||||||
// constness et. al.
|
///
|
||||||
//
|
/// This is unfortunately a lot of bloat, but is needed to properly track
|
||||||
// We should probably make the constness tracking separate, so it doesn't
|
/// constness et. al.
|
||||||
// bloat that much, but hey, we already bloat the heck out of builtin types.
|
///
|
||||||
fn build_ty_wrapper(&mut self,
|
/// We should probably make the constness tracking separate, so it doesn't
|
||||||
with_id: ItemId,
|
/// bloat that much, but hey, we already bloat the heck out of builtin
|
||||||
wrapped_id: ItemId,
|
/// types.
|
||||||
parent_id: Option<ItemId>,
|
pub fn build_ty_wrapper(&mut self,
|
||||||
ty: &clang::Type)
|
with_id: ItemId,
|
||||||
-> ItemId {
|
wrapped_id: ItemId,
|
||||||
|
parent_id: Option<ItemId>,
|
||||||
|
ty: &clang::Type)
|
||||||
|
-> ItemId {
|
||||||
let spelling = ty.spelling();
|
let spelling = ty.spelling();
|
||||||
let is_const = ty.is_const();
|
let is_const = ty.is_const();
|
||||||
let layout = ty.fallible_layout().ok();
|
let layout = ty.fallible_layout().ok();
|
||||||
@ -1331,7 +1434,9 @@ impl PartialType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TemplateDeclaration for PartialType {
|
impl TemplateDeclaration for PartialType {
|
||||||
fn self_template_params(&self, _ctx: &BindgenContext) -> Option<Vec<ItemId>> {
|
fn self_template_params(&self,
|
||||||
|
_ctx: &BindgenContext)
|
||||||
|
-> Option<Vec<ItemId>> {
|
||||||
// Maybe at some point we will eagerly parse named types, but for now we
|
// Maybe at some point we will eagerly parse named types, but for now we
|
||||||
// don't and this information is unavailable.
|
// don't and this information is unavailable.
|
||||||
None
|
None
|
||||||
|
@ -1,23 +1,26 @@
|
|||||||
//! Generating Graphviz `dot` files from our IR.
|
//! Generating Graphviz `dot` files from our IR.
|
||||||
|
|
||||||
|
use super::context::{BindgenContext, ItemId};
|
||||||
|
use super::traversal::Trace;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use super::context::{BindgenContext, ItemId};
|
|
||||||
use super::traversal::Trace;
|
|
||||||
|
|
||||||
/// A trait for anything that can write attributes as `<table>` rows to a dot
|
/// A trait for anything that can write attributes as `<table>` rows to a dot
|
||||||
/// file.
|
/// file.
|
||||||
pub trait DotAttributes {
|
pub trait DotAttributes {
|
||||||
/// Write this thing's attributes to the given output. Each attribute must
|
/// Write this thing's attributes to the given output. Each attribute must
|
||||||
/// be its own `<tr>...</tr>`.
|
/// be its own `<tr>...</tr>`.
|
||||||
fn dot_attributes<W>(&self, ctx: &BindgenContext, out: &mut W) -> io::Result<()>
|
fn dot_attributes<W>(&self,
|
||||||
|
ctx: &BindgenContext,
|
||||||
|
out: &mut W)
|
||||||
|
-> io::Result<()>
|
||||||
where W: io::Write;
|
where W: io::Write;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a graphviz dot file containing our IR.
|
/// Write a graphviz dot file containing our IR.
|
||||||
pub fn write_dot_file<P>(ctx: &BindgenContext, path: P) -> io::Result<()>
|
pub fn write_dot_file<P>(ctx: &BindgenContext, path: P) -> io::Result<()>
|
||||||
where P: AsRef<Path>
|
where P: AsRef<Path>,
|
||||||
{
|
{
|
||||||
let file = try!(File::create(path));
|
let file = try!(File::create(path));
|
||||||
let mut dot_file = io::BufWriter::new(file);
|
let mut dot_file = io::BufWriter::new(file);
|
||||||
@ -32,16 +35,21 @@ pub fn write_dot_file<P>(ctx: &BindgenContext, path: P) -> io::Result<()>
|
|||||||
try!(item.dot_attributes(ctx, &mut dot_file));
|
try!(item.dot_attributes(ctx, &mut dot_file));
|
||||||
try!(writeln!(&mut dot_file, r#"</table> >];"#));
|
try!(writeln!(&mut dot_file, r#"</table> >];"#));
|
||||||
|
|
||||||
item.trace(ctx, &mut |sub_id: ItemId, _edge_kind| {
|
item.trace(ctx,
|
||||||
|
&mut |sub_id: ItemId, _edge_kind| {
|
||||||
if err.is_some() {
|
if err.is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match writeln!(&mut dot_file, "{} -> {};", id.as_usize(), sub_id.as_usize()) {
|
match writeln!(&mut dot_file,
|
||||||
Ok(_) => {},
|
"{} -> {};",
|
||||||
|
id.as_usize(),
|
||||||
|
sub_id.as_usize()) {
|
||||||
|
Ok(_) => {}
|
||||||
Err(e) => err = Some(Err(e)),
|
Err(e) => err = Some(Err(e)),
|
||||||
}
|
}
|
||||||
}, &());
|
},
|
||||||
|
&());
|
||||||
|
|
||||||
if let Some(err) = err {
|
if let Some(err) = err {
|
||||||
return err;
|
return err;
|
||||||
|
@ -60,7 +60,7 @@ impl Enum {
|
|||||||
|
|
||||||
let declaration = ty.declaration().canonical();
|
let declaration = ty.declaration().canonical();
|
||||||
let repr = declaration.enum_type()
|
let repr = declaration.enum_type()
|
||||||
.and_then(|et| Item::from_ty(&et, None, None, ctx).ok());
|
.and_then(|et| Item::from_ty(&et, declaration, None, ctx).ok());
|
||||||
let mut variants = vec![];
|
let mut variants = vec![];
|
||||||
|
|
||||||
// Assume signedness since the default type by the C standard is an int.
|
// Assume signedness since the default type by the C standard is an int.
|
||||||
@ -99,7 +99,7 @@ impl Enum {
|
|||||||
Annotations::new(&cursor)
|
Annotations::new(&cursor)
|
||||||
.and_then(|anno| if anno.hide() {
|
.and_then(|anno| if anno.hide() {
|
||||||
Some(EnumVariantCustomBehavior::Hide)
|
Some(EnumVariantCustomBehavior::Hide)
|
||||||
} else if
|
} else if
|
||||||
anno.constify_enum_variant() {
|
anno.constify_enum_variant() {
|
||||||
Some(EnumVariantCustomBehavior::Constify)
|
Some(EnumVariantCustomBehavior::Constify)
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,9 +5,9 @@ use super::dot::DotAttributes;
|
|||||||
use super::item::Item;
|
use super::item::Item;
|
||||||
use super::traversal::{EdgeKind, Trace, Tracer};
|
use super::traversal::{EdgeKind, Trace, Tracer};
|
||||||
use super::ty::TypeKind;
|
use super::ty::TypeKind;
|
||||||
use ir::derive::CanDeriveDebug;
|
|
||||||
use clang;
|
use clang;
|
||||||
use clang_sys::CXCallingConv;
|
use clang_sys::CXCallingConv;
|
||||||
|
use ir::derive::CanDeriveDebug;
|
||||||
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
|
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
|
||||||
use std::io;
|
use std::io;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
@ -63,11 +63,16 @@ impl Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DotAttributes for Function {
|
impl DotAttributes for Function {
|
||||||
fn dot_attributes<W>(&self, _ctx: &BindgenContext, out: &mut W) -> io::Result<()>
|
fn dot_attributes<W>(&self,
|
||||||
where W: io::Write
|
_ctx: &BindgenContext,
|
||||||
|
out: &mut W)
|
||||||
|
-> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
{
|
{
|
||||||
if let Some(ref mangled) = self.mangled_name {
|
if let Some(ref mangled) = self.mangled_name {
|
||||||
try!(writeln!(out, "<tr><td>mangled name</td><td>{}</td></tr>", mangled));
|
try!(writeln!(out,
|
||||||
|
"<tr><td>mangled name</td><td>{}</td></tr>",
|
||||||
|
mangled));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -188,8 +193,7 @@ impl FunctionSig {
|
|||||||
let name = arg.spelling();
|
let name = arg.spelling();
|
||||||
let name =
|
let name =
|
||||||
if name.is_empty() { None } else { Some(name) };
|
if name.is_empty() { None } else { Some(name) };
|
||||||
let ty =
|
let ty = Item::from_ty_or_ref(arg_ty, *arg, None, ctx);
|
||||||
Item::from_ty_or_ref(arg_ty, Some(*arg), None, ctx);
|
|
||||||
(name, ty)
|
(name, ty)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
@ -200,10 +204,8 @@ impl FunctionSig {
|
|||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
cursor.visit(|c| {
|
cursor.visit(|c| {
|
||||||
if c.kind() == CXCursor_ParmDecl {
|
if c.kind() == CXCursor_ParmDecl {
|
||||||
let ty = Item::from_ty_or_ref(c.cur_type(),
|
let ty =
|
||||||
Some(c),
|
Item::from_ty_or_ref(c.cur_type(), c, None, ctx);
|
||||||
None,
|
|
||||||
ctx);
|
|
||||||
let name = c.spelling();
|
let name = c.spelling();
|
||||||
let name =
|
let name =
|
||||||
if name.is_empty() { None } else { Some(name) };
|
if name.is_empty() { None } else { Some(name) };
|
||||||
@ -246,7 +248,7 @@ impl FunctionSig {
|
|||||||
} else {
|
} else {
|
||||||
try!(ty.ret_type().ok_or(ParseError::Continue))
|
try!(ty.ret_type().ok_or(ParseError::Continue))
|
||||||
};
|
};
|
||||||
let ret = Item::from_ty_or_ref(ty_ret_type, None, None, ctx);
|
let ret = Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx);
|
||||||
let abi = get_abi(ty.call_conv());
|
let abi = get_abi(ty.call_conv());
|
||||||
|
|
||||||
if abi.is_none() {
|
if abi.is_none() {
|
||||||
@ -317,10 +319,8 @@ impl ClangSubItemParser for Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Grab the signature using Item::from_ty.
|
// Grab the signature using Item::from_ty.
|
||||||
let sig = try!(Item::from_ty(&cursor.cur_type(),
|
let sig =
|
||||||
Some(cursor),
|
try!(Item::from_ty(&cursor.cur_type(), cursor, None, context));
|
||||||
None,
|
|
||||||
context));
|
|
||||||
|
|
||||||
let name = cursor.spelling();
|
let name = cursor.spelling();
|
||||||
assert!(!name.is_empty(), "Empty function name?");
|
assert!(!name.is_empty(), "Empty function name?");
|
||||||
@ -368,7 +368,8 @@ impl CanDeriveDebug for FunctionSig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match self.abi {
|
match self.abi {
|
||||||
Some(abi::Abi::C) | None => true,
|
Some(abi::Abi::C) |
|
||||||
|
None => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
583
src/ir/item.rs
583
src/ir/item.rs
@ -3,10 +3,12 @@
|
|||||||
use super::annotations::Annotations;
|
use super::annotations::Annotations;
|
||||||
use super::context::{BindgenContext, ItemId, PartialType};
|
use super::context::{BindgenContext, ItemId, PartialType};
|
||||||
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
|
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
|
||||||
use super::dot::{DotAttributes};
|
use super::dot::DotAttributes;
|
||||||
use super::function::Function;
|
use super::function::Function;
|
||||||
use super::item_kind::ItemKind;
|
use super::item_kind::ItemKind;
|
||||||
|
use super::layout::Opaque;
|
||||||
use super::module::Module;
|
use super::module::Module;
|
||||||
|
use super::template::AsNamed;
|
||||||
use super::traversal::{EdgeKind, Trace, Tracer};
|
use super::traversal::{EdgeKind, Trace, Tracer};
|
||||||
use super::ty::{TemplateDeclaration, Type, TypeKind};
|
use super::ty::{TemplateDeclaration, Type, TypeKind};
|
||||||
use clang;
|
use clang;
|
||||||
@ -15,8 +17,8 @@ use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
|
|||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::iter;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
/// A trait to get the canonical name from an item.
|
/// A trait to get the canonical name from an item.
|
||||||
///
|
///
|
||||||
@ -128,6 +130,35 @@ impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsNamed for ItemId {
|
||||||
|
type Extra = ();
|
||||||
|
|
||||||
|
fn as_named(&self, ctx: &BindgenContext, _: &()) -> Option<ItemId> {
|
||||||
|
ctx.resolve_item(*self).as_named(ctx, &())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsNamed for Item {
|
||||||
|
type Extra = ();
|
||||||
|
|
||||||
|
fn as_named(&self, ctx: &BindgenContext, _: &()) -> Option<ItemId> {
|
||||||
|
self.kind.as_named(ctx, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsNamed for ItemKind {
|
||||||
|
type Extra = Item;
|
||||||
|
|
||||||
|
fn as_named(&self, ctx: &BindgenContext, item: &Item) -> Option<ItemId> {
|
||||||
|
match *self {
|
||||||
|
ItemKind::Type(ref ty) => ty.as_named(ctx, item),
|
||||||
|
ItemKind::Module(..) |
|
||||||
|
ItemKind::Function(..) |
|
||||||
|
ItemKind::Var(..) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Pure convenience
|
// Pure convenience
|
||||||
impl ItemCanonicalName for ItemId {
|
impl ItemCanonicalName for ItemId {
|
||||||
fn canonical_name(&self, ctx: &BindgenContext) -> String {
|
fn canonical_name(&self, ctx: &BindgenContext) -> String {
|
||||||
@ -224,8 +255,14 @@ impl CanDeriveDebug for Item {
|
|||||||
type Extra = ();
|
type Extra = ();
|
||||||
|
|
||||||
fn can_derive_debug(&self, ctx: &BindgenContext, _: ()) -> bool {
|
fn can_derive_debug(&self, ctx: &BindgenContext, _: ()) -> bool {
|
||||||
ctx.options().derive_debug &&
|
if self.detect_derive_debug_cycle.get() {
|
||||||
match self.kind {
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.detect_derive_debug_cycle.set(true);
|
||||||
|
|
||||||
|
let result = ctx.options().derive_debug &&
|
||||||
|
match self.kind {
|
||||||
ItemKind::Type(ref ty) => {
|
ItemKind::Type(ref ty) => {
|
||||||
if self.is_opaque(ctx) {
|
if self.is_opaque(ctx) {
|
||||||
ty.layout(ctx)
|
ty.layout(ctx)
|
||||||
@ -235,7 +272,11 @@ impl CanDeriveDebug for Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
self.detect_derive_debug_cycle.set(false);
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +304,13 @@ impl<'a> CanDeriveCopy<'a> for Item {
|
|||||||
type Extra = ();
|
type Extra = ();
|
||||||
|
|
||||||
fn can_derive_copy(&self, ctx: &BindgenContext, _: ()) -> bool {
|
fn can_derive_copy(&self, ctx: &BindgenContext, _: ()) -> bool {
|
||||||
match self.kind {
|
if self.detect_derive_copy_cycle.get() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.detect_derive_copy_cycle.set(true);
|
||||||
|
|
||||||
|
let result = match self.kind {
|
||||||
ItemKind::Type(ref ty) => {
|
ItemKind::Type(ref ty) => {
|
||||||
if self.is_opaque(ctx) {
|
if self.is_opaque(ctx) {
|
||||||
ty.layout(ctx)
|
ty.layout(ctx)
|
||||||
@ -273,7 +320,11 @@ impl<'a> CanDeriveCopy<'a> for Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
self.detect_derive_copy_cycle.set(false);
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_derive_copy_in_array(&self, ctx: &BindgenContext, _: ()) -> bool {
|
fn can_derive_copy_in_array(&self, ctx: &BindgenContext, _: ()) -> bool {
|
||||||
@ -346,6 +397,16 @@ pub struct Item {
|
|||||||
parent_id: ItemId,
|
parent_id: ItemId,
|
||||||
/// The item kind.
|
/// The item kind.
|
||||||
kind: ItemKind,
|
kind: ItemKind,
|
||||||
|
/// Detect cycles when determining if we can derive debug/copy or not, and
|
||||||
|
/// avoid infinite recursion.
|
||||||
|
detect_derive_debug_cycle: Cell<bool>,
|
||||||
|
detect_derive_copy_cycle: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<ItemId> for Item {
|
||||||
|
fn as_ref(&self) -> &ItemId {
|
||||||
|
&self.id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Item {
|
impl Item {
|
||||||
@ -366,9 +427,22 @@ impl Item {
|
|||||||
comment: comment,
|
comment: comment,
|
||||||
annotations: annotations.unwrap_or_default(),
|
annotations: annotations.unwrap_or_default(),
|
||||||
kind: kind,
|
kind: kind,
|
||||||
|
detect_derive_debug_cycle: Cell::new(false),
|
||||||
|
detect_derive_copy_cycle: Cell::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_opaque_type(with_id: ItemId,
|
||||||
|
ty: &clang::Type,
|
||||||
|
ctx: &mut BindgenContext)
|
||||||
|
-> ItemId {
|
||||||
|
let ty = Opaque::from_clang_ty(ty);
|
||||||
|
let kind = ItemKind::Type(ty);
|
||||||
|
let parent = ctx.root_module();
|
||||||
|
ctx.add_item(Item::new(with_id, None, None, parent, kind), None, None);
|
||||||
|
with_id
|
||||||
|
}
|
||||||
|
|
||||||
/// Get this `Item`'s identifier.
|
/// Get this `Item`'s identifier.
|
||||||
pub fn id(&self) -> ItemId {
|
pub fn id(&self) -> ItemId {
|
||||||
self.id
|
self.id
|
||||||
@ -474,184 +548,12 @@ impl Item {
|
|||||||
self.kind().as_type()
|
self.kind().as_type()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this item a named template type parameter?
|
|
||||||
pub fn is_named(&self) -> bool {
|
|
||||||
self.as_type()
|
|
||||||
.map(|ty| ty.is_named())
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a reference to this item's underlying `Function`. Panic if this is
|
/// Get a reference to this item's underlying `Function`. Panic if this is
|
||||||
/// some other kind of item.
|
/// some other kind of item.
|
||||||
pub fn expect_function(&self) -> &Function {
|
pub fn expect_function(&self) -> &Function {
|
||||||
self.kind().expect_function()
|
self.kind().expect_function()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether an item contains in its "type signature" some named type.
|
|
||||||
///
|
|
||||||
/// This function is used to avoid unused template parameter errors in Rust
|
|
||||||
/// when generating typedef declarations, and also to know whether we need
|
|
||||||
/// to generate a `PhantomData` member for a template parameter.
|
|
||||||
///
|
|
||||||
/// For example, in code like the following:
|
|
||||||
///
|
|
||||||
/// ```c++
|
|
||||||
/// template<typename T, typename U>
|
|
||||||
/// struct Foo {
|
|
||||||
/// T bar;
|
|
||||||
///
|
|
||||||
/// struct Baz {
|
|
||||||
/// U bas;
|
|
||||||
/// };
|
|
||||||
/// };
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Both `Foo` and `Baz` contain both `T` and `U` template parameters in
|
|
||||||
/// their signature:
|
|
||||||
///
|
|
||||||
/// * `Foo<T, U>`
|
|
||||||
/// * `Bar<T, U>`
|
|
||||||
///
|
|
||||||
/// But the Rust structure for `Foo` would look like:
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// struct Foo<T, U> {
|
|
||||||
/// bar: T,
|
|
||||||
/// _phantom0: ::std::marker::PhantomData<U>,
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// because none of its member fields contained the `U` type in the
|
|
||||||
/// signature. Similarly, `Bar` would contain a `PhantomData<T>` type, for
|
|
||||||
/// the same reason.
|
|
||||||
///
|
|
||||||
/// Note that this is somewhat similar to `applicable_template_args`, but
|
|
||||||
/// this also takes into account other kind of types, like arrays,
|
|
||||||
/// (`[T; 40]`), pointers: `*mut T`, etc...
|
|
||||||
///
|
|
||||||
/// Normally we could do this check just in the `Type` kind, but we also
|
|
||||||
/// need to check the `applicable_template_args` more generally, since we
|
|
||||||
/// could need a type transitively from our parent, see the test added in
|
|
||||||
/// commit 2a3f93074dd2898669dbbce6e97e5cc4405d7cb1.
|
|
||||||
///
|
|
||||||
/// It's kind of unfortunate (in the sense that it's a sort of complex
|
|
||||||
/// process), but I think it should get all the cases.
|
|
||||||
fn signature_contains_named_type(&self,
|
|
||||||
ctx: &BindgenContext,
|
|
||||||
ty: &Type)
|
|
||||||
-> bool {
|
|
||||||
debug_assert!(ty.is_named());
|
|
||||||
self.expect_type().signature_contains_named_type(ctx, ty) ||
|
|
||||||
self.applicable_template_args(ctx).iter().any(|template| {
|
|
||||||
ctx.resolve_type(*template).signature_contains_named_type(ctx, ty)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the template arguments that apply to a struct. This is a concept
|
|
||||||
/// needed because of type declarations inside templates, for example:
|
|
||||||
///
|
|
||||||
/// ```c++
|
|
||||||
/// template<typename T>
|
|
||||||
/// class Foo {
|
|
||||||
/// typedef T element_type;
|
|
||||||
/// typedef int Bar;
|
|
||||||
///
|
|
||||||
/// template<typename U>
|
|
||||||
/// class Baz {
|
|
||||||
/// };
|
|
||||||
/// };
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// In this case, the applicable template arguments for the different types
|
|
||||||
/// would be:
|
|
||||||
///
|
|
||||||
/// * `Foo`: [`T`]
|
|
||||||
/// * `Foo::element_type`: [`T`]
|
|
||||||
/// * `Foo::Bar`: [`T`]
|
|
||||||
/// * `Foo::Baz`: [`T`, `U`]
|
|
||||||
///
|
|
||||||
/// You might notice that we can't generate something like:
|
|
||||||
///
|
|
||||||
/// ```rust,ignore
|
|
||||||
/// type Foo_Bar<T> = ::std::os::raw::c_int;
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// since that would be invalid Rust. Still, conceptually, `Bar` *could* use
|
|
||||||
/// the template parameter type `T`, and that's exactly what this method
|
|
||||||
/// represents. The unused template parameters get stripped in the
|
|
||||||
/// `signature_contains_named_type` check.
|
|
||||||
pub fn applicable_template_args(&self,
|
|
||||||
ctx: &BindgenContext)
|
|
||||||
-> Vec<ItemId> {
|
|
||||||
let ty = match *self.kind() {
|
|
||||||
ItemKind::Type(ref ty) => ty,
|
|
||||||
_ => return vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
fn parent_contains(ctx: &BindgenContext,
|
|
||||||
parent_template_args: &[ItemId],
|
|
||||||
item: ItemId)
|
|
||||||
-> bool {
|
|
||||||
let item_ty = ctx.resolve_type(item);
|
|
||||||
parent_template_args.iter().any(|parent_item| {
|
|
||||||
let parent_ty = ctx.resolve_type(*parent_item);
|
|
||||||
match (parent_ty.kind(), item_ty.kind()) {
|
|
||||||
(&TypeKind::Named, &TypeKind::Named) => {
|
|
||||||
parent_ty.name() == item_ty.name()
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
match *ty.kind() {
|
|
||||||
TypeKind::Named => vec![self.id()],
|
|
||||||
TypeKind::Array(inner, _) |
|
|
||||||
TypeKind::Pointer(inner) |
|
|
||||||
TypeKind::Reference(inner) |
|
|
||||||
TypeKind::ResolvedTypeRef(inner) => {
|
|
||||||
ctx.resolve_item(inner).applicable_template_args(ctx)
|
|
||||||
}
|
|
||||||
TypeKind::Alias(inner) => {
|
|
||||||
let parent_args = ctx.resolve_item(self.parent_id())
|
|
||||||
.applicable_template_args(ctx);
|
|
||||||
let inner = ctx.resolve_item(inner);
|
|
||||||
|
|
||||||
// Avoid unused type parameters, sigh.
|
|
||||||
parent_args.iter()
|
|
||||||
.cloned()
|
|
||||||
.filter(|arg| {
|
|
||||||
let arg = ctx.resolve_type(*arg);
|
|
||||||
arg.is_named() &&
|
|
||||||
inner.signature_contains_named_type(ctx, arg)
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
// XXX Is this completely correct? Partial template specialization
|
|
||||||
// is hard anyways, sigh...
|
|
||||||
TypeKind::TemplateAlias(_, ref args) |
|
|
||||||
TypeKind::TemplateInstantiation(_, ref args) => args.clone(),
|
|
||||||
// In a template specialization we've got all we want.
|
|
||||||
TypeKind::Comp(ref ci) if ci.is_template_specialization() => {
|
|
||||||
ci.template_args().iter().cloned().collect()
|
|
||||||
}
|
|
||||||
TypeKind::Comp(ref ci) => {
|
|
||||||
let mut parent_template_args =
|
|
||||||
ctx.resolve_item(self.parent_id())
|
|
||||||
.applicable_template_args(ctx);
|
|
||||||
|
|
||||||
for ty in ci.template_args() {
|
|
||||||
if !parent_contains(ctx, &parent_template_args, *ty) {
|
|
||||||
parent_template_args.push(*ty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parent_template_args
|
|
||||||
}
|
|
||||||
_ => vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Is this item a module?
|
/// Is this item a module?
|
||||||
pub fn is_module(&self) -> bool {
|
pub fn is_module(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
@ -680,6 +582,7 @@ impl Item {
|
|||||||
debug_assert!(ctx.in_codegen_phase(),
|
debug_assert!(ctx.in_codegen_phase(),
|
||||||
"You're not supposed to call this yet");
|
"You're not supposed to call this yet");
|
||||||
self.annotations.opaque() ||
|
self.annotations.opaque() ||
|
||||||
|
self.as_type().map_or(false, |ty| ty.is_opaque()) ||
|
||||||
ctx.opaque_by_name(&self.canonical_path(ctx))
|
ctx.opaque_by_name(&self.canonical_path(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -719,19 +622,12 @@ impl Item {
|
|||||||
match *item.kind() {
|
match *item.kind() {
|
||||||
ItemKind::Type(ref ty) => {
|
ItemKind::Type(ref ty) => {
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
// If we're a template specialization, our name is our
|
TypeKind::ResolvedTypeRef(inner) => {
|
||||||
// parent's name.
|
|
||||||
TypeKind::Comp(ref ci)
|
|
||||||
if ci.is_template_specialization() => {
|
|
||||||
let specialized =
|
|
||||||
ci.specialized_template().unwrap();
|
|
||||||
item = ctx.resolve_item(specialized);
|
|
||||||
}
|
|
||||||
// Same as above.
|
|
||||||
TypeKind::ResolvedTypeRef(inner) |
|
|
||||||
TypeKind::TemplateInstantiation(inner, _) => {
|
|
||||||
item = ctx.resolve_item(inner);
|
item = ctx.resolve_item(inner);
|
||||||
}
|
}
|
||||||
|
TypeKind::TemplateInstantiation(ref inst) => {
|
||||||
|
item = ctx.resolve_item(inst.template_definition());
|
||||||
|
}
|
||||||
_ => return item.id(),
|
_ => return item.id(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -845,7 +741,7 @@ impl Item {
|
|||||||
|
|
||||||
// Named template type arguments are never namespaced, and never
|
// Named template type arguments are never namespaced, and never
|
||||||
// mangled.
|
// mangled.
|
||||||
if target.as_type().map_or(false, |ty| ty.is_named()) {
|
if target.is_named(ctx, &()) {
|
||||||
return base_name;
|
return base_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -917,8 +813,11 @@ impl Item {
|
|||||||
pub type ItemSet = BTreeSet<ItemId>;
|
pub type ItemSet = BTreeSet<ItemId>;
|
||||||
|
|
||||||
impl DotAttributes for Item {
|
impl DotAttributes for Item {
|
||||||
fn dot_attributes<W>(&self, ctx: &BindgenContext, out: &mut W) -> io::Result<()>
|
fn dot_attributes<W>(&self,
|
||||||
where W: io::Write
|
ctx: &BindgenContext,
|
||||||
|
out: &mut W)
|
||||||
|
-> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
{
|
{
|
||||||
try!(writeln!(out,
|
try!(writeln!(out,
|
||||||
"<tr><td>{:?}</td></tr>
|
"<tr><td>{:?}</td></tr>
|
||||||
@ -930,20 +829,26 @@ impl DotAttributes for Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TemplateDeclaration for ItemId {
|
impl TemplateDeclaration for ItemId {
|
||||||
fn self_template_params(&self, ctx: &BindgenContext) -> Option<Vec<ItemId>> {
|
fn self_template_params(&self,
|
||||||
|
ctx: &BindgenContext)
|
||||||
|
-> Option<Vec<ItemId>> {
|
||||||
ctx.resolve_item_fallible(*self)
|
ctx.resolve_item_fallible(*self)
|
||||||
.and_then(|item| item.self_template_params(ctx))
|
.and_then(|item| item.self_template_params(ctx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TemplateDeclaration for Item {
|
impl TemplateDeclaration for Item {
|
||||||
fn self_template_params(&self, ctx: &BindgenContext) -> Option<Vec<ItemId>> {
|
fn self_template_params(&self,
|
||||||
|
ctx: &BindgenContext)
|
||||||
|
-> Option<Vec<ItemId>> {
|
||||||
self.kind.self_template_params(ctx)
|
self.kind.self_template_params(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TemplateDeclaration for ItemKind {
|
impl TemplateDeclaration for ItemKind {
|
||||||
fn self_template_params(&self, ctx: &BindgenContext) -> Option<Vec<ItemId>> {
|
fn self_template_params(&self,
|
||||||
|
ctx: &BindgenContext)
|
||||||
|
-> Option<Vec<ItemId>> {
|
||||||
match *self {
|
match *self {
|
||||||
ItemKind::Type(ref ty) => ty.self_template_params(ctx),
|
ItemKind::Type(ref ty) => ty.self_template_params(ctx),
|
||||||
// If we start emitting bindings to explicitly instantiated
|
// If we start emitting bindings to explicitly instantiated
|
||||||
@ -969,7 +874,7 @@ fn visit_child(cur: clang::Cursor,
|
|||||||
return CXChildVisit_Break;
|
return CXChildVisit_Break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*result = Item::from_ty_with_id(id, ty, Some(cur), parent_id, ctx);
|
*result = Item::from_ty_with_id(id, ty, cur, parent_id, ctx);
|
||||||
|
|
||||||
match *result {
|
match *result {
|
||||||
Ok(..) => CXChildVisit_Break,
|
Ok(..) => CXChildVisit_Break,
|
||||||
@ -1062,8 +967,8 @@ impl ClangItemParser for Item {
|
|||||||
// twice, handle them separately.
|
// twice, handle them separately.
|
||||||
{
|
{
|
||||||
let applicable_cursor = cursor.definition().unwrap_or(cursor);
|
let applicable_cursor = cursor.definition().unwrap_or(cursor);
|
||||||
match Self::from_ty(&applicable_cursor.cur_type(),
|
match Item::from_ty(&applicable_cursor.cur_type(),
|
||||||
Some(applicable_cursor),
|
applicable_cursor,
|
||||||
parent_id,
|
parent_id,
|
||||||
ctx) {
|
ctx) {
|
||||||
Ok(ty) => return Ok(ty),
|
Ok(ty) => return Ok(ty),
|
||||||
@ -1105,7 +1010,7 @@ impl ClangItemParser for Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_ty_or_ref(ty: clang::Type,
|
fn from_ty_or_ref(ty: clang::Type,
|
||||||
location: Option<clang::Cursor>,
|
location: clang::Cursor,
|
||||||
parent_id: Option<ItemId>,
|
parent_id: Option<ItemId>,
|
||||||
ctx: &mut BindgenContext)
|
ctx: &mut BindgenContext)
|
||||||
-> ItemId {
|
-> ItemId {
|
||||||
@ -1125,7 +1030,7 @@ impl ClangItemParser for Item {
|
|||||||
/// `BindgenContext::resolve_typerefs`.
|
/// `BindgenContext::resolve_typerefs`.
|
||||||
fn from_ty_or_ref_with_id(potential_id: ItemId,
|
fn from_ty_or_ref_with_id(potential_id: ItemId,
|
||||||
ty: clang::Type,
|
ty: clang::Type,
|
||||||
location: Option<clang::Cursor>,
|
location: clang::Cursor,
|
||||||
parent_id: Option<ItemId>,
|
parent_id: Option<ItemId>,
|
||||||
ctx: &mut BindgenContext)
|
ctx: &mut BindgenContext)
|
||||||
-> ItemId {
|
-> ItemId {
|
||||||
@ -1137,16 +1042,20 @@ impl ClangItemParser for Item {
|
|||||||
|
|
||||||
if ctx.collected_typerefs() {
|
if ctx.collected_typerefs() {
|
||||||
debug!("refs already collected, resolving directly");
|
debug!("refs already collected, resolving directly");
|
||||||
return Self::from_ty_with_id(potential_id,
|
return Item::from_ty_with_id(potential_id,
|
||||||
&ty,
|
&ty,
|
||||||
location,
|
location,
|
||||||
parent_id,
|
parent_id,
|
||||||
ctx)
|
ctx)
|
||||||
.expect("Unable to resolve type");
|
.unwrap_or_else(|_| {
|
||||||
|
Item::new_opaque_type(potential_id, &ty, ctx)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ty) =
|
if let Some(ty) = ctx.builtin_or_resolved_ty(potential_id,
|
||||||
ctx.builtin_or_resolved_ty(potential_id, parent_id, &ty, location) {
|
parent_id,
|
||||||
|
&ty,
|
||||||
|
Some(location)) {
|
||||||
debug!("{:?} already resolved: {:?}", ty, location);
|
debug!("{:?} already resolved: {:?}", ty, location);
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
@ -1169,14 +1078,13 @@ impl ClangItemParser for Item {
|
|||||||
potential_id
|
potential_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn from_ty(ty: &clang::Type,
|
fn from_ty(ty: &clang::Type,
|
||||||
location: Option<clang::Cursor>,
|
location: clang::Cursor,
|
||||||
parent_id: Option<ItemId>,
|
parent_id: Option<ItemId>,
|
||||||
ctx: &mut BindgenContext)
|
ctx: &mut BindgenContext)
|
||||||
-> Result<ItemId, ParseError> {
|
-> Result<ItemId, ParseError> {
|
||||||
let id = ctx.next_item_id();
|
let id = ctx.next_item_id();
|
||||||
Self::from_ty_with_id(id, ty, location, parent_id, ctx)
|
Item::from_ty_with_id(id, ty, location, parent_id, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is one of the trickiest methods you'll find (probably along with
|
/// This is one of the trickiest methods you'll find (probably along with
|
||||||
@ -1189,21 +1097,41 @@ impl ClangItemParser for Item {
|
|||||||
/// context.
|
/// context.
|
||||||
fn from_ty_with_id(id: ItemId,
|
fn from_ty_with_id(id: ItemId,
|
||||||
ty: &clang::Type,
|
ty: &clang::Type,
|
||||||
location: Option<clang::Cursor>,
|
location: clang::Cursor,
|
||||||
parent_id: Option<ItemId>,
|
parent_id: Option<ItemId>,
|
||||||
ctx: &mut BindgenContext)
|
ctx: &mut BindgenContext)
|
||||||
-> Result<ItemId, ParseError> {
|
-> Result<ItemId, ParseError> {
|
||||||
use clang_sys::*;
|
use clang_sys::*;
|
||||||
|
|
||||||
|
debug!("Item::from_ty_with_id: {:?}\n\
|
||||||
|
\tty = {:?},\n\
|
||||||
|
\tlocation = {:?}",
|
||||||
|
id,
|
||||||
|
ty,
|
||||||
|
location);
|
||||||
|
|
||||||
|
if ty.kind() == clang_sys::CXType_Unexposed ||
|
||||||
|
location.cur_type().kind() == clang_sys::CXType_Unexposed {
|
||||||
|
|
||||||
|
if ty.is_associated_type() ||
|
||||||
|
location.cur_type().is_associated_type() {
|
||||||
|
return Ok(Item::new_opaque_type(id, ty, ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(id) = Item::named_type(Some(id), location, ctx) {
|
||||||
|
return Ok(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let decl = {
|
let decl = {
|
||||||
let decl = ty.declaration();
|
let decl = ty.declaration();
|
||||||
decl.definition().unwrap_or(decl)
|
decl.definition().unwrap_or(decl)
|
||||||
};
|
};
|
||||||
|
|
||||||
let comment = decl.raw_comment()
|
let comment = decl.raw_comment()
|
||||||
.or_else(|| location.as_ref().and_then(|l| l.raw_comment()));
|
.or_else(|| location.raw_comment());
|
||||||
let annotations = Annotations::new(&decl)
|
let annotations = Annotations::new(&decl)
|
||||||
.or_else(|| location.as_ref().and_then(|l| Annotations::new(l)));
|
.or_else(|| Annotations::new(&location));
|
||||||
|
|
||||||
if let Some(ref annotations) = annotations {
|
if let Some(ref annotations) = annotations {
|
||||||
if let Some(ref replaced) = annotations.use_instead_of() {
|
if let Some(ref replaced) = annotations.use_instead_of() {
|
||||||
@ -1212,7 +1140,7 @@ impl ClangItemParser for Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ty) =
|
if let Some(ty) =
|
||||||
ctx.builtin_or_resolved_ty(id, parent_id, ty, location) {
|
ctx.builtin_or_resolved_ty(id, parent_id, ty, Some(location)) {
|
||||||
return Ok(ty);
|
return Ok(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1220,11 +1148,10 @@ impl ClangItemParser for Item {
|
|||||||
let mut valid_decl = decl.kind() != CXCursor_NoDeclFound;
|
let mut valid_decl = decl.kind() != CXCursor_NoDeclFound;
|
||||||
let declaration_to_look_for = if valid_decl {
|
let declaration_to_look_for = if valid_decl {
|
||||||
decl.canonical()
|
decl.canonical()
|
||||||
} else if location.is_some() &&
|
} else if location.kind() ==
|
||||||
location.unwrap().kind() ==
|
|
||||||
CXCursor_ClassTemplate {
|
CXCursor_ClassTemplate {
|
||||||
valid_decl = true;
|
valid_decl = true;
|
||||||
location.unwrap()
|
location
|
||||||
} else {
|
} else {
|
||||||
decl
|
decl
|
||||||
};
|
};
|
||||||
@ -1255,51 +1182,47 @@ impl ClangItemParser for Item {
|
|||||||
relevant_parent_id,
|
relevant_parent_id,
|
||||||
ItemKind::Type(item)),
|
ItemKind::Type(item)),
|
||||||
declaration,
|
declaration,
|
||||||
location);
|
Some(location));
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
Err(ParseError::Continue) => Err(ParseError::Continue),
|
Err(ParseError::Continue) => Err(ParseError::Continue),
|
||||||
Err(ParseError::Recurse) => {
|
Err(ParseError::Recurse) => {
|
||||||
debug!("Item::from_ty recursing in the ast");
|
debug!("Item::from_ty recursing in the ast");
|
||||||
let mut result = Err(ParseError::Recurse);
|
let mut result = Err(ParseError::Recurse);
|
||||||
if let Some(ref location) = location {
|
|
||||||
// Need to pop here, otherwise we'll get stuck.
|
|
||||||
//
|
|
||||||
// TODO: Find a nicer interface, really. Also, the
|
|
||||||
// declaration_to_look_for suspiciously shares a lot of
|
|
||||||
// logic with ir::context, so we should refactor that.
|
|
||||||
if valid_decl {
|
|
||||||
let finished = ctx.finish_parsing();
|
|
||||||
assert_eq!(*finished.decl(), declaration_to_look_for);
|
|
||||||
}
|
|
||||||
|
|
||||||
location.visit(|cur| {
|
// Need to pop here, otherwise we'll get stuck.
|
||||||
visit_child(cur, id, ty, parent_id, ctx, &mut result)
|
//
|
||||||
});
|
// TODO: Find a nicer interface, really. Also, the
|
||||||
|
// declaration_to_look_for suspiciously shares a lot of
|
||||||
if valid_decl {
|
// logic with ir::context, so we should refactor that.
|
||||||
let partial_ty =
|
if valid_decl {
|
||||||
PartialType::new(declaration_to_look_for, id);
|
let finished = ctx.finish_parsing();
|
||||||
ctx.begin_parsing(partial_ty);
|
assert_eq!(*finished.decl(), declaration_to_look_for);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location.visit(|cur| {
|
||||||
|
visit_child(cur, id, ty, parent_id, ctx, &mut result)
|
||||||
|
});
|
||||||
|
|
||||||
|
if valid_decl {
|
||||||
|
let partial_ty = PartialType::new(declaration_to_look_for,
|
||||||
|
id);
|
||||||
|
ctx.begin_parsing(partial_ty);
|
||||||
|
}
|
||||||
|
|
||||||
// If we have recursed into the AST all we know, and we still
|
// If we have recursed into the AST all we know, and we still
|
||||||
// haven't found what we've got, let's just make a named type.
|
// haven't found what we've got, let's just try and make a named
|
||||||
|
// type.
|
||||||
//
|
//
|
||||||
// This is what happens with some template members, for example.
|
// This is what happens with some template members, for example.
|
||||||
//
|
|
||||||
// FIXME: Maybe we should restrict this to things with parent?
|
|
||||||
// It's harmless, but if we restrict that, then
|
|
||||||
// tests/headers/nsStyleAutoArray.hpp crashes.
|
|
||||||
if let Err(ParseError::Recurse) = result {
|
if let Err(ParseError::Recurse) = result {
|
||||||
warn!("Unknown type, assuming named template type: \
|
warn!("Unknown type, assuming named template type: \
|
||||||
id = {:?}; spelling = {}",
|
id = {:?}; spelling = {}",
|
||||||
id,
|
id,
|
||||||
ty.spelling());
|
ty.spelling());
|
||||||
Ok(Self::named_type_with_id(id,
|
Item::named_type(Some(id), location, ctx)
|
||||||
ty.spelling(),
|
.map(Ok)
|
||||||
relevant_parent_id,
|
.unwrap_or(Err(ParseError::Recurse))
|
||||||
ctx))
|
|
||||||
} else {
|
} else {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@ -1317,40 +1240,150 @@ impl ClangItemParser for Item {
|
|||||||
/// A named type is a template parameter, e.g., the "T" in Foo<T>. They're
|
/// A named type is a template parameter, e.g., the "T" in Foo<T>. They're
|
||||||
/// always local so it's the only exception when there's no declaration for
|
/// always local so it's the only exception when there's no declaration for
|
||||||
/// a type.
|
/// a type.
|
||||||
///
|
fn named_type(with_id: Option<ItemId>,
|
||||||
/// It must have an id, and must not be the current module id. Ideally we
|
location: clang::Cursor,
|
||||||
/// could assert the parent id is a Comp(..) type, but that info isn't
|
ctx: &mut BindgenContext)
|
||||||
/// available yet.
|
-> Option<ItemId> {
|
||||||
fn named_type_with_id<S>(id: ItemId,
|
let ty = location.cur_type();
|
||||||
name: S,
|
|
||||||
parent_id: ItemId,
|
|
||||||
ctx: &mut BindgenContext)
|
|
||||||
-> ItemId
|
|
||||||
where S: Into<String>,
|
|
||||||
{
|
|
||||||
// see tests/headers/const_tparam.hpp
|
|
||||||
// and tests/headers/variadic_tname.hpp
|
|
||||||
let name = name.into().replace("const ", "").replace(".", "");
|
|
||||||
|
|
||||||
ctx.add_item(Item::new(id,
|
debug!("Item::named_type:\n\
|
||||||
None,
|
\twith_id = {:?},\n\
|
||||||
None,
|
\tty = {} {:?},\n\
|
||||||
parent_id,
|
\tlocation: {:?}",
|
||||||
ItemKind::Type(Type::named(name))),
|
with_id,
|
||||||
None,
|
ty.spelling(),
|
||||||
None);
|
ty,
|
||||||
|
location);
|
||||||
|
|
||||||
id
|
if ty.kind() != clang_sys::CXType_Unexposed {
|
||||||
}
|
// If the given cursor's type's kind is not Unexposed, then we
|
||||||
|
// aren't looking at a template parameter. This check may need to be
|
||||||
|
// updated in the future if they start properly exposing template
|
||||||
|
// type parameters.
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
fn named_type<S>(name: S,
|
let ty_spelling = ty.spelling();
|
||||||
parent_id: ItemId,
|
|
||||||
ctx: &mut BindgenContext)
|
// Clang does not expose any information about template type parameters
|
||||||
-> ItemId
|
// via their clang::Type, nor does it give us their canonical cursors
|
||||||
where S: Into<String>,
|
// the straightforward way. However, there are three situations from
|
||||||
{
|
// which we can find the definition of the template type parameter, if
|
||||||
let id = ctx.next_item_id();
|
// the cursor is indeed looking at some kind of a template type
|
||||||
Self::named_type_with_id(id, name, parent_id, ctx)
|
// parameter or use of one:
|
||||||
|
//
|
||||||
|
// 1. The cursor is pointing at the template type parameter's
|
||||||
|
// definition. This is the trivial case.
|
||||||
|
//
|
||||||
|
// (kind = TemplateTypeParameter, ...)
|
||||||
|
//
|
||||||
|
// 2. The cursor is pointing at a TypeRef whose referenced() cursor is
|
||||||
|
// situation (1).
|
||||||
|
//
|
||||||
|
// (kind = TypeRef,
|
||||||
|
// referenced = (kind = TemplateTypeParameter, ...),
|
||||||
|
// ...)
|
||||||
|
//
|
||||||
|
// 3. The cursor is pointing at some use of a template type parameter
|
||||||
|
// (for example, in a FieldDecl), and this cursor has a child cursor
|
||||||
|
// whose spelling is the same as the parent's type's spelling, and whose
|
||||||
|
// kind is a TypeRef of the situation (2) variety.
|
||||||
|
//
|
||||||
|
// (kind = FieldDecl,
|
||||||
|
// type = (kind = Unexposed,
|
||||||
|
// spelling = "T",
|
||||||
|
// ...),
|
||||||
|
// children =
|
||||||
|
// (kind = TypeRef,
|
||||||
|
// spelling = "T",
|
||||||
|
// referenced = (kind = TemplateTypeParameter,
|
||||||
|
// spelling = "T",
|
||||||
|
// ...),
|
||||||
|
// ...)
|
||||||
|
// ...)
|
||||||
|
//
|
||||||
|
// TODO: The alternative to this hacky pattern matching would be to
|
||||||
|
// maintain proper scopes of template parameters while parsing and use
|
||||||
|
// de Brujin indices to access template parameters, which clang exposes
|
||||||
|
// in the cursor's type's canonical type's spelling:
|
||||||
|
// "type-parameter-x-y". That is probably a better approach long-term,
|
||||||
|
// but maintaining these scopes properly would require more changes to
|
||||||
|
// the whole libclang -> IR parsing code.
|
||||||
|
|
||||||
|
fn is_template_with_spelling(refd: &clang::Cursor,
|
||||||
|
spelling: &str)
|
||||||
|
-> bool {
|
||||||
|
refd.kind() == clang_sys::CXCursor_TemplateTypeParameter &&
|
||||||
|
refd.spelling() == spelling
|
||||||
|
}
|
||||||
|
|
||||||
|
let definition = if is_template_with_spelling(&location,
|
||||||
|
&ty_spelling) {
|
||||||
|
// Situation (1)
|
||||||
|
location
|
||||||
|
} else if location.kind() ==
|
||||||
|
clang_sys::CXCursor_TypeRef {
|
||||||
|
// Situation (2)
|
||||||
|
match location.referenced() {
|
||||||
|
Some(refd) if is_template_with_spelling(&refd,
|
||||||
|
&ty_spelling) => refd,
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Situation (3)
|
||||||
|
let mut definition = None;
|
||||||
|
|
||||||
|
location.visit(|child| {
|
||||||
|
let child_ty = child.cur_type();
|
||||||
|
if child_ty.kind() == clang_sys::CXCursor_TypeRef &&
|
||||||
|
child_ty.spelling() == ty_spelling {
|
||||||
|
match child.referenced() {
|
||||||
|
Some(refd) if is_template_with_spelling(&refd, &ty_spelling) => {
|
||||||
|
definition = Some(refd);
|
||||||
|
return clang_sys::CXChildVisit_Break;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clang_sys::CXChildVisit_Continue
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(def) = definition {
|
||||||
|
def
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assert!(is_template_with_spelling(&definition, &ty_spelling));
|
||||||
|
|
||||||
|
// Named types are always parented to the root module. They are never
|
||||||
|
// referenced with namespace prefixes, and they can't inherit anything
|
||||||
|
// from their parent either, so it is simplest to just hang them off
|
||||||
|
// something we know will always exist.
|
||||||
|
let parent = ctx.root_module();
|
||||||
|
|
||||||
|
if let Some(id) = ctx.get_named_type(&definition) {
|
||||||
|
if let Some(with_id) = with_id {
|
||||||
|
return Some(ctx.build_ty_wrapper(with_id, id, Some(parent), &ty));
|
||||||
|
} else {
|
||||||
|
return Some(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See tests/headers/const_tparam.hpp and
|
||||||
|
// tests/headers/variadic_tname.hpp.
|
||||||
|
let name = ty_spelling.replace("const ", "")
|
||||||
|
.replace(".", "");
|
||||||
|
|
||||||
|
let id = with_id.unwrap_or_else(|| ctx.next_item_id());
|
||||||
|
let item = Item::new(id,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
parent,
|
||||||
|
ItemKind::Type(Type::named(name)));
|
||||||
|
ctx.add_named_type(item, definition);
|
||||||
|
Some(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
//! Different variants of an `Item` in our intermediate representation.
|
//! Different variants of an `Item` in our intermediate representation.
|
||||||
|
|
||||||
use std::io;
|
|
||||||
use super::context::BindgenContext;
|
use super::context::BindgenContext;
|
||||||
use super::dot::DotAttributes;
|
use super::dot::DotAttributes;
|
||||||
use super::function::Function;
|
use super::function::Function;
|
||||||
use super::module::Module;
|
use super::module::Module;
|
||||||
use super::ty::Type;
|
use super::ty::Type;
|
||||||
use super::var::Var;
|
use super::var::Var;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
/// A item we parse and translate.
|
/// A item we parse and translate.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -41,7 +41,7 @@ impl ItemKind {
|
|||||||
ItemKind::Module(..) => "Module",
|
ItemKind::Module(..) => "Module",
|
||||||
ItemKind::Type(..) => "Type",
|
ItemKind::Type(..) => "Type",
|
||||||
ItemKind::Function(..) => "Function",
|
ItemKind::Function(..) => "Function",
|
||||||
ItemKind::Var(..) => "Var"
|
ItemKind::Var(..) => "Var",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,10 +127,15 @@ impl ItemKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DotAttributes for ItemKind {
|
impl DotAttributes for ItemKind {
|
||||||
fn dot_attributes<W>(&self, ctx: &BindgenContext, out: &mut W) -> io::Result<()>
|
fn dot_attributes<W>(&self,
|
||||||
where W: io::Write
|
ctx: &BindgenContext,
|
||||||
|
out: &mut W)
|
||||||
|
-> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
{
|
{
|
||||||
try!(writeln!(out, "<tr><td>kind</td><td>{}</td></tr>", self.kind_name()));
|
try!(writeln!(out,
|
||||||
|
"<tr><td>kind</td><td>{}</td></tr>",
|
||||||
|
self.kind_name()));
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
ItemKind::Module(ref module) => module.dot_attributes(ctx, out),
|
ItemKind::Module(ref module) => module.dot_attributes(ctx, out),
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
use super::context::BindgenContext;
|
use super::context::BindgenContext;
|
||||||
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
|
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
|
||||||
use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
|
use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind};
|
||||||
|
use clang;
|
||||||
use std::{cmp, mem};
|
use std::{cmp, mem};
|
||||||
|
|
||||||
/// A type that represents the struct layout of a type.
|
/// A type that represents the struct layout of a type.
|
||||||
@ -20,7 +21,8 @@ pub struct Layout {
|
|||||||
fn test_layout_for_size() {
|
fn test_layout_for_size() {
|
||||||
let ptr_size = mem::size_of::<*mut ()>();
|
let ptr_size = mem::size_of::<*mut ()>();
|
||||||
assert_eq!(Layout::for_size(ptr_size), Layout::new(ptr_size, ptr_size));
|
assert_eq!(Layout::for_size(ptr_size), Layout::new(ptr_size, ptr_size));
|
||||||
assert_eq!(Layout::for_size(3 * ptr_size), Layout::new(3 * ptr_size, ptr_size));
|
assert_eq!(Layout::for_size(3 * ptr_size),
|
||||||
|
Layout::new(3 * ptr_size, ptr_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Layout {
|
impl Layout {
|
||||||
@ -38,7 +40,8 @@ impl Layout {
|
|||||||
/// alignment possible.
|
/// alignment possible.
|
||||||
pub fn for_size(size: usize) -> Self {
|
pub fn for_size(size: usize) -> Self {
|
||||||
let mut next_align = 2;
|
let mut next_align = 2;
|
||||||
while size % next_align == 0 && next_align <= mem::size_of::<*mut ()>() {
|
while size % next_align == 0 &&
|
||||||
|
next_align <= mem::size_of::<*mut ()>() {
|
||||||
next_align *= 2;
|
next_align *= 2;
|
||||||
}
|
}
|
||||||
Layout {
|
Layout {
|
||||||
@ -65,9 +68,17 @@ impl Layout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// When we are treating a type as opaque, it is just a blob with a `Layout`.
|
/// When we are treating a type as opaque, it is just a blob with a `Layout`.
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Opaque(pub Layout);
|
pub struct Opaque(pub Layout);
|
||||||
|
|
||||||
impl Opaque {
|
impl Opaque {
|
||||||
|
/// Construct a new opaque type from the given clang type.
|
||||||
|
pub fn from_clang_ty(ty: &clang::Type) -> Type {
|
||||||
|
let layout = Layout::new(ty.size(), ty.align());
|
||||||
|
let ty_kind = TypeKind::Opaque;
|
||||||
|
Type::new(None, Some(layout), ty_kind, false)
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the known rust type we should use to create a correctly-aligned
|
/// Return the known rust type we should use to create a correctly-aligned
|
||||||
/// field with this layout.
|
/// field with this layout.
|
||||||
pub fn known_rust_type_for_array(&self) -> Option<&'static str> {
|
pub fn known_rust_type_for_array(&self) -> Option<&'static str> {
|
||||||
|
@ -16,6 +16,7 @@ pub mod item_kind;
|
|||||||
pub mod layout;
|
pub mod layout;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
pub mod named;
|
pub mod named;
|
||||||
|
pub mod template;
|
||||||
pub mod traversal;
|
pub mod traversal;
|
||||||
pub mod ty;
|
pub mod ty;
|
||||||
pub mod var;
|
pub mod var;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
//! Intermediate representation for modules (AKA C++ namespaces).
|
//! Intermediate representation for modules (AKA C++ namespaces).
|
||||||
|
|
||||||
use std::io;
|
|
||||||
use super::context::{BindgenContext, ItemId};
|
use super::context::{BindgenContext, ItemId};
|
||||||
use super::dot::DotAttributes;
|
use super::dot::DotAttributes;
|
||||||
use clang;
|
use clang;
|
||||||
use parse::{ClangSubItemParser, ParseError, ParseResult};
|
use parse::{ClangSubItemParser, ParseError, ParseResult};
|
||||||
use parse_one;
|
use parse_one;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
/// Whether this module is inline or not.
|
/// Whether this module is inline or not.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
@ -59,12 +59,13 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DotAttributes for Module {
|
impl DotAttributes for Module {
|
||||||
fn dot_attributes<W>(&self, _ctx: &BindgenContext, out: &mut W) -> io::Result<()>
|
fn dot_attributes<W>(&self,
|
||||||
where W: io::Write
|
_ctx: &BindgenContext,
|
||||||
|
out: &mut W)
|
||||||
|
-> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
{
|
{
|
||||||
writeln!(out,
|
writeln!(out, "<tr><td>ModuleKind</td><td>{:?}</td></tr>", self.kind)
|
||||||
"<tr><td>ModuleKind</td><td>{:?}</td></tr>",
|
|
||||||
self.kind)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
206
src/ir/named.rs
206
src/ir/named.rs
@ -126,12 +126,13 @@
|
|||||||
//!
|
//!
|
||||||
//! [spa]: https://cs.au.dk/~amoeller/spa/spa.pdf
|
//! [spa]: https://cs.au.dk/~amoeller/spa/spa.pdf
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt;
|
|
||||||
use super::context::{BindgenContext, ItemId};
|
use super::context::{BindgenContext, ItemId};
|
||||||
use super::item::ItemSet;
|
use super::item::ItemSet;
|
||||||
|
use super::template::AsNamed;
|
||||||
use super::traversal::{EdgeKind, Trace};
|
use super::traversal::{EdgeKind, Trace};
|
||||||
use super::ty::{TemplateDeclaration, TypeKind};
|
use super::ty::{TemplateDeclaration, TypeKind};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
/// An analysis in the monotone framework.
|
/// An analysis in the monotone framework.
|
||||||
///
|
///
|
||||||
@ -163,7 +164,7 @@ pub trait MonotoneFramework: Sized + fmt::Debug {
|
|||||||
/// The final output of this analysis. Once we have reached a fix-point, we
|
/// The final output of this analysis. Once we have reached a fix-point, we
|
||||||
/// convert `self` into this type, and return it as the final result of the
|
/// convert `self` into this type, and return it as the final result of the
|
||||||
/// analysis.
|
/// analysis.
|
||||||
type Output: From<Self>;
|
type Output: From<Self> + fmt::Debug;
|
||||||
|
|
||||||
/// Construct a new instance of this analysis.
|
/// Construct a new instance of this analysis.
|
||||||
fn new(extra: Self::Extra) -> Self;
|
fn new(extra: Self::Extra) -> Self;
|
||||||
@ -191,12 +192,8 @@ pub trait MonotoneFramework: Sized + fmt::Debug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Run an analysis in the monotone framework.
|
/// Run an analysis in the monotone framework.
|
||||||
// TODO: This allow(...) is just temporary until we replace
|
|
||||||
// `Item::signature_contains_named_type` with
|
|
||||||
// `analyze::<UsedTemplateParameters>`.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn analyze<Analysis>(extra: Analysis::Extra) -> Analysis::Output
|
pub fn analyze<Analysis>(extra: Analysis::Extra) -> Analysis::Output
|
||||||
where Analysis: MonotoneFramework
|
where Analysis: MonotoneFramework,
|
||||||
{
|
{
|
||||||
let mut analysis = Analysis::new(extra);
|
let mut analysis = Analysis::new(extra);
|
||||||
let mut worklist = analysis.initial_worklist();
|
let mut worklist = analysis.initial_worklist();
|
||||||
@ -256,13 +253,19 @@ pub fn analyze<Analysis>(extra: Analysis::Extra) -> Analysis::Output
|
|||||||
/// self_template_param_usage(_) = { }
|
/// self_template_param_usage(_) = { }
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct UsedTemplateParameters<'a> {
|
pub struct UsedTemplateParameters<'ctx, 'gen>
|
||||||
ctx: &'a BindgenContext<'a>,
|
where 'gen: 'ctx,
|
||||||
used: HashMap<ItemId, ItemSet>,
|
{
|
||||||
|
ctx: &'ctx BindgenContext<'gen>,
|
||||||
|
|
||||||
|
// The Option is only there for temporary moves out of the hash map. See the
|
||||||
|
// comments in `UsedTemplateParameters::constrain` below.
|
||||||
|
used: HashMap<ItemId, Option<ItemSet>>,
|
||||||
|
|
||||||
dependencies: HashMap<ItemId, Vec<ItemId>>,
|
dependencies: HashMap<ItemId, Vec<ItemId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> UsedTemplateParameters<'a> {
|
impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
|
||||||
fn consider_edge(kind: EdgeKind) -> bool {
|
fn consider_edge(kind: EdgeKind) -> bool {
|
||||||
match kind {
|
match kind {
|
||||||
// For each of these kinds of edges, if the referent uses a template
|
// For each of these kinds of edges, if the referent uses a template
|
||||||
@ -271,19 +274,24 @@ impl<'a> UsedTemplateParameters<'a> {
|
|||||||
EdgeKind::TemplateArgument |
|
EdgeKind::TemplateArgument |
|
||||||
EdgeKind::BaseMember |
|
EdgeKind::BaseMember |
|
||||||
EdgeKind::Field |
|
EdgeKind::Field |
|
||||||
EdgeKind::InnerType |
|
|
||||||
EdgeKind::InnerVar |
|
|
||||||
EdgeKind::Constructor |
|
EdgeKind::Constructor |
|
||||||
EdgeKind::VarType |
|
EdgeKind::VarType |
|
||||||
|
EdgeKind::FunctionReturn |
|
||||||
|
EdgeKind::FunctionParameter |
|
||||||
EdgeKind::TypeReference => true,
|
EdgeKind::TypeReference => true,
|
||||||
|
|
||||||
// We can't emit machine code for new instantiations of function
|
// An inner var or type using a template parameter is orthogonal
|
||||||
// templates and class templates' methods (and don't detect explicit
|
// from whether we use it. See template-param-usage-{6,11}.hpp.
|
||||||
// instantiations) so we must ignore template parameters that are
|
EdgeKind::InnerVar | EdgeKind::InnerType => false,
|
||||||
// only used by functions.
|
|
||||||
EdgeKind::Method |
|
// We can't emit machine code for new monomorphizations of class
|
||||||
EdgeKind::FunctionReturn |
|
// templates' methods (and don't detect explicit instantiations) so
|
||||||
EdgeKind::FunctionParameter => false,
|
// we must ignore template parameters that are only used by
|
||||||
|
// methods. This doesn't apply to a function type's return or
|
||||||
|
// parameter types, however, because of type aliases of function
|
||||||
|
// pointers that use template parameters, eg
|
||||||
|
// tests/headers/struct_with_typedef_template_arg.hpp
|
||||||
|
EdgeKind::Method => false,
|
||||||
|
|
||||||
// If we considered these edges, we would end up mistakenly claiming
|
// If we considered these edges, we would end up mistakenly claiming
|
||||||
// that every template parameter always used.
|
// that every template parameter always used.
|
||||||
@ -299,25 +307,30 @@ impl<'a> UsedTemplateParameters<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MonotoneFramework for UsedTemplateParameters<'a> {
|
impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
|
||||||
type Node = ItemId;
|
type Node = ItemId;
|
||||||
type Extra = &'a BindgenContext<'a>;
|
type Extra = &'ctx BindgenContext<'gen>;
|
||||||
type Output = HashMap<ItemId, ItemSet>;
|
type Output = HashMap<ItemId, ItemSet>;
|
||||||
|
|
||||||
fn new(ctx: &'a BindgenContext<'a>) -> UsedTemplateParameters<'a> {
|
fn new(ctx: &'ctx BindgenContext<'gen>)
|
||||||
|
-> UsedTemplateParameters<'ctx, 'gen> {
|
||||||
let mut used = HashMap::new();
|
let mut used = HashMap::new();
|
||||||
let mut dependencies = HashMap::new();
|
let mut dependencies = HashMap::new();
|
||||||
|
|
||||||
for item in ctx.whitelisted_items() {
|
for item in ctx.whitelisted_items() {
|
||||||
dependencies.entry(item).or_insert(vec![]);
|
dependencies.entry(item).or_insert(vec![]);
|
||||||
used.insert(item, ItemSet::new());
|
used.insert(item, Some(ItemSet::new()));
|
||||||
|
|
||||||
{
|
{
|
||||||
// We reverse our natural IR graph edges to find dependencies
|
// We reverse our natural IR graph edges to find dependencies
|
||||||
// between nodes.
|
// between nodes.
|
||||||
item.trace(ctx, &mut |sub_item, _| {
|
item.trace(ctx,
|
||||||
dependencies.entry(sub_item).or_insert(vec![]).push(item);
|
&mut |sub_item, _| {
|
||||||
}, &());
|
dependencies.entry(sub_item)
|
||||||
|
.or_insert(vec![])
|
||||||
|
.push(item);
|
||||||
|
},
|
||||||
|
&());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additionally, whether a template instantiation's template
|
// Additionally, whether a template instantiation's template
|
||||||
@ -326,14 +339,18 @@ impl<'a> MonotoneFramework for UsedTemplateParameters<'a> {
|
|||||||
ctx.resolve_item(item)
|
ctx.resolve_item(item)
|
||||||
.as_type()
|
.as_type()
|
||||||
.map(|ty| match ty.kind() {
|
.map(|ty| match ty.kind() {
|
||||||
&TypeKind::TemplateInstantiation(decl, ref args) => {
|
&TypeKind::TemplateInstantiation(ref inst) => {
|
||||||
let decl = ctx.resolve_type(decl);
|
let decl = ctx.resolve_type(inst.template_definition());
|
||||||
|
let args = inst.template_arguments();
|
||||||
|
// Although template definitions should always have
|
||||||
|
// template parameters, there is a single exception:
|
||||||
|
// opaque templates. Hence the unwrap_or.
|
||||||
let params = decl.self_template_params(ctx)
|
let params = decl.self_template_params(ctx)
|
||||||
.expect("a template instantiation's referenced \
|
.unwrap_or(vec![]);
|
||||||
template declaration should have template \
|
|
||||||
parameters");
|
|
||||||
for (arg, param) in args.iter().zip(params.iter()) {
|
for (arg, param) in args.iter().zip(params.iter()) {
|
||||||
dependencies.entry(*arg).or_insert(vec![]).push(*param);
|
dependencies.entry(*arg)
|
||||||
|
.or_insert(vec![])
|
||||||
|
.push(*param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -352,59 +369,81 @@ impl<'a> MonotoneFramework for UsedTemplateParameters<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn constrain(&mut self, id: ItemId) -> bool {
|
fn constrain(&mut self, id: ItemId) -> bool {
|
||||||
let original_len = self.used[&id].len();
|
// Invariant: all hash map entries' values are `Some` upon entering and
|
||||||
|
// exiting this method.
|
||||||
|
debug_assert!(self.used.values().all(|v| v.is_some()));
|
||||||
|
|
||||||
|
// Take the set for this id out of the hash map while we mutate it based
|
||||||
|
// on other hash map entries. We *must* put it back into the hash map at
|
||||||
|
// the end of this method. This allows us to side-step HashMap's lack of
|
||||||
|
// an analog to slice::split_at_mut.
|
||||||
|
let mut used_by_this_id =
|
||||||
|
self.used.get_mut(&id).unwrap().take().unwrap();
|
||||||
|
|
||||||
|
let original_len = used_by_this_id.len();
|
||||||
|
|
||||||
// First, add this item's self template parameter usage.
|
|
||||||
let item = self.ctx.resolve_item(id);
|
let item = self.ctx.resolve_item(id);
|
||||||
let ty_kind = item.as_type().map(|ty| ty.kind());
|
let ty_kind = item.as_type().map(|ty| ty.kind());
|
||||||
match ty_kind {
|
match ty_kind {
|
||||||
|
// Named template type parameters trivially use themselves.
|
||||||
Some(&TypeKind::Named) => {
|
Some(&TypeKind::Named) => {
|
||||||
// This is a trivial use of the template type parameter.
|
used_by_this_id.insert(id);
|
||||||
self.used.get_mut(&id).unwrap().insert(id);
|
|
||||||
}
|
}
|
||||||
Some(&TypeKind::TemplateInstantiation(decl, ref args)) => {
|
|
||||||
// A template instantiation's concrete template argument is
|
// A template instantiation's concrete template argument is
|
||||||
// only used if the template declaration uses the
|
// only used if the template declaration uses the
|
||||||
// corresponding template parameter.
|
// corresponding template parameter.
|
||||||
|
Some(&TypeKind::TemplateInstantiation(ref inst)) => {
|
||||||
|
let decl = self.ctx.resolve_type(inst.template_definition());
|
||||||
|
let args = inst.template_arguments();
|
||||||
|
|
||||||
let params = decl.self_template_params(self.ctx)
|
let params = decl.self_template_params(self.ctx)
|
||||||
.expect("a template instantiation's referenced \
|
.unwrap_or(vec![]);
|
||||||
template declaration should have template \
|
|
||||||
parameters");
|
|
||||||
for (arg, param) in args.iter().zip(params.iter()) {
|
for (arg, param) in args.iter().zip(params.iter()) {
|
||||||
if self.used[&decl].contains(param) {
|
let used_by_definition = self.used
|
||||||
if self.ctx.resolve_item(*arg).is_named() {
|
[&inst.template_definition()]
|
||||||
self.used.get_mut(&id).unwrap().insert(*arg);
|
.as_ref()
|
||||||
|
.unwrap();
|
||||||
|
if used_by_definition.contains(param) {
|
||||||
|
if let Some(named) = arg.as_named(self.ctx, &()) {
|
||||||
|
used_by_this_id.insert(named);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
|
// Otherwise, add the union of each of its referent item's template
|
||||||
|
// parameter usage.
|
||||||
|
_ => {
|
||||||
|
item.trace(self.ctx,
|
||||||
|
&mut |sub_id, edge_kind| {
|
||||||
|
if sub_id == id || !Self::consider_edge(edge_kind) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let used_by_sub_id = self.used[&sub_id]
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.cloned();
|
||||||
|
used_by_this_id.extend(used_by_sub_id);
|
||||||
|
},
|
||||||
|
&());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second, add the union of each of its referent item's template
|
let new_len = used_by_this_id.len();
|
||||||
// parameter usage.
|
|
||||||
item.trace(self.ctx, &mut |sub_id, edge_kind| {
|
|
||||||
if sub_id == id || !Self::consider_edge(edge_kind) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This clone is unfortunate because we are potentially thrashing
|
|
||||||
// malloc. We could investigate replacing the ItemSet values with
|
|
||||||
// Rc<RefCell<ItemSet>> to make the borrow checker happy, but it
|
|
||||||
// isn't clear that the added indirection wouldn't outweigh the cost
|
|
||||||
// of malloc'ing a new ItemSet here. Ideally, `HashMap` would have a
|
|
||||||
// `split_entries` method analogous to `slice::split_at_mut`...
|
|
||||||
let to_add = self.used[&sub_id].clone();
|
|
||||||
self.used.get_mut(&id).unwrap().extend(to_add);
|
|
||||||
}, &());
|
|
||||||
|
|
||||||
let new_len = self.used[&id].len();
|
|
||||||
assert!(new_len >= original_len);
|
assert!(new_len >= original_len);
|
||||||
|
|
||||||
|
// Put the set back in the hash map and restore our invariant.
|
||||||
|
self.used.insert(id, Some(used_by_this_id));
|
||||||
|
debug_assert!(self.used.values().all(|v| v.is_some()));
|
||||||
|
|
||||||
new_len != original_len
|
new_len != original_len
|
||||||
}
|
}
|
||||||
|
|
||||||
fn each_depending_on<F>(&self, item: ItemId, mut f: F)
|
fn each_depending_on<F>(&self, item: ItemId, mut f: F)
|
||||||
where F: FnMut(Self::Node)
|
where F: FnMut(ItemId),
|
||||||
{
|
{
|
||||||
if let Some(edges) = self.dependencies.get(&item) {
|
if let Some(edges) = self.dependencies.get(&item) {
|
||||||
for item in edges {
|
for item in edges {
|
||||||
@ -414,16 +453,20 @@ impl<'a> MonotoneFramework for UsedTemplateParameters<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<UsedTemplateParameters<'a>> for HashMap<ItemId, ItemSet> {
|
impl<'ctx, 'gen> From<UsedTemplateParameters<'ctx, 'gen>>
|
||||||
fn from(used_templ_params: UsedTemplateParameters) -> Self {
|
for HashMap<ItemId, ItemSet> {
|
||||||
|
fn from(used_templ_params: UsedTemplateParameters<'ctx, 'gen>) -> Self {
|
||||||
used_templ_params.used
|
used_templ_params.used
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (k, v.unwrap()))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::collections::{HashMap, HashSet};
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
// Here we find the set of nodes that are reachable from any given
|
// Here we find the set of nodes that are reachable from any given
|
||||||
// node. This is a lattice mapping nodes to subsets of all nodes. Our join
|
// node. This is a lattice mapping nodes to subsets of all nodes. Our join
|
||||||
@ -489,7 +532,7 @@ mod tests {
|
|||||||
g.0.insert(Node(8), vec![]);
|
g.0.insert(Node(8), vec![]);
|
||||||
g
|
g
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reverse(&self) -> Graph {
|
fn reverse(&self) -> Graph {
|
||||||
let mut reversed = Graph::default();
|
let mut reversed = Graph::default();
|
||||||
for (node, edges) in self.0.iter() {
|
for (node, edges) in self.0.iter() {
|
||||||
@ -537,8 +580,9 @@ mod tests {
|
|||||||
// Yes, what follows is a **terribly** inefficient set union
|
// Yes, what follows is a **terribly** inefficient set union
|
||||||
// implementation. Don't copy this code outside of this test!
|
// implementation. Don't copy this code outside of this test!
|
||||||
|
|
||||||
let original_size = self.reachable.entry(node).or_insert(HashSet::new()).len();
|
let original_size =
|
||||||
|
self.reachable.entry(node).or_insert(HashSet::new()).len();
|
||||||
|
|
||||||
for sub_node in self.graph.0[&node].iter() {
|
for sub_node in self.graph.0[&node].iter() {
|
||||||
self.reachable.get_mut(&node).unwrap().insert(*sub_node);
|
self.reachable.get_mut(&node).unwrap().insert(*sub_node);
|
||||||
|
|
||||||
@ -557,7 +601,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn each_depending_on<F>(&self, node: Node, mut f: F)
|
fn each_depending_on<F>(&self, node: Node, mut f: F)
|
||||||
where F: FnMut(Node)
|
where F: FnMut(Node),
|
||||||
{
|
{
|
||||||
for dep in self.reversed.0[&node].iter() {
|
for dep in self.reversed.0[&node].iter() {
|
||||||
f(*dep);
|
f(*dep);
|
||||||
@ -578,19 +622,19 @@ mod tests {
|
|||||||
println!("reachable = {:#?}", reachable);
|
println!("reachable = {:#?}", reachable);
|
||||||
|
|
||||||
fn nodes<A>(nodes: A) -> HashSet<Node>
|
fn nodes<A>(nodes: A) -> HashSet<Node>
|
||||||
where A: AsRef<[usize]>
|
where A: AsRef<[usize]>,
|
||||||
{
|
{
|
||||||
nodes.as_ref().iter().cloned().map(Node).collect()
|
nodes.as_ref().iter().cloned().map(Node).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut expected = HashMap::new();
|
let mut expected = HashMap::new();
|
||||||
expected.insert(Node(1), nodes([3,4,5,6,7,8]));
|
expected.insert(Node(1), nodes([3, 4, 5, 6, 7, 8]));
|
||||||
expected.insert(Node(2), nodes([2]));
|
expected.insert(Node(2), nodes([2]));
|
||||||
expected.insert(Node(3), nodes([3,4,5,6,7,8]));
|
expected.insert(Node(3), nodes([3, 4, 5, 6, 7, 8]));
|
||||||
expected.insert(Node(4), nodes([3,4,5,6,7,8]));
|
expected.insert(Node(4), nodes([3, 4, 5, 6, 7, 8]));
|
||||||
expected.insert(Node(5), nodes([3,4,5,6,7,8]));
|
expected.insert(Node(5), nodes([3, 4, 5, 6, 7, 8]));
|
||||||
expected.insert(Node(6), nodes([8]));
|
expected.insert(Node(6), nodes([8]));
|
||||||
expected.insert(Node(7), nodes([3,4,5,6,7,8]));
|
expected.insert(Node(7), nodes([3, 4, 5, 6, 7, 8]));
|
||||||
expected.insert(Node(8), nodes([]));
|
expected.insert(Node(8), nodes([]));
|
||||||
println!("expected = {:#?}", expected);
|
println!("expected = {:#?}", expected);
|
||||||
|
|
||||||
|
193
src/ir/template.rs
Normal file
193
src/ir/template.rs
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
//! Template declaration and instantiation related things.
|
||||||
|
//!
|
||||||
|
//! The nomenclature surrounding templates is often confusing, so here are a few
|
||||||
|
//! brief definitions:
|
||||||
|
//!
|
||||||
|
//! * "Template definition": a class/struct/alias/function definition that takes
|
||||||
|
//! generic template parameters. For example:
|
||||||
|
//!
|
||||||
|
//! ```c++
|
||||||
|
//! template<typename T>
|
||||||
|
//! class List<T> {
|
||||||
|
//! // ...
|
||||||
|
//! };
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! * "Template instantiation": an instantiation is a use of a template with
|
||||||
|
//! concrete template arguments. For example, `List<int>`.
|
||||||
|
//!
|
||||||
|
//! * "Template specialization": an alternative template definition providing a
|
||||||
|
//! custom definition for instantiations with the matching template
|
||||||
|
//! arguments. This C++ feature is unsupported by bindgen. For example:
|
||||||
|
//!
|
||||||
|
//! ```c++
|
||||||
|
//! template<>
|
||||||
|
//! class List<int> {
|
||||||
|
//! // Special layout for int lists...
|
||||||
|
//! };
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use super::context::{BindgenContext, ItemId};
|
||||||
|
use super::derive::{CanDeriveCopy, CanDeriveDebug};
|
||||||
|
use super::item::Item;
|
||||||
|
use super::layout::Layout;
|
||||||
|
use super::traversal::{EdgeKind, Trace, Tracer};
|
||||||
|
use clang;
|
||||||
|
use parse::ClangItemParser;
|
||||||
|
|
||||||
|
/// A trait for things which may or may not be a named template type parameter.
|
||||||
|
pub trait AsNamed {
|
||||||
|
/// Any extra information the implementor might need to make this decision.
|
||||||
|
type Extra;
|
||||||
|
|
||||||
|
/// Convert this thing to the item id of a named template type parameter.
|
||||||
|
fn as_named(&self,
|
||||||
|
ctx: &BindgenContext,
|
||||||
|
extra: &Self::Extra)
|
||||||
|
-> Option<ItemId>;
|
||||||
|
|
||||||
|
/// Is this a named template type parameter?
|
||||||
|
fn is_named(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool {
|
||||||
|
self.as_named(ctx, extra).is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A concrete instantiation of a generic template.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct TemplateInstantiation {
|
||||||
|
/// The template definition which this is instantiating.
|
||||||
|
definition: ItemId,
|
||||||
|
/// The concrete template arguments, which will be substituted in the
|
||||||
|
/// definition for the generic template parameters.
|
||||||
|
args: Vec<ItemId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TemplateInstantiation {
|
||||||
|
/// Construct a new template instantiation from the given parts.
|
||||||
|
pub fn new<I>(template_definition: ItemId,
|
||||||
|
template_args: I)
|
||||||
|
-> TemplateInstantiation
|
||||||
|
where I: IntoIterator<Item = ItemId>,
|
||||||
|
{
|
||||||
|
TemplateInstantiation {
|
||||||
|
definition: template_definition,
|
||||||
|
args: template_args.into_iter().collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the template definition for this instantiation.
|
||||||
|
pub fn template_definition(&self) -> ItemId {
|
||||||
|
self.definition
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the concrete template arguments used in this instantiation.
|
||||||
|
pub fn template_arguments(&self) -> &[ItemId] {
|
||||||
|
&self.args[..]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a `TemplateInstantiation` from a clang `Type`.
|
||||||
|
pub fn from_ty(ty: &clang::Type,
|
||||||
|
ctx: &mut BindgenContext)
|
||||||
|
-> TemplateInstantiation {
|
||||||
|
use clang_sys::*;
|
||||||
|
|
||||||
|
let template_args = ty.template_args()
|
||||||
|
.map_or(vec![], |args| {
|
||||||
|
args.filter(|t| t.kind() != CXType_Invalid)
|
||||||
|
.map(|t| {
|
||||||
|
Item::from_ty_or_ref(t, t.declaration(), None, ctx)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
|
||||||
|
let definition = ty.declaration()
|
||||||
|
.specialized()
|
||||||
|
.or_else(|| {
|
||||||
|
let mut template_ref = None;
|
||||||
|
ty.declaration().visit(|child| {
|
||||||
|
if child.kind() == CXCursor_TemplateRef {
|
||||||
|
template_ref = Some(child);
|
||||||
|
return CXVisit_Break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instantiations of template aliases might have the
|
||||||
|
// TemplateRef to the template alias definition arbitrarily
|
||||||
|
// deep, so we need to recurse here and not only visit
|
||||||
|
// direct children.
|
||||||
|
CXChildVisit_Recurse
|
||||||
|
});
|
||||||
|
|
||||||
|
template_ref.and_then(|cur| cur.referenced())
|
||||||
|
})
|
||||||
|
.expect("Should have found the template definition one way or another");
|
||||||
|
|
||||||
|
let template_definition =
|
||||||
|
Item::from_ty_or_ref(definition.cur_type(), definition, None, ctx);
|
||||||
|
|
||||||
|
TemplateInstantiation::new(template_definition, template_args)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does this instantiation have a vtable?
|
||||||
|
pub fn has_vtable(&self, ctx: &BindgenContext) -> bool {
|
||||||
|
ctx.resolve_type(self.definition).has_vtable(ctx) ||
|
||||||
|
self.args.iter().any(|arg| ctx.resolve_type(*arg).has_vtable(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does this instantiation have a destructor?
|
||||||
|
pub fn has_destructor(&self, ctx: &BindgenContext) -> bool {
|
||||||
|
ctx.resolve_type(self.definition).has_destructor(ctx) ||
|
||||||
|
self.args.iter().any(|arg| ctx.resolve_type(*arg).has_destructor(ctx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> CanDeriveCopy<'a> for TemplateInstantiation {
|
||||||
|
type Extra = ();
|
||||||
|
|
||||||
|
fn can_derive_copy(&self, ctx: &BindgenContext, _: ()) -> bool {
|
||||||
|
self.definition.can_derive_copy(ctx, ()) &&
|
||||||
|
self.args.iter().all(|arg| arg.can_derive_copy(ctx, ()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_derive_copy_in_array(&self, ctx: &BindgenContext, _: ()) -> bool {
|
||||||
|
self.definition.can_derive_copy_in_array(ctx, ()) &&
|
||||||
|
self.args.iter().all(|arg| arg.can_derive_copy_in_array(ctx, ()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CanDeriveDebug for TemplateInstantiation {
|
||||||
|
type Extra = Option<Layout>;
|
||||||
|
|
||||||
|
fn can_derive_debug(&self,
|
||||||
|
ctx: &BindgenContext,
|
||||||
|
layout: Option<Layout>)
|
||||||
|
-> bool {
|
||||||
|
self.args.iter().all(|arg| arg.can_derive_debug(ctx, ())) &&
|
||||||
|
ctx.resolve_type(self.definition)
|
||||||
|
.as_comp()
|
||||||
|
.and_then(|c| {
|
||||||
|
// For non-type template parameters, we generate an opaque
|
||||||
|
// blob, and in this case the instantiation has a better
|
||||||
|
// idea of the layout than the definition does.
|
||||||
|
if c.has_non_type_template_params() {
|
||||||
|
let opaque = layout.unwrap_or(Layout::zero()).opaque();
|
||||||
|
Some(opaque.can_derive_debug(ctx, ()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| self.definition.can_derive_debug(ctx, ()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trace for TemplateInstantiation {
|
||||||
|
type Extra = ();
|
||||||
|
|
||||||
|
fn trace<T>(&self, _ctx: &BindgenContext, tracer: &mut T, _: &())
|
||||||
|
where T: Tracer,
|
||||||
|
{
|
||||||
|
tracer.visit_kind(self.definition, EdgeKind::TemplateDeclaration);
|
||||||
|
for &item in self.template_arguments() {
|
||||||
|
tracer.visit_kind(item, EdgeKind::TemplateArgument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -318,7 +318,7 @@ pub trait Tracer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F> Tracer for F
|
impl<F> Tracer for F
|
||||||
where F: FnMut(ItemId, EdgeKind)
|
where F: FnMut(ItemId, EdgeKind),
|
||||||
{
|
{
|
||||||
fn visit_kind(&mut self, item: ItemId, kind: EdgeKind) {
|
fn visit_kind(&mut self, item: ItemId, kind: EdgeKind) {
|
||||||
(*self)(item, kind)
|
(*self)(item, kind)
|
||||||
|
1041
src/ir/ty.rs
1041
src/ir/ty.rs
File diff suppressed because it is too large
Load Diff
@ -87,15 +87,20 @@ impl Var {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DotAttributes for Var {
|
impl DotAttributes for Var {
|
||||||
fn dot_attributes<W>(&self, _ctx: &BindgenContext, out: &mut W) -> io::Result<()>
|
fn dot_attributes<W>(&self,
|
||||||
where W: io::Write
|
_ctx: &BindgenContext,
|
||||||
|
out: &mut W)
|
||||||
|
-> io::Result<()>
|
||||||
|
where W: io::Write,
|
||||||
{
|
{
|
||||||
if self.is_const {
|
if self.is_const {
|
||||||
try!(writeln!(out, "<tr><td>const</td><td>true</td></tr>"));
|
try!(writeln!(out, "<tr><td>const</td><td>true</td></tr>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mangled) = self.mangled_name {
|
if let Some(ref mangled) = self.mangled_name {
|
||||||
try!(writeln!(out, "<tr><td>mangled name</td><td>{}</td></tr>", mangled));
|
try!(writeln!(out,
|
||||||
|
"<tr><td>mangled name</td><td>{}</td></tr>",
|
||||||
|
mangled));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -202,7 +207,7 @@ impl ClangSubItemParser for Var {
|
|||||||
// XXX this is redundant, remove!
|
// XXX this is redundant, remove!
|
||||||
let is_const = ty.is_const();
|
let is_const = ty.is_const();
|
||||||
|
|
||||||
let ty = match Item::from_ty(&ty, Some(cursor), None, ctx) {
|
let ty = match Item::from_ty(&ty, cursor, None, ctx) {
|
||||||
Ok(ty) => ty,
|
Ok(ty) => ty,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
assert_eq!(ty.kind(),
|
assert_eq!(ty.kind(),
|
||||||
|
26
src/parse.rs
26
src/parse.rs
@ -49,7 +49,7 @@ pub trait ClangItemParser: Sized {
|
|||||||
|
|
||||||
/// Parse this item from the given Clang type.
|
/// Parse this item from the given Clang type.
|
||||||
fn from_ty(ty: &clang::Type,
|
fn from_ty(ty: &clang::Type,
|
||||||
location: Option<clang::Cursor>,
|
location: clang::Cursor,
|
||||||
parent: Option<ItemId>,
|
parent: Option<ItemId>,
|
||||||
ctx: &mut BindgenContext)
|
ctx: &mut BindgenContext)
|
||||||
-> Result<ItemId, ParseError>;
|
-> Result<ItemId, ParseError>;
|
||||||
@ -58,7 +58,7 @@ pub trait ClangItemParser: Sized {
|
|||||||
/// newly parsed item.
|
/// newly parsed item.
|
||||||
fn from_ty_with_id(id: ItemId,
|
fn from_ty_with_id(id: ItemId,
|
||||||
ty: &clang::Type,
|
ty: &clang::Type,
|
||||||
location: Option<clang::Cursor>,
|
location: clang::Cursor,
|
||||||
parent: Option<ItemId>,
|
parent: Option<ItemId>,
|
||||||
ctx: &mut BindgenContext)
|
ctx: &mut BindgenContext)
|
||||||
-> Result<ItemId, ParseError>;
|
-> Result<ItemId, ParseError>;
|
||||||
@ -66,7 +66,7 @@ pub trait ClangItemParser: Sized {
|
|||||||
/// Parse this item from the given Clang type, or if we haven't resolved all
|
/// Parse this item from the given Clang type, or if we haven't resolved all
|
||||||
/// the other items this one depends on, an unresolved reference.
|
/// the other items this one depends on, an unresolved reference.
|
||||||
fn from_ty_or_ref(ty: clang::Type,
|
fn from_ty_or_ref(ty: clang::Type,
|
||||||
location: Option<clang::Cursor>,
|
location: clang::Cursor,
|
||||||
parent_id: Option<ItemId>,
|
parent_id: Option<ItemId>,
|
||||||
context: &mut BindgenContext)
|
context: &mut BindgenContext)
|
||||||
-> ItemId;
|
-> ItemId;
|
||||||
@ -75,26 +75,16 @@ pub trait ClangItemParser: Sized {
|
|||||||
/// `ItemId` for the newly parsed item.
|
/// `ItemId` for the newly parsed item.
|
||||||
fn from_ty_or_ref_with_id(potential_id: ItemId,
|
fn from_ty_or_ref_with_id(potential_id: ItemId,
|
||||||
ty: clang::Type,
|
ty: clang::Type,
|
||||||
location: Option<clang::Cursor>,
|
location: clang::Cursor,
|
||||||
parent_id: Option<ItemId>,
|
parent_id: Option<ItemId>,
|
||||||
context: &mut BindgenContext)
|
context: &mut BindgenContext)
|
||||||
-> ItemId;
|
-> ItemId;
|
||||||
|
|
||||||
/// Create a named template type.
|
/// Create a named template type.
|
||||||
fn named_type<S>(name: S,
|
fn named_type(with_id: Option<ItemId>,
|
||||||
parent: ItemId,
|
location: clang::Cursor,
|
||||||
context: &mut BindgenContext)
|
ctx: &mut BindgenContext)
|
||||||
-> ItemId
|
-> Option<ItemId>;
|
||||||
where S: Into<String>;
|
|
||||||
|
|
||||||
/// Identical to `named_type`, but use `id` as the resulting item's
|
|
||||||
/// `ItemId`.
|
|
||||||
fn named_type_with_id<S>(id: ItemId,
|
|
||||||
name: S,
|
|
||||||
parent: ItemId,
|
|
||||||
context: &mut BindgenContext)
|
|
||||||
-> ItemId
|
|
||||||
where S: Into<String>;
|
|
||||||
|
|
||||||
/// Create a builtin type.
|
/// Create a builtin type.
|
||||||
fn builtin_type(kind: TypeKind,
|
fn builtin_type(kind: TypeKind,
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
use ir::context::BindgenContext;
|
use ir::context::BindgenContext;
|
||||||
use ir::item::{Item, ItemAncestors, ItemCanonicalName};
|
use ir::item::{Item, ItemAncestors, ItemCanonicalName};
|
||||||
|
use ir::ty::TemplateDeclaration;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
// Like `canonical_path`, except we always take namespaces into account, ignore
|
// Like `canonical_path`, except we always take namespaces into account, ignore
|
||||||
@ -83,9 +84,9 @@ pub fn generate_dummy_uses<W>(ctx: &mut BindgenContext,
|
|||||||
// these.
|
// these.
|
||||||
!ty.is_builtin_or_named() &&
|
!ty.is_builtin_or_named() &&
|
||||||
// And finally, we won't be creating any dummy
|
// And finally, we won't be creating any dummy
|
||||||
// specializations, so ignore template declarations and
|
// instantiations, so ignore template declarations and
|
||||||
// partial specializations.
|
// instantiations.
|
||||||
item.applicable_template_args(ctx).is_empty()
|
item.all_template_params(ctx).is_none()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
3
tests/expectations/lib.rs
Normal file → Executable file
3
tests/expectations/lib.rs
Normal file → Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
@ -5,11 +5,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct std_allocator_traits<_Alloc> {
|
pub struct std_allocator_traits {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_Alloc>,
|
|
||||||
}
|
|
||||||
impl <_Alloc> Default for std_allocator_traits<_Alloc> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
|
pub type std_allocator_traits___size_type<_Alloc> = _Alloc;
|
||||||
|
@ -5,10 +5,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct DataType<_Tp> {
|
pub struct DataType {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_Tp>,
|
|
||||||
}
|
}
|
||||||
pub type DataType_value_type<_Tp> = _Tp;
|
pub type DataType_value_type<_Tp> = _Tp;
|
||||||
pub type DataType_work_type<_Tp> = DataType_value_type<_Tp>;
|
pub type DataType_work_type<_Tp> = DataType_value_type<_Tp>;
|
||||||
@ -27,9 +26,6 @@ pub const DataType_type_: DataType__bindgen_ty_1 =
|
|||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum DataType__bindgen_ty_1 { generic_type = 0, }
|
pub enum DataType__bindgen_ty_1 { generic_type = 0, }
|
||||||
impl <_Tp> Default for DataType<_Tp> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Default, Copy)]
|
||||||
pub struct Foo {
|
pub struct Foo {
|
||||||
|
@ -30,12 +30,11 @@ impl <T> ::std::fmt::Debug for __BindgenUnionField<T> {
|
|||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct TErrorResult<T> {
|
pub struct TErrorResult {
|
||||||
pub mResult: ::std::os::raw::c_int,
|
pub mResult: ::std::os::raw::c_int,
|
||||||
pub __bindgen_anon_1: TErrorResult__bindgen_ty_1<T>,
|
pub __bindgen_anon_1: TErrorResult__bindgen_ty_1,
|
||||||
pub mMightHaveUnreported: bool,
|
pub mMightHaveUnreported: bool,
|
||||||
pub mUnionState: TErrorResult_UnionState,
|
pub mUnionState: TErrorResult_UnionState,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState =
|
pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState =
|
||||||
TErrorResult_UnionState::HasMessage;
|
TErrorResult_UnionState::HasMessage;
|
||||||
@ -44,31 +43,28 @@ pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState =
|
|||||||
pub enum TErrorResult_UnionState { HasMessage = 0, }
|
pub enum TErrorResult_UnionState { HasMessage = 0, }
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct TErrorResult_Message<T> {
|
pub struct TErrorResult_Message {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct TErrorResult_DOMExceptionInfo<T> {
|
pub struct TErrorResult_DOMExceptionInfo {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct TErrorResult__bindgen_ty_1<T> {
|
pub struct TErrorResult__bindgen_ty_1 {
|
||||||
pub mMessage: __BindgenUnionField<*mut TErrorResult_Message<T>>,
|
pub mMessage: __BindgenUnionField<*mut TErrorResult_Message>,
|
||||||
pub mDOMExceptionInfo: __BindgenUnionField<*mut TErrorResult_DOMExceptionInfo<T>>,
|
pub mDOMExceptionInfo: __BindgenUnionField<*mut TErrorResult_DOMExceptionInfo>,
|
||||||
pub bindgen_union_field: u64,
|
pub bindgen_union_field: u64,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
impl <T> Default for TErrorResult<T> {
|
impl Default for TErrorResult {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy)]
|
#[derive(Debug, Copy)]
|
||||||
pub struct ErrorResult {
|
pub struct ErrorResult {
|
||||||
pub _base: TErrorResult<::std::os::raw::c_int>,
|
pub _base: TErrorResult,
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn bindgen_test_layout_ErrorResult() {
|
fn bindgen_test_layout_ErrorResult() {
|
||||||
@ -84,13 +80,11 @@ impl Default for ErrorResult {
|
|||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn __bindgen_test_layout_template_1() {
|
fn __bindgen_test_layout_TErrorResult_instantiation_21() {
|
||||||
assert_eq!(::std::mem::size_of::<TErrorResult<::std::os::raw::c_int>>() ,
|
assert_eq!(::std::mem::size_of::<TErrorResult>() , 24usize , concat ! (
|
||||||
24usize , concat ! (
|
|
||||||
"Size of template specialization: " , stringify ! (
|
"Size of template specialization: " , stringify ! (
|
||||||
TErrorResult<::std::os::raw::c_int> ) ));
|
TErrorResult ) ));
|
||||||
assert_eq!(::std::mem::align_of::<TErrorResult<::std::os::raw::c_int>>() ,
|
assert_eq!(::std::mem::align_of::<TErrorResult>() , 8usize , concat ! (
|
||||||
8usize , concat ! (
|
|
||||||
"Alignment of template specialization: " , stringify ! (
|
"Alignment of template specialization: " , stringify ! (
|
||||||
TErrorResult<::std::os::raw::c_int> ) ));
|
TErrorResult ) ));
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,9 @@ impl Clone for Foo {
|
|||||||
fn clone(&self) -> Self { *self }
|
fn clone(&self) -> Self { *self }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Bar<T> {
|
pub struct Bar {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for Bar<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "_Z5Test2v"]
|
#[link_name = "_Z5Test2v"]
|
||||||
|
@ -5,13 +5,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct std_char_traits<_CharT> {
|
pub struct std_char_traits {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_CharT>,
|
|
||||||
}
|
|
||||||
impl <_CharT> Default for std_char_traits<_CharT> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Default, Copy)]
|
||||||
|
@ -77,7 +77,7 @@ extern "C" {
|
|||||||
pub static mut var: A_B;
|
pub static mut var: A_B;
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn __bindgen_test_layout_template_1() {
|
fn __bindgen_test_layout_A_D_instantiation_16() {
|
||||||
assert_eq!(::std::mem::size_of::<A_D<::std::os::raw::c_int>>() , 4usize ,
|
assert_eq!(::std::mem::size_of::<A_D<::std::os::raw::c_int>>() , 4usize ,
|
||||||
concat ! (
|
concat ! (
|
||||||
"Size of template specialization: " , stringify ! (
|
"Size of template specialization: " , stringify ! (
|
||||||
|
@ -34,7 +34,7 @@ impl Default for WithoutDtor {
|
|||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn __bindgen_test_layout_template_1() {
|
fn __bindgen_test_layout_HandleWithDtor_instantiation_10() {
|
||||||
assert_eq!(::std::mem::size_of::<HandleWithDtor<::std::os::raw::c_int>>()
|
assert_eq!(::std::mem::size_of::<HandleWithDtor<::std::os::raw::c_int>>()
|
||||||
, 8usize , concat ! (
|
, 8usize , concat ! (
|
||||||
"Size of template specialization: " , stringify ! (
|
"Size of template specialization: " , stringify ! (
|
||||||
|
@ -5,26 +5,17 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Test<Args> {
|
pub struct Test {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<Args>,
|
|
||||||
}
|
|
||||||
impl <Args> Default for Test<Args> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct Outer<T> {
|
|
||||||
pub _address: u8,
|
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Outer_Inner<T> {
|
pub struct Outer {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
impl <T> Default for Outer<T> {
|
#[repr(C)]
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct Outer_Inner {
|
||||||
|
pub _address: u8,
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Foo<T> {
|
pub struct Foo {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for Foo<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy)]
|
#[derive(Debug, Default, Copy)]
|
||||||
|
@ -5,13 +5,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Base<T> {
|
pub struct Base {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for Base<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy)]
|
#[derive(Debug, Copy)]
|
||||||
@ -32,13 +28,9 @@ impl Default for Derived {
|
|||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct BaseWithDestructor<T> {
|
pub struct BaseWithDestructor {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for BaseWithDestructor<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -59,22 +51,21 @@ impl Default for DerivedFromBaseWithDestructor {
|
|||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn __bindgen_test_layout_template_1() {
|
fn __bindgen_test_layout_Base_instantiation_9() {
|
||||||
assert_eq!(::std::mem::size_of::<Base<Derived>>() , 1usize , concat ! (
|
assert_eq!(::std::mem::size_of::<Base>() , 1usize , concat ! (
|
||||||
"Size of template specialization: " , stringify ! (
|
"Size of template specialization: " , stringify ! ( Base ) ));
|
||||||
Base<Derived> ) ));
|
assert_eq!(::std::mem::align_of::<Base>() , 1usize , concat ! (
|
||||||
assert_eq!(::std::mem::align_of::<Base<Derived>>() , 1usize , concat ! (
|
"Alignment of template specialization: " , stringify ! ( Base )
|
||||||
"Alignment of template specialization: " , stringify ! (
|
));
|
||||||
Base<Derived> ) ));
|
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn __bindgen_test_layout_template_2() {
|
fn __bindgen_test_layout_BaseWithDestructor_instantiation_12() {
|
||||||
assert_eq!(::std::mem::size_of::<BaseWithDestructor<DerivedFromBaseWithDestructor>>()
|
assert_eq!(::std::mem::size_of::<BaseWithDestructor>() , 1usize , concat !
|
||||||
, 1usize , concat ! (
|
(
|
||||||
"Size of template specialization: " , stringify ! (
|
"Size of template specialization: " , stringify ! (
|
||||||
BaseWithDestructor<DerivedFromBaseWithDestructor> ) ));
|
BaseWithDestructor ) ));
|
||||||
assert_eq!(::std::mem::align_of::<BaseWithDestructor<DerivedFromBaseWithDestructor>>()
|
assert_eq!(::std::mem::align_of::<BaseWithDestructor>() , 1usize , concat
|
||||||
, 1usize , concat ! (
|
! (
|
||||||
"Alignment of template specialization: " , stringify ! (
|
"Alignment of template specialization: " , stringify ! (
|
||||||
BaseWithDestructor<DerivedFromBaseWithDestructor> ) ));
|
BaseWithDestructor ) ));
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Foo<T> {
|
pub struct Foo {
|
||||||
pub bar: ::std::os::raw::c_int,
|
pub bar: ::std::os::raw::c_int,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for Foo<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,7 @@
|
|||||||
|
|
||||||
pub type __void_t = ::std::os::raw::c_void;
|
pub type __void_t = ::std::os::raw::c_void;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct __iterator_traits<_Iterator> {
|
pub struct __iterator_traits {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_Iterator>,
|
|
||||||
}
|
|
||||||
impl <_Iterator> Default for __iterator_traits<_Iterator> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct std_fbstring_core<Char> {
|
pub struct std_fbstring_core {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<Char>,
|
|
||||||
}
|
}
|
||||||
pub type std_fbstring_core_category_type = u8;
|
pub type std_fbstring_core_category_type = u8;
|
||||||
pub const std_fbstring_core_Category_Bar: std_fbstring_core_Category =
|
pub const std_fbstring_core_Category_Bar: std_fbstring_core_Category =
|
||||||
@ -16,6 +15,3 @@ pub const std_fbstring_core_Category_Bar: std_fbstring_core_Category =
|
|||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum std_fbstring_core_Category { Foo = 0, }
|
pub enum std_fbstring_core_Category { Foo = 0, }
|
||||||
impl <Char> Default for std_fbstring_core<Char> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
|
@ -5,11 +5,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct B<T> {
|
pub struct B {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for B<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,14 @@
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Rooted<T> {
|
pub struct Rooted {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
impl <T> Default for Rooted<T> {
|
impl Default for Rooted {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct js_RootedBase<T> {
|
pub struct js_RootedBase {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for js_RootedBase<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
|
@ -5,20 +5,15 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Foo<T> {
|
pub struct Foo {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
pub type Foo_elem_type<T> = T;
|
pub type Foo_elem_type<T> = T;
|
||||||
pub type Foo_ptr_type<T> = *mut T;
|
pub type Foo_ptr_type<T> = *mut T;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Foo_Bar<T> {
|
pub struct Foo_Bar {
|
||||||
pub x: ::std::os::raw::c_int,
|
pub x: ::std::os::raw::c_int,
|
||||||
pub y: ::std::os::raw::c_int,
|
pub y: ::std::os::raw::c_int,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for Foo<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
|
@ -5,20 +5,15 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct js_RootedBase<T> {
|
pub struct js_RootedBase {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for js_RootedBase<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Rooted<T> {
|
pub struct Rooted {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
impl <T> Default for Rooted<T> {
|
impl Default for Rooted {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Wohoo<T> {
|
pub struct Wohoo {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for Wohoo<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -6,17 +6,17 @@
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct LinkedList<T> {
|
pub struct LinkedList {
|
||||||
pub next: *mut LinkedList<T>,
|
pub next: *mut LinkedList,
|
||||||
pub prev: *mut LinkedList<T>,
|
pub prev: *mut LinkedList,
|
||||||
}
|
}
|
||||||
impl <T> Default for LinkedList<T> {
|
impl Default for LinkedList {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy)]
|
#[derive(Debug, Copy)]
|
||||||
pub struct InstantiateIt {
|
pub struct InstantiateIt {
|
||||||
pub m_list: LinkedList<::std::os::raw::c_int>,
|
pub m_list: LinkedList,
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn bindgen_test_layout_InstantiateIt() {
|
fn bindgen_test_layout_InstantiateIt() {
|
||||||
|
@ -6,11 +6,10 @@
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct JS_PersistentRooted<c> {
|
pub struct JS_PersistentRooted {
|
||||||
pub _base: a,
|
pub _base: a,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<c>,
|
|
||||||
}
|
}
|
||||||
impl <c> Default for JS_PersistentRooted<c> {
|
impl Default for JS_PersistentRooted {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -6,17 +6,17 @@
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct List<Elem> {
|
pub struct List {
|
||||||
pub next: *mut List<Elem>,
|
pub next: *mut List,
|
||||||
}
|
}
|
||||||
impl <Elem> Default for List<Elem> {
|
impl Default for List {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct PersistentRooted<GcThing> {
|
pub struct PersistentRooted {
|
||||||
pub root_list: List<PersistentRooted<GcThing>>,
|
pub root_list: List,
|
||||||
}
|
}
|
||||||
impl <GcThing> Default for PersistentRooted<GcThing> {
|
impl Default for PersistentRooted {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
|
@ -29,28 +29,21 @@ impl <T> ::std::fmt::Debug for __BindgenUnionField<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct basic_string<_CharT, _Traits, _Allocator> {
|
pub struct basic_string {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_CharT>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<_Traits>,
|
|
||||||
pub _phantom_2: ::std::marker::PhantomData<_Allocator>,
|
|
||||||
}
|
}
|
||||||
pub type basic_string_size_type = ::std::os::raw::c_ulonglong;
|
pub type basic_string_size_type = ::std::os::raw::c_ulonglong;
|
||||||
pub type basic_string_value_type = ::std::os::raw::c_schar;
|
pub type basic_string_value_type = ::std::os::raw::c_schar;
|
||||||
pub type basic_string_pointer = *mut basic_string_value_type;
|
pub type basic_string_pointer = *mut basic_string_value_type;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct basic_string___long<_CharT, _Traits, _Allocator> {
|
pub struct basic_string___long {
|
||||||
pub __cap_: basic_string_size_type,
|
pub __cap_: basic_string_size_type,
|
||||||
pub __size_: basic_string_size_type,
|
pub __size_: basic_string_size_type,
|
||||||
pub __data_: basic_string_pointer,
|
pub __data_: basic_string_pointer,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_CharT>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<_Traits>,
|
|
||||||
pub _phantom_2: ::std::marker::PhantomData<_Allocator>,
|
|
||||||
}
|
}
|
||||||
impl <_CharT, _Traits, _Allocator> Default for
|
impl Default for basic_string___long {
|
||||||
basic_string___long<_CharT, _Traits, _Allocator> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
pub const basic_string___min_cap: basic_string__bindgen_ty_1 =
|
pub const basic_string___min_cap: basic_string__bindgen_ty_1 =
|
||||||
@ -60,42 +53,28 @@ pub const basic_string___min_cap: basic_string__bindgen_ty_1 =
|
|||||||
pub enum basic_string__bindgen_ty_1 { __min_cap = 0, }
|
pub enum basic_string__bindgen_ty_1 { __min_cap = 0, }
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct basic_string___short<_CharT, _Traits, _Allocator> {
|
pub struct basic_string___short {
|
||||||
pub __bindgen_anon_1: basic_string___short__bindgen_ty_1<_CharT, _Traits,
|
pub __bindgen_anon_1: basic_string___short__bindgen_ty_1,
|
||||||
_Allocator>,
|
|
||||||
pub __data_: *mut basic_string_value_type,
|
pub __data_: *mut basic_string_value_type,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_CharT>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<_Traits>,
|
|
||||||
pub _phantom_2: ::std::marker::PhantomData<_Allocator>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct basic_string___short__bindgen_ty_1<_CharT, _Traits, _Allocator> {
|
pub struct basic_string___short__bindgen_ty_1 {
|
||||||
pub __size_: __BindgenUnionField<::std::os::raw::c_uchar>,
|
pub __size_: __BindgenUnionField<::std::os::raw::c_uchar>,
|
||||||
pub __lx: __BindgenUnionField<basic_string_value_type>,
|
pub __lx: __BindgenUnionField<basic_string_value_type>,
|
||||||
pub bindgen_union_field: u8,
|
pub bindgen_union_field: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_CharT>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<_Traits>,
|
|
||||||
pub _phantom_2: ::std::marker::PhantomData<_Allocator>,
|
|
||||||
}
|
}
|
||||||
impl <_CharT, _Traits, _Allocator> Default for
|
impl Default for basic_string___short {
|
||||||
basic_string___short<_CharT, _Traits, _Allocator> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct basic_string___ulx<_CharT, _Traits, _Allocator> {
|
pub struct basic_string___ulx {
|
||||||
pub __lx: __BindgenUnionField<basic_string___long<_CharT, _Traits,
|
pub __lx: __BindgenUnionField<basic_string___long>,
|
||||||
_Allocator>>,
|
pub __lxx: __BindgenUnionField<basic_string___short>,
|
||||||
pub __lxx: __BindgenUnionField<basic_string___short<_CharT, _Traits,
|
|
||||||
_Allocator>>,
|
|
||||||
pub bindgen_union_field: [u8; 0usize],
|
pub bindgen_union_field: [u8; 0usize],
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_CharT>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<_Traits>,
|
|
||||||
pub _phantom_2: ::std::marker::PhantomData<_Allocator>,
|
|
||||||
}
|
}
|
||||||
impl <_CharT, _Traits, _Allocator> Default for
|
impl Default for basic_string___ulx {
|
||||||
basic_string___ulx<_CharT, _Traits, _Allocator> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
pub const basic_string___n_words: basic_string__bindgen_ty_2 =
|
pub const basic_string___n_words: basic_string__bindgen_ty_2 =
|
||||||
@ -105,48 +84,28 @@ pub const basic_string___n_words: basic_string__bindgen_ty_2 =
|
|||||||
pub enum basic_string__bindgen_ty_2 { __n_words = 0, }
|
pub enum basic_string__bindgen_ty_2 { __n_words = 0, }
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct basic_string___raw<_CharT, _Traits, _Allocator> {
|
pub struct basic_string___raw {
|
||||||
pub __words: *mut basic_string_size_type,
|
pub __words: *mut basic_string_size_type,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_CharT>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<_Traits>,
|
|
||||||
pub _phantom_2: ::std::marker::PhantomData<_Allocator>,
|
|
||||||
}
|
}
|
||||||
impl <_CharT, _Traits, _Allocator> Default for
|
impl Default for basic_string___raw {
|
||||||
basic_string___raw<_CharT, _Traits, _Allocator> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct basic_string___rep<_CharT, _Traits, _Allocator> {
|
pub struct basic_string___rep {
|
||||||
pub __bindgen_anon_1: basic_string___rep__bindgen_ty_1<_CharT, _Traits,
|
pub __bindgen_anon_1: basic_string___rep__bindgen_ty_1,
|
||||||
_Allocator>,
|
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_CharT>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<_Traits>,
|
|
||||||
pub _phantom_2: ::std::marker::PhantomData<_Allocator>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct basic_string___rep__bindgen_ty_1<_CharT, _Traits, _Allocator> {
|
pub struct basic_string___rep__bindgen_ty_1 {
|
||||||
pub __l: __BindgenUnionField<basic_string___long<_CharT, _Traits,
|
pub __l: __BindgenUnionField<basic_string___long>,
|
||||||
_Allocator>>,
|
pub __s: __BindgenUnionField<basic_string___short>,
|
||||||
pub __s: __BindgenUnionField<basic_string___short<_CharT, _Traits,
|
pub __r: __BindgenUnionField<basic_string___raw>,
|
||||||
_Allocator>>,
|
|
||||||
pub __r: __BindgenUnionField<basic_string___raw<_CharT, _Traits,
|
|
||||||
_Allocator>>,
|
|
||||||
pub bindgen_union_field: [u8; 0usize],
|
pub bindgen_union_field: [u8; 0usize],
|
||||||
pub _phantom_0: ::std::marker::PhantomData<_CharT>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<_Traits>,
|
|
||||||
pub _phantom_2: ::std::marker::PhantomData<_Allocator>,
|
|
||||||
}
|
}
|
||||||
impl <_CharT, _Traits, _Allocator> Default for
|
impl Default for basic_string___rep__bindgen_ty_1 {
|
||||||
basic_string___rep__bindgen_ty_1<_CharT, _Traits, _Allocator> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
impl <_CharT, _Traits, _Allocator> Default for
|
impl Default for basic_string___rep {
|
||||||
basic_string___rep<_CharT, _Traits, _Allocator> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
impl <_CharT, _Traits, _Allocator> Default for
|
|
||||||
basic_string<_CharT, _Traits, _Allocator> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
|
15
tests/expectations/tests/issue-544-stylo-creduce-2.rs
Normal file
15
tests/expectations/tests/issue-544-stylo-creduce-2.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Foo {
|
||||||
|
pub member: Foo_SecondAlias,
|
||||||
|
}
|
||||||
|
pub type Foo_FirstAlias = [u8; 0usize];
|
||||||
|
pub type Foo_SecondAlias = [u8; 0usize];
|
||||||
|
impl Default for Foo {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
14
tests/expectations/tests/issue-544-stylo-creduce.rs
Normal file
14
tests/expectations/tests/issue-544-stylo-creduce.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy)]
|
||||||
|
pub struct a {
|
||||||
|
pub _address: u8,
|
||||||
|
}
|
||||||
|
impl Clone for a {
|
||||||
|
fn clone(&self) -> Self { *self }
|
||||||
|
}
|
@ -5,22 +5,12 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct RefPtr<T> {
|
pub struct RefPtr {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct RefPtr_Proxy<T, R, Args> {
|
pub struct RefPtr_Proxy {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<R>,
|
|
||||||
pub _phantom_2: ::std::marker::PhantomData<Args>,
|
|
||||||
}
|
|
||||||
impl <T, R, Args> Default for RefPtr_Proxy<T, R, Args> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
impl <T> Default for RefPtr<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,7 @@
|
|||||||
|
|
||||||
/** <div rustbindgen nocopy></div> */
|
/** <div rustbindgen nocopy></div> */
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct CopiableButWait<T> {
|
pub struct CopiableButWait {
|
||||||
pub whatever: ::std::os::raw::c_int,
|
pub whatever: ::std::os::raw::c_int,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for CopiableButWait<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
|
@ -27,16 +27,15 @@ impl Clone for OtherOpaque {
|
|||||||
*/
|
*/
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Opaque<T> {
|
pub struct Opaque {
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
impl <T> Default for Opaque<T> {
|
impl Default for Opaque {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy)]
|
#[derive(Debug, Copy)]
|
||||||
pub struct WithOpaquePtr {
|
pub struct WithOpaquePtr {
|
||||||
pub whatever: *mut Opaque<::std::os::raw::c_int>,
|
pub whatever: *mut (),
|
||||||
pub other: u32,
|
pub other: u32,
|
||||||
pub t: OtherOpaque,
|
pub t: OtherOpaque,
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,10 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct RandomTemplate<T> {
|
pub struct RandomTemplate {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for RandomTemplate<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
/** <div rustbindgen opaque></div> */
|
/** <div rustbindgen opaque></div> */
|
||||||
pub type ShouldBeOpaque = [u8; 0usize];
|
pub type ShouldBeOpaque = [u8; 0usize];
|
||||||
pub type ShouldNotBeOpaque = RandomTemplate<f32>;
|
pub type ShouldNotBeOpaque = RandomTemplate;
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct Base {
|
||||||
|
pub _address: u8,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct Derived {
|
||||||
|
pub b: bool,
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn __bindgen_test_layout__bindgen_ty_id_20_instantiation_14() {
|
||||||
|
assert_eq!(::std::mem::size_of::<[u32; 2usize]>() , 8usize , concat ! (
|
||||||
|
"Size of template specialization: " , stringify ! (
|
||||||
|
[u32; 2usize] ) ));
|
||||||
|
assert_eq!(::std::mem::align_of::<[u32; 2usize]>() , 4usize , concat ! (
|
||||||
|
"Alignment of template specialization: " , stringify ! (
|
||||||
|
[u32; 2usize] ) ));
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy)]
|
||||||
|
pub struct Usage {
|
||||||
|
pub _address: u8,
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
#[link_name = "_ZN5Usage13static_memberE"]
|
||||||
|
pub static mut Usage_static_member: [u32; 2usize];
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn bindgen_test_layout_Usage() {
|
||||||
|
assert_eq!(::std::mem::size_of::<Usage>() , 1usize , concat ! (
|
||||||
|
"Size of: " , stringify ! ( Usage ) ));
|
||||||
|
assert_eq! (::std::mem::align_of::<Usage>() , 1usize , concat ! (
|
||||||
|
"Alignment of " , stringify ! ( Usage ) ));
|
||||||
|
}
|
||||||
|
impl Clone for Usage {
|
||||||
|
fn clone(&self) -> Self { *self }
|
||||||
|
}
|
@ -8,18 +8,14 @@
|
|||||||
* <div rustbindgen replaces="nsTArray"></div>
|
* <div rustbindgen replaces="nsTArray"></div>
|
||||||
*/
|
*/
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct nsTArray<T> {
|
pub struct nsTArray {
|
||||||
pub y: ::std::os::raw::c_uint,
|
pub y: ::std::os::raw::c_uint,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for nsTArray<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy)]
|
#[derive(Debug, Copy)]
|
||||||
pub struct Test {
|
pub struct Test {
|
||||||
pub a: nsTArray<::std::os::raw::c_long>,
|
pub a: nsTArray,
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn bindgen_test_layout_Test() {
|
fn bindgen_test_layout_Test() {
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy)]
|
|
||||||
pub struct C {
|
pub struct C {
|
||||||
pub arr: [u32; 3usize],
|
pub arr: [u32; 3usize],
|
||||||
}
|
}
|
||||||
@ -21,9 +20,6 @@ fn bindgen_test_layout_C() {
|
|||||||
"Alignment of field: " , stringify ! ( C ) , "::" , stringify
|
"Alignment of field: " , stringify ! ( C ) , "::" , stringify
|
||||||
! ( arr ) ));
|
! ( arr ) ));
|
||||||
}
|
}
|
||||||
impl Clone for C {
|
|
||||||
fn clone(&self) -> Self { *self }
|
|
||||||
}
|
|
||||||
impl Default for C {
|
impl Default for C {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Proxy<T, Args> {
|
pub struct Proxy {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<Args>,
|
|
||||||
}
|
}
|
||||||
pub type Proxy_foo<T> =
|
pub type Proxy_foo<T> =
|
||||||
::std::option::Option<unsafe extern "C" fn(bar: *mut T)>;
|
::std::option::Option<unsafe extern "C" fn(bar: *mut T)>;
|
||||||
impl <T, Args> Default for Proxy<T, Args> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
|
@ -5,36 +5,22 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Foo<T> {
|
pub struct Foo {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
pub type Foo_FunctionPtr<T> =
|
pub type Foo_FunctionPtr<T> =
|
||||||
::std::option::Option<unsafe extern "C" fn() -> T>;
|
::std::option::Option<unsafe extern "C" fn() -> T>;
|
||||||
impl <T> Default for Foo<T> {
|
#[repr(C)]
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct RefPtr {
|
||||||
|
pub _address: u8,
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct RefPtr<T> {
|
pub struct RefPtr_Proxy {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct RefPtr_Proxy<T, R, Args> {
|
|
||||||
pub _address: u8,
|
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<R>,
|
|
||||||
pub _phantom_2: ::std::marker::PhantomData<Args>,
|
|
||||||
}
|
}
|
||||||
pub type RefPtr_Proxy_member_function<R, Args> =
|
pub type RefPtr_Proxy_member_function<R, Args> =
|
||||||
::std::option::Option<unsafe extern "C" fn(arg1: Args) -> R>;
|
::std::option::Option<unsafe extern "C" fn(arg1: Args) -> R>;
|
||||||
impl <T, R, Args> Default for RefPtr_Proxy<T, R, Args> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
impl <T> Default for RefPtr<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
pub type Returner<T> = ::std::option::Option<unsafe extern "C" fn() -> T>;
|
pub type Returner<T> = ::std::option::Option<unsafe extern "C" fn() -> T>;
|
||||||
|
14
tests/expectations/tests/template-param-usage-0.rs
Normal file
14
tests/expectations/tests/template-param-usage-0.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct UsesTemplateParameter<T> {
|
||||||
|
pub t: T,
|
||||||
|
}
|
||||||
|
impl <T> Default for UsesTemplateParameter<T> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
11
tests/expectations/tests/template-param-usage-1.rs
Normal file
11
tests/expectations/tests/template-param-usage-1.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct DoesNotUseTemplateParameter {
|
||||||
|
pub x: ::std::os::raw::c_int,
|
||||||
|
}
|
25
tests/expectations/tests/template-param-usage-10.rs
Normal file
25
tests/expectations/tests/template-param-usage-10.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct DoublyIndirectUsage<T, U> {
|
||||||
|
pub doubly_indirect: DoublyIndirectUsage_IndirectUsage<T, U>,
|
||||||
|
}
|
||||||
|
pub type DoublyIndirectUsage_Aliased<T> = T;
|
||||||
|
pub type DoublyIndirectUsage_Typedefed<U> = U;
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct DoublyIndirectUsage_IndirectUsage<T, U> {
|
||||||
|
pub member: DoublyIndirectUsage_Aliased<T>,
|
||||||
|
pub another: DoublyIndirectUsage_Typedefed<U>,
|
||||||
|
}
|
||||||
|
impl <T, U> Default for DoublyIndirectUsage_IndirectUsage<T, U> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
||||||
|
impl <T, U> Default for DoublyIndirectUsage<T, U> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
11
tests/expectations/tests/template-param-usage-11.rs
Normal file
11
tests/expectations/tests/template-param-usage-11.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct DoesNotUseT {
|
||||||
|
pub _address: u8,
|
||||||
|
}
|
23
tests/expectations/tests/template-param-usage-12.rs
Normal file
23
tests/expectations/tests/template-param-usage-12.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct BaseUsesT<T> {
|
||||||
|
pub t: *mut T,
|
||||||
|
}
|
||||||
|
impl <T> Default for BaseUsesT<T> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct CrtpUsesU<U> {
|
||||||
|
pub _base: BaseUsesT<CrtpUsesU<U>>,
|
||||||
|
pub usage: U,
|
||||||
|
}
|
||||||
|
impl <U> Default for CrtpUsesU<U> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
20
tests/expectations/tests/template-param-usage-13.rs
Normal file
20
tests/expectations/tests/template-param-usage-13.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct BaseIgnoresT {
|
||||||
|
pub x: ::std::os::raw::c_int,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct CrtpUsesU<U> {
|
||||||
|
pub _base: BaseIgnoresT,
|
||||||
|
pub usage: U,
|
||||||
|
}
|
||||||
|
impl <U> Default for CrtpUsesU<U> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
20
tests/expectations/tests/template-param-usage-14.rs
Normal file
20
tests/expectations/tests/template-param-usage-14.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct BaseIgnoresT {
|
||||||
|
pub x: ::std::os::raw::c_int,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct CrtpIgnoresU {
|
||||||
|
pub _base: BaseIgnoresT,
|
||||||
|
pub y: ::std::os::raw::c_int,
|
||||||
|
}
|
||||||
|
impl Default for CrtpIgnoresU {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
23
tests/expectations/tests/template-param-usage-15.rs
Normal file
23
tests/expectations/tests/template-param-usage-15.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct BaseUsesT<T> {
|
||||||
|
pub usage: *mut T,
|
||||||
|
}
|
||||||
|
impl <T> Default for BaseUsesT<T> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct CrtpIgnoresU {
|
||||||
|
pub _base: BaseUsesT<CrtpIgnoresU>,
|
||||||
|
pub y: ::std::os::raw::c_int,
|
||||||
|
}
|
||||||
|
impl Default for CrtpIgnoresU {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
22
tests/expectations/tests/template-param-usage-2.rs
Normal file
22
tests/expectations/tests/template-param-usage-2.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct UsesTemplateParameter<T> {
|
||||||
|
pub t: T,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct UsesTemplateParameter_AlsoUsesTemplateParameter<T> {
|
||||||
|
pub also: T,
|
||||||
|
}
|
||||||
|
impl <T> Default for UsesTemplateParameter_AlsoUsesTemplateParameter<T> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
||||||
|
impl <T> Default for UsesTemplateParameter<T> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
24
tests/expectations/tests/template-param-usage-3.rs
Normal file
24
tests/expectations/tests/template-param-usage-3.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct UsesTemplateParameter<T> {
|
||||||
|
pub t: T,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct UsesTemplateParameter_AlsoUsesTemplateParameterAndMore<T, U> {
|
||||||
|
pub also: T,
|
||||||
|
pub more: U,
|
||||||
|
}
|
||||||
|
impl <T, U> Default for
|
||||||
|
UsesTemplateParameter_AlsoUsesTemplateParameterAndMore<T, U> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
||||||
|
impl <T> Default for UsesTemplateParameter<T> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
19
tests/expectations/tests/template-param-usage-4.rs
Normal file
19
tests/expectations/tests/template-param-usage-4.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct UsesTemplateParameter<T> {
|
||||||
|
pub t: T,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct UsesTemplateParameter_DoesNotUseTemplateParameters {
|
||||||
|
pub x: ::std::os::raw::c_int,
|
||||||
|
}
|
||||||
|
impl <T> Default for UsesTemplateParameter<T> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
15
tests/expectations/tests/template-param-usage-5.rs
Normal file
15
tests/expectations/tests/template-param-usage-5.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct IndirectlyUsesTemplateParameter<T> {
|
||||||
|
pub aliased: IndirectlyUsesTemplateParameter_Aliased<T>,
|
||||||
|
}
|
||||||
|
pub type IndirectlyUsesTemplateParameter_Aliased<T> = T;
|
||||||
|
impl <T> Default for IndirectlyUsesTemplateParameter<T> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
12
tests/expectations/tests/template-param-usage-6.rs
Normal file
12
tests/expectations/tests/template-param-usage-6.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct DoesNotUseTemplateParameter {
|
||||||
|
pub x: ::std::os::raw::c_int,
|
||||||
|
}
|
||||||
|
pub type DoesNotUseTemplateParameter_ButAliasDoesUseIt<T> = T;
|
16
tests/expectations/tests/template-param-usage-7.rs
Normal file
16
tests/expectations/tests/template-param-usage-7.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct DoesNotUseU<T, V> {
|
||||||
|
pub t: T,
|
||||||
|
pub v: V,
|
||||||
|
}
|
||||||
|
impl <T, V> Default for DoesNotUseU<T, V> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
||||||
|
pub type Alias = DoesNotUseU<::std::os::raw::c_int, ::std::os::raw::c_schar>;
|
17
tests/expectations/tests/template-param-usage-8.rs
Normal file
17
tests/expectations/tests/template-param-usage-8.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct IndirectUsage<T, U> {
|
||||||
|
pub member1: IndirectUsage_Typedefed<T>,
|
||||||
|
pub member2: IndirectUsage_Aliased<U>,
|
||||||
|
}
|
||||||
|
pub type IndirectUsage_Typedefed<T> = T;
|
||||||
|
pub type IndirectUsage_Aliased<U> = U;
|
||||||
|
impl <T, U> Default for IndirectUsage<T, U> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
22
tests/expectations/tests/template-param-usage-9.rs
Normal file
22
tests/expectations/tests/template-param-usage-9.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* automatically generated by rust-bindgen */
|
||||||
|
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct DoesNotUse {
|
||||||
|
pub _address: u8,
|
||||||
|
}
|
||||||
|
pub type DoesNotUse_Aliased<T> = T;
|
||||||
|
pub type DoesNotUse_Typedefed<U> = U;
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct DoesNotUse_IndirectUsage<T, U> {
|
||||||
|
pub member: DoesNotUse_Aliased<T>,
|
||||||
|
pub another: DoesNotUse_Typedefed<U>,
|
||||||
|
}
|
||||||
|
impl <T, U> Default for DoesNotUse_IndirectUsage<T, U> {
|
||||||
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
|
}
|
@ -6,37 +6,34 @@
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Foo<T, U> {
|
pub struct Foo<T> {
|
||||||
pub m_member: T,
|
pub m_member: T,
|
||||||
pub m_member_ptr: *mut T,
|
pub m_member_ptr: *mut T,
|
||||||
pub m_member_arr: [T; 1usize],
|
pub m_member_arr: [T; 1usize],
|
||||||
pub _phantom_1: ::std::marker::PhantomData<U>,
|
|
||||||
}
|
}
|
||||||
impl <T, U> Default for Foo<T, U> {
|
impl <T> Default for Foo<T> {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "_Z3bar3FooIiiE"]
|
#[link_name = "_Z3bar3FooIiiE"]
|
||||||
pub fn bar(foo: Foo<::std::os::raw::c_int, ::std::os::raw::c_int>);
|
pub fn bar(foo: Foo<::std::os::raw::c_int>);
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct D<T> {
|
pub struct D {
|
||||||
pub m_foo: D_MyFoo,
|
pub m_foo: D_MyFoo,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
pub type D_MyFoo = Foo<::std::os::raw::c_int, ::std::os::raw::c_int>;
|
pub type D_MyFoo = Foo<::std::os::raw::c_int>;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct D_U<T, Z> {
|
pub struct D_U<Z> {
|
||||||
pub m_nested_foo: D_MyFoo,
|
pub m_nested_foo: D_MyFoo,
|
||||||
pub m_baz: Z,
|
pub m_baz: Z,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
impl <T, Z> Default for D_U<T, Z> {
|
impl <Z> Default for D_U<Z> {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
impl <T> Default for D<T> {
|
impl Default for D {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -104,10 +101,9 @@ impl Default for PODButContainsDtor {
|
|||||||
/** <div rustbindgen opaque> */
|
/** <div rustbindgen opaque> */
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Opaque<T> {
|
pub struct Opaque {
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
impl <T> Default for Opaque<T> {
|
impl Default for Opaque {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -143,11 +139,10 @@ impl <T> Default for NestedReplaced<T> {
|
|||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct NestedBase<T, U> {
|
pub struct NestedBase<T> {
|
||||||
pub buff: *mut T,
|
pub buff: *mut T,
|
||||||
pub _phantom_1: ::std::marker::PhantomData<U>,
|
|
||||||
}
|
}
|
||||||
impl <T, U> Default for NestedBase<T, U> {
|
impl <T> Default for NestedBase<T> {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -184,13 +179,9 @@ impl Clone for Untemplated {
|
|||||||
fn clone(&self) -> Self { *self }
|
fn clone(&self) -> Self { *self }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Templated<T> {
|
pub struct Templated {
|
||||||
pub m_untemplated: Untemplated,
|
pub m_untemplated: Untemplated,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for Templated<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* If the replacement doesn't happen at the parse level the container would be
|
* If the replacement doesn't happen at the parse level the container would be
|
||||||
@ -237,27 +228,23 @@ impl <T> Default for ReplacedWithoutDestructorFwd<T> {
|
|||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct TemplateWithVar<T> {
|
pub struct TemplateWithVar {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for TemplateWithVar<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn __bindgen_test_layout_template_1() {
|
fn __bindgen_test_layout_Foo_instantiation_95() {
|
||||||
assert_eq!(::std::mem::size_of::<Foo<::std::os::raw::c_int, ::std::os::raw::c_int>>()
|
assert_eq!(::std::mem::size_of::<Foo<::std::os::raw::c_int>>() , 24usize ,
|
||||||
, 24usize , concat ! (
|
concat ! (
|
||||||
"Size of template specialization: " , stringify ! (
|
"Size of template specialization: " , stringify ! (
|
||||||
Foo<::std::os::raw::c_int, ::std::os::raw::c_int> ) ));
|
Foo<::std::os::raw::c_int> ) ));
|
||||||
assert_eq!(::std::mem::align_of::<Foo<::std::os::raw::c_int, ::std::os::raw::c_int>>()
|
assert_eq!(::std::mem::align_of::<Foo<::std::os::raw::c_int>>() , 8usize ,
|
||||||
, 8usize , concat ! (
|
concat ! (
|
||||||
"Alignment of template specialization: " , stringify ! (
|
"Alignment of template specialization: " , stringify ! (
|
||||||
Foo<::std::os::raw::c_int, ::std::os::raw::c_int> ) ));
|
Foo<::std::os::raw::c_int> ) ));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn __bindgen_test_layout_template_2() {
|
fn __bindgen_test_layout_Rooted_instantiation_106() {
|
||||||
assert_eq!(::std::mem::size_of::<Rooted<*mut ::std::os::raw::c_void>>() ,
|
assert_eq!(::std::mem::size_of::<Rooted<*mut ::std::os::raw::c_void>>() ,
|
||||||
24usize , concat ! (
|
24usize , concat ! (
|
||||||
"Size of template specialization: " , stringify ! (
|
"Size of template specialization: " , stringify ! (
|
||||||
@ -268,7 +255,7 @@ fn __bindgen_test_layout_template_2() {
|
|||||||
Rooted<*mut ::std::os::raw::c_void> ) ));
|
Rooted<*mut ::std::os::raw::c_void> ) ));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn __bindgen_test_layout_template_3() {
|
fn __bindgen_test_layout_WithDtor_instantiation_114() {
|
||||||
assert_eq!(::std::mem::size_of::<WithDtor<::std::os::raw::c_int>>() ,
|
assert_eq!(::std::mem::size_of::<WithDtor<::std::os::raw::c_int>>() ,
|
||||||
4usize , concat ! (
|
4usize , concat ! (
|
||||||
"Size of template specialization: " , stringify ! (
|
"Size of template specialization: " , stringify ! (
|
||||||
|
@ -5,10 +5,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Wrapper<T> {
|
pub struct Wrapper {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@ -19,6 +18,3 @@ impl <T> Default for Wrapper_Wrapped<T> {
|
|||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
pub type Wrapper_Type<T> = Wrapper_Wrapped<T>;
|
pub type Wrapper_Type<T> = Wrapper_Wrapped<T>;
|
||||||
impl <T> Default for Wrapper<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
|
@ -7,11 +7,9 @@
|
|||||||
pub type foo =
|
pub type foo =
|
||||||
::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
|
::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Foo<T, U> {
|
pub struct Foo {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
pub _phantom_1: ::std::marker::PhantomData<U>,
|
|
||||||
}
|
}
|
||||||
pub type Foo_Char<T> = T;
|
pub type Foo_Char<T> = T;
|
||||||
pub type Foo_FooPtrTypedef<T> = *mut Foo_Char<T>;
|
pub type Foo_FooPtrTypedef<T> = *mut Foo_Char<T>;
|
||||||
@ -20,6 +18,3 @@ pub type Foo_nsCOMArrayEnumFunc<T> =
|
|||||||
aData:
|
aData:
|
||||||
*mut ::std::os::raw::c_void)
|
*mut ::std::os::raw::c_void)
|
||||||
-> bool>;
|
-> bool>;
|
||||||
impl <T, U> Default for Foo<T, U> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
|
@ -5,22 +5,14 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct detail_PointerType<T> {
|
pub struct detail_PointerType {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
pub type detail_PointerType_Type<T> = *mut T;
|
pub type detail_PointerType_Type<T> = *mut T;
|
||||||
impl <T> Default for detail_PointerType<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct UniquePtr<T> {
|
pub struct UniquePtr {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
pub type UniquePtr_Pointer<T> = detail_PointerType<T>;
|
|
||||||
impl <T> Default for UniquePtr<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
|
pub type UniquePtr_Pointer = detail_PointerType;
|
||||||
|
@ -31,7 +31,7 @@ impl <T> ::std::fmt::Debug for __BindgenUnionField<T> {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy)]
|
#[derive(Debug, Copy)]
|
||||||
pub struct nsFoo {
|
pub struct nsFoo {
|
||||||
pub mBar: mozilla_StyleShapeSource<::std::os::raw::c_int>,
|
pub mBar: mozilla_StyleShapeSource,
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn bindgen_test_layout_nsFoo() {
|
fn bindgen_test_layout_nsFoo() {
|
||||||
@ -89,21 +89,16 @@ impl Clone for mozilla_Position {
|
|||||||
fn clone(&self) -> Self { *self }
|
fn clone(&self) -> Self { *self }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct mozilla_StyleShapeSource<ReferenceBox> {
|
pub struct mozilla_StyleShapeSource {
|
||||||
pub __bindgen_anon_1: mozilla_StyleShapeSource__bindgen_ty_1<ReferenceBox>,
|
pub __bindgen_anon_1: mozilla_StyleShapeSource__bindgen_ty_1,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<ReferenceBox>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct mozilla_StyleShapeSource__bindgen_ty_1<ReferenceBox> {
|
pub struct mozilla_StyleShapeSource__bindgen_ty_1 {
|
||||||
pub mPosition: __BindgenUnionField<*mut mozilla_Position>,
|
pub mPosition: __BindgenUnionField<*mut mozilla_Position>,
|
||||||
pub mFragmentOrURL: __BindgenUnionField<*mut mozilla_FragmentOrURL>,
|
pub mFragmentOrURL: __BindgenUnionField<*mut mozilla_FragmentOrURL>,
|
||||||
pub bindgen_union_field: u64,
|
pub bindgen_union_field: u64,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<ReferenceBox>,
|
|
||||||
}
|
|
||||||
impl <ReferenceBox> Default for mozilla_StyleShapeSource<ReferenceBox> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy)]
|
#[derive(Debug, Copy)]
|
||||||
|
@ -29,37 +29,30 @@ impl <T> ::std::fmt::Debug for __BindgenUnionField<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct NastyStruct<T> {
|
pub struct NastyStruct {
|
||||||
pub mIsSome: bool,
|
pub mIsSome: bool,
|
||||||
pub mStorage: NastyStruct__bindgen_ty_1<T>,
|
pub mStorage: NastyStruct__bindgen_ty_1,
|
||||||
pub __bindgen_anon_1: NastyStruct__bindgen_ty_2<T>,
|
pub __bindgen_anon_1: NastyStruct__bindgen_ty_2,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct NastyStruct__bindgen_ty_1<T> {
|
pub struct NastyStruct__bindgen_ty_1 {
|
||||||
pub mFoo: __BindgenUnionField<*mut ::std::os::raw::c_void>,
|
pub mFoo: __BindgenUnionField<*mut ::std::os::raw::c_void>,
|
||||||
pub mDummy: __BindgenUnionField<::std::os::raw::c_ulong>,
|
pub mDummy: __BindgenUnionField<::std::os::raw::c_ulong>,
|
||||||
pub bindgen_union_field: u64,
|
pub bindgen_union_field: u64,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct NastyStruct__bindgen_ty_2<T> {
|
pub struct NastyStruct__bindgen_ty_2 {
|
||||||
pub wat: __BindgenUnionField<::std::os::raw::c_short>,
|
pub wat: __BindgenUnionField<::std::os::raw::c_short>,
|
||||||
pub wut: __BindgenUnionField<*mut ::std::os::raw::c_int>,
|
pub wut: __BindgenUnionField<*mut ::std::os::raw::c_int>,
|
||||||
pub bindgen_union_field: u64,
|
pub bindgen_union_field: u64,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for NastyStruct<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Whatever<T> {
|
pub struct Whatever {
|
||||||
pub mTPtr: __BindgenUnionField<*mut ::std::os::raw::c_void>,
|
pub mTPtr: __BindgenUnionField<*mut ::std::os::raw::c_void>,
|
||||||
pub mInt: __BindgenUnionField<::std::os::raw::c_int>,
|
pub mInt: __BindgenUnionField<::std::os::raw::c_int>,
|
||||||
pub bindgen_union_field: u64,
|
pub bindgen_union_field: u64,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct VariadicFunctionObject<T> {
|
pub struct VariadicFunctionObject {
|
||||||
pub _address: u8,
|
pub _address: u8,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
|
||||||
impl <T> Default for VariadicFunctionObject<T> {
|
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,11 @@ impl Clone for UnknownUnits {
|
|||||||
pub type Float = f32;
|
pub type Float = f32;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct PointTyped<units, F> {
|
pub struct PointTyped<F> {
|
||||||
pub x: F,
|
pub x: F,
|
||||||
pub y: F,
|
pub y: F,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<units>,
|
|
||||||
}
|
}
|
||||||
impl <units, F> Default for PointTyped<units, F> {
|
impl <F> Default for PointTyped<F> {
|
||||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||||
}
|
}
|
||||||
pub type IntPoint = PointTyped<UnknownUnits, f32>;
|
pub type IntPoint = PointTyped<f32>;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
pub struct WhitelistMe<T> {
|
pub struct WhitelistMe<T> {
|
||||||
pub foo: ::std::os::raw::c_int,
|
pub foo: ::std::os::raw::c_int,
|
||||||
pub bar: WhitelistMe_Inner<T>,
|
pub bar: WhitelistMe_Inner<T>,
|
||||||
pub _phantom_0: ::std::marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
8
tests/headers/issue-544-stylo-creduce-2.hpp
Normal file
8
tests/headers/issue-544-stylo-creduce-2.hpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Foo {
|
||||||
|
template <typename> using FirstAlias = typename T::Associated;
|
||||||
|
template <typename U> using SecondAlias = Foo<FirstAlias<U>>;
|
||||||
|
SecondAlias<int> member;
|
||||||
|
};
|
5
tests/headers/issue-544-stylo-creduce.hpp
Normal file
5
tests/headers/issue-544-stylo-creduce.hpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename> class a;
|
||||||
|
template <typename b, typename... c> class a<b(c...)> { a(const a &); };
|
||||||
|
template <typename b, typename... c> a<b(c...)>::a(const a &) {}
|
40
tests/headers/partial-specialization-and-inheritance.hpp
Normal file
40
tests/headers/partial-specialization-and-inheritance.hpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// bindgen-unstable
|
||||||
|
|
||||||
|
// This was originally a test case generated by creducing errors in SpiderMonkey
|
||||||
|
// bindings generation. I've tried to make it understandable by giving more
|
||||||
|
// meaningful names to everything, and a couple comments.
|
||||||
|
//
|
||||||
|
// We don't support partial template specialization, but we *should*
|
||||||
|
// successfully parse this header, and generate bindings for it, but the usage
|
||||||
|
// of the partial template specialization should result in opaque blobs.
|
||||||
|
|
||||||
|
// A base class providing a method.
|
||||||
|
template <typename T>
|
||||||
|
class Base {
|
||||||
|
public:
|
||||||
|
void some_method(T, T);
|
||||||
|
};
|
||||||
|
|
||||||
|
// A template with a default representation.
|
||||||
|
template <typename U>
|
||||||
|
class Derived {
|
||||||
|
bool b;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A partial specialization for pointers. Note that this should have a different
|
||||||
|
// and larger layout than the template it is specializing.
|
||||||
|
template <typename U>
|
||||||
|
class Derived<U*> : public Base<U*> {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A struct that uses the partial specialization and method from the partial
|
||||||
|
// specialization's base class.
|
||||||
|
struct Usage {
|
||||||
|
Usage() {
|
||||||
|
static_member.some_method(this, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Derived<Usage*> static_member;
|
||||||
|
};
|
6
tests/headers/template-param-usage-0.hpp
Normal file
6
tests/headers/template-param-usage-0.hpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class UsesTemplateParameter {
|
||||||
|
T t;
|
||||||
|
};
|
6
tests/headers/template-param-usage-1.hpp
Normal file
6
tests/headers/template-param-usage-1.hpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class DoesNotUseTemplateParameter {
|
||||||
|
int x;
|
||||||
|
};
|
14
tests/headers/template-param-usage-10.hpp
Normal file
14
tests/headers/template-param-usage-10.hpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T, typename U, typename NeverUsed>
|
||||||
|
class DoublyIndirectUsage {
|
||||||
|
using Aliased = T;
|
||||||
|
typedef U Typedefed;
|
||||||
|
|
||||||
|
class IndirectUsage {
|
||||||
|
Aliased member;
|
||||||
|
Typedefed another;
|
||||||
|
};
|
||||||
|
|
||||||
|
IndirectUsage doubly_indirect;
|
||||||
|
};
|
6
tests/headers/template-param-usage-11.hpp
Normal file
6
tests/headers/template-param-usage-11.hpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class DoesNotUseT {
|
||||||
|
static T but_static_member_does;
|
||||||
|
};
|
11
tests/headers/template-param-usage-12.hpp
Normal file
11
tests/headers/template-param-usage-12.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class BaseUsesT {
|
||||||
|
T* t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
class CrtpUsesU : public BaseUsesT<CrtpUsesU<U>> {
|
||||||
|
U usage;
|
||||||
|
};
|
11
tests/headers/template-param-usage-13.hpp
Normal file
11
tests/headers/template-param-usage-13.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class BaseIgnoresT {
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
class CrtpUsesU : public BaseIgnoresT<CrtpUsesU<U>> {
|
||||||
|
U usage;
|
||||||
|
};
|
11
tests/headers/template-param-usage-14.hpp
Normal file
11
tests/headers/template-param-usage-14.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class BaseIgnoresT {
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
class CrtpIgnoresU : public BaseIgnoresT<CrtpIgnoresU<U>> {
|
||||||
|
int y;
|
||||||
|
};
|
11
tests/headers/template-param-usage-15.hpp
Normal file
11
tests/headers/template-param-usage-15.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class BaseUsesT {
|
||||||
|
T* usage;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
class CrtpIgnoresU : public BaseUsesT<CrtpIgnoresU<U>> {
|
||||||
|
int y;
|
||||||
|
};
|
10
tests/headers/template-param-usage-2.hpp
Normal file
10
tests/headers/template-param-usage-2.hpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class UsesTemplateParameter {
|
||||||
|
T t;
|
||||||
|
|
||||||
|
class AlsoUsesTemplateParameter {
|
||||||
|
T also;
|
||||||
|
};
|
||||||
|
};
|
12
tests/headers/template-param-usage-3.hpp
Normal file
12
tests/headers/template-param-usage-3.hpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class UsesTemplateParameter {
|
||||||
|
T t;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
class AlsoUsesTemplateParameterAndMore {
|
||||||
|
T also;
|
||||||
|
U more;
|
||||||
|
};
|
||||||
|
};
|
11
tests/headers/template-param-usage-4.hpp
Normal file
11
tests/headers/template-param-usage-4.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class UsesTemplateParameter {
|
||||||
|
T t;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
class DoesNotUseTemplateParameters {
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
};
|
8
tests/headers/template-param-usage-5.hpp
Normal file
8
tests/headers/template-param-usage-5.hpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class IndirectlyUsesTemplateParameter {
|
||||||
|
using Aliased = T;
|
||||||
|
|
||||||
|
Aliased aliased;
|
||||||
|
};
|
8
tests/headers/template-param-usage-6.hpp
Normal file
8
tests/headers/template-param-usage-6.hpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class DoesNotUseTemplateParameter {
|
||||||
|
using ButAliasDoesUseIt = T;
|
||||||
|
|
||||||
|
int x;
|
||||||
|
};
|
10
tests/headers/template-param-usage-7.hpp
Normal file
10
tests/headers/template-param-usage-7.hpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T, typename U, typename V>
|
||||||
|
class DoesNotUseU {
|
||||||
|
T t;
|
||||||
|
V v;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The bool should go away becuase U is not used.
|
||||||
|
using Alias = DoesNotUseU<int, bool, char>;
|
10
tests/headers/template-param-usage-8.hpp
Normal file
10
tests/headers/template-param-usage-8.hpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
class IndirectUsage {
|
||||||
|
typedef T Typedefed;
|
||||||
|
using Aliased = U;
|
||||||
|
|
||||||
|
Typedefed member1;
|
||||||
|
Aliased member2;
|
||||||
|
};
|
12
tests/headers/template-param-usage-9.hpp
Normal file
12
tests/headers/template-param-usage-9.hpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// bindgen-flags: -- -std=c++14
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
class DoesNotUse {
|
||||||
|
using Aliased = T;
|
||||||
|
typedef U Typedefed;
|
||||||
|
|
||||||
|
class IndirectUsage {
|
||||||
|
Aliased member;
|
||||||
|
Typedefed another;
|
||||||
|
};
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user