summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml24
-rw-r--r--build.rs7
-rwxr-xr-xsrc/bin/bindgen.rs83
-rw-r--r--src/clang.rs179
-rw-r--r--src/clangll.rs6
-rw-r--r--src/codegen/helpers.rs113
-rw-r--r--src/codegen/mod.rs1904
-rw-r--r--src/gen.rs2364
-rw-r--r--src/hacks/mod.rs1
-rw-r--r--src/hacks/refcell.rs464
-rw-r--r--src/ir/annotations.rs141
-rw-r--r--src/ir/comp.rs718
-rw-r--r--src/ir/context.rs685
-rw-r--r--src/ir/enum_ty.rs110
-rw-r--r--src/ir/function.rs220
-rw-r--r--src/ir/int.rs30
-rw-r--r--src/ir/item.rs681
-rw-r--r--src/ir/item_kind.rs89
-rw-r--r--src/ir/layout.rs26
-rw-r--r--src/ir/mod.rs12
-rw-r--r--src/ir/module.rs52
-rw-r--r--src/ir/ty.rs537
-rw-r--r--src/ir/var.rs160
-rwxr-xr-xsrc/lib.rs224
-rw-r--r--src/parse.rs48
-rw-r--r--src/parser.rs1516
-rw-r--r--src/regex_set.rs58
-rw-r--r--src/types.rs882
-rw-r--r--tests/expectations/accessors.rs136
-rw-r--r--tests/expectations/annotation_hide.rs22
-rw-r--r--tests/expectations/anon_enum.rs23
-rw-r--r--tests/expectations/anon_enum_whitelist.rs13
-rw-r--r--tests/expectations/anon_union.rs73
-rw-r--r--tests/expectations/arg_keyword.rs10
-rw-r--r--tests/expectations/class.rs63
-rw-r--r--tests/expectations/class_nested.rs49
-rw-r--r--tests/expectations/class_no_members.rs39
-rw-r--r--tests/expectations/class_static.rs24
-rw-r--r--tests/expectations/class_use_as.rs30
-rw-r--r--tests/expectations/class_with_dtor.rs12
-rw-r--r--tests/expectations/class_with_inner_struct.rs205
-rw-r--r--tests/expectations/class_with_typedef.rs56
-rw-r--r--tests/expectations/const_ptr.rs9
-rw-r--r--tests/expectations/const_resolved_ty.rs9
-rw-r--r--tests/expectations/const_tparam.rs11
-rw-r--r--tests/expectations/crtp.rs24
-rw-r--r--tests/expectations/decl_ptr_to_array.rs3
-rw-r--r--tests/expectations/duplicated_constants_in_ns.rs12
-rw-r--r--tests/expectations/empty_template_param_name.rs12
-rw-r--r--tests/expectations/enum.rs8
-rw-r--r--tests/expectations/enum_alias.rs9
-rw-r--r--tests/expectations/enum_and_vtable_mangling.rs29
-rw-r--r--tests/expectations/enum_dupe.rs6
-rw-r--r--tests/expectations/enum_explicit_type.rs20
-rw-r--r--tests/expectations/enum_negative.rs4
-rw-r--r--tests/expectations/enum_packed.rs12
-rw-r--r--tests/expectations/extern.rs3
-rw-r--r--tests/expectations/forward_declared_struct.rs28
-rw-r--r--tests/expectations/func_proto.rs3
-rw-r--r--tests/expectations/func_ptr.rs8
-rw-r--r--tests/expectations/func_ptr_in_struct.rs25
-rw-r--r--tests/expectations/func_with_func_ptr_arg.rs2
-rw-r--r--tests/expectations/in_class_typedef.rs21
-rw-r--r--tests/expectations/inherit_named.rs17
-rw-r--r--tests/expectations/inherit_typedef.rs33
-rw-r--r--tests/expectations/inner_const.rs27
-rw-r--r--tests/expectations/inner_template_self.rs22
-rw-r--r--tests/expectations/jsval_layout_opaque.rs163
-rw-r--r--tests/expectations/keywords.rs108
-rw-r--r--tests/expectations/moar_bitfields.rs48
-rw-r--r--tests/expectations/mutable.rs34
-rw-r--r--tests/expectations/namespace.rs71
-rw-r--r--tests/expectations/nested.rs51
-rw-r--r--tests/expectations/nested_vtable.rs48
-rw-r--r--tests/expectations/no_copy.rs4
-rw-r--r--tests/expectations/nsStyleAutoArray.rs8
-rw-r--r--tests/expectations/only_bitfields.rs44
-rw-r--r--tests/expectations/opaque_in_struct.rs17
-rw-r--r--tests/expectations/opaque_pointer.rs29
-rw-r--r--tests/expectations/opaque_typedef.rs13
-rw-r--r--tests/expectations/overflowed_enum.rs8
-rw-r--r--tests/expectations/private.rs46
-rw-r--r--tests/expectations/redeclaration.rs9
-rw-r--r--tests/expectations/ref_argument_array.rs24
-rw-r--r--tests/expectations/size_t_template.rs13
-rw-r--r--tests/expectations/struct_containing_forward_declared_struct.rs30
-rw-r--r--tests/expectations/struct_with_anon_struct.rs30
-rw-r--r--tests/expectations/struct_with_anon_struct_array.rs52
-rw-r--r--tests/expectations/struct_with_anon_struct_pointer.rs31
-rw-r--r--tests/expectations/struct_with_anon_union.rs43
-rw-r--r--tests/expectations/struct_with_anon_unnamed_struct.rs31
-rw-r--r--tests/expectations/struct_with_anon_unnamed_union.rs44
-rw-r--r--tests/expectations/struct_with_bitfields.rs150
-rw-r--r--tests/expectations/struct_with_derive_debug.rs56
-rw-r--r--tests/expectations/struct_with_nesting.rs91
-rw-r--r--tests/expectations/struct_with_packing.rs14
-rw-r--r--tests/expectations/struct_with_struct.rs30
-rw-r--r--tests/expectations/template.rs144
-rw-r--r--tests/expectations/typeref.rs92
-rw-r--r--tests/expectations/union_dtor.rs23
-rw-r--r--tests/expectations/union_fields.rs35
-rw-r--r--tests/expectations/union_template.rs58
-rw-r--r--tests/expectations/union_with_anon_struct.rs46
-rw-r--r--tests/expectations/union_with_anon_struct_bitfield.rs89
-rw-r--r--tests/expectations/union_with_anon_union.rs56
-rw-r--r--tests/expectations/union_with_anon_unnamed_struct.rs51
-rw-r--r--tests/expectations/union_with_anon_unnamed_union.rs61
-rw-r--r--tests/expectations/union_with_big_member.rs53
-rw-r--r--tests/expectations/union_with_nesting.rs106
-rw-r--r--tests/expectations/unknown_attr.rs16
-rw-r--r--tests/expectations/using.rs6
-rw-r--r--tests/expectations/variadic_template_args.rs21
-rw-r--r--tests/expectations/virtual_dtor.rs19
-rw-r--r--tests/expectations/virtual_overloaded.rs24
-rw-r--r--tests/expectations/vtable_recursive_sig.rs33
-rw-r--r--tests/expectations/weird_bitfields.rs130
-rw-r--r--tests/expectations/what_is_going_on.rs29
-rw-r--r--tests/expectations/whitelist_basic.rs18
-rw-r--r--tests/headers/anon_enum.hpp5
-rw-r--r--tests/headers/anon_enum_whitelist.h6
-rw-r--r--tests/headers/anon_union.hpp20
-rw-r--r--tests/headers/arg_keyword.hpp1
-rw-r--r--tests/headers/const_ptr.hpp3
-rw-r--r--tests/headers/const_resolved_ty.h3
-rw-r--r--tests/headers/const_tparam.hpp4
-rw-r--r--tests/headers/duplicated_constants_in_ns.hpp2
-rw-r--r--tests/headers/empty_template_param_name.hpp4
-rw-r--r--tests/headers/enum_alias.hpp7
-rw-r--r--tests/headers/in_class_typedef.hpp10
-rw-r--r--tests/headers/inherit_named.hpp5
-rw-r--r--tests/headers/inherit_typedef.hpp5
-rw-r--r--tests/headers/inner_const.hpp6
-rw-r--r--tests/headers/jsval_layout_opaque.hpp15
-rw-r--r--tests/headers/nested_vtable.hpp8
-rw-r--r--tests/headers/opaque_typedef.hpp2
-rw-r--r--tests/headers/private.hpp2
-rw-r--r--tests/headers/redeclaration.hpp7
-rw-r--r--tests/headers/typeref.hpp28
-rw-r--r--tests/headers/unknown_attr.h6
-rw-r--r--tests/headers/virtual_dtor.hpp3
-rw-r--r--tests/headers/what_is_going_on.hpp19
-rw-r--r--tests/headers/whitelist_basic.hpp15
142 files changed, 8115 insertions, 6967 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 04a13eb4..fdc102c8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,14 +1,18 @@
[package]
-authors = ["Jyun-Yan You <jyyou.tw@gmail.com>"]
+authors = [
+ "Jyun-Yan You <jyyou.tw@gmail.com>",
+ "Emilio Cobos Álvarez <ecoal95@gmail.com>",
+ "The Servo project developers",
+]
build = "build.rs"
description = "A binding generator for Rust"
-homepage = "https://github.com/crabtw/rust-bindgen"
+homepage = "https://github.com/servo/rust-bindgen"
keywords = ["bindings", "ffi", "code-generation"]
license = "BSD-3-Clause"
name = "bindgen"
readme = "README.md"
-repository = "https://github.com/crabtw/rust-bindgen"
-version = "0.16.0"
+repository = "https://github.com/servo/rust-bindgen"
+version = "0.17.0"
[[bin]]
doc = false
@@ -20,14 +24,16 @@ quasi_codegen = "0.15"
[dependencies]
clang-sys = "0.8.0"
docopt = "0.6.82"
-libc = "0.2.*"
-log = "0.3.*"
+libc = "0.2"
+log = "0.3"
+env_logger = "0.3"
rustc-serialize = "0.3.19"
-syntex_syntax = "0.38"
+syntex_syntax = "0.43"
+regex = "0.1"
[dependencies.aster]
features = ["with-syntex"]
-version = "0.21.1"
+version = "0.26"
[dependencies.clippy]
optional = true
@@ -35,7 +41,7 @@ version = "*"
[dependencies.quasi]
features = ["with-syntex"]
-version = "0.15"
+version = "0.19"
[features]
llvm_stable = []
diff --git a/build.rs b/build.rs
index 624be282..b9cf3e60 100644
--- a/build.rs
+++ b/build.rs
@@ -5,11 +5,12 @@ mod codegen {
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
- let src = Path::new("src/gen.rs");
- let dst = Path::new(&out_dir).join("gen.rs");
+ let src = Path::new("src/codegen/mod.rs");
+ let dst = Path::new(&out_dir).join("codegen.rs");
quasi_codegen::expand(&src, &dst).unwrap();
- println!("cargo:rerun-if-changed=src/gen.rs");
+ println!("cargo:rerun-if-changed=src/codegen/mod.rs");
+ println!("cargo:rerun-if-changed=src/codegen/helpers.rs");
}
}
diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs
index 8c515131..1e92ee6d 100755
--- a/src/bin/bindgen.rs
+++ b/src/bin/bindgen.rs
@@ -2,6 +2,7 @@
#![crate_type = "bin"]
extern crate bindgen;
+extern crate env_logger;
#[macro_use]
extern crate docopt;
#[macro_use]
@@ -9,25 +10,12 @@ extern crate log;
extern crate clang_sys;
extern crate rustc_serialize;
-use bindgen::{Bindings, BindgenOptions, LinkType, Logger};
+use bindgen::{Bindings, BindgenOptions, LinkType};
use std::io;
use std::path;
use std::env;
use std::default::Default;
use std::fs;
-use std::process::exit;
-
-struct StdLogger;
-
-impl Logger for StdLogger {
- fn error(&self, msg: &str) {
- println!("{}", msg);
- }
-
- fn warn(&self, msg: &str) {
- println!("{}", msg);
- }
-}
const USAGE: &'static str = "
Usage:
@@ -40,6 +28,9 @@ Usage:
[--dtor-attr=<attr>...] \
[--opaque-type=<type>...] \
[--blacklist-type=<type>...] \
+ [--whitelist-type=<type>...] \
+ [--whitelist-function=<name>...] \
+ [--whitelist-var=<name>...] \
<input-header> \
[-- <clang-args>...]
@@ -95,15 +86,25 @@ Options:
ulonglong
slonglong
- --raw-line=<raw> TODO
- --dtor-attr=<attr> TODO
- --no-class-constants TODO
- --no-unstable-rust TODO
- --no-namespaced-constants TODO
- --no-bitfield-methods TODO
- --ignore-methods TODO
- --opaque-type=<type> TODO
- --blacklist-type=<type> TODO
+ --raw-line=<raw> Add a raw line at the beginning of the output.
+ --dtor-attr=<attr> Attributes to add to structures with destructor.
+ --no-class-constants Avoid generating class constants.
+ --no-unstable-rust Avoid generating unstable rust.
+ --no-namespaced-constants Avoid generating constants right under namespaces.
+ --no-bitfield-methods Avoid generating methods for bitfield access.
+ --ignore-methods Avoid generating all kind of methods.
+ --opaque-type=<type> Mark a type as opaque.
+ --blacklist-type=<type> Mark a type as hidden.
+ --whitelist-type=<type> Whitelist the type. If this set or any other
+ of the whitelisting sets is not empty, then
+ all the non-whitelisted types (or dependant)
+ won't be generated.
+ --whitelist-function=<regex> Whitelist all the free-standing functions
+ matching <regex>. Same behavior on emptyness
+ than the type whitelisting.
+ --whitelist-var=<regex> Whitelist all the free-standing variables
+ matching <regex>. Same behavior on emptyness
+ than the type whitelisting.
<clang-args> Options other than stated above are passed
directly through to clang.
@@ -134,6 +135,9 @@ struct Args {
flag_ignore_methods: bool,
flag_opaque_type: Vec<String>,
flag_blacklist_type: Vec<String>,
+ flag_whitelist_type: Vec<String>,
+ flag_whitelist_function: Vec<String>,
+ flag_whitelist_var: Vec<String>,
arg_clang_args: Vec<String>,
}
@@ -182,7 +186,10 @@ impl Into<ParseResult<(BindgenOptions, Box<io::Write>)>> for Args {
options.gen_bitfield_methods = !self.flag_no_bitfield_methods;
options.ignore_methods = self.flag_ignore_methods;
options.opaque_types.extend(self.flag_opaque_type.drain(..));
- options.blacklist_type.extend(self.flag_blacklist_type.drain(..));
+ options.hidden_types.extend(self.flag_blacklist_type.drain(..));
+ options.whitelisted_types.extend(self.flag_whitelist_type.drain(..));
+ options.whitelisted_functions.extend(self.flag_whitelist_function.drain(..));
+ options.whitelisted_vars.extend(self.flag_whitelist_var.drain(..));
options.clang_args.extend(self.arg_clang_args.drain(..));
options.clang_args.push(self.arg_input_header);
@@ -191,6 +198,13 @@ impl Into<ParseResult<(BindgenOptions, Box<io::Write>)>> for Args {
}
pub fn main() {
+ log::set_logger(|max_log_level| {
+ use env_logger::Logger;
+ let env_logger = Logger::new();
+ max_log_level.set(env_logger.filter());
+ Box::new(env_logger)
+ }).expect("Failed to set logger.");
+
let mut bind_args: Vec<_> = env::args().collect();
if let Some(clang) = clang_sys::support::Clang::find(None) {
@@ -217,24 +231,13 @@ pub fn main() {
.and_then(|d| d.argv(bind_args.iter()).decode())
.unwrap_or_else(|e| e.exit());
- let logger = StdLogger;
let result: ParseResult<_> = args.into();
let (options, out) = result.unwrap_or_else(|msg| {
- logger.error(&msg);
- exit(-1);
+ panic!("Failed to generate_bindings: {:?}", msg);
});
- match Bindings::generate(&options, Some(&logger as &Logger), None) {
- Ok(bindings) => match bindings.write(out) {
- Ok(()) => (),
- Err(e) => {
- logger.error(&format!("Unable to write bindings to file. {}", e));
- exit(-1);
- }
- },
- Err(()) => {
- logger.error("Failed to generate bindings".into());
- exit(-1);
- }
- }
+ let bindings = Bindings::generate(options, None)
+ .expect("Unable to generate bindings");
+ bindings.write(out)
+ .expect("Unable to write bindings to file.");
}
diff --git a/src/clang.rs b/src/clang.rs
index f8a68e12..5618007b 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -15,9 +15,24 @@ pub struct Cursor {
x: CXCursor
}
+impl fmt::Debug for Cursor {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "Cursor({} kind: {}, loc: {})",
+ self.spelling(), kind_to_str(self.kind()), self.location())
+ }
+}
+
pub type CursorVisitor<'s> = for<'a, 'b> FnMut(&'a Cursor, &'b Cursor) -> Enum_CXChildVisitResult + 's;
impl Cursor {
+ pub fn is_declaration(&self) -> bool {
+ unsafe { clang_isDeclaration(self.kind()) != 0 }
+ }
+
+ pub fn null() -> Self {
+ Cursor { x: unsafe { clang_getNullCursor() } }
+ }
+
// common
pub fn spelling(&self) -> String {
unsafe {
@@ -43,18 +58,71 @@ impl Cursor {
}
}
+ pub fn fallible_semantic_parent(&self) -> Option<Cursor> {
+ let sp = self.semantic_parent();
+ if sp == *self || !sp.is_valid() {
+ return None;
+ }
+ Some(sp)
+ }
+
pub fn semantic_parent(&self) -> Cursor {
unsafe {
Cursor { x: clang_getCursorSemanticParent(self.x) }
}
}
+ pub fn num_template_args(&self) -> c_int {
+ unsafe {
+ clang_Cursor_getNumTemplateArguments(self.x)
+ }
+ }
+
+
+ /// This function gets the translation unit cursor. Note that we shouldn't
+ /// create a TranslationUnit struct here, because bindgen assumes there will
+ /// only be one of them alive at a time, and dispose it on drop. That can
+ /// change if this would be required, but I think we can survive fine
+ /// without it.
+ pub fn translation_unit(&self) -> Cursor {
+ assert!(self.is_valid());
+ unsafe {
+ let tu = clang_Cursor_getTranslationUnit(self.x);
+ let cursor = Cursor {
+ x: clang_getTranslationUnitCursor(tu),
+ };
+ assert!(cursor.is_valid());
+ cursor
+ }
+ }
+
+ pub fn is_toplevel(&self) -> bool {
+ let mut semantic_parent = self.semantic_parent();
+
+ while semantic_parent.kind() == CXCursor_Namespace ||
+ semantic_parent.kind() == CXCursor_NamespaceAlias ||
+ semantic_parent.kind() == CXCursor_NamespaceRef
+ {
+ semantic_parent = semantic_parent.semantic_parent();
+ }
+
+ let tu = self.translation_unit();
+ // Yes, the second can happen with, e.g., macro definitions.
+ semantic_parent == tu || semantic_parent == tu.semantic_parent()
+ }
+
pub fn kind(&self) -> Enum_CXCursorKind {
unsafe {
clang_getCursorKind(self.x)
}
}
+ pub fn is_anonymous(&self) -> bool {
+ unsafe {
+ clang_Cursor_isAnonymous(self.x) != 0
+ }
+ }
+
pub fn is_template(&self) -> bool {
self.specialized().is_valid()
}
@@ -77,10 +145,11 @@ impl Cursor {
}
}
- pub fn raw_comment(&self) -> String {
- unsafe {
+ pub fn raw_comment(&self) -> Option<String> {
+ let s = unsafe {
String_ { x: clang_Cursor_getRawCommentText(self.x) }.to_string()
- }
+ };
+ if s.is_empty() { None } else { Some(s) }
}
pub fn comment(&self) -> Comment {
@@ -165,12 +234,18 @@ impl Cursor {
}
}
- pub fn enum_val(&self) -> i64 {
+ pub fn enum_val_signed(&self) -> i64 {
unsafe {
clang_getEnumConstantDeclValue(self.x) as i64
}
}
+ pub fn enum_val_unsigned(&self) -> u64 {
+ unsafe {
+ clang_getEnumConstantDeclUnsignedValue(self.x) as u64
+ }
+ }
+
// typedef
pub fn typedef_type(&self) -> Type {
unsafe {
@@ -195,7 +270,7 @@ impl Cursor {
pub fn args(&self) -> Vec<Cursor> {
unsafe {
let num = self.num_args() as usize;
- let mut args = vec!();
+ let mut args = vec![];
for i in 0..num {
args.push(Cursor { x: clang_Cursor_getArgument(self.x, i as c_uint) });
}
@@ -235,6 +310,12 @@ impl Cursor {
}
}
+ pub fn method_is_const(&self) -> bool {
+ unsafe {
+ clang_CXXMethod_isConst(self.x) != 0
+ }
+ }
+
pub fn method_is_virtual(&self) -> bool {
unsafe {
clang_CXXMethod_isVirtual(self.x) != 0
@@ -274,29 +355,40 @@ impl PartialEq for Cursor {
clang_equalCursors(self.x, other.x) == 1
}
}
-
- fn ne(&self, other: &Cursor) -> bool {
- !self.eq(other)
- }
}
impl Eq for Cursor {}
impl Hash for Cursor {
fn hash<H: Hasher>(&self, state: &mut H) {
- self.x.kind.hash(state);
- self.x.xdata.hash(state);
- self.x.data[0].hash(state);
- self.x.data[1].hash(state);
- self.x.data[2].hash(state);
+ unsafe { clang_hashCursor(self.x) }.hash(state)
}
}
// type
+#[derive(Clone, Hash)]
pub struct Type {
x: CXType
}
+impl PartialEq for Type {
+ fn eq(&self, other: &Self) -> bool {
+ unsafe {
+ clang_equalTypes(self.x, other.x) != 0
+ }
+ }
+}
+
+impl Eq for Type {}
+
+impl fmt::Debug for Type {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "Type({}, kind: {}, decl: {:?}, canon: {:?})",
+ self.spelling(), type_to_str(self.kind()), self.declaration(),
+ self.declaration().canonical())
+ }
+}
+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum LayoutError {
Invalid,
@@ -358,7 +450,7 @@ impl Type {
pub fn is_const(&self) -> bool {
unsafe {
- clang_isConstQualifiedType(self.x) == 1
+ clang_isConstQualifiedType(self.x) != 0
}
}
@@ -378,6 +470,24 @@ impl Type {
}
}
+ pub fn fallible_align(&self) -> Result<usize, LayoutError> {
+ unsafe {
+ let val = clang_Type_getAlignOf(self.x);
+ if val < 0 {
+ Err(LayoutError::from(val as i32))
+ } else {
+ Ok(val as usize)
+ }
+ }
+ }
+
+ pub fn fallible_layout(&self) -> Result<::ir::layout::Layout, LayoutError> {
+ use ir::layout::Layout;
+ let size = try!(self.fallible_size());
+ let align = try!(self.fallible_align());
+ Ok(Layout::new(size, align))
+ }
+
pub fn align(&self) -> usize {
unsafe {
let val = clang_Type_getAlignOf(self.x);
@@ -427,7 +537,7 @@ impl Type {
// function
pub fn is_variadic(&self) -> bool {
unsafe {
- clang_isFunctionTypeVariadic(self.x) == 1
+ clang_isFunctionTypeVariadic(self.x) != 0
}
}
@@ -581,21 +691,25 @@ pub struct Index {
}
impl Index {
- pub fn create(pch: bool, diag: bool) -> Index {
+ pub fn new(pch: bool, diag: bool) -> Index {
unsafe {
Index { x: clang_createIndex(pch as c_int, diag as c_int) }
}
}
+}
- pub fn dispose(&self) {
+impl fmt::Debug for Index {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "Index {{ }}")
+ }
+}
+
+impl Drop for Index {
+ fn drop(&mut self) {
unsafe {
clang_disposeIndex(self.x);
}
}
-
- pub fn is_null(&self) -> bool {
- self.x.is_null()
- }
}
// Token
@@ -609,6 +723,12 @@ pub struct TranslationUnit {
x: CXTranslationUnit
}
+impl fmt::Debug for TranslationUnit {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "TranslationUnit {{ }}")
+ }
+}
+
impl TranslationUnit {
pub fn parse(ix: &Index, file: &str, cmd_args: &[String],
unsaved: &[UnsavedFile], opts: ::libc::c_uint) -> TranslationUnit {
@@ -655,12 +775,6 @@ impl TranslationUnit {
}
}
- pub fn dispose(&self) {
- unsafe {
- clang_disposeTranslationUnit(self.x);
- }
- }
-
pub fn is_null(&self) -> bool {
self.x.is_null()
}
@@ -687,6 +801,15 @@ impl TranslationUnit {
}
}
+impl Drop for TranslationUnit {
+ fn drop(&mut self) {
+ unsafe {
+ clang_disposeTranslationUnit(self.x);
+ }
+ }
+}
+
+
// Diagnostic
pub struct Diagnostic {
x: CXDiagnostic
diff --git a/src/clangll.rs b/src/clangll.rs
index b94356bc..47f41ff1 100644
--- a/src/clangll.rs
+++ b/src/clangll.rs
@@ -428,7 +428,7 @@ pub const CXCallingConv_X86_64SysV: c_uint = 11;
pub const CXCallingConv_Invalid: c_uint = 100;
pub const CXCallingConv_Unexposed: c_uint = 200;
#[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Hash)]
pub struct CXType {
pub kind: Enum_CXTypeKind,
pub data: [*mut c_void; 2],
@@ -1076,6 +1076,7 @@ extern "C" {
pub fn clang_Cursor_getNumArguments(C: CXCursor) -> c_int;
pub fn clang_Cursor_getArgument(C: CXCursor, i: c_uint) ->
CXCursor;
+ pub fn clang_Cursor_getNumTemplateArguments(T: CXCursor) -> c_int;
pub fn clang_Cursor_getTemplateArgumentKind(C: CXCursor, i: c_uint) ->
CXTemplateArgumentKind;
pub fn clang_Cursor_getTemplateArgumentValue(C: CXCursor, i: c_uint) ->
@@ -1148,6 +1149,7 @@ extern "C" {
pieceIndex: c_uint,
options: c_uint) ->
CXSourceRange;
+ pub fn clang_Cursor_getOffsetOfField(C: CXCursor) -> c_longlong;
pub fn clang_getCursorDisplayName(arg1: CXCursor) -> CXString;
pub fn clang_getCursorReferenced(arg1: CXCursor) -> CXCursor;
pub fn clang_getCursorDefinition(arg1: CXCursor) -> CXCursor;
@@ -1168,6 +1170,7 @@ extern "C" {
pub fn clang_Cursor_getMangling(C: CXCursor) -> CXString;
pub fn clang_Cursor_getParsedComment(C: CXCursor) -> CXComment;
pub fn clang_Cursor_getModule(C: CXCursor) -> CXModule;
+ pub fn clang_Cursor_isAnonymous(C: CXCursor) -> c_uint;
pub fn clang_Module_getASTFile(Module: CXModule) -> CXFile;
pub fn clang_Module_getParent(Module: CXModule) -> CXModule;
pub fn clang_Module_getName(Module: CXModule) -> CXString;
@@ -1241,6 +1244,7 @@ extern "C" {
pub fn clang_FullComment_getAsHTML(Comment: CXComment) -> CXString;
pub fn clang_FullComment_getAsXML(Comment: CXComment) -> CXString;
pub fn clang_CXXMethod_isPureVirtual(C: CXCursor) -> c_uint;
+ pub fn clang_CXXMethod_isConst(C: CXCursor) -> c_uint;
pub fn clang_CXXMethod_isStatic(C: CXCursor) -> c_uint;
pub fn clang_CXXMethod_isVirtual(C: CXCursor) -> c_uint;
pub fn clang_CXXField_isMutable(C: CXCursor) -> c_uint;
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs
new file mode 100644
index 00000000..e2fc1120
--- /dev/null
+++ b/src/codegen/helpers.rs
@@ -0,0 +1,113 @@
+/// Helpers for code generation that don't need macro expansion.
+
+use aster;
+use ir::layout::Layout;
+use syntax::ast;
+use syntax::codemap::respan;
+use syntax::ptr::P;
+
+
+pub mod attributes {
+ use aster;
+ use syntax::ast;
+
+ pub fn repr(which: &str) -> ast::Attribute {
+ aster::AstBuilder::new().attr().list("repr").words(&[which]).build()
+ }
+
+ pub fn repr_list(which_ones: &[&str]) -> ast::Attribute {
+ aster::AstBuilder::new().attr().list("repr").words(which_ones).build()
+ }
+
+ pub fn derives(which_ones: &[&str]) -> ast::Attribute {
+ aster::AstBuilder::new().attr().list("derive").words(which_ones).build()
+ }
+
+ pub fn inline() -> ast::Attribute {
+ aster::AstBuilder::new().attr().word("inline")
+ }
+
+ pub fn doc(comment: &str) -> ast::Attribute {
+ aster::AstBuilder::new().attr().doc(comment)
+ }
+
+ pub fn link_name(name: &str) -> ast::Attribute {
+ aster::AstBuilder::new().attr().name_value("link_name").str(name)
+ }
+}
+
+/// Generates a proper type for a field or type with a given `Layout`, that is,
+/// a type with the correct size and alignment restrictions.
+pub struct BlobTyBuilder {
+ layout: Layout,
+}
+
+impl BlobTyBuilder {
+ pub fn new(layout: Layout) -> Self {
+ BlobTyBuilder {
+ layout: layout,
+ }
+ }
+
+ pub fn build(self) -> P<ast::Ty> {
+ use std::cmp;
+
+ let ty_name = match self.layout.align {
+ 8 => "u64",
+ 4 => "u32",
+ 2 => "u16",
+ 1 | _ => "u8",
+ };
+ let data_len = if ty_name == "u8" {
+ self.layout.size
+ } else {
+ self.layout.size / cmp::max(self.layout.align, 1)
+ };
+
+ let inner_ty = aster::AstBuilder::new().ty().path().id(ty_name).build();
+ if data_len == 1 {
+ inner_ty
+ } else {
+ ArrayTyBuilder::new().with_len(data_len).build(inner_ty)
+ }
+ }
+}
+
+pub struct ArrayTyBuilder {
+ len: usize,
+}
+
+impl ArrayTyBuilder {
+ pub fn new() -> Self {
+ ArrayTyBuilder {
+ len: 0,
+ }
+ }
+
+ pub fn with_len(mut self, len: usize) -> Self {
+ self.len = len;
+ self
+ }
+
+ pub fn build(self, ty: P<ast::Ty>) -> P<ast::Ty> {
+ use syntax::codemap::DUMMY_SP;
+ let size =
+ ast::LitKind::Int(self.len as u64,
+ ast::LitIntType::Unsigned(ast::UintTy::Us));
+ let size = ast::ExprKind::Lit(P(respan(DUMMY_SP, size)));
+ let array_kind = ast::TyKind::FixedLengthVec(ty,
+ P(ast::Expr {
+ id: ast::DUMMY_NODE_ID,
+ node: size,
+ span: DUMMY_SP,
+ attrs: ast::ThinVec::new(),
+ })
+ );
+
+ P(ast::Ty {
+ id: ast::DUMMY_NODE_ID,
+ node: array_kind,
+ span: DUMMY_SP,
+ })
+ }
+}
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
new file mode 100644
index 00000000..62cebf46
--- /dev/null
+++ b/src/codegen/mod.rs
@@ -0,0 +1,1904 @@
+mod helpers;
+
+use self::helpers::{attributes, ArrayTyBuilder, BlobTyBuilder};
+
+use ir::context::BindgenContext;
+use ir::item::{Item, ItemId, ItemCanonicalName, ItemCanonicalPath};
+use ir::ty::{Type, TypeKind};
+use ir::int::IntKind;
+use ir::module::Module;
+use ir::var::Var;
+use ir::enum_ty::Enum;
+use ir::function::{Function, FunctionSig};
+use ir::item_kind::ItemKind;
+use ir::comp::{CompKind, CompInfo, Field, Method};
+use ir::layout::Layout;
+use ir::annotations::FieldAccessorKind;
+
+use std::ops;
+use std::mem;
+use std::collections::BTreeSet;
+use std::collections::HashSet;
+use std::collections::hash_map::{HashMap, Entry};
+
+use syntax::abi::Abi;
+use syntax::ast;
+use syntax::codemap::{Span, respan};
+use syntax::ptr::P;
+use aster;
+
+fn root_import(ctx: &BindgenContext) -> P<ast::Item> {
+ assert!(ctx.options().enable_cxx_namespaces, "Somebody messed it up");
+ let root = ctx.root_module().canonical_name(ctx);
+ let root_ident = ctx.rust_ident(&root);
+ quote_item!(ctx.ext_cx(), use $root_ident;).unwrap()
+}
+
+struct CodegenResult {
+ items: Vec<P<ast::Item>>,
+ saw_union: bool,
+ items_seen: HashSet<ItemId>,
+ /// The set of generated function names, needed because in C/C++ is legal to
+ /// do something like:
+ ///
+ /// ```
+ /// extern "C" {
+ /// void foo();
+ /// }
+ ///
+ /// extern "C" {
+ /// void foo();
+ /// }
+ /// ```
+ ///
+ /// Being these two different declarations.
+ functions_seen: HashSet<String>,
+}
+
+impl CodegenResult {
+ fn new() -> Self {
+ CodegenResult {
+ items: vec![],
+ saw_union: false,
+ items_seen: Default::default(),
+ functions_seen: Default::default(),
+ }
+ }
+
+ fn saw_union(&mut self) {
+ self.saw_union = true;
+ }
+
+ fn seen(&self, item: ItemId) -> bool {
+ self.items_seen.contains(&item)
+ }
+
+ fn set_seen(&mut self, item: ItemId) {
+ self.items_seen.insert(item);
+ }
+
+ fn seen_function(&self, name: &str) -> bool {
+ self.functions_seen.contains(name)
+ }
+
+ fn saw_function(&mut self, name: &str) {
+ self.functions_seen.insert(name.into());
+ }
+
+ fn inner<F>(&mut self, cb: F) -> Vec<P<ast::Item>>
+ where F: FnOnce(&mut Self)
+ {
+ let mut new = Self::new();
+
+ cb(&mut new);
+
+ self.saw_union |= new.saw_union;
+
+ new.items
+ }
+}
+
+impl ops::Deref for CodegenResult {
+ type Target = Vec<P<ast::Item>>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.items
+ }
+}
+
+impl ops::DerefMut for CodegenResult {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.items
+ }
+}
+
+struct ForeignModBuilder {
+ inner: ast::ForeignMod,
+}
+
+impl ForeignModBuilder {
+ fn new(abi: Abi) -> Self {
+ ForeignModBuilder {
+ inner: ast::ForeignMod {
+ abi: abi,
+ items: vec![],
+ }
+ }
+ }
+
+ fn with_foreign_item(mut self, item: ast::ForeignItem) -> Self {
+ self.inner.items.push(item);
+ self
+ }
+
+ #[allow(dead_code)]
+ fn with_foreign_items<I>(mut self, items: I) -> Self
+ where I: IntoIterator<Item=ast::ForeignItem>
+ {
+ self.inner.items.extend(items.into_iter());
+ self
+ }
+
+ fn build(self, ctx: &BindgenContext) -> P<ast::Item> {
+ use syntax::codemap::DUMMY_SP;
+ P(ast::Item {
+ ident: ctx.rust_ident(""),
+ id: ast::DUMMY_NODE_ID,
+ node: ast::ItemKind::ForeignMod(self.inner),
+ vis: ast::Visibility::Public,
+ attrs: vec![],
+ span: DUMMY_SP,
+ })
+ }
+}
+
+/// A trait to convert a rust type into a pointer, optionally const, to the same
+/// type.
+///
+/// This is done due to aster's lack of pointer builder, I guess I should PR
+/// there.
+trait ToPtr {
+ fn to_ptr(self, is_const: bool, span: Span) -> P<ast::Ty>;
+}
+
+impl ToPtr for P<ast::Ty> {
+ fn to_ptr(self, is_const: bool, span: Span) -> Self {
+ let ty = ast::TyKind::Ptr(ast::MutTy {
+ ty: self,
+ mutbl: if is_const {
+ ast::Mutability::Immutable
+ } else {
+ ast::Mutability::Mutable
+ }
+ });
+ P(ast::Ty {
+ id: ast::DUMMY_NODE_ID,
+ node: ty,
+ span: span,
+ })
+ }
+}
+
+trait CodeGenerator {
+ /// Extra information from the caller.
+ type Extra;
+
+ fn codegen(&self,
+ ctx: &BindgenContext,
+ result: &mut CodegenResult,
+ extra: &Self::Extra);
+}
+
+impl CodeGenerator for Item {
+ type Extra = ();
+
+ fn codegen(&self,
+ ctx: &BindgenContext,
+ result: &mut CodegenResult,
+ _extra: &()) {
+ if self.is_hidden(ctx) || result.seen(self.id()) {
+ return;
+ }
+
+ result.set_seen(self.id());
+
+ match *self.kind() {
+ ItemKind::Module(ref module) => {
+ if !ctx.options().enable_cxx_namespaces && self.id() == ctx.root_module() {
+ return;
+ }
+
+ module.codegen(ctx, result, self);
+ },
+ ItemKind::Function(ref fun) => {
+ if !ctx.options().ignore_functions {
+ fun.codegen(ctx, result, self);
+ }
+ },
+ ItemKind::Var(ref var) => {
+ var.codegen(ctx, result, self);
+ },
+ ItemKind::Type(ref ty) => {
+ ty.codegen(ctx, result, self);
+ }
+ }
+ }
+}
+
+impl CodeGenerator for Module {
+ type Extra = Item;
+
+ fn codegen(&self,
+ ctx: &BindgenContext,
+ result: &mut CodegenResult,
+ item: &Item) {
+ if !ctx.options().enable_cxx_namespaces {
+ for child in self.children() {
+ ctx.resolve_item(*child).codegen(ctx, result, &());
+ }
+ return;
+ }
+
+ let inner_items = result.inner(|result| {
+ result.push(root_import(ctx));
+ for child in self.children() {
+ ctx.resolve_item(*child).codegen(ctx, result, &());
+ }
+ });
+
+ let module = ast::ItemKind::Mod(ast::Mod {
+ inner: ctx.span(),
+ items: inner_items,
+ });
+
+ let name = item.canonical_name(ctx);
+ let item = aster::AstBuilder::new().item().pub_()
+ .build_item_kind(name, module);
+
+ result.push(item);
+ }
+}
+
+impl CodeGenerator for Var {
+ type Extra = Item;
+ fn codegen(&self,
+ ctx: &BindgenContext,
+ result: &mut CodegenResult,
+ item: &Item) {
+ let name = item.canonical_name(ctx);
+ let ty = self.ty().to_rust_ty(ctx);
+
+ if let Some(val) = self.val() {
+ let const_item = aster::AstBuilder::new().item().pub_().const_(name)
+ .expr().int(val).build(ty);
+ result.push(const_item)
+ } else {
+ let mut attrs = vec![];
+ if let Some(mangled) = self.mangled_name() {
+ attrs.push(attributes::link_name(mangled));
+ } else if name != self.name() {
+ attrs.push(attributes::link_name(self.name()));
+ }
+
+ let item = ast::ForeignItem {
+ ident: ctx.rust_ident_raw(&name),
+ attrs: attrs,
+ node: ast::ForeignItemKind::Static(ty, !self.is_const()),
+ id: ast::DUMMY_NODE_ID,
+ span: ctx.span(),
+ vis: ast::Visibility::Public,
+ };
+
+ let item = ForeignModBuilder::new(Abi::C)
+ .with_foreign_item(item)
+ .build(ctx);
+ result.push(item);
+ }
+ }
+}
+
+impl CodeGenerator for Type {
+ type Extra = Item;
+
+ fn codegen(&self,
+ ctx: &BindgenContext,
+ result: &mut CodegenResult,
+ item: &Item) {
+ match *self.kind() {
+ TypeKind::Void |
+ TypeKind::NullPtr |
+ TypeKind::Int(..) |
+ TypeKind::Float(..) |
+ TypeKind::Array(..) |
+ TypeKind::Pointer(..) |
+ TypeKind::Reference(..) |
+ TypeKind::TemplateRef(..) |
+ TypeKind::Function(..) |
+ TypeKind::ResolvedTypeRef(..) |
+ TypeKind::Named(..) => {
+ // These items don't need code generation, they only need to be
+ // converted to rust types in fields, arguments, and such.
+ return;
+ }
+ TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
+ TypeKind::Alias(ref spelling, inner) => {
+ let inner_item = ctx.resolve_item(inner);
+ let name = item.canonical_name(ctx);
+
+ // Try to catch the common pattern:
+ //
+ // typedef struct foo { ... } foo;
+ //
+ // here.
+ //
+ if inner_item.canonical_name(ctx) == name {
+ return;
+ }
+
+ // If this is a known named type, disallow generating anything
+ // for it too.
+ if utils::type_from_named(ctx, spelling, inner).is_some() {
+ return;
+ }
+
+ let mut applicable_template_args = item.applicable_template_args(ctx);
+ let inner_rust_type = if item.is_opaque(ctx) {
+ applicable_template_args.clear();
+ // Pray if there's no layout.
+ let layout = self.layout(ctx).unwrap_or_else(Layout::zero);
+ BlobTyBuilder::new(layout).build()
+ } else {
+ inner_item.to_rust_ty(ctx)
+ };
+
+ let rust_name = ctx.rust_ident(&name);
+ let mut typedef = aster::AstBuilder::new().item().pub_();
+
+ if let Some(comment) = item.comment() {
+ typedef = typedef.attr().doc(comment);
+ }
+
+ let mut generics = typedef.type_(rust_name).generics();
+ for template_arg in applicable_template_args.iter() {
+ let template_arg = ctx.resolve_type(*template_arg);
+ if template_arg.is_named() {
+ let name = template_arg.name().unwrap();
+ if name.contains("typename ") {
+ error!("Item contained `typename`'d template param: {:?}", item);
+ return;
+ }
+ generics = generics.ty_param_id(template_arg.name().unwrap());
+ }
+ }
+
+ let typedef = generics.build().build_ty(inner_rust_type);
+ result.push(typedef)
+ }
+ TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item),
+ ref u @ TypeKind::UnresolvedTypeRef(..)
+ => unreachable!("Should have been resolved after parsing {:?}!", u),
+ }
+ }
+}
+
+struct Vtable<'a> {
+ item_id: ItemId,
+ #[allow(dead_code)]
+ methods: &'a [Method],
+ #[allow(dead_code)]
+ base_classes: &'a [ItemId],
+}
+
+impl<'a> Vtable<'a> {
+ fn new(item_id: ItemId, methods: &'a [Method], base_classes: &'a [ItemId]) -> Self {
+ Vtable {
+ item_id: item_id,
+ methods: methods,
+ base_classes: base_classes,
+ }
+ }
+}
+
+impl<'a> CodeGenerator for Vtable<'a> {
+ type Extra = Item;
+
+ fn codegen(&self,
+ ctx: &BindgenContext,
+ result: &mut CodegenResult,
+ item: &Item) {
+ assert_eq!(item.id(), self.item_id);
+ // For now, generate an empty struct, later we should generate function
+ // pointers and whatnot.
+ let vtable = aster::AstBuilder::new().item().pub_()
+ .with_attr(attributes::repr("C"))
+ .struct_(self.canonical_name(ctx))
+ .build();
+ result.push(vtable);
+ }
+}
+
+impl<'a> ItemCanonicalName for Vtable<'a> {
+ fn canonical_name(&self, _ctx: &BindgenContext) -> String {
+ format!("bindgen_vtable_{}", self.item_id)
+ }
+}
+
+impl<'a> ItemToRustTy for Vtable<'a> {
+ fn to_rust_ty(&self, ctx: &BindgenContext) -> P<ast::Ty> {
+ aster::ty::TyBuilder::new().id(self.canonical_name(ctx))
+ }
+}
+
+struct Bitfield<'a> {
+ index: usize,
+ fields: Vec<&'a Field>,
+}
+
+impl<'a> Bitfield<'a> {
+ fn new(index: usize, fields: Vec<&'a Field>) -> Self {
+ Bitfield {
+ index: index,
+ fields: fields,
+ }
+ }
+
+ fn codegen_fields(self,
+ ctx: &BindgenContext,
+ fields: &mut Vec<ast::StructField>,
+ methods: &mut Vec<ast::ImplItem>) {
+ use aster::struct_field::StructFieldBuilder;
+ use std::cmp;
+ let mut total_width = self.fields.iter()
+ .fold(0u32, |acc, f| acc + f.bitfield().unwrap());
+
+ if !total_width.is_power_of_two() || total_width < 8 {
+ total_width = cmp::max(8, total_width.next_power_of_two());
+ }
+ debug_assert_eq!(total_width % 8, 0);
+ let total_width_in_bytes = total_width as usize / 8;
+
+ let bitfield_type =
+ BlobTyBuilder::new(Layout::new(total_width_in_bytes, total_width_in_bytes)).build();
+ let field_name = format!("_bitfield_{}", self.index);
+ let field_ident = ctx.ext_cx().ident_of(&field_name);
+ let field = StructFieldBuilder::named(&field_name).pub_()
+ .build_ty(bitfield_type.clone());
+ fields.push(field);
+
+
+ let mut offset = 0;
+ for field in self.fields {
+ let width = field.bitfield().unwrap();
+ let field_name = field.name()
+ .map(ToOwned::to_owned)
+ .unwrap_or_else(|| format!("at_offset_{}", offset));
+
+ let field_item = ctx.resolve_item(field.ty());
+ let field_ty_layout = field_item.kind().expect_type()
+ .layout(ctx)
+ .expect("Bitfield without layout? Gah!");
+
+ let field_type = field_item.to_rust_ty(ctx);
+ let int_type = BlobTyBuilder::new(field_ty_layout).build();
+
+ let getter_name = ctx.ext_cx().ident_of(&field_name);
+ let setter_name = ctx.ext_cx().ident_of(&format!("set_{}", &field_name));
+ let mask = ((1usize << width) - 1) << offset;
+ // The transmute is unfortunate, but it's needed for enums in
+ // bitfields.
+ let item = quote_item!(ctx.ext_cx(),
+ impl X {
+ #[inline]
+ pub fn $getter_name(&self) -> $field_type {
+ unsafe {
+ ::std::mem::transmute(
+ ((self.$field_ident & ($mask as $bitfield_type)) >> $offset)
+ as $int_type)
+ }
+ }
+
+ #[inline]
+ pub fn $setter_name(&mut self, val: $field_type) {
+ self.$field_ident &= !($mask as $bitfield_type);
+ self.$field_ident |= (val as $int_type as $bitfield_type << $offset) & ($mask as $bitfield_type);
+ }
+ }
+ ).unwrap();
+
+ let items = match item.unwrap().node {
+ ast::ItemKind::Impl(_, _, _, _, _, items) => items,
+ _ => unreachable!(),
+ };
+
+ methods.extend(items.into_iter());
+ offset += width;
+ }
+ }
+}
+
+impl CodeGenerator for CompInfo {
+ type Extra = Item;
+
+ fn codegen(&self,
+ ctx: &BindgenContext,
+ result: &mut CodegenResult,
+ item: &Item) {
+ use aster::struct_field::StructFieldBuilder;
+ // Don't output classes with template parameters that aren't types, and
+ // also don't output template specializations, neither total or partial.
+ //
+ // TODO: Generate layout tests for template specializations, yay!
+ if self.has_non_type_template_params() || self.is_template_specialization() {
+ return;
+ }
+
+ let applicable_template_args = item.applicable_template_args(ctx);
+
+ let mut attributes = vec![];
+ let mut needs_clone_impl = false;
+ if let Some(comment) = item.comment() {
+ attributes.push(attributes::doc(comment));
+ }
+ if self.packed() {
+ attributes.push(attributes::repr_list(&["C", "packed"]));
+ } else {
+ attributes.push(attributes::repr("C"));
+ }
+
+ let mut derives = vec![];
+ let ty = item.expect_type();
+ if ty.can_derive_debug(ctx) {
+ derives.push("Debug");
+ }
+
+ if ty.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
+ derives.push("Copy");
+ if !applicable_template_args.is_empty() {
+ // FIXME: This requires extra logic if you have a big array in a
+ // templated struct. The reason for this is that the magic:
+ // fn clone(&self) -> Self { *self }
+ // doesn't work for templates.
+ //
+ // It's not hard to fix though.
+ derives.push("Clone");
+ } else {
+ needs_clone_impl = true;
+ }
+ }
+
+ if !derives.is_empty() {
+ attributes.push(attributes::derives(&derives))
+ }
+
+ let mut template_args_used = vec![false; applicable_template_args.len()];
+ let canonical_name = item.canonical_name(ctx);
+ let builder = aster::AstBuilder::new().item().pub_()
+ .with_attrs(attributes)
+ .struct_(&canonical_name);
+
+ // Generate the vtable from the method list if appropriate.
+ // TODO: I don't know how this could play with virtual methods that are
+ // not in the list of methods found by us, we'll see. Also, could the
+ // order of the vtable pointers vary?
+ //
+ // FIXME: Once we generate proper vtables, we need to codegen the
+ // vtable, but *not* generate a field for it in the case that
+ // needs_explicit_vtable is false but has_vtable is true.
+ //
+ // Also, we need to generate the vtable in such a way it "inherits" from
+ // the parent too.
+ let mut fields = vec![];
+ if self.needs_explicit_vtable(ctx) {
+ let vtable = Vtable::new(item.id(),
+ self.methods(),
+ self.base_members());
+ vtable.codegen(ctx, result, item);
+
+ let vtable_type = vtable.to_rust_ty(ctx).to_ptr(true, ctx.span());
+
+ let vtable_field = StructFieldBuilder::named("vtable_").pub_()
+ .build_ty(vtable_type);
+
+ fields.push(vtable_field);
+ }
+
+ for (i, base) in self.base_members().iter().enumerate() {
+ let base_ty = ctx.resolve_type(*base);
+ // NB: We won't include unsized types in our base chain because they
+ // would contribute to our size given the dummy field we insert for
+ // unsized types.
+ //
+ // NB: Canonical type is here because it could be inheriting from a
+ // typedef, for example, and the lack of `unwrap()` is because we
+ // can inherit from a template parameter, yes.
+ if base_ty.is_unsized(ctx) {
+ continue;
+ }
+
+ for (i, ty) in applicable_template_args.iter().enumerate() {
+ if base_ty.signature_contains_named_type(ctx, ctx.resolve_type(*ty)) {
+ template_args_used[i] = true;
+ }
+ }
+
+ let inner = base.to_rust_ty(ctx);
+ let field_name = if i == 0 {
+ "_base".into()
+ } else {
+ format!("_base_{}", i)
+ };
+
+ let field = StructFieldBuilder::named(field_name)
+ .pub_().build_ty(inner);
+ fields.push(field);
+ }
+
+ let is_union = self.kind() == CompKind::Union;
+ if is_union {
+ result.saw_union();
+ }
+
+ let layout = item.kind().expect_type().layout(ctx);
+
+ let mut current_bitfield_width = None;
+ let mut current_bitfield_layout: Option<Layout> = None;
+ let mut current_bitfield_fields = vec![];
+ let mut bitfield_count = 0;
+ let struct_fields = self.fields();
+ let fields_should_be_private = item.annotations()
+ .private_fields()
+ .unwrap_or(false);
+ let struct_accessor_kind = item.annotations()
+ .accessor_kind()
+ .unwrap_or(FieldAccessorKind::None);
+
+ let mut methods = vec![];
+ let mut anonymous_field_count = 0;
+ for field in struct_fields {
+ debug_assert_eq!(current_bitfield_width.is_some(),
+ current_bitfield_layout.is_some());
+ debug_assert_eq!(current_bitfield_width.is_some(),
+ !current_bitfield_fields.is_empty());
+
+ let field_ty = ctx.resolve_type(field.ty());
+
+ // Try to catch a bitfield contination early.
+ if let (Some(ref mut bitfield_width), Some(width)) = (current_bitfield_width, field.bitfield()) {
+ let layout = current_bitfield_layout.unwrap();
+ debug!("Testing bitfield continuation {} {} {:?}",
+ *bitfield_width, width, layout);
+ if *bitfield_width + width <= (layout.size * 8) as u32 {
+ *bitfield_width += width;
+ current_bitfield_fields.push(field);
+ continue;
+ }
+ }
+
+ // Flush the current bitfield.
+ if current_bitfield_width.is_some() {
+ debug_assert!(!current_bitfield_fields.is_empty());
+ let bitfield_fields =
+ mem::replace(&mut current_bitfield_fields, vec![]);
+ bitfield_count += 1;
+ Bitfield::new(bitfield_count, bitfield_fields)
+ .codegen_fields(ctx, &mut fields, &mut methods);
+ current_bitfield_width = None;
+ current_bitfield_layout = None;
+ }
+ debug_assert!(current_bitfield_fields.is_empty());
+
+ if let Some(width) = field.bitfield() {
+ let layout = field_ty.layout(ctx)
+ .expect("Bitfield type without layout?");
+ current_bitfield_width = Some(width);
+ current_bitfield_layout = Some(layout);
+ current_bitfield_fields.push(field);
+ continue;
+ }
+
+ for (i, ty) in applicable_template_args.iter().enumerate() {
+ if field_ty.signature_contains_named_type(ctx, ctx.resolve_type(*ty)) {
+ template_args_used[i] = true;
+ }
+ }
+
+ let ty = field.ty().to_rust_ty(ctx);
+
+ let ty = if is_union {
+ quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
+ } else {
+ ty
+ };
+
+ let mut attrs = vec![];
+ if let Some(comment) = field.comment() {
+ attrs.push(attributes::doc(comment));
+ }
+ let field_name = match field.name() {
+ Some(name) => ctx.rust_mangle(name).into_owned(),
+ None => {
+ anonymous_field_count += 1;
+ format!("__bindgen_anon_{}", anonymous_field_count)
+ }
+ };
+
+ let is_private = field.annotations()
+ .private_fields()
+ .unwrap_or(fields_should_be_private);
+
+ let accessor_kind = field.annotations()
+ .accessor_kind()
+ .unwrap_or(struct_accessor_kind);
+
+ let mut field = StructFieldBuilder::named(&field_name);
+
+ if !is_private {
+ field = field.pub_();
+ }
+
+ let field = field.with_attrs(attrs)
+ .build_ty(ty.clone());
+
+ fields.push(field);
+
+ // TODO: Factor the following code out, please!
+ if accessor_kind == FieldAccessorKind::None {
+ continue;
+ }
+
+ let getter_name =
+ ctx.rust_ident_raw(&format!("get_{}", field_name));
+ let mutable_getter_name =
+ ctx.rust_ident_raw(&format!("get_{}_mut", field_name));
+ let field_name = ctx.rust_ident_raw(&field_name);
+
+ let accessor_methods_impl = match accessor_kind {
+ FieldAccessorKind::None => unreachable!(),
+ FieldAccessorKind::Regular => {
+ quote_item!(ctx.ext_cx(),
+ impl X {
+ #[inline]
+ pub fn $getter_name(&self) -> &$ty {
+ &self.$field_name
+ }
+
+ #[inline]
+ pub fn $mutable_getter_name(&mut self) -> &mut $ty {
+ &mut self.$field_name
+ }
+ }
+ )
+ }
+ FieldAccessorKind::Unsafe => {
+ quote_item!(ctx.ext_cx(),
+ impl X {
+ #[inline]
+ pub unsafe fn $getter_name(&self) -> &$ty {
+ &self.$field_name
+ }
+
+ #[inline]
+ pub unsafe fn $mutable_getter_name(&mut self) -> &mut $ty {
+ &mut self.$field_name
+ }
+ }
+ )
+ }
+ FieldAccessorKind::Immutable => {
+ quote_item!(ctx.ext_cx(),
+ impl X {
+ #[inline]
+ pub fn $getter_name(&self) -> &$ty {
+ &self.$field_name
+ }
+ }
+ )
+ }
+ };
+
+ match accessor_methods_impl.unwrap().node {
+ ast::ItemKind::Impl(_, _, _, _, _, ref items)
+ => methods.extend(items.clone()),
+ _ => unreachable!()
+ }
+ }
+
+ // Flush the last bitfield if any.
+ //
+ // FIXME: Reduce duplication with the loop above.
+ // FIXME: May need to pass current_bitfield_layout too.
+ if current_bitfield_width.is_some() {
+ debug_assert!(!current_bitfield_fields.is_empty());
+ let bitfield_fields = mem::replace(&mut current_bitfield_fields, vec![]);
+ bitfield_count += 1;
+ Bitfield::new(bitfield_count, bitfield_fields)
+ .codegen_fields(ctx, &mut fields, &mut methods);
+ }
+ debug_assert!(current_bitfield_fields.is_empty());
+
+ if is_union {
+ let layout = layout.expect("Unable to get layout information?");
+ let ty = BlobTyBuilder::new(layout).build();
+ let field = StructFieldBuilder::named("bindgen_union_field").pub_()
+ .build_ty(ty);
+ fields.push(field);
+ }
+
+ // Yeah, sorry about that.
+ if item.is_opaque(ctx) {
+ fields.clear();
+ methods.clear();
+ for i in 0..template_args_used.len() {
+ template_args_used[i] = false;
+ }
+
+ match layout {
+ Some(l) => {
+ let ty = BlobTyBuilder::new(l).build();
+ let field = StructFieldBuilder::named("_bindgen_opaque_blob").pub_()
+ .build_ty(ty);
+ fields.push(field);
+ }
+ None => {
+ warn!("Opaque type without layout! Expect dragons!");
+ }
+ }
+ }
+
+ // C requires every struct to be addressable, so what C compilers do is
+ // making the struct 1-byte sized.
+ //
+ // NOTE: This check is conveniently here to avoid the dummy fields we
+ // may add for unused template parameters.
+ if self.is_unsized(ctx) {
+ let ty = BlobTyBuilder::new(Layout::new(1, 1)).build();
+ let field = StructFieldBuilder::named("_address").pub_()
+ .build_ty(ty);
+ 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 field =
+ StructFieldBuilder::named(format!("_phantom_{}", i)).pub_()
+ .build_ty(quote_ty!(ctx.ext_cx(), ::std::marker::PhantomData<$ident>));
+ fields.push(field)
+ }
+ }
+
+
+ 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
+ // template specialisations that would need to be
+ // instantiated.
+ //
+ // TODO: Add template args from the parent, here and in
+ // `to_rust_ty`!!
+ let template_arg = ctx.resolve_type(*template_arg);
+ generics = generics.ty_param_id(template_arg.name().unwrap());
+ }
+
+ let generics = generics.build();
+
+ let rust_struct = builder.with_generics(generics.clone())
+ .with_fields(fields).build();
+ result.push(rust_struct);
+
+ // Generate the inner types and all that stuff.
+ //
+ // TODO: In the future we might want to be smart, and use nested
+ // modules, and whatnot.
+ for ty in self.inner_types() {
+ let child_item = ctx.resolve_item(*ty);
+ // assert_eq!(child_item.parent_id(), item.id());
+ child_item.codegen(ctx, result, &());
+ }
+
+ // NOTE: Some unexposed attributes (like alignment attributes) may
+ // affect layout, so we're bad and pray to the gods for avoid sending
+ // all the tests to shit when parsing things like max_align_t.
+ if self.found_unknown_attr() {
+ warn!("Type {} has an unkown attribute that may affect layout", canonical_name);
+ }
+ if applicable_template_args.is_empty() && !self.found_unknown_attr() {
+ for var in self.inner_vars() {
+ ctx.resolve_item(*var).codegen(ctx, result, &());
+ }
+
+ if let Some(layout) = layout {
+ let fn_name =
+ ctx.rust_ident_raw(&format!("bindgen_test_layout_{}", canonical_name));
+ let ident = ctx.rust_ident_raw(&canonical_name);
+ let size_of_expr =
+ quote_expr!(ctx.ext_cx(), ::std::mem::size_of::<$ident>());
+ let align_of_expr =
+ quote_expr!(ctx.ext_cx(), ::std::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);
+ assert_eq!($align_of_expr, $align);
+ }).unwrap();
+ result.push(item);
+ }
+
+ let mut method_names = Default::default();
+ for method in self.methods() {
+ method.codegen_method(ctx, &mut methods, &mut method_names, result, item);
+ }
+ }
+
+ // NB: We can't use to_rust_ty here since for opaque types this tries to
+ // use the specialization knowledge to generate a blob field.
+ let ty_for_impl = aster::AstBuilder::new().ty().path().id(&canonical_name).build();
+ if needs_clone_impl {
+ let impl_ = quote_item!(ctx.ext_cx(),
+ impl X {
+ fn clone(&self) -> Self { *self }
+ }
+ );
+
+ let impl_ = match impl_.unwrap().node {
+ ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(),
+ _ => unreachable!(),
+ };
+
+ let clone_impl =
+ aster::AstBuilder::new().item().impl_()
+ .trait_().id("Clone").build()
+ .with_generics(generics.clone())
+ .with_items(impl_)
+ .build_ty(ty_for_impl.clone());
+
+ result.push(clone_impl);
+ }
+
+ if !methods.is_empty() {
+ let methods =
+ aster::AstBuilder::new().item().impl_()
+ .with_generics(generics)
+ .with_items(methods)
+ .build_ty(ty_for_impl);
+ result.push(methods);
+ }
+ }
+}
+
+trait MethodCodegen {
+ fn codegen_method(&self,
+ ctx: &BindgenContext,
+ methods: &mut Vec<ast::ImplItem>,
+ method_names: &mut HashMap<String, usize>,
+ result: &mut CodegenResult,
+ parent: &Item);
+}
+
+impl MethodCodegen for Method {
+ fn codegen_method(&self,
+ ctx: &BindgenContext,
+ methods: &mut Vec<ast::ImplItem>,
+ method_names: &mut HashMap<String, usize>,
+ result: &mut CodegenResult,
+ _parent: &Item) {
+ if ctx.options().ignore_methods {
+ return;
+ }
+
+ if self.is_virtual() {
+ return; // FIXME
+ }
+ // First of all, output the actual function.
+ ctx.resolve_item(self.signature()).codegen(ctx, result, &());
+
+ let function_item = ctx.resolve_item(self.signature());
+ let function = function_item.expect_function();
+ let mut name = function.name().to_owned();
+ let signature_item = ctx.resolve_item(function.signature());
+ let signature = match *signature_item.expect_type().kind() {
+ TypeKind::Function(ref sig) => sig,
+ _ => panic!("How in the world?"),
+ };
+
+ let count = {
+ let mut count = method_names.entry(name.clone())
+ .or_insert(0);
+ *count += 1;
+ *count - 1
+ };
+
+ if count != 0 {
+ name.push_str(&count.to_string());
+ }
+
+ let function_name = function_item.canonical_name(ctx);
+ let mut fndecl = utils::rust_fndecl_from_signature(ctx, signature_item).unwrap();
+ if !self.is_static() {
+ let mutability = if self.is_const() {
+ ast::Mutability::Immutable
+ } else {
+ ast::Mutability::Mutable
+ };
+
+ assert!(!fndecl.inputs.is_empty());
+ // FIXME: use aster here.
+ fndecl.inputs[0] = ast::Arg {
+ ty: P(ast::Ty {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::TyKind::Rptr(None, ast::MutTy {
+ ty: P(ast::Ty {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::TyKind::ImplicitSelf,
+ span: ctx.span()
+ }),
+ mutbl: mutability,
+ }),
+ span: ctx.span(),
+ }),
+ pat: P(ast::Pat {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Immutable),
+ respan(ctx.span(), ctx.ext_cx().ident_of("self")),
+ None),
+ span: ctx.span(),
+ }),
+ id: ast::DUMMY_NODE_ID,
+ };
+ }
+
+ let sig = ast::MethodSig {
+ unsafety: ast::Unsafety::Unsafe,
+ abi: Abi::Rust,
+ decl: P(fndecl.clone()),
+ generics: ast::Generics::default(),
+ constness: respan(ctx.span(), ast::Constness::NotConst),
+ };
+
+ // TODO: We need to keep in sync the argument names, so we should unify
+ // this with the other loop that decides them.
+ let mut unnamed_arguments = 0;
+ let mut exprs = signature.argument_types().iter().map(|&(ref name, _ty)| {
+ let arg_name = match *name {
+ Some(ref name) => ctx.rust_mangle(name).into_owned(),
+ None => {
+ unnamed_arguments += 1;
+ format!("arg{}", unnamed_arguments)
+ }
+ };
+ aster::expr::ExprBuilder::new().id(arg_name)
+ }).collect::<Vec<_>>();
+
+ if !self.is_static() {
+ assert!(!exprs.is_empty());
+ exprs[0] = if self.is_const() {
+ quote_expr!(ctx.ext_cx(), &*self)
+ } else {
+ quote_expr!(ctx.ext_cx(), &mut *self)
+ };
+ };
+
+ let call = aster::expr::ExprBuilder::new().call()
+ .id(function_name)
+ .with_args(exprs)
+ .build();
+
+ let block = ast::Block {
+ stmts: vec![
+ ast::Stmt {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::StmtKind::Expr(call),
+ span: ctx.span(),
+ }
+ ],
+ id: ast::DUMMY_NODE_ID,
+ rules: ast::BlockCheckMode::Default,
+ span: ctx.span(),
+ };
+
+ let mut attrs = vec![];
+ attrs.push(attributes::inline());
+
+ let item = ast::ImplItem {
+ id: ast::DUMMY_NODE_ID,
+ ident: ctx.ext_cx().ident_of(&name),
+ vis: ast::Visibility::Public,
+ attrs: attrs,
+ node: ast::ImplItemKind::Method(sig, P(block)),
+ defaultness: ast::Defaultness::Final,
+ span: ctx.span(),
+ };
+
+ methods.push(item);
+ }
+}
+
+impl CodeGenerator for Enum {
+ type Extra = Item;
+
+ fn codegen(&self,
+ ctx: &BindgenContext,
+ result: &mut CodegenResult,
+ item: &Item) {
+ use ir::enum_ty::EnumVariantValue;
+
+ let name = item.canonical_name(ctx);
+ let layout = item.expect_type().layout(ctx);
+
+ let repr = self.repr().map(|repr| ctx.resolve_type(repr));
+ let repr = match repr {
+ Some(repr) => match *repr.canonical_type(ctx).kind() {
+ TypeKind::Int(int_kind) => int_kind,
+ _ => panic!("Unexpected type as enum repr"),
+ },
+ None => {
+ warn!("Guessing type of enum! Forward declarations of enums shouldn't be legal!");
+ IntKind::Int
+ }
+ };
+
+ let signed = repr.is_signed();
+ let size = layout.map(|l| l.size).unwrap_or(0);
+ let repr_name = match (signed, size) {
+ (true, 1) => "i8",
+ (false, 1) => "u8",
+ (true, 2) => "i16",
+ (false, 2) => "u16",
+ (true, 4) => "i32",
+ (false, 4) => "u32",
+ (true, 8) => "i64",
+ (false, 8) => "u64",
+ _ => {
+ warn!("invalid enum decl: signed: {}, size: {}", signed, size);
+ "i32"
+ }
+ };
+
+ let mut builder = aster::AstBuilder::new().item().pub_();
+
+ // FIXME: Rust forbids repr with empty enums. Remove this condition when
+ // this is allowed.
+ if !self.variants().is_empty() {
+ builder = builder.with_attr(attributes::repr(repr_name));
+ }
+
+ if let Some(comment) = item.comment() {
+ builder = builder.with_attr(attributes::doc(comment));
+ }
+
+ let derives =
+ attributes::derives(&["Debug", "Copy", "Clone", "PartialEq", "Eq", "Hash"]);
+
+ builder = builder.with_attr(derives);
+
+ let mut builder = builder.enum_(&name);
+
+ fn add_constant(enum_: &Type,
+ // Only to avoid recomputing every time.
+ enum_canonical_name: &str,
+ // May be the same as "variant" if it's because the enum
+ // is unnamed and we still haven't seen the value.
+ variant_name: &str,
+ referenced_name: &str,
+ enum_rust_ty: P<ast::Ty>,
+ result: &mut CodegenResult) {
+ let constant_name = if enum_.name().is_some() {
+ format!("{}_{}", enum_canonical_name, variant_name)
+ } else {
+ variant_name.into()
+ };
+
+ let constant = aster::AstBuilder::new().item().pub_()
+ .const_(constant_name)
+ .expr().path()
+ .ids(&[&*enum_canonical_name, referenced_name])
+ .build().build(enum_rust_ty);
+ result.push(constant);
+ }
+
+ // A map where we keep a value -> variant relation.
+ let mut seen_values = HashMap::<_, String>::new();
+ let enum_ty = item.expect_type();
+ let enum_rust_ty = item.to_rust_ty(ctx);
+ for variant in self.variants().iter() {
+ match seen_values.entry(variant.val()) {
+ Entry::Occupied(ref entry) => {
+ let existing_variant_name = entry.get();
+ let variant_name = ctx.rust_mangle(variant.name());
+ add_constant(enum_ty, &name, &*variant_name,
+ existing_variant_name, enum_rust_ty.clone(),
+ result);
+ }
+ Entry::Vacant(entry) => {
+ let expr = aster::AstBuilder::new().expr();
+ let expr = match variant.val() {
+ EnumVariantValue::Signed(val) => expr.int(val),
+ EnumVariantValue::Unsigned(val) => expr.uint(val),
+ };
+ let variant_name = ctx.rust_mangle(variant.name());
+ builder = builder.with_variant_(ast::Variant_ {
+ name: ctx.rust_ident(&*variant_name),
+ attrs: vec![],
+ data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
+ disr_expr: Some(expr),
+ });
+
+ // If it's an unnamed enum, we also generate a constant so
+ // it can be properly accessed.
+ if enum_ty.name().is_none() {
+ // NB: if we want to do this for other kind of nested
+ // enums we can probably mangle the name.
+ if item.is_toplevel(ctx) {
+ add_constant(enum_ty, &name, &variant_name,
+ &variant_name, enum_rust_ty.clone(),
+ result);
+ }
+ }
+
+ entry.insert(variant_name.into_owned());
+ }
+ }
+ }
+
+
+ result.push(builder.build());
+ }
+}
+
+trait ToRustTy {
+ type Extra;
+
+ fn to_rust_ty(&self, ctx: &BindgenContext, extra: &Self::Extra) -> P<ast::Ty>;
+}
+
+trait ItemToRustTy {
+ fn to_rust_ty(&self, ctx: &BindgenContext) -> P<ast::Ty>;
+}
+
+// Convenience implementation.
+impl ItemToRustTy for ItemId {
+ fn to_rust_ty(&self, ctx: &BindgenContext) -> P<ast::Ty> {
+ ctx.resolve_item(*self).to_rust_ty(ctx)
+ }
+}
+
+impl ItemToRustTy for Item {
+ fn to_rust_ty(&self, ctx: &BindgenContext) -> P<ast::Ty> {
+ self.kind().expect_type().to_rust_ty(ctx, self)
+ }
+}
+
+fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> {
+ let ident = ctx.rust_ident_raw(&name);
+ quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident)
+}
+
+impl ToRustTy for Type {
+ type Extra = Item;
+
+ fn to_rust_ty(&self, ctx: &BindgenContext, item: &Item) -> P<ast::Ty> {
+ macro_rules! raw {
+ ($ty: ident) => {
+ raw_type(ctx, stringify!($ty))
+ }
+ }
+ match *self.kind() {
+ TypeKind::Void => raw!(c_void),
+ // TODO: we should do something smart with nullptr, or maybe *const
+ // c_void is enough?
+ TypeKind::NullPtr => quote_ty!(ctx.ext_cx(), *const ::std::os::raw::c_void),
+ TypeKind::Int(ik) => {
+ match ik {
+ IntKind::Bool => aster::ty::TyBuilder::new().bool(),
+ IntKind::Char => raw!(c_char),
+ IntKind::UChar => raw!(c_uchar),
+ IntKind::Short => raw!(c_short),
+ IntKind::UShort => raw!(c_ushort),
+ IntKind::Int => raw!(c_int),
+ IntKind::UInt => raw!(c_uint),
+ IntKind::Long => raw!(c_long),
+ IntKind::ULong => raw!(c_ulong),
+ IntKind::LongLong => raw!(c_longlong),
+ IntKind::ULongLong => raw!(c_ulonglong),
+ IntKind::U16 => aster::ty::TyBuilder::new().u16(),
+ IntKind::U32 => aster::ty::TyBuilder::new().u32(),
+ }
+ }
+ TypeKind::Float(fk) => {
+ use ir::ty::FloatKind;
+ // TODO: we probably should just take the type layout into
+ // account?
+ match fk {
+ FloatKind::Float => aster::ty::TyBuilder::new().f32(),
+ FloatKind::Double |
+ FloatKind::LongDouble => aster::ty::TyBuilder::new().f64(),
+ }
+ }
+ TypeKind::Function(ref fs) => {
+ let ty = fs.to_rust_ty(ctx, item);
+ aster::AstBuilder::new().ty().option().build(ty)
+ }
+ TypeKind::Array(item, len) => {
+ let inner = item.to_rust_ty(ctx);
+ ArrayTyBuilder::new().with_len(len).build(inner)
+ }
+ TypeKind::Enum(..) => {
+ let path = item.canonical_path(ctx);
+ aster::AstBuilder::new().ty().path().ids(path).build()
+ }
+ TypeKind::TemplateRef(inner, ref template_args) => {
+ // PS: Sorry for the duplication here.
+ let mut inner_ty = inner.to_rust_ty(ctx).unwrap();
+
+ if let ast::TyKind::Path(_, ref mut path) = inner_ty.node {
+ path.segments.last_mut().unwrap().parameters =
+ ast::PathParameters::AngleBracketed(
+ ast::AngleBracketedParameterData {
+ lifetimes: vec![],
+ types: P::from_vec(template_args.iter().map(|arg| {
+ arg.to_rust_ty(ctx)
+ }).collect()),
+ bindings: P::from_vec(vec![]),
+ }
+ );
+ }
+
+ P(inner_ty)
+ }
+ TypeKind::ResolvedTypeRef(inner) => inner.to_rust_ty(ctx),
+ TypeKind::Alias(ref spelling, inner) => {
+ if item.is_opaque(ctx) {
+ // Pray if there's no available layout.
+ let layout = self.layout(ctx).unwrap_or_else(Layout::zero);
+ BlobTyBuilder::new(layout).build()
+ } else if let Some(ty) = utils::type_from_named(ctx, spelling, inner) {
+ ty
+ } else {
+ utils::build_templated_path(item, ctx, true)
+ }
+ }
+ TypeKind::Comp(ref info) => {
+ if item.is_opaque(ctx) || info.has_non_type_template_params() {
+ return match self.layout(ctx) {
+ Some(layout) => {
+ BlobTyBuilder::new(layout).build()
+ }
+ None => {
+ warn!("Couldn't compute layout for a type with non \
+ template params or opaque, expect dragons!");
+ aster::AstBuilder::new().ty().unit()
+ }
+ }
+ }
+
+ utils::build_templated_path(item, ctx, false)
+ }
+ TypeKind::Pointer(inner) |
+ TypeKind::Reference(inner) => {
+ let inner = ctx.resolve_item(inner);
+ inner.to_rust_ty(ctx).to_ptr(inner.expect_type().is_const(), ctx.span())
+ }
+ TypeKind::Named(..) => {
+ let name = item.canonical_name(ctx);
+ let ident = ctx.rust_ident(&name);
+ quote_ty!(ctx.ext_cx(), $ident)
+ }
+ ref u @ TypeKind::UnresolvedTypeRef(..)
+ => unreachable!("Should have been resolved after parsing {:?}!", u),
+ }
+ }
+}
+
+impl ToRustTy for FunctionSig {
+ type Extra = Item;
+
+ fn to_rust_ty(&self, ctx: &BindgenContext, _item: &Item) -> P<ast::Ty> {
+ // TODO: we might want to consider ignoring the reference return value.
+ let return_item = ctx.resolve_item(self.return_type());
+ let ret = if let TypeKind::Void = *return_item.kind().expect_type().kind() {
+ ast::FunctionRetTy::Default(ctx.span())
+ } else {
+ ast::FunctionRetTy::Ty(return_item.to_rust_ty(ctx))
+ };
+
+ let mut unnamed_arguments = 0;
+ let arguments = self.argument_types().iter().map(|&(ref name, ty)| {
+ let arg_item = ctx.resolve_item(ty);
+ let arg_ty = arg_item.kind().expect_type();
+
+ // From the C90 standard (http://c0x.coding-guidelines.com/6.7.5.3.html)
+ // 1598 - A declaration of a parameter as “array of type” shall be
+ // adjusted to “qualified pointer to type”, where the type qualifiers
+ // (if any) are those specified within the [ and ] of the array type
+ // derivation.
+ let arg_ty = if let TypeKind::Array(t, _) = *arg_ty.kind() {
+ t.to_rust_ty(ctx).to_ptr(arg_ty.is_const(), ctx.span())
+ } else {
+ arg_item.to_rust_ty(ctx)
+ };
+
+ let arg_name = match *name {
+ Some(ref name) => ctx.rust_mangle(name).into_owned(),
+ None => {
+ unnamed_arguments += 1;
+ format!("arg{}", unnamed_arguments)
+ }
+ };
+
+ assert!(!arg_name.is_empty());
+
+ ast::Arg {
+ ty: arg_ty,
+ pat: aster::AstBuilder::new().pat().id(arg_name),
+ id: ast::DUMMY_NODE_ID,
+ }
+ }).collect::<Vec<_>>();
+
+ let decl = P(ast::FnDecl {
+ inputs: arguments,
+ output: ret,
+ variadic: self.is_variadic(),
+ });
+
+ let fnty = ast::TyKind::BareFn(P(ast::BareFnTy {
+ unsafety: ast::Unsafety::Unsafe,
+ abi: self.abi(),
+ lifetimes: vec![],
+ decl: decl,
+ }));
+
+ P(ast::Ty {
+ id: ast::DUMMY_NODE_ID,
+ node: fnty,
+ span: ctx.span(),
+ })
+ }
+}
+
+impl CodeGenerator for Function {
+ type Extra = Item;
+
+ fn codegen(&self,
+ ctx: &BindgenContext,
+ result: &mut CodegenResult,
+ item: &Item) {
+ let name = self.name();
+ let canonical_name = item.canonical_name(ctx);
+
+ // TODO: Maybe warn here if there's a type/argument mismatch, or
+ // something?
+ if result.seen_function(&canonical_name) {
+ return;
+ }
+ result.saw_function(&canonical_name);
+
+ let signature_item = ctx.resolve_item(self.signature());
+ let signature = signature_item.kind().expect_type();
+ let signature = match *signature.kind() {
+ TypeKind::Function(ref sig) => sig,
+ _ => panic!("How?"),
+ };
+
+ let fndecl = utils::rust_fndecl_from_signature(ctx, signature_item);
+
+ let mut attributes = vec![];
+
+ if let Some(comment) = item.comment() {
+ attributes.push(attributes::doc(comment));
+ }
+
+ if let Some(mangled) = self.mangled_name() {
+ attributes.push(attributes::link_name(mangled));
+ } else if name != canonical_name {
+ attributes.push(attributes::link_name(name));
+ }
+
+ let foreign_item_kind =
+ ast::ForeignItemKind::Fn(fndecl, ast::Generics::default());
+
+ let foreign_item =
+ ast::ForeignItem {
+ ident: ctx.rust_ident_raw(&canonical_name),
+ attrs: attributes,
+ node: foreign_item_kind,
+ id: ast::DUMMY_NODE_ID,
+ span: ctx.span(),
+ vis: ast::Visibility::Public,
+ };
+
+ let item = ForeignModBuilder::new(signature.abi())
+ .with_foreign_item(foreign_item)
+ .build(ctx);
+
+ result.push(item);
+ }
+}
+
+type ItemSet = BTreeSet<ItemId>;
+
+trait TypeCollector {
+ type Extra;
+
+ fn collect_types(&self,
+ context: &BindgenContext,
+ types: &mut ItemSet,
+ extra: &Self::Extra);
+}
+
+impl TypeCollector for ItemId {
+ type Extra = ();
+
+ fn collect_types(&self,
+ context: &BindgenContext,
+ types: &mut ItemSet,
+ extra: &()) {
+ context.resolve_item(*self).collect_types(context, types, extra);
+ }
+}
+
+impl TypeCollector for Item {
+ type Extra = ();
+
+ fn collect_types(&self,
+ context: &BindgenContext,
+ types: &mut ItemSet,
+ _extra: &()) {
+ if self.is_hidden(context) || types.contains(&self.id()) {
+ return;
+ }
+
+ match *self.kind() {
+ ItemKind::Type(ref ty) => {
+ types.insert(self.id());
+ if !self.is_opaque(context) {
+ ty.collect_types(context, types, self);
+ }
+ }
+ _ => {}, // FIXME.
+ }
+ }
+}
+
+impl TypeCollector for Type {
+ type Extra = Item;
+
+ fn collect_types(&self,
+ context: &BindgenContext,
+ types: &mut ItemSet,
+ item: &Item) {
+ match *self.kind() {
+ TypeKind::Pointer(inner) |
+ TypeKind::Reference(inner) |
+ TypeKind::Array(inner, _) |
+ TypeKind::Alias(_, inner) |
+ TypeKind::Named(_, Some(inner)) |
+ TypeKind::ResolvedTypeRef(inner)
+ => inner.collect_types(context, types, &()),
+
+ TypeKind::TemplateRef(inner, ref template_args) => {
+ inner.collect_types(context, types, &());
+ for item in template_args {
+ item.collect_types(context, types, &());
+ }
+ }
+ TypeKind::Comp(ref ci) => ci.collect_types(context, types, item),
+ TypeKind::Function(ref sig) => {
+ sig.collect_types(context, types, item)
+ }
+ // FIXME: Pending types!
+ ref other @ _ => {
+ debug!("Ignoring: {:?}", other);
+ },
+ }
+ }
+}
+
+impl TypeCollector for FunctionSig {
+ type Extra = Item;
+
+ fn collect_types(&self,
+ context: &BindgenContext,
+ types: &mut ItemSet,
+ _item: &Item) {
+ self.return_type().collect_types(context, types, &());
+
+ for &(_, ty) in self.argument_types() {
+ ty.collect_types(context, types, &());
+ }
+ }
+}
+
+impl TypeCollector for CompInfo {
+ type Extra = Item;
+
+ fn collect_types(&self,
+ context: &BindgenContext,
+ types: &mut ItemSet,
+ item: &Item) {
+ if let Some(template) = self.specialized_template() {
+ template.collect_types(context, types, &());
+ }
+
+ let applicable_template_args = item.applicable_template_args(context);
+ for arg in applicable_template_args {
+ arg.collect_types(context, types, &());
+ }
+
+ for base in self.base_members() {
+ base.collect_types(context, types, &());
+ }
+
+ for field in self.fields() {
+ field.ty().collect_types(context, types, &());
+ }
+
+ for ty in self.inner_types() {
+ ty.collect_types(context, types, &());
+ }
+
+ // FIXME(emilio): Methods, VTable?
+ }
+}
+
+pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
+ context.gen(|context| {
+ let mut result = CodegenResult::new();
+
+ debug!("codegen: {:?}", context.options());
+
+ // If the whitelisted types and functions sets are empty, just generate
+ // everything.
+ if context.options().whitelisted_types.is_empty() &&
+ context.options().whitelisted_functions.is_empty() &&
+ context.options().whitelisted_vars.is_empty() {
+ for (_item_id, item) in context.items() {
+ // Non-toplevel item parents are the responsible one for generating
+ // them.
+ if item.is_toplevel(context) {
+ item.codegen(context, &mut result, &());
+ }
+ }
+ } else {
+ // Recursively collect all the types dependent on the whitelisted
+ // types, then generate them.
+ //
+ // FIXME(emilio): This pass is probably slow, but it can't be faster
+ // than docopt anyway :)
+ let mut items = ItemSet::new();
+ for (_item_id, item) in context.items() {
+ // FIXME(emilio): This probably should look only at whether the
+ // parent is a module.
+ if !item.is_toplevel(context) {
+ continue;
+ }
+
+ let name = item.canonical_name(context);
+ match *item.kind() {
+ ItemKind::Type(ref ty) => {
+ if context.options().whitelisted_types.matches(&name) {
+ item.collect_types(context, &mut items, &());
+ }
+ // Unnamed top-level enums are special and we whitelist
+ // them via the whitelisted_vars filter, since they're
+ // effectively top-level constants, and there's no way
+ // for them to be referenced consistently.
+ if let TypeKind::Enum(ref enum_) = *ty.kind() {
+ if ty.name().is_none() {
+ if enum_.variants().iter().any(|variant| {
+ context.options().whitelisted_vars.matches(&variant.name())
+ }) {
+ item.collect_types(context, &mut items, &());
+ }
+ }
+ }
+ }
+ ItemKind::Function(ref fun) => {
+ if context.options().whitelisted_functions.matches(&name) {
+ items.insert(item.id());
+ fun.signature().collect_types(context, &mut items, &());
+ }
+ }
+ ItemKind::Var(ref var) => {
+ if context.options().whitelisted_vars.matches(&name) {
+ items.insert(item.id());
+ var.ty().collect_types(context, &mut items, &());
+ }
+ }
+ ItemKind::Module(..) => {}
+ }
+ }
+
+ fn contains_parent(ctx: &BindgenContext, types: &ItemSet, id: ItemId) -> bool {
+ let item = ctx.resolve_item(id);
+ let mut last = id;
+ let mut current = item.parent_id();
+
+ while last != current {
+ if types.contains(&current) {
+ return true;
+ }
+ last = current;
+ current = ctx.resolve_item(current).parent_id();
+ }
+
+ false
+ }
+
+ for item_id in items.iter() {
+ let item = context.resolve_item(*item_id);
+ if item.is_toplevel(context) || !contains_parent(context, &items, *item_id) {
+ item.codegen(context, &mut result, &());
+ }
+ }
+ }
+ let saw_union = result.saw_union;
+ let mut result = result.items;
+ if saw_union {
+ utils::prepend_union_types(context, &mut result);
+ }
+ result
+ })
+}
+
+mod utils {
+ use ir::context::BindgenContext;
+ use ir::item::{Item, ItemCanonicalPath, ItemId};
+ use ir::ty::TypeKind;
+ use syntax::ast;
+ use syntax::ptr::P;
+ use std::mem;
+ use super::ItemToRustTy;
+ use aster;
+
+ pub fn prepend_union_types(ctx: &BindgenContext, result: &mut Vec<P<ast::Item>>) {
+ let union_field_decl = quote_item!(ctx.ext_cx(),
+ #[derive(Debug)]
+ #[repr(C)]
+ pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
+ ).unwrap();
+
+ let union_field_impl = quote_item!(&ctx.ext_cx(),
+ impl<T> __BindgenUnionField<T> {
+ #[inline]
+ pub fn new() -> Self {
+ __BindgenUnionField(::std::marker::PhantomData)
+ }
+
+ #[inline]
+ pub unsafe fn as_ref(&self) -> &T {
+ ::std::mem::transmute(self)
+ }
+
+ #[inline]
+ pub unsafe fn as_mut(&mut self) -> &mut T {
+ ::std::mem::transmute(self)
+ }
+ }
+ ).unwrap();
+
+ let union_field_default_impl = quote_item!(&ctx.ext_cx(),
+ impl<T> ::std::default::Default for __BindgenUnionField<T> {
+ #[inline]
+ fn default() -> Self {
+ Self::new()
+ }
+ }
+ ).unwrap();
+
+ let union_field_clone_impl = quote_item!(&ctx.ext_cx(),
+ impl<T> ::std::clone::Clone for __BindgenUnionField<T> {
+ #[inline]
+ fn clone(&self) -> Self {
+ Self::new()
+ }
+ }
+ ).unwrap();
+
+ let union_field_copy_impl = quote_item!(&ctx.ext_cx(),
+ impl<T> ::std::marker::Copy for __BindgenUnionField<T> {}
+ ).unwrap();
+
+ let items = vec![
+ union_field_decl, union_field_impl,
+ union_field_default_impl,
+ union_field_clone_impl,
+ union_field_copy_impl,
+ ];
+
+ let old_items = mem::replace(result, items);
+ result.extend(old_items.into_iter());
+ }
+
+
+ pub fn build_templated_path(item: &Item, ctx: &BindgenContext, only_named: bool) -> P<ast::Ty> {
+ let path = item.canonical_path(ctx);
+
+ let builder = aster::AstBuilder::new().ty().path();
+ let template_args = if only_named {
+ item.applicable_template_args(ctx).iter().filter(|arg| {
+ ctx.resolve_type(**arg).is_named()
+ }).map(|arg| {
+ arg.to_rust_ty(ctx)
+ }).collect::<Vec<_>>()
+ } else {
+ item.applicable_template_args(ctx).iter().map(|arg| {
+ arg.to_rust_ty(ctx)
+ }).collect::<Vec<_>>()
+ };
+
+ // XXX: I suck at aster.
+ if path.len() == 1 {
+ return builder.segment(&path[0])
+ .with_tys(template_args).build().build();
+ }
+
+ let mut builder = builder.id(&path[0]);
+ for (i, segment) in path.iter().skip(1).enumerate() {
+ // Take into account the skip(1)
+ builder = if i == path.len() - 2 {
+ // XXX Extra clone courtesy of the borrow checker.
+ builder.segment(&segment)
+ .with_tys(template_args.clone()).build()
+ } else {
+ builder.segment(&segment).build()
+ }
+ }
+
+ builder.build()
+ }
+
+ fn primitive_ty(ctx: &BindgenContext, name: &str) -> P<ast::Ty> {
+ let ident = ctx.rust_ident_raw(&name);
+ quote_ty!(ctx.ext_cx(), $ident)
+ }
+
+ pub fn type_from_named(ctx: &BindgenContext,
+ name: &str,
+ _inner: ItemId) -> Option<P<ast::Ty>> {
+ // FIXME: We could use the inner item to check this is really a
+ // primitive type but, who the heck overrides these anyway?
+ macro_rules! ty {
+ ($which:ident) => {{
+ primitive_ty(ctx, stringify!($which))
+ }}
+ }
+ Some(match name {
+ "int8_t" => ty!(i8),
+ "uint8_t" => ty!(u8),
+ "int16_t" => ty!(i16),
+ "uint16_t" => ty!(u16),
+ "int32_t" => ty!(i32),
+ "uint32_t" => ty!(u32),
+ "int64_t" => ty!(i64),
+ "uint64_t" => ty!(u64),
+
+ "uintptr_t" |
+ "size_t" => ty!(usize),
+
+ "intptr_t" |
+ "ptrdiff_t" |
+ "ssize_t" => ty!(isize),
+ _ => return None,
+ })
+ }
+
+ pub fn rust_fndecl_from_signature(ctx: &BindgenContext, sig: &Item) -> P<ast::FnDecl> {
+ use codegen::ToRustTy;
+
+ let signature = sig.kind().expect_type();
+ let signature = match *signature.kind() {
+ TypeKind::Function(ref sig) => sig,
+ _ => panic!("How?"),
+ };
+
+ let decl_ty = signature.to_rust_ty(ctx, sig);
+ match decl_ty.unwrap().node {
+ ast::TyKind::BareFn(bare_fn) => bare_fn.unwrap().decl,
+ _ => panic!("How did this happen exactly?"),
+ }
+ }
+}
diff --git a/src/gen.rs b/src/gen.rs
deleted file mode 100644
index eab4478a..00000000
--- a/src/gen.rs
+++ /dev/null
@@ -1,2364 +0,0 @@
-use std;
-use hacks::refcell::RefCell;
-use std::vec::Vec;
-use std::rc::Rc;
-use std::collections::HashMap;
-use syntax::abi::Abi;
-use syntax::ast;
-use syntax::codemap::{Span, respan, ExpnInfo, NameAndSpan, MacroBang};
-use syntax::ext::base;
-use syntax::ext::build::AstBuilder;
-use syntax::ext::expand::ExpansionConfig;
-use syntax::ext::quote::rt::ToTokens;
-use syntax::feature_gate::Features;
-use syntax::parse;
-use syntax::parse::token::{InternedString, intern};
-use syntax::attr::mk_attr_id;
-use syntax::ptr::P;
-use syntax::print::pprust::tts_to_string;
-
-use super::BindgenOptions;
-use super::LinkType;
-use parser::Accessor;
-use types::*;
-use aster;
-
-struct GenCtx<'r> {
- ext_cx: base::ExtCtxt<'r>,
- options: BindgenOptions,
- span: Span,
- module_map: ModuleMap,
- current_module_id: ModuleId,
- saw_union: bool,
-}
-
-impl<'r> GenCtx<'r> {
- fn full_path_for_module(&self, id: ModuleId) -> Vec<String> {
- if !self.options.enable_cxx_namespaces {
- return vec![];
- }
-
- let mut ret = vec![];
-
- let mut current_id = Some(id);
- while let Some(current) = current_id {
- let module = &self.module_map.get(&current).unwrap();
- ret.push(module.name.clone());
- current_id = module.parent_id;
- }
-
- if self.current_module_id == ROOT_MODULE_ID {
- ret.pop(); // The root module doens'n need a root:: in the pattern
- }
-
- ret.reverse();
- ret
- }
-
- fn current_module_mut(&mut self) -> &mut Module {
- let id = self.current_module_id;
- self.module_map.get_mut(&id).expect("Module not found!")
- }
-}
-
-fn first<A, B>((val, _): (A, B)) -> A {
- val
-}
-
-fn ref_eq<T>(thing: &T, other: &T) -> bool {
- (thing as *const T) == (other as *const T)
-}
-
-fn rust_id(ctx: &GenCtx, name: &str) -> (String, bool) {
- let token = parse::token::Ident(ctx.ext_cx.ident_of(name));
- if token.is_any_keyword() ||
- name.contains("@") ||
- name.contains("?") ||
- name.contains("$") ||
- "bool" == name
- {
- let mut s = name.to_owned();
- s = s.replace("@", "_");
- s = s.replace("?", "_");
- s = s.replace("$", "_");
- s.push_str("_");
- (s, true)
- } else {
- (name.to_owned(), false)
- }
-}
-
-fn rust_type_id(ctx: &GenCtx, name: &str) -> String {
- match name {
- "bool" | "uint" | "u8" | "u16" |
- "u32" | "f32" | "f64" | "i8" |
- "i16" | "i32" | "i64" | "Self" |
- "str" => {
- let mut s = name.to_owned();
- s.push_str("_");
- s
- }
- "int8_t" => "i8".to_owned(),
- "uint8_t" => "u8".to_owned(),
- "int16_t" => "i16".to_owned(),
- "uint16_t" => "u16".to_owned(),
- "int32_t" => "i32".to_owned(),
- "uint32_t" => "u32".to_owned(),
- "int64_t" => "i64".to_owned(),
- "uint64_t" => "u64".to_owned(),
- "uintptr_t"
- | "size_t" => "usize".to_owned(),
- "intptr_t"
- | "ptrdiff_t"
- | "ssize_t" => "isize".to_owned(),
- _ => first(rust_id(ctx, name))
- }
-}
-
-fn comp_name(ctx: &GenCtx, kind: CompKind, name: &str) -> String {
- match kind {
- CompKind::Struct => struct_name(ctx, name),
- CompKind::Union => union_name(ctx, name),
- }
-}
-
-fn struct_name(ctx: &GenCtx, name: &str) -> String {
- if ctx.options.rename_types {
- format!("Struct_{}", name)
- } else {
- name.to_owned()
- }
-}
-
-fn union_name(ctx: &GenCtx, name: &str) -> String {
- if ctx.options.rename_types {
- format!("Union_{}", name)
- } else {
- name.to_owned()
- }
-}
-
-fn enum_name(ctx: &GenCtx, name: &str) -> String {
- if ctx.options.rename_types {
- format!("Enum_{}", name)
- } else {
- name.to_owned()
- }
-}
-
-fn gen_unmangle_method(ctx: &mut GenCtx,
- v: &VarInfo,
- counts: &mut HashMap<String, isize>,
- self_kind: Option<ast::Mutability>)
- -> ast::ImplItem {
- let mut fndecl;
- let mut args = vec![];
-
- if let Some(mutability) = self_kind {
- let selfexpr = match mutability {
- ast::Mutability::Immutable => quote_expr!(&ctx.ext_cx, &*self),
- ast::Mutability::Mutable => quote_expr!(&ctx.ext_cx, &mut *self),
- };
- args.push(selfexpr);
- }
-
- match v.ty {
- TFuncPtr(ref sig) => {
- fndecl = cfuncty_to_rs(ctx,
- &*sig.ret_ty, sig.args.as_slice(),
- false);
- let mut unnamed: usize = 0;
- let iter = if !args.is_empty() {
- sig.args[1..].iter()
- } else {
- sig.args.iter()
- };
- for &(ref n, _) in iter {
- let argname = if n.is_empty() {
- unnamed += 1;
- format!("arg{}", unnamed)
- } else {
- first(rust_id(ctx, &n))
- };
- let expr = aster::AstBuilder::new().expr().path()
- .segment(&argname).build().build();
- args.push(expr);
- }
- },
- _ => unreachable!()
- };
-
-
- if let Some(mutability) = self_kind {
- assert!(!fndecl.inputs.is_empty());
- fndecl.inputs[0] = ast::Arg {
- ty: P(ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ast::TyKind::Rptr(None, ast::MutTy {
- ty: P(ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ast::TyKind::ImplicitSelf,
- span: ctx.span
- }),
- mutbl: mutability,
- }),
- span: ctx.span,
- }),
- pat: P(ast::Pat {
- id: ast::DUMMY_NODE_ID,
- node: ast::PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Immutable),
- respan(ctx.span, ctx.ext_cx.ident_of("self")),
- None),
- span: ctx.span,
- }),
- id: ast::DUMMY_NODE_ID,
- };
- }
-
- let sig = ast::MethodSig {
- unsafety: ast::Unsafety::Unsafe,
- abi: Abi::Rust,
- decl: P(fndecl),
- generics: ast::Generics::default(),
- constness: ast::Constness::NotConst,
- };
-
- let mangled_rs = first(rust_id(ctx, &v.mangled));
- let call = P(ast::Expr {
- id: ast::DUMMY_NODE_ID,
- node: ast::ExprKind::Call(
- P(ast::Expr {
- id: ast::DUMMY_NODE_ID,
- node: ast::ExprKind::Path(None, ast::Path {
- span: ctx.span,
- global: false,
- segments: vec![ast::PathSegment {
- identifier: ctx.ext_cx.ident_of(&mangled_rs),
- parameters: ast::PathParameters::none()
- }]
- }),
- span: ctx.span,
- attrs: ast::ThinVec::new(),
- }),
- args
- ),
- span: ctx.span,
- attrs: ast::ThinVec::new(),
- });
-
- let block = ast::Block {
- stmts: vec![
- ast::Stmt {
- id: ast::DUMMY_NODE_ID,
- node: ast::StmtKind::Expr(call),
- span: ctx.span,
- }
- ],
- id: ast::DUMMY_NODE_ID,
- rules: ast::BlockCheckMode::Default,
- span: ctx.span
- };
-
- let mut name = v.name.clone();
- let mut count = 0;
- match counts.get(&v.name) {
- Some(x) => {
- count = *x;
- name.push_str(&x.to_string());
- },
- None => ()
- }
- count += 1;
- counts.insert(v.name.clone(), count);
-
- let mut attrs = mk_doc_attr(ctx, &v.comment);
- attrs.push(respan(ctx.span, ast::Attribute_ {
- id: mk_attr_id(),
- style: ast::AttrStyle::Outer,
- value: P(respan(ctx.span, ast::MetaItemKind::Word(InternedString::new("inline")))),
- is_sugared_doc: false
- }));
-
- let name = first(rust_id(ctx, &name));
-
- ast::ImplItem {
- id: ast::DUMMY_NODE_ID,
- ident: ctx.ext_cx.ident_of(&name),
- vis: ast::Visibility::Public,
- attrs: attrs,
- node: ast::ImplItemKind::Method(sig, P(block)),
- defaultness: ast::Defaultness::Final,
- span: ctx.span
- }
-}
-
-pub fn gen_mods(links: &[(String, LinkType)],
- map: ModuleMap,
- options: BindgenOptions,
- span: Span) -> Vec<P<ast::Item>> {
- // Create a dummy ExtCtxt. We only need this for string interning and that uses TLS.
- let mut features = Features::new();
- features.quote = true;
-
- let cfg = ExpansionConfig::default("xxx".to_owned());
- let sess = parse::ParseSess::new();
- let mut loader = base::DummyMacroLoader;
- let mut ctx = GenCtx {
- ext_cx: base::ExtCtxt::new(&sess, vec![], cfg, &mut loader),
- options: options,
- span: span,
- module_map: map,
- current_module_id: ROOT_MODULE_ID,
- saw_union: false,
- };
-
- ctx.ext_cx.bt_push(ExpnInfo {
- call_site: ctx.span,
- callee: NameAndSpan {
- format: MacroBang(intern("")),
- allow_internal_unstable: false,
- span: None
- }
- });
-
- if let Some(root_mod) = gen_mod(&mut ctx, ROOT_MODULE_ID, links, span) {
- // Move out of the pointer so we can mutate it
- let mut root_mod_item = root_mod.and_then(|item| item);
-
- gen_union_field_definitions_if_necessary(&mut ctx, &mut root_mod_item);
-
- if !ctx.options.enable_cxx_namespaces {
- match root_mod_item.node {
- // XXX This clone might be really expensive, but doing:
- ast::ItemKind::Mod(root) => {
- return root.items;
- }
- _ => unreachable!(),
- }
- }
-
- let ident = root_mod_item.ident;
- let root_export = quote_item!(&ctx.ext_cx, pub use $ident::*;).unwrap();
-
- vec![root_export, P(root_mod_item)]
- } else {
- vec![]
- }
-}
-
-fn gen_mod(mut ctx: &mut GenCtx,
- module_id: ModuleId,
- links: &[(String, LinkType)],
- span: Span) -> Option<P<ast::Item>> {
-
- // XXX avoid this clone
- let module = ctx.module_map.get(&module_id).unwrap().clone();
-
- // Import just the root to minimise name conflicts
- let mut globals = if module_id != ROOT_MODULE_ID {
- // XXX Pass this previously instead of looking it up always?
- let root_ident = ctx.ext_cx.ident_of(&ctx.module_map.get(&ROOT_MODULE_ID).unwrap().name);
- let root_use = quote_item!(&ctx.ext_cx, use $root_ident;).unwrap();
- vec![root_use]
- } else {
- vec![]
- };
-
- ctx.current_module_id = module_id;
-
- globals.extend(gen_globals(&mut ctx, links, &module.globals).into_iter());
-
- globals.extend(module.children_ids.iter().filter_map(|id| {
- gen_mod(ctx, *id, links, span.clone())
- }));
-
- if !globals.is_empty() {
- Some(P(ast::Item {
- ident: ctx.ext_cx.ident_of(&module.name),
- attrs: vec![],
- id: ast::DUMMY_NODE_ID,
- node: ast::ItemKind::Mod(ast::Mod {
- inner: span,
- items: globals,
- }),
- vis: ast::Visibility::Public,
- span: span.clone(),
- }))
- } else {
- None
- }
-}
-
-fn gen_global(mut ctx: &mut GenCtx,
- g: Global,
- defs: &mut Vec<P<ast::Item>>) {
- match g {
- GType(ti) => {
- let t = ti.borrow().clone();
- defs.extend(ctypedef_to_rs(&mut ctx, t).into_iter())
- },
- GCompDecl(ci) => {
- let mut c = ci.borrow().clone();
- let name = comp_name(&ctx, c.kind, &c.name);
- // Use the reference template if any
- while let Some(TComp(ref_template)) = c.ref_template.clone() {
- if c.name != ref_template.borrow().name {
- break;
- }
- c = ref_template.borrow().clone();
- }
- if !c.args.is_empty() &&
- !c.args.iter().any(|a| a.name().map(|name| name.is_empty()).unwrap_or(true)) {
- defs.extend(comp_to_rs(&mut ctx, &name, c).into_iter());
- } else {
- defs.push(opaque_to_rs(&mut ctx, &name, c.layout()));
- }
- },
- GComp(ci) => {
- let c = ci.borrow().clone();
- let name = comp_name(&ctx, c.kind, &c.name);
- defs.extend(comp_to_rs(&mut ctx, &name, c).into_iter())
- },
- GEnumDecl(ei) => {
- let e = ei.borrow().clone();
- let name = enum_name(&ctx, &e.name);
- let dummy = EnumItem::new("_BindgenOpaqueEnum".to_owned(), "".to_owned(), 0);
-
- defs.extend(cenum_to_rs(&mut ctx, &name, e.kind, e.comment, &[dummy], e.layout).into_iter())
- },
- GEnum(ei) => {
- let e = ei.borrow().clone();
- let name = enum_name(&ctx, &e.name);
- defs.extend(cenum_to_rs(&mut ctx, &name, e.kind, e.comment, &e.items, e.layout).into_iter())
- },
- GVar(vi) => {
- let v = vi.borrow();
- let ty = cty_to_rs(&mut ctx, &v.ty, v.is_const, true);
- defs.push(const_to_rs(&mut ctx, &v.name, v.val.unwrap(), ty));
- },
- _ => { }
- }
-}
-
-fn gen_globals(mut ctx: &mut GenCtx,
- links: &[(String, LinkType)],
- globs: &[Global]) -> Vec<P<ast::Item>> {
- let uniq_globs = tag_dup_decl(globs);
-
- let mut fs = vec![];
- let mut vs = vec![];
- let mut gs = vec![];
- for g in uniq_globs.into_iter() {
- match g {
- GOther => {}
- GFunc(_) => fs.push(g),
- GVar(_) => {
- let is_int_const = {
- match g {
- GVar(ref vi) => {
- let v = vi.borrow();
- v.is_const && v.val.is_some()
- }
- _ => unreachable!()
- }
- };
- if is_int_const {
- gs.push(g);
- } else {
- vs.push(g);
- }
- }
- _ => gs.push(g)
- }
- }
-
- let mut defs = vec![];
- gs = remove_redundant_decl(gs);
-
- for mut g in gs.into_iter() {
- if let Some(substituted) = ctx.current_module_mut().translations.remove(&g.name()) {
- match (substituted.layout(), g.layout()) {
- (Some(l), Some(lg)) if l.size == lg.size => {},
- (None, None) => {},
- _ => {
- warn!("warning: substituted type for {} does not match its size", g.name());
- }
- }
- g = substituted;
- }
-
- gen_global(ctx, g, &mut defs);
- }
-
- let mut pending_translations = std::mem::replace(&mut ctx.current_module_mut().translations, HashMap::new());
- for (name, g) in pending_translations.drain() {
- warn!("warning: generating definition for not found type: {}", name);
- gen_global(ctx, g, &mut defs);
- }
-
- let vars: Vec<_> = vs.into_iter().map(|v| {
- match v {
- GVar(vi) => {
- let v = vi.borrow();
- cvar_to_rs(&mut ctx, v.name.clone(), v.mangled.clone(), &v.ty, v.is_const)
- },
- _ => unreachable!()
- }
- }).collect();
-
- let mut unmangle_count: HashMap<String, isize> = HashMap::new();
- let funcs = {
- let func_list = fs.into_iter().map(|f| {
- match f {
- GFunc(vi) => {
- let v = vi.borrow();
- match v.ty {
- TFuncPtr(ref sig) => {
- let mut name = v.name.clone();
- let mut count = 0;
- match unmangle_count.get(&v.name) {
- Some(x) => {
- count = *x;
- name.push_str(&x.to_string());
- },
- None => ()
- }
- count += 1;
- unmangle_count.insert(v.name.clone(), count);
-
- let decl = cfunc_to_rs(&mut ctx, name, v.mangled.clone(), v.comment.clone(),
- &*sig.ret_ty, &sig.args[..],
- sig.is_variadic, ast::Visibility::Public);
- (sig.abi, decl)
- }
- _ => unreachable!()
- }
- },
- _ => unreachable!()
- }
- });
-
- let mut map: HashMap<Abi, Vec<_>> = HashMap::new();
- for (abi, func) in func_list {
- map.entry(abi).or_insert(vec![]).push(func);
- }
- map
- };
-
- if !vars.is_empty() {
- defs.push(mk_extern(&mut ctx, links, vars, Abi::C));
- }
-
- for (abi, funcs) in funcs.into_iter() {
- defs.push(mk_extern(&mut ctx, &links, funcs, abi));
- }
-
- //let attrs = vec!(mk_attr_list(&mut ctx, "allow", ["dead_code", "non_camel_case_types", "uppercase_variables"]));
-
- defs
-}
-
-fn mk_extern(ctx: &GenCtx, links: &[(String, LinkType)],
- foreign_items: Vec<ast::ForeignItem>,
- abi: Abi) -> P<ast::Item> {
- let attrs: Vec<_> = links.iter().map(|&(ref l, ref k)| {
- let k = match *k {
- LinkType::Default => None,
- LinkType::Static => Some("static"),
- LinkType::Framework => Some("framework")
- };
- let link_name = P(respan(ctx.span, ast::MetaItemKind::NameValue(
- InternedString::new("name"),
- respan(ctx.span, ast::LitKind::Str(intern(l).as_str(), ast::StrStyle::Cooked))
- )));
- let link_args = match k {
- None => vec!(link_name),
- Some(ref k) => vec!(link_name, P(respan(ctx.span, ast::MetaItemKind::NameValue(
- InternedString::new("kind"),
- respan(ctx.span, ast::LitKind::Str(intern(k).as_str(), ast::StrStyle::Cooked))
- ))))
- };
- respan(ctx.span, ast::Attribute_ {
- id: mk_attr_id(),
- style: ast::AttrStyle::Outer,
- value: P(respan(ctx.span, ast::MetaItemKind::List(
- InternedString::new("link"),
- link_args)
- )),
- is_sugared_doc: false
- })
- }).collect();
-
- let mut items = vec![];
- items.extend(foreign_items.into_iter());
- let ext = ast::ItemKind::ForeignMod(ast::ForeignMod {
- abi: abi,
- items: items
- });
-
- P(ast::Item {
- ident: ctx.ext_cx.ident_of(""),
- attrs: attrs,
- id: ast::DUMMY_NODE_ID,
- node: ext,
- vis: ast::Visibility::Inherited,
- span: ctx.span
- })
-}
-
-fn mk_impl(_ctx: &GenCtx, ty: P<ast::Ty>,
- items: Vec<ast::ImplItem>)
- -> P<ast::Item> {
- aster::AstBuilder::new().item().impl_().with_items(items).build_ty(ty)
-}
-
-fn remove_redundant_decl(gs: Vec<Global>) -> Vec<Global> {
- fn check_decl(a: &Global, ty: &Type) -> bool {
- match *a {
- GComp(ref ci1) => match *ty {
- TComp(ref ci2) => {
- ref_eq(ci1, ci2) && ci1.borrow().name.is_empty()
- },
- _ => false
- },
- GEnum(ref ei1) => match *ty {
- TEnum(ref ei2) => {
- ref_eq(ei1, ei2) && ei1.borrow().name.is_empty()
- },
- _ => false
- },
- _ => false
- }
- }
-
- let typedefs: Vec<Type> = gs.iter().filter_map(|g|
- match *g {
- GType(ref ti) => Some(ti.borrow().ty.clone()),
- _ => None
- }
- ).collect();
-
- gs.into_iter().filter(|g|
- !typedefs.iter().any(|t| check_decl(g, t))
- ).collect()
-}
-
-fn tag_dup_decl(gs: &[Global]) -> Vec<Global> {
- fn check(name1: &str, name2: &str) -> bool {
- !name1.is_empty() && name1 == name2
- }
-
- fn check_dup(g1: &Global, g2: &Global) -> bool {
- match (g1, g2) {
- (&GType(ref ti1), &GType(ref ti2)) => {
- let a = ti1.borrow();
- let b = ti2.borrow();
- check(&a.name, &b.name)
- },
- (&GComp(ref ci1), &GComp(ref ci2)) => {
- let a = ci1.borrow();
- let b = ci2.borrow();
- check(&a.name, &b.name)
- },
- (&GCompDecl(ref ci1), &GCompDecl(ref ci2)) => {
- let a = ci1.borrow();
- let b = ci2.borrow();
- check(&a.name, &b.name)
- },
- (&GEnum(ref ei1), &GEnum(ref ei2)) => {
- let a = ei1.borrow();
- let b = ei2.borrow();
- check(&a.name, &b.name)
- },
- (&GEnumDecl(ref ei1), &GEnumDecl(ref ei2)) => {
- let a = ei1.borrow();
- let b = ei2.borrow();
- check(&a.name, &b.name)
- },
- (&GVar(ref vi1), &GVar(ref vi2)) => {
- let a = vi1.borrow();
- let b = vi2.borrow();
- check(&a.name, &b.name) &&
- check(&a.mangled, &b.mangled)
- },
- (&GFunc(ref vi1), &GFunc(ref vi2)) => {
- let a = vi1.borrow();
- let b = vi2.borrow();
- check(&a.name, &b.name) &&
- check(&a.mangled, &b.mangled)
- },
- _ => false
- }
- }
-
- fn check_opaque_dup(g1: &Global, g2: &Global) -> bool {
- match (g1, g2) {
- (&GCompDecl(ref ci1), &GComp(ref ci2)) => {
- let a = ci1.borrow();
- let b = ci2.borrow();
- check(&a.name, &b.name)
- },
- (&GEnumDecl(ref ei1), &GEnum(ref ei2)) => {
- let a = ei1.borrow();
- let b = ei2.borrow();
- check(&a.name, &b.name)
- },
- _ => false,
- }
- }
-
- if gs.is_empty() {
- return vec![];
- }
-
- let mut step: Vec<Global> = vec![];
- step.push(gs[0].clone());
-
- for (i, _gsi) in gs.iter().enumerate().skip(1) {
- let mut dup = false;
- for j in 0..i {
- if i == j {
- continue;
- }
- if check_dup(&gs[i], &gs[j]) {
- dup = true;
- break;
- }
- }
- if !dup {
- step.push(gs[i].clone());
- }
- }
-
- let len = step.len();
- let mut res: Vec<Global> = vec![];
- for i in 0..len {
- let mut dup = false;
- match &step[i] {
- &GCompDecl(_) | &GEnumDecl(_) => {
- for j in 0..len {
- if i == j {
- continue;
- }
- if check_opaque_dup(&step[i], &step[j]) {
- dup = true;
- break;
- }
- }
- },
- _ => (),
- }
-
- if !dup {
- res.push(step[i].clone());
- }
- }
-
- res
-}
-
-fn ctypedef_to_rs(ctx: &mut GenCtx, ty: TypeInfo) -> Vec<P<ast::Item>> {
- fn mk_item(ctx: &GenCtx, name: &str, comment: &str, ty: &Type) -> P<ast::Item> {
- let rust_name = rust_type_id(ctx, name);
- let rust_ty = if cty_is_translatable(ty) {
- cty_to_rs(ctx, ty, true, true)
- } else {
- cty_to_rs(ctx, &TVoid, true, true)
- };
- aster::AstBuilder::new().item().pub_()
- .with_attrs(mk_doc_attr(ctx, comment))
- .type_(&rust_name).build_ty(P(rust_ty))
- }
-
- if ty.hide {
- return vec![];
- }
-
- if ty.opaque {
- return mk_opaque_struct(ctx, &ty.name, &ty.layout);
- }
-
- let item = match ty.ty {
- TComp(ref ci) => {
- assert!(!ci.borrow().name.is_empty());
- mk_item(ctx, &ty.name, &ty.comment, &ty.ty)
- },
- TEnum(ref ei) => {
- assert!(!ei.borrow().name.is_empty());
- mk_item(ctx, &ty.name, &ty.comment, &ty.ty)
- },
- _ => mk_item(ctx, &ty.name, &ty.comment, &ty.ty),
- };
-
- vec![item]
-}
-
-fn comp_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo)
- -> Vec<P<ast::Item>> {
- if ci.hide {
- return vec![];
- }
-
- if ci.opaque {
- let name = first(rust_id(ctx, &ci.name));
- return mk_opaque_struct(ctx, &name, &ci.layout());
- }
-
- if ci.has_non_type_template_params ||
- ci.args.iter().any(|f| f == &TVoid) {
- return vec![];
- }
-
- let mut template_args_used = vec![false; ci.args.len()];
-
- match ci.kind {
- CompKind::Struct => cstruct_to_rs(ctx, name, ci, &mut template_args_used),
- CompKind::Union => cunion_to_rs(ctx, name, ci, &mut template_args_used),
- }
-}
-
-fn comp_attrs(ctx: &GenCtx, ci: &CompInfo, name: &str, extra: &mut Vec<P<ast::Item>>) -> Vec<ast::Attribute> {
- let mut attrs = mk_doc_attr(ctx, &ci.comment);
- attrs.push(mk_repr_attr(ctx, &ci.layout()));
- let mut derives = vec![];
-
- if ci.can_derive_debug() && ctx.options.derive_debug {
- derives.push("Debug");
- }
-
- if ci.has_destructor() {
- for attr in ctx.options.dtor_attrs.iter() {
- let attr = ctx.ext_cx.ident_of(attr);
- attrs.push(quote_attr!(&ctx.ext_cx, #[$attr]));
- }
- }
-
- if ci.can_derive_copy() {
- derives.push("Copy");
-
- // TODO: make mk_clone_impl work for template arguments,
- // meanwhile just fallback to deriving.
- if ci.args.is_empty() {
- extra.push(mk_clone_impl(ctx, name));
- } else {
- derives.push("Clone");
- }
- }
-
- if !derives.is_empty() {
- attrs.push(mk_deriving_attr(ctx, &derives));
- }
-
- attrs
-}
-
-fn gen_accessors(ctx: &mut GenCtx, name: &str, ty: &ast::Ty, accessor: Accessor,
- methods: &mut Vec<ast::ImplItem>) {
- if accessor == Accessor::None {
- return;
- }
- let ident = ctx.ext_cx.ident_of(&format!("{}", name));
- let mutable_getter_name = ctx.ext_cx.ident_of(&format!("get_{}_mut", name));
- let getter_name = ctx.ext_cx.ident_of(&format!("get_{}", name));
- let imp = match accessor {
- Accessor::Regular => quote_item!(&ctx.ext_cx,
- impl X {
- #[inline]
- pub fn $getter_name(&self) -> & $ty {
- & self.$ident
- }
- pub fn $mutable_getter_name(&mut self) -> &mut $ty {
- &mut self.$ident
- }
- }
- ),
- Accessor::Unsafe => quote_item!(&ctx.ext_cx,
- impl X {
- #[inline]
- pub unsafe fn $getter_name(&self) -> & $ty {
- & self.$ident
- }
- pub unsafe fn $mutable_getter_name(&mut self) -> &mut $ty {
- &mut self.$ident
- }
- }
- ),
- Accessor::Immutable => quote_item!(&ctx.ext_cx,
- impl X {
- #[inline]
- pub fn $getter_name(&self) -> & $ty {
- & self.$ident
- }
- }
- ),
- _ => return
- };
- match imp.unwrap().node {
- ast::ItemKind::Impl(_, _, _, _, _, ref items) => methods.extend(items.clone()),
- _ => unreachable!()
- }
-}
-
-fn add_extra_template_fields_if_needed(ctx: &GenCtx,
- template_args: &[Type],
- template_args_used: &[bool],
- fields: &mut Vec<ast::StructField>) {
- let mut phantom_count = 0;
- for (i, arg) in template_args.iter().enumerate() {
- if template_args_used[i] {
- continue;
- }
-
- let f_name = format!("_phantom{}", phantom_count);
- phantom_count += 1;
- let inner_type = P(cty_to_rs(ctx, &arg, true, false));
-
- fields.push(ast::StructField {
- span: ctx.span,
- ident: Some(ctx.ext_cx.ident_of(&f_name)),
- vis: ast::Visibility::Public,
- id: ast::DUMMY_NODE_ID,
- ty: quote_ty!(&ctx.ext_cx, ::std::marker::PhantomData<$inner_type>),
- attrs: vec![],
- });
- }
-}
-
-fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo,
- template_args_used: &mut [bool]) -> Vec<P<ast::Item>> {
- let layout = ci.layout();
- let members = &ci.members;
- let template_args = &ci.args;
- let methodlist = &ci.methods;
- let mut fields = vec![];
- let mut methods = vec![];
- // Nested composites may need to emit declarations and implementations as
- // they are encountered. The declarations end up in 'extra' and are emitted
- // after the current struct.
- let mut extra = vec![];
- let mut unnamed: u32 = 0;
- let mut bitfields: u32 = 0;
-
- let id = rust_type_id(ctx, name);
- let id_ty = P(mk_ty(ctx, false, &[id.clone()]));
-
- if ci.has_vtable {
- let mut vffields = vec![];
- let base_vftable = match members.get(0) {
- Some(&CompMember::Field(FieldInfo { ty: TComp(ref ci2), .. })) => {
- let ci2 = ci2.borrow();
- if ci2.has_vtable {
- Some(format!("_vftable_{}", ci2.name))
- } else {
- None
- }
- },
- _ => None,
- };
-
- if let Some(ref base) = base_vftable {
- let field = ast::StructField {
- span: ctx.span,
- vis: ast::Visibility::Public,
- ident: Some(ctx.ext_cx.ident_of("_base")),
- id: ast::DUMMY_NODE_ID,
- ty: P(mk_ty(ctx, false, &[base.clone()])),
- attrs: vec![],
- };
- vffields.push(field);
- }
-
- let mut counts: HashMap<String, isize> = HashMap::new();
- for vm in ci.vmethods.iter() {
- let ty = match vm.ty {
- TFuncPtr(ref sig) => {
- let decl = cfuncty_to_rs(ctx, &*sig.ret_ty, sig.args.as_slice(), sig.is_variadic);
- mk_fn_proto_ty(ctx, &decl, sig.abi)
- },
- _ => unreachable!()
- };
-
- let mut name = vm.name.clone();
- let mut count = 0;
- match counts.get(&vm.name) {
- Some(x) => {
- count = *x;
- name.push_str(&x.to_string());
- },
- None => ()
- }
- count += 1;
- counts.insert(vm.name.clone(), count);
-
- let name = first(rust_id(ctx, &name));
-
- vffields.push(ast::StructField {
- span: ctx.span,
- vis: ast::Visibility::Public,
- ident: Some(ctx.ext_cx.ident_of(&name)),
- id: ast::DUMMY_NODE_ID,
- ty: P(ty),
- attrs: vec![],
- });
- }
-
- // FIXME: rustc actually generates tons of warnings
- // due to an empty repr(C) type, so we just generate
- // a dummy field with pointer-alignment to supress it.
- if vffields.is_empty() {
- vffields.push(mk_blob_field(ctx, "_bindgen_empty_ctype_warning_fix",
- &Layout::new(::std::mem::size_of::<*mut ()>(), ::std::mem::align_of::<*mut ()>())));
- }
-
- let vf_name = format!("_vftable_{}", name);
- let item = aster::AstBuilder::new().item()
- .with_attr(mk_repr_attr(ctx, &layout))
- .pub_()
- .struct_(&vf_name)
- .with_fields(vffields).build();
-
- extra.push(item);
-
- if base_vftable.is_none() {
- let vf_type = mk_ty(ctx, false, &[vf_name]);
- fields.push(ast::StructField {
- span: ctx.span,
- ident: Some(ctx.ext_cx.ident_of("_vftable")),
- vis: ast::Visibility::Public,
- id: ast::DUMMY_NODE_ID,
- ty: P(mk_ptrty(ctx, &vf_type, true)),
- attrs: vec![]
- });
- }
- }
-
- let mut anon_enum_count = 0;
- let mut setters = vec![];
-
- for m in members.iter() {
- match *m {
- CompMember::Enum(ref ei) => {
- let empty_name = ei.borrow().name.is_empty();
- if empty_name {
- ei.borrow_mut().name = format!("{}_enum{}", name, anon_enum_count);
- anon_enum_count += 1;
- }
-
- let e = ei.borrow().clone();
- extra.extend(cenum_to_rs(ctx, &e.name, e.kind, e.comment, &e.items, e.layout).into_iter());
- }
- CompMember::Field(ref f) => {
- let f_name = match f.bitfields {
- Some(_) => {
- bitfields += 1;
- format!("_bitfield_{}", bitfields)
- }
- None => rust_type_id(ctx, &f.name)
- };
-
- let is_translatable = cty_is_translatable(&f.ty);
- if !is_translatable || f.ty.is_opaque() {
- if !is_translatable {
- warn!("{}::{} not translatable, void: {}", ci.name, f.name, f.ty == TVoid);
- }
- if let Some(layout) = f.ty.layout() {
- fields.push(mk_blob_field(ctx, &f_name, &layout));
- }
- continue;
- }
-
- if ctx.options.gen_bitfield_methods {
- let mut offset: u32 = 0;
- if let Some(ref bitfields) = f.bitfields {
- for &(ref bf_name, bf_size) in bitfields.iter() {
- setters.extend(gen_bitfield_methods(ctx, &f_name, bf_name, &f.ty, offset as usize, bf_size).into_iter());
- offset += bf_size;
- }
- setters.push(gen_fullbitfield_method(ctx, &f_name, &f.ty, bitfields))
- }
- }
-
- // If the member is not a template argument, it needs the full path.
- let mut needs_full_path = true;
- for (index, arg) in template_args.iter().enumerate() {
- let used = f.ty.signature_contains_type(arg);
-
- if used {
- template_args_used[index] = true;
- needs_full_path = *arg == f.ty || match f.ty {
- TPtr(ref t, _, _, _) => **t != *arg,
- TArray(ref t, _, _) => **t != *arg,
- _ => true,
- };
- break;
- }
- }
-
- let rust_ty = P(cty_to_rs(ctx, &f.ty, f.bitfields.is_none(), needs_full_path));
-
- // Wrap mutable fields in a Cell/UnsafeCell
- let rust_ty = if f.mutable {
- if !f.ty.can_derive_copy() {
- quote_ty!(&ctx.ext_cx, ::std::cell::UnsafeCell<$rust_ty>)
- // We can only wrap in a cell for non-copiable types, since
- // Cell<T>: Clone, but not Copy.
- //
- // It's fine though, since mutating copiable types is trivial
- // and doesn't make a lot of sense marking fields as `mutable`.
- } else if !ci.can_derive_copy() {
- quote_ty!(&ctx.ext_cx, ::std::cell::Cell<$rust_ty>)
- } else {
- rust_ty
- }
- } else {
- rust_ty
- };
- let vis = if f.private {
- ast::Visibility::Inherited
- } else {
- ast::Visibility::Public
- };
- gen_accessors(ctx, &f_name, &rust_ty, f.accessor, &mut methods);
- let field = ast::StructField {
- span: ctx.span,
- ident: Some(ctx.ext_cx.ident_of(&f_name)),
- vis: vis,
- id: ast::DUMMY_NODE_ID,
- ty: rust_ty,
- attrs: mk_doc_attr(ctx, &f.comment)
- };
- fields.push(field);
- }
- CompMember::Comp(ref rc_c) => {
- let name_is_empty = rc_c.borrow().name.is_empty();
-
- if name_is_empty {
- let c = rc_c.borrow();
- unnamed += 1;
- let field_name = format!("_bindgen_data_{}_", unnamed);
- fields.push(mk_blob_field(ctx, &field_name, &c.layout()));
- methods.extend(gen_comp_methods(ctx, &field_name, 0, c.kind, &c.members, &mut extra).into_iter());
- } else {
- let name = comp_name(&ctx, rc_c.borrow().kind, &rc_c.borrow().name);
- extra.extend(comp_to_rs(ctx, &name, rc_c.borrow().clone()).into_iter());
- }
- }
- }
- }
-
- add_extra_template_fields_if_needed(ctx, template_args,
- template_args_used,
- &mut fields);
-
- if !setters.is_empty() {
- extra.push(mk_impl(ctx, id_ty.clone(), setters));
- }
-
- let field_count = fields.len();
- let variant_data = if fields.is_empty() {
- ast::VariantData::Unit(ast::DUMMY_NODE_ID)
- } else {
- ast::VariantData::Struct(fields, ast::DUMMY_NODE_ID)
- };
-
- let ty_params = mk_ty_params(ctx, &template_args);
-
- let def = ast::ItemKind::Struct(
- variant_data,
- ast::Generics {
- lifetimes: vec![],
- ty_params: P::from_vec(ty_params),
- where_clause: ast::WhereClause {
- id: ast::DUMMY_NODE_ID,
- predicates: vec![]
- }
- }
- );
-
- let attrs = comp_attrs(&ctx, &ci, name, &mut extra);
-
- let struct_def = ast::Item {
- ident: ctx.ext_cx.ident_of(&id),
- attrs: attrs,
- id: ast::DUMMY_NODE_ID,
- node: def,
- vis: ast::Visibility::Public,
- span: ctx.span
- };
-
- let mut items = vec![P(struct_def)];
- if !methods.is_empty() {
- items.push(mk_impl(ctx, id_ty.clone(), methods));
- }
-
- // Template args have incomplete type in general
- //
- // XXX if x is a class without members, C++ still will report
- // sizeof(x) == 1, since it requires to be adressable.
- //
- // We maybe should add a dummy byte if it's the case, but...
- // That could play wrong with inheritance.
- //
- // So for now don't generate a test if the struct/class is empty
- // or has only empty bases.
- if ci.args.is_empty() && field_count > 0 &&
- (ci.has_nonempty_base || ci.base_members < field_count) {
- extra.push(mk_test_fn(ctx, name, &layout));
- }
-
- items.extend(extra.into_iter());
-
- let mut mangledlist = vec![];
- let mut unmangledlist = vec![];
- let mut unmangle_count: HashMap<String, isize> = HashMap::new();
- for v in methodlist {
- let v = v.clone();
- match v.ty {
- TFuncPtr(ref sig) => {
- let name = v.mangled.clone();
- let explicit_self = if v.is_static {
- None
- } else if v.is_const {
- Some(ast::Mutability::Immutable)
- } else {
- Some(ast::Mutability::Mutable)
- };
- unmangledlist.push(gen_unmangle_method(ctx, &v, &mut unmangle_count, explicit_self));
- mangledlist.push(cfunc_to_rs(ctx, name, String::new(), String::new(),
- &*sig.ret_ty, sig.args.as_slice(),
- sig.is_variadic, ast::Visibility::Inherited));
- }
- _ => unreachable!()
- }
- }
- if !mangledlist.is_empty() {
- items.push(mk_extern(ctx, &[], mangledlist, Abi::C));
- items.push(mk_impl(ctx, id_ty, unmangledlist));
- }
-
- if !ci.vars.is_empty() && template_args.is_empty() {
- let vars = ci.vars.into_iter().map(|v| {
- let vi = v.varinfo();
- let v = vi.borrow_mut();
- let mut var_name = v.name.clone();
- if !v.mangled.is_empty() {
- var_name = format!("{}_consts_{}", name, v.name);
- }
- cvar_to_rs(ctx, var_name, v.mangled.clone(), &v.ty, v.is_const)
- }).collect();
-
- items.push(mk_extern(ctx, &[], vars, Abi::C));
- }
- items
-}
-
-fn opaque_to_rs(ctx: &mut GenCtx, name: &str, _layout: Layout) -> P<ast::Item> {
- // XXX can't repr(C) an empty enum
- let id = rust_type_id(ctx, name);
- let ident = ctx.ext_cx.ident_of(&id);
- quote_item!(&ctx.ext_cx, pub enum $ident {}).unwrap()
-}
-
-fn cunion_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo,
- template_args_used: &mut [bool]) -> Vec<P<ast::Item>> {
- const UNION_DATA_FIELD_NAME: &'static str = "_bindgen_data_";
-
- ctx.saw_union = true;
-
- let members = &ci.members;
- let layout = ci.layout();
-
- fn mk_item(ctx: &GenCtx, name: &str, item: ast::ItemKind, vis:
- ast::Visibility, attrs: Vec<ast::Attribute>) -> P<ast::Item> {
- P(ast::Item {
- ident: ctx.ext_cx.ident_of(name),
- attrs: attrs,
- id: ast::DUMMY_NODE_ID,
- node: item,
- vis: vis,
- span: ctx.span
- })
- }
-
- let tmp_ci = Rc::new(RefCell::new(ci.clone()));
- let union = TComp(tmp_ci);
-
-
- // Nested composites may need to emit declarations and implementations as
- // they are encountered. The declarations end up in 'extra' and are emitted
- // after the current union.
- let mut extra = vec![];
-
- fn mk_union_field(ctx: &GenCtx, name: &str, ty: ast::Ty) -> ast::StructField {
- let field_ty = if !ctx.options.enable_cxx_namespaces ||
- ctx.current_module_id == ROOT_MODULE_ID {
- quote_ty!(&ctx.ext_cx, __BindgenUnionField<$ty>)
- } else {
- quote_ty!(&ctx.ext_cx, root::__BindgenUnionField<$ty>)
- };
-
- ast::StructField {
- span: ctx.span,
- ident: Some(ctx.ext_cx.ident_of(name)),
- vis: ast::Visibility::Public,
- id: ast::DUMMY_NODE_ID,
- ty: field_ty,
- attrs: vec![],
- }
- }
-
- let mut fields =
- members.iter().flat_map(|member| {
- if let CompMember::Field(ref f) = *member {
- let mut needs_full_path = true;
- for (index, arg) in ci.args.iter().enumerate() {
- let used = f.ty.signature_contains_type(arg);
-
- if used {
- template_args_used[index] = true;
- needs_full_path = *arg == f.ty || match f.ty {
- TPtr(ref t, _, _, _) => **t != *arg,
- TArray(ref t, _, _) => **t != *arg,
- _ => true,
- };
- break;
- }
- }
-
- let cty = cty_to_rs(ctx, &f.ty, false, needs_full_path);
- Some(mk_union_field(ctx, &f.name, cty))
- } else {
- None
- }
- }).collect::<Vec<_>>();
-
- fields.push(mk_blob_field(ctx, UNION_DATA_FIELD_NAME, &layout));
-
- add_extra_template_fields_if_needed(ctx, &ci.args,
- template_args_used,
- &mut fields);
-
- let ty_params = mk_ty_params(ctx, &ci.args);
-
- let generics = ast::Generics {
- lifetimes: vec![],
- ty_params: P::from_vec(ty_params),
- where_clause: ast::WhereClause {
- id: ast::DUMMY_NODE_ID,
- predicates: vec![]
- }
- };
-
- // TODO: use aster here.
- let def = ast::ItemKind::Struct(
- ast::VariantData::Struct(fields, ast::DUMMY_NODE_ID),
- generics.clone()
- );
-
- let union_id = rust_type_id(ctx, name);
-
- let union_attrs = comp_attrs(&ctx, &ci, name, &mut extra);
-
- if ci.args.is_empty() {
- extra.push(mk_test_fn(ctx, &name, &layout));
- }
-
- let union_def = mk_item(ctx, &union_id, def, ast::Visibility::Public, union_attrs);
- let union_impl = ast::ItemKind::Impl(
- ast::Unsafety::Normal,
- ast::ImplPolarity::Positive,
- generics,
- None,
- P(cty_to_rs(ctx, &union, true, true)),
- gen_comp_methods(ctx, UNION_DATA_FIELD_NAME, 0, CompKind::Union, &members, &mut extra),
- );
- let mut items = vec!(
- union_def,
- mk_item(ctx, "", union_impl, ast::Visibility::Inherited, vec![])
- );
-
- items.extend(extra.into_iter());
- items
-}
-
-fn const_to_rs(ctx: &mut GenCtx, name: &str, val: i64, val_ty: ast::Ty) -> P<ast::Item> {
- let id = first(rust_id(ctx, name));
- aster::AstBuilder::new().item().pub_().const_(&id)
- .expr().int(val)
- .ty().build(P(val_ty))
-}
-
-fn enum_size_to_unsigned_max_value(size: usize) -> u64 {
- match size {
- 1 => std::u8::MAX as u64,
- 2 => std::u16::MAX as u64,
- 4 => std::u32::MAX as u64,
- 8 => std::u64::MAX,
- _ => unreachable!("invalid enum size: {}", size)
- }
-}
-
-fn enum_size_to_rust_type_name(signed: bool, size: usize) -> &'static str {
- match (signed, size) {
- (true, 1) => "i8",
- (false, 1) => "u8",
- (true, 2) => "i16",
- (false, 2) => "u16",
- (true, 4) => "i32",
- (false, 4) => "u32",
- (true, 8) => "i64",
- (false, 8) => "u64",
- _ => {
- warn!("invalid enum decl: signed: {}, size: {}", signed, size);
- "i32"
- }
- }
-}
-
-fn cenum_value_to_int_lit(ctx: &mut GenCtx,
- enum_is_signed: bool,
- size: usize,
- value: i64) -> P<ast::Expr> {
- if enum_is_signed {
- if value == std::i64::MIN {
- let lit = ast::LitKind::Int(std::u64::MAX, ast::LitIntType::Unsuffixed);
- ctx.ext_cx.expr_lit(ctx.span, lit)
- } else {
- let lit = ast::LitKind::Int(value.abs() as u64, ast::LitIntType::Unsuffixed);
- let expr = ctx.ext_cx.expr_lit(ctx.span, lit);
- if value < 0 {
- ctx.ext_cx.expr(ctx.span, ast::ExprKind::Unary(ast::UnOp::Neg, expr))
- } else {
- expr
- }
- }
- } else {
- let u64_value = value as u64 & enum_size_to_unsigned_max_value(size);
- let int_lit = ast::LitKind::Int(u64_value, ast::LitIntType::Unsuffixed);
- ctx.ext_cx.expr_lit(ctx.span, int_lit)
- }
-}
-
-fn cenum_to_rs(ctx: &mut GenCtx,
- name: &str,
- kind: IKind,
- comment: String,
- enum_items: &[EnumItem],
- layout: Layout) -> Vec<P<ast::Item>> {
- let enum_name = ctx.ext_cx.ident_of(name);
- let enum_ty = ctx.ext_cx.ty_ident(ctx.span, enum_name);
- let enum_is_signed = kind.is_signed();
- let enum_repr = enum_size_to_rust_type_name(enum_is_signed, layout.size);
-
- let mut items = vec![];
-
- if !ctx.options.rust_enums {
- items.push(ctx.ext_cx.item_ty(ctx.span,
- enum_name,
- ctx.ext_cx.ty_ident(ctx.span,
- ctx.ext_cx.ident_of(enum_repr))));
- for item in enum_items {
- let value = cenum_value_to_int_lit(ctx, enum_is_signed, layout.size, item.val);
- let name = first(rust_id(ctx, &item.name));
- items.push(ctx.ext_cx.item_const(ctx.span, ctx.ext_cx.ident_of(&name), enum_ty.clone(), value));
- }
- return items;
- }
-
- let mut variants = vec![];
- let mut found_values = HashMap::new();
- for item in enum_items {
- let name = first(rust_id(ctx, &item.name));
- let name = ctx.ext_cx.ident_of(&name);
- if let Some(orig) = found_values.get(&item.val) {
- let value = ctx.ext_cx.expr_path(
- ctx.ext_cx.path(ctx.span, vec![enum_name, *orig]));
- items.push(P(ast::Item {
- ident: name,
- attrs: vec![],
- id: ast::DUMMY_NODE_ID,
- node: ast::ItemKind::Const(enum_ty.clone(), value),
- vis: ast::Visibility::Public,
- span: ctx.span,
- }));
- continue;
- }
-
- found_values.insert(item.val, name);
- let value = cenum_value_to_int_lit(
- ctx, enum_is_signed, layout.size, item.val);
-
- variants.push(respan(ctx.span, ast::Variant_ {
- name: name,
- attrs: vec![],
- data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
- disr_expr: Some(value),
- }));
- }
-
- let enum_repr = InternedString::new(enum_repr);
-
- let repr_arg = ctx.ext_cx.meta_word(ctx.span, enum_repr);
- let repr_list = ctx.ext_cx.meta_list(ctx.span, InternedString::new("repr"), vec![repr_arg]);
-
- let mut attrs = mk_doc_attr(ctx, &comment);
- attrs.push(respan(ctx.span, ast::Attribute_ {
- id: mk_attr_id(),
- style: ast::AttrStyle::Outer,
- value: repr_list,
- is_sugared_doc: false,
- }));
-
- attrs.push(if ctx.options.derive_debug {
- mk_deriving_attr(ctx, &["Debug", "Copy", "Clone", "Eq", "PartialEq", "Hash"])
- } else {
- mk_deriving_attr(ctx, &["Copy", "Clone", "Eq", "PartialEq", "Hash"])
- });
-
- items.push(P(ast::Item {
- ident: enum_name,
- attrs: attrs,
- id: ast::DUMMY_NODE_ID,
- node: ast::ItemKind::Enum(ast::EnumDef { variants: variants }, ast::Generics::default()),
- vis: ast::Visibility::Public,
- span: ctx.span,
- }));
-
- items
-}
-
-/// Generates accessors for fields in nested structs and unions which must be
-/// represented in Rust as an untyped array. This process may generate
-/// declarations and implementations that must be placed at the root level.
-/// These are emitted into `extra`.
-fn gen_comp_methods(ctx: &mut GenCtx, data_field: &str, data_offset: usize,
- kind: CompKind, members: &[CompMember],
- extra: &mut Vec<P<ast::Item>>) -> Vec<ast::ImplItem> {
- let mk_field_method = |ctx: &mut GenCtx, f: &FieldInfo, offset: usize| {
- // TODO: Implement bitfield accessors
- if f.bitfields.is_some() { return None; }
-
- let f_name = first(rust_id(ctx, &f.name));
- let ret_ty = P(cty_to_rs(ctx, &TPtr(Box::new(f.ty.clone()), false, false, Layout::zero()), true, true));
-
- // When the offset is zero, generate slightly prettier code.
- let method = {
- let impl_str = format!(r"
- impl X {{
- pub unsafe fn {}(&mut self) -> {} {{
- let raw: *mut u8 = ::std::mem::transmute(&self.{});
- ::std::mem::transmute(raw.offset({}))
- }}
- }}
- ", f_name, tts_to_string(&ret_ty.to_tokens(&ctx.ext_cx)[..]), data_field, offset);
-
- parse::new_parser_from_source_str(ctx.ext_cx.parse_sess(),
- ctx.ext_cx.cfg(), "".to_string(), impl_str).parse_item().unwrap().unwrap()
- };
-
- method.and_then(|i| {
- match i.node {
- ast::ItemKind::Impl(_, _, _, _, _, mut items) => {
- items.pop()
- }
- _ => unreachable!("impl parsed to something other than impl")
- }
- })
- };
-
- let mut offset = data_offset;
- let mut methods = vec![];
- for m in members.into_iter() {
- let advance_by = match *m {
- CompMember::Field(ref f) => {
- if ctx.options.gen_bitfield_methods {
- methods.extend(mk_field_method(ctx, f, offset).into_iter());
- }
- f.ty.size()
- }
- CompMember::Comp(ref rc_c) => {
- let c = rc_c.borrow();
- let name = comp_name(&ctx, c.kind, &c.name);
- extra.extend(comp_to_rs(ctx, &name, c.clone()).into_iter());
- c.layout().size
- }
- CompMember::Enum(_) => 0
- };
- match kind {
- CompKind::Struct => { offset += advance_by; }
- CompKind::Union => { }
- }
- }
- methods
-}
-
-fn type_for_bitfield_width(ctx: &mut GenCtx, width: u32, is_arg: bool) -> ast::Ty {
- let input_type = if width > 16 {
- "u32"
- } else if width > 8 {
- "u16"
- } else if width > 1 {
- "u8"
- } else {
- if is_arg {
- "bool"
- } else {
- "u8"
- }
- };
- mk_ty(ctx, false, &[input_type.to_owned()])
-}
-
-fn gen_bitfield_methods(ctx: &mut GenCtx, bindgen_name: &str,
- field_name: &str, field_type: &Type,
- offset: usize, width: u32) -> Vec<ast::ImplItem> {
- let input_type = type_for_bitfield_width(ctx, width, true);
- let width = width as usize;
-
- let field_type = cty_to_rs(ctx, field_type, false, true);
-
- let real_field_name = if field_name.is_empty() {
- format!("at_offset_{}", offset)
- } else {
- field_name.into()
- };
-
-
- let bindgen_ident = ctx.ext_cx.ident_of(bindgen_name);
- let setter_name = ctx.ext_cx.ident_of(&format!("set_{}", real_field_name));
- let getter_name = ctx.ext_cx.ident_of(&real_field_name);
-
- let mask = ((1usize << width) - 1) << offset;
- let item = quote_item!(&ctx.ext_cx,
- impl X {
- #[inline]
- pub fn $getter_name(&self) -> $field_type {
- (self.$bindgen_ident & ($mask as $field_type)) >> $offset
- }
-
- #[inline]
- pub fn $setter_name(&mut self, val: $input_type) {
- self.$bindgen_ident &= !($mask as $field_type);
- self.$bindgen_ident |= (val as $field_type << $offset) & ($mask as $field_type);
- }
- }
- ).unwrap();
-
- match item.node {
- ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(),
- _ => unreachable!()
- }
-}
-
-fn gen_fullbitfield_method(ctx: &mut GenCtx, bindgen_name: &String,
- bitfield_type: &Type, bitfields: &[(String, u32)]) -> ast::ImplItem {
- let field_type = cty_to_rs(ctx, bitfield_type, false, true);
- let mut args = vec![];
- let mut unnamed: usize = 0;
- for &(ref name, width) in bitfields.iter() {
- let ident = if name.is_empty() {
- unnamed += 1;
- let dummy = format!("unnamed_bitfield{}", unnamed);
- ctx.ext_cx.ident_of(&dummy)
- } else {
- ctx.ext_cx.ident_of(name)
- };
- args.push(ast::Arg {
- ty: P(type_for_bitfield_width(ctx, width, true)),
- pat: P(ast::Pat {
- id: ast::DUMMY_NODE_ID,
- node: ast::PatKind::Ident(
- ast::BindingMode::ByValue(ast::Mutability::Immutable),
- respan(ctx.span, ident),
- None
- ),
- span: ctx.span
- }),
- id: ast::DUMMY_NODE_ID,
- });
- }
-
- let fndecl = ast::FnDecl {
- inputs: args,
- output: ast::FunctionRetTy::Ty(P(field_type.clone())),
- variadic: false
- };
-
- let mut offset = 0;
-
- let mut exprs = quote_expr!(&ctx.ext_cx, 0);
-
- let mut unnamed: usize = 0;
- for &(ref name, width) in bitfields.iter() {
- let name_ident = if name.is_empty() {
- unnamed += 1;
- let dummy = format!("unnamed_bitfield{}", unnamed);
- ctx.ext_cx.ident_of(&dummy)
- } else {
- ctx.ext_cx.ident_of(name)
- };
- exprs = quote_expr!(&ctx.ext_cx,
- $exprs | (($name_ident as $field_type) << $offset)
- );
-
- offset += width;
- }
-
- let block = ast::Block {
- stmts: vec![
- ast::Stmt {
- id: ast::DUMMY_NODE_ID,
- node: ast::StmtKind::Expr(exprs),
- span: ctx.span,
- }
- ],
- id: ast::DUMMY_NODE_ID,
- rules: ast::BlockCheckMode::Default,
- span: ctx.span
- };
-
- let mut attrs = vec![];
-
- let node = ast::ImplItemKind::Method(
- ast::MethodSig {
- unsafety: ast::Unsafety::Normal,
- abi: Abi::Rust,
- decl: P(fndecl),
- generics: ast::Generics::default(),
- constness: if ctx.options.unstable_rust {
- ast::Constness::Const
- } else {
- attrs.push(quote_attr!(&ctx.ext_cx, #[inline]));
- ast::Constness::NotConst
- },
- }, P(block)
- );
-
- ast::ImplItem {
- id: ast::DUMMY_NODE_ID,
- ident: ctx.ext_cx.ident_of(&format!("new{}", bindgen_name)),
- vis: ast::Visibility::Public,
- attrs: attrs,
- node: node,
- span: ctx.span,
- defaultness: ast::Defaultness::Final,
- }
-}
-
-fn mk_blob_field(ctx: &GenCtx, name: &str, layout: &Layout) -> ast::StructField {
- let ty_name = match layout.align {
- 8 => "u64",
- 4 => "u32",
- 2 => "u16",
- 1 | _ => "u8",
- };
- let data_len = if ty_name == "u8" { layout.size } else { layout.size / layout.align };
-
- let base_ty = mk_ty(ctx, false, &[ty_name.to_owned()]);
- let data_ty = if data_len == 1 {
- P(base_ty)
- } else {
- P(mk_arrty(ctx, &base_ty, data_len))
- };
- ast::StructField {
- span: ctx.span,
- vis: ast::Visibility::Public,
- ident: Some(ctx.ext_cx.ident_of(name)),
- id: ast::DUMMY_NODE_ID,
- ty: data_ty,
- attrs: vec![]
- }
-}
-
-fn mk_link_name_attr(ctx: &GenCtx, name: String) -> ast::Attribute {
- let lit = respan(ctx.span, ast::LitKind::Str(intern(&name).as_str(), ast::StrStyle::Cooked));
- let attr_val = P(respan(ctx.span, ast::MetaItemKind::NameValue(
- InternedString::new("link_name"), lit
- )));
- let attr = ast::Attribute_ {
- id: mk_attr_id(),
- style: ast::AttrStyle::Outer,
- value: attr_val,
- is_sugared_doc: false
- };
- respan(ctx.span, attr)
-}
-
-fn mk_repr_attr(ctx: &GenCtx, layout: &Layout) -> ast::Attribute {
- let mut values = vec!(P(respan(ctx.span, ast::MetaItemKind::Word(InternedString::new("C")))));
- if layout.packed {
- values.push(P(respan(ctx.span, ast::MetaItemKind::Word(InternedString::new("packed")))));
- }
- let attr_val = P(respan(ctx.span, ast::MetaItemKind::List(
- InternedString::new("repr"),
- values
- )));
-
- respan(ctx.span, ast::Attribute_ {
- id: mk_attr_id(),
- style: ast::AttrStyle::Outer,
- value: attr_val,
- is_sugared_doc: false
- })
-}
-
-// NB: This requires that the type you implement it for also
-// implements Copy.
-//
-// Implements std::clone::Clone using dereferencing.
-//
-// This is to bypass big arrays not implementing clone,
-// but implementing copy due to hacks inside rustc's internals.
-fn mk_clone_impl(ctx: &GenCtx, ty_name: &str) -> P<ast::Item> {
- let impl_str = format!(r"
- impl ::std::clone::Clone for {} {{
- fn clone(&self) -> Self {{ *self }}
- }}
- ", ty_name);
-
- parse::new_parser_from_source_str(ctx.ext_cx.parse_sess(),
- ctx.ext_cx.cfg(), "".to_owned(), impl_str).parse_item().unwrap().unwrap()
-}
-
-fn mk_deriving_attr(ctx: &GenCtx, attrs: &[&'static str]) -> ast::Attribute {
- let attr_val = P(respan(ctx.span, ast::MetaItemKind::List(
- InternedString::new("derive"),
- attrs.iter().map(|attr| {
- P(respan(ctx.span, ast::MetaItemKind::Word(InternedString::new(attr))))
- }).collect()
- )));
-
- respan(ctx.span, ast::Attribute_ {
- id: mk_attr_id(),
- style: ast::AttrStyle::Outer,
- value: attr_val,
- is_sugared_doc: false
- })
-}
-
-fn mk_doc_attr(ctx: &GenCtx, doc: &str) -> Vec<ast::Attribute> {
- if doc.is_empty() {
- return vec![];
- }
-
- let attr_val = P(respan(ctx.span, ast::MetaItemKind::NameValue(
- InternedString::new("doc"),
- respan(ctx.span, ast::LitKind::Str(intern(doc).as_str(), ast::StrStyle::Cooked))
- )));
-
- vec!(respan(ctx.span, ast::Attribute_ {
- id: mk_attr_id(),
- style: ast::AttrStyle::Outer,
- value: attr_val,
- is_sugared_doc: true
- }))
-}
-
-fn cvar_to_rs(ctx: &mut GenCtx, name: String,
- mangled: String, ty: &Type,
- is_const: bool) -> ast::ForeignItem {
- let (rust_name, was_mangled) = rust_id(ctx, &name);
-
- let mut attrs = vec![];
- if !mangled.is_empty() {
- attrs.push(mk_link_name_attr(ctx, mangled));
- } else if was_mangled {
- attrs.push(mk_link_name_attr(ctx, name));
- }
-
- let val_ty = P(cty_to_rs(ctx, ty, true, true));
-
- ast::ForeignItem {
- ident: ctx.ext_cx.ident_of(&rust_name),
- attrs: attrs,
- node: ast::ForeignItemKind::Static(val_ty, !is_const),
- id: ast::DUMMY_NODE_ID,
- span: ctx.span,
- vis: ast::Visibility::Public,
- }
-}
-
-fn cfuncty_to_rs(ctx: &GenCtx,
- rty: &Type,
- aty: &[(String, Type)],
- var: bool) -> ast::FnDecl {
-
- let ret = match *rty {
- TVoid => ast::FunctionRetTy::Default(ctx.span),
- // Disable references in returns for now
- TPtr(ref t, is_const, _, ref layout) =>
- ast::FunctionRetTy::Ty(P(cty_to_rs(ctx, &TPtr(t.clone(), is_const, false, layout.clone()), true, true))),
- _ => ast::FunctionRetTy::Ty(P(cty_to_rs(ctx, rty, true, true)))
- };
-
- let mut unnamed: usize = 0;
- let args: Vec<ast::Arg> = aty.iter().map(|arg| {
- let (ref n, ref t) = *arg;
-
- let arg_name = if n.is_empty() {
- unnamed += 1;
- format!("arg{}", unnamed)
- } else {
- first(rust_id(ctx, &n))
- };
-
- // From the C90 standard (http://c0x.coding-guidelines.com/6.7.5.3.html)
- // 1598 - A declaration of a parameter as “array of type” shall be
- // adjusted to “qualified pointer to type”, where the type qualifiers
- // (if any) are those specified within the [ and ] of the array type
- // derivation.
- let arg_ty = P(match *t {
- TArray(ref typ, _, l) => cty_to_rs(ctx, &TPtr(typ.clone(), false, false, l), true, true),
- _ => cty_to_rs(ctx, t, true, true),
- });
-
- ast::Arg {
- ty: arg_ty,
- pat: P(ast::Pat {
- id: ast::DUMMY_NODE_ID,
- node: ast::PatKind::Ident(
- ast::BindingMode::ByValue(ast::Mutability::Immutable),
- respan(ctx.span, ctx.ext_cx.ident_of(&arg_name)),
- None
- ),
- span: ctx.span
- }),
- id: ast::DUMMY_NODE_ID,
- }
- }).collect();
-
- let var = !args.is_empty() && var;
- ast::FnDecl {
- inputs: args,
- output: ret,
- variadic: var
- }
-}
-
-fn cfunc_to_rs(ctx: &mut GenCtx,
- name: String,
- mangled: String,
- comment: String,
- rty: &Type,
- aty: &[(String, Type)],
- var: bool,
- vis: ast::Visibility) -> ast::ForeignItem {
- let var = !aty.is_empty() && var;
- let decl = ast::ForeignItemKind::Fn(
- P(cfuncty_to_rs(ctx, rty, aty, var)),
- ast::Generics::default()
- );
-
- let (rust_name, was_mangled) = rust_id(ctx, &name);
-
- let mut attrs = mk_doc_attr(ctx, &comment);
- if !mangled.is_empty() {
- attrs.push(mk_link_name_attr(ctx, mangled));
- } else if was_mangled {
- attrs.push(mk_link_name_attr(ctx, name));
- }
-
- ast::ForeignItem {
- ident: ctx.ext_cx.ident_of(&rust_name),
- attrs: attrs,
- node: decl,
- id: ast::DUMMY_NODE_ID,
- span: ctx.span,
- vis: vis,
- }
-}
-
-fn cty_to_rs(ctx: &GenCtx, ty: &Type, allow_bool: bool, use_full_path: bool) -> ast::Ty {
- let prefix = vec!["std".to_owned(), "os".to_owned(), "raw".to_owned()];
- let raw = |fragment: &str| {
- let mut path = prefix.clone();
- path.push(fragment.to_owned());
- path
- };
-
- match *ty {
- TVoid => mk_ty(ctx, true, &raw("c_void")),
- TInt(i, ref layout) => match i {
- IBool => {
- let ty_name = match layout.size {
- 1 if allow_bool => "bool",
- 2 => "u16",
- 4 => "u32",
- 8 => "u64",
- _ => "u8",
- };
- mk_ty(ctx, false, &[ty_name.to_owned()])
- },
- ISChar => mk_ty(ctx, true, &raw("c_char")),
- IUChar => mk_ty(ctx, true, &raw("c_uchar")),
- IInt => mk_ty(ctx, true, &raw("c_int")),
- IUInt => mk_ty(ctx, true, &raw("c_uint")),
- IShort => mk_ty(ctx, true, &raw("c_short")),
- IUShort => mk_ty(ctx, true, &raw("c_ushort")),
- ILong => mk_ty(ctx, true, &raw("c_long")),
- IULong => mk_ty(ctx, true, &raw("c_ulong")),
- ILongLong => mk_ty(ctx, true, &raw("c_longlong")),
- IULongLong => mk_ty(ctx, true, &raw("c_ulonglong"))
- },
- TFloat(f, _) => match f {
- FFloat => mk_ty(ctx, false, &["f32".to_owned()]),
- FDouble => mk_ty(ctx, false, &["f64".to_owned()])
- },
- TPtr(ref t, is_const, _is_ref, _) => {
- let id = cty_to_rs(ctx, &**t, allow_bool, use_full_path);
- mk_ptrty(ctx, &id, is_const)
- },
- TArray(ref t, s, _) => {
- let ty = cty_to_rs(ctx, &**t, allow_bool, use_full_path);
- mk_arrty(ctx, &ty, s)
- },
- TFuncPtr(ref sig) => {
- let decl = cfuncty_to_rs(ctx, &*sig.ret_ty, &sig.args[..], sig.is_variadic);
- mk_fnty(ctx, &decl, sig.abi)
- },
- TFuncProto(ref sig) => {
- let decl = cfuncty_to_rs(ctx, &*sig.ret_ty, &sig.args[..], sig.is_variadic);
- mk_fn_proto_ty(ctx, &decl, sig.abi)
- },
- TNamed(ref ti) => {
- let id = rust_type_id(ctx, &ti.borrow().name);
-
- if use_full_path {
- let mut path = ctx.full_path_for_module(ti.borrow().module_id);
- path.push(id);
- mk_ty(ctx, false, &path)
- } else {
- mk_ty(ctx, false, &[id])
- }
- },
- TComp(ref ci) => {
- let c = ci.borrow();
- let id = comp_name(&ctx, c.kind, &c.name);
-
- let args = c.args.iter().map(|gt| {
- P(cty_to_rs(ctx, gt, allow_bool, false))
- }).collect();
-
- if use_full_path {
- let mut path = ctx.full_path_for_module(c.module_id());
- path.push(id);
- mk_ty_args(ctx, false, &path, args)
- } else {
- mk_ty_args(ctx, false, &[id], args)
- }
- },
- TEnum(ref ei) => {
- let e = ei.borrow();
- let id = enum_name(&ctx, &e.name);
-
- if use_full_path {
- let mut path = ctx.full_path_for_module(e.module_id);
- path.push(id);
- mk_ty(ctx, false, &path)
- } else {
- mk_ty(ctx, false, &[id])
- }
- }
- }
-}
-
-fn cty_is_translatable(ty: &Type) -> bool {
- match *ty {
- TVoid => false,
- TArray(ref t, _, _) => {
- cty_is_translatable(&**t)
- },
- TComp(ref ci) => {
- let c = ci.borrow();
- !c.args.iter().any(|gt| gt == &TVoid) && !c.has_non_type_template_params
- },
- _ => true,
- }
-}
-
-fn mk_ty(ctx: &GenCtx, global: bool, segments: &[String]) -> ast::Ty {
- mk_ty_args(ctx, global, segments, vec![])
-}
-
-fn mk_ty_args(ctx: &GenCtx, global: bool, segments: &[String], args: Vec<P<ast::Ty>>) -> ast::Ty {
- let segment_count = segments.len();
- let ty = ast::TyKind::Path(
- None,
- ast::Path {
- span: ctx.span,
- global: global,
- segments: segments.iter().enumerate().map(|(i, s)| {
- ast::PathSegment {
- identifier: ctx.ext_cx.ident_of(s),
- parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
- lifetimes: vec![],
- types: if i == segment_count - 1 { P::from_vec(args.clone()) } else { P::new() },
- bindings: P::new(),
- }),
- }
- }).collect()
- },
- );
-
- ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ty,
- span: ctx.span
- }
-}
-
-fn mk_ptrty(ctx: &GenCtx, base: &ast::Ty, is_const: bool) -> ast::Ty {
- let ty = ast::TyKind::Ptr(ast::MutTy {
- ty: P(base.clone()),
- mutbl: if is_const { ast::Mutability::Immutable } else { ast::Mutability::Mutable }
- });
-
- ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ty,
- span: ctx.span
- }
-}
-
-#[allow(dead_code)]
-fn mk_refty(ctx: &mut GenCtx, base: &ast::Ty, is_const: bool) -> ast::Ty {
- let ty = ast::TyKind::Rptr(
- None,
- ast::MutTy {
- ty: P(base.clone()),
- mutbl: if is_const { ast::Mutability::Immutable } else { ast::Mutability::Mutable }
- }
- );
-
- ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ty,
- span: ctx.span
- }
-}
-
-fn mk_arrty(ctx: &GenCtx, base: &ast::Ty, n: usize) -> ast::Ty {
- let int_lit = ast::LitKind::Int(n as u64, ast::LitIntType::Unsigned(ast::UintTy::Us));
- let sz = ast::ExprKind::Lit(P(respan(ctx.span, int_lit)));
- let ty = ast::TyKind::FixedLengthVec(
- P(base.clone()),
- P(ast::Expr {
- id: ast::DUMMY_NODE_ID,
- node: sz,
- span: ctx.span,
- attrs: ast::ThinVec::new(),
- })
- );
-
- ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ty,
- span: ctx.span
- }
-}
-
-fn mk_fn_proto_ty(ctx: &GenCtx,
- decl: &ast::FnDecl,
- abi: Abi) -> ast::Ty {
- let fnty = ast::TyKind::BareFn(P(ast::BareFnTy {
- unsafety: ast::Unsafety::Unsafe,
- abi: abi,
- lifetimes: vec![],
- decl: P(decl.clone())
- }));
-
- ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: fnty,
- span: ctx.span,
- }
-}
-
-fn mk_fnty(ctx: &GenCtx, decl: &ast::FnDecl, abi: Abi) -> ast::Ty {
- let fnty = ast::TyKind::BareFn(P(ast::BareFnTy {
- unsafety: ast::Unsafety::Unsafe,
- abi: abi,
- lifetimes: vec![],
- decl: P(decl.clone())
- }));
-
- let segs = vec![
- ast::PathSegment {
- identifier: ctx.ext_cx.ident_of("std"),
- parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
- lifetimes: vec![],
- types: P::new(),
- bindings: P::new(),
- }),
- },
- ast::PathSegment {
- identifier: ctx.ext_cx.ident_of("option"),
- parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
- lifetimes: vec![],
- types: P::new(),
- bindings: P::new(),
- }),
- },
- ast::PathSegment {
- identifier: ctx.ext_cx.ident_of("Option"),
- parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
- lifetimes: vec![],
- types: P::from_vec(vec![
- P(ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: fnty,
- span: ctx.span
- })
- ]),
- bindings: P::new(),
- }),
- }
- ];
-
- ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ast::TyKind::Path(
- None,
- ast::Path {
- span: ctx.span,
- global: true,
- segments: segs
- },
- ),
- span: ctx.span
- }
-}
-
-fn mk_test_fn(ctx: &GenCtx, name: &str, layout: &Layout) -> P<ast::Item> {
- let size = layout.size;
- let align = layout.align;
- let struct_name = ctx.ext_cx.ident_of(name);
-
- let fn_name = ctx.ext_cx.ident_of(&format!("bindgen_test_layout_{}", name));
-
- let size_of_expr = quote_expr!(&ctx.ext_cx, ::std::mem::size_of::<$struct_name>());
- let align_of_expr = quote_expr!(&ctx.ext_cx, ::std::mem::align_of::<$struct_name>());
- let item = quote_item!(&ctx.ext_cx,
- #[test]
- fn $fn_name() {
- assert_eq!($size_of_expr, $size);
- assert_eq!($align_of_expr, $align);
- }).unwrap();
- item
-}
-
-fn mk_opaque_struct(ctx: &GenCtx, name: &str, layout: &Layout) -> Vec<P<ast::Item>> {
- let blob_field = mk_blob_field(ctx, "_bindgen_opaque_blob", layout);
- let variant_data = if layout.size == 0 {
- ast::VariantData::Unit(ast::DUMMY_NODE_ID)
- } else {
- ast::VariantData::Struct(vec![blob_field], ast::DUMMY_NODE_ID)
- };
-
- let def = ast::ItemKind::Struct(
- variant_data,
- ast::Generics {
- lifetimes: vec![],
- ty_params: P::new(),
- where_clause: ast::WhereClause {
- id: ast::DUMMY_NODE_ID,
- predicates: vec![]
- }
- }
- );
-
- let struct_decl = P(ast::Item {
- ident: ctx.ext_cx.ident_of(&name),
- attrs: vec![mk_repr_attr(ctx, layout)],
- id: ast::DUMMY_NODE_ID,
- node: def,
- vis: ast::Visibility::Public,
- span: ctx.span
- });
-
- let mut ret = vec![struct_decl];
-
- // The test should always be correct but...
- if *layout != Layout::zero() {
- ret.push(mk_test_fn(ctx, &name, layout));
- }
-
- ret
-}
-
-/// Generates a vector of rust's ty params from a list of types
-fn mk_ty_params(ctx: &GenCtx, template_args: &[Type]) -> Vec<ast::TyParam> {
- template_args.iter().map(|gt| {
- let name = match *gt {
- TNamed(ref ti) => {
- ctx.ext_cx.ident_of(&ti.borrow().name)
- },
- _ => ctx.ext_cx.ident_of("")
- };
- ast::TyParam {
- ident: name,
- id: ast::DUMMY_NODE_ID,
- bounds: P::new(),
- default: None,
- span: ctx.span
- }
- }).collect()
-}
-
-fn gen_union_field_definitions_if_necessary(ctx: &mut GenCtx, mut root_mod: &mut ast::Item) {
- if !ctx.saw_union {
- return;
- }
-
- let union_field_decl = quote_item!(&ctx.ext_cx,
- #[derive(Copy, Debug)]
- #[repr(C)]
- pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
- ).unwrap();
-
- let union_field_impl = quote_item!(&ctx.ext_cx,
- impl<T> __BindgenUnionField<T> {
- #[inline]
- pub fn new() -> Self {
- __BindgenUnionField(::std::marker::PhantomData)
- }
-
- #[inline]
- pub unsafe fn as_ref(&self) -> &T {
- ::std::mem::transmute(self)
- }
-
- #[inline]
- pub unsafe fn as_mut(&mut self) -> &mut T {
- ::std::mem::transmute(self)
- }
- }
- ).unwrap();
-
- let union_field_default_impl = quote_item!(&ctx.ext_cx,
- impl<T> ::std::default::Default for __BindgenUnionField<T> {
- #[inline]
- fn default() -> Self {
- Self::new()
- }
- }
- ).unwrap();
-
- let union_field_clone_impl = quote_item!(&ctx.ext_cx,
- impl<T> ::std::clone::Clone for __BindgenUnionField<T> {
- #[inline]
- fn clone(&self) -> Self {
- Self::new()
- }
- }
- ).unwrap();
-
- let items = vec![union_field_decl, union_field_impl, union_field_default_impl, union_field_clone_impl];
- match root_mod.node {
- ast::ItemKind::Mod(ref mut root) => {
- let old_items = std::mem::replace(&mut root.items, items);
- root.items.extend(old_items.into_iter());
- }
- _ => unreachable!(),
- }
-}
diff --git a/src/hacks/mod.rs b/src/hacks/mod.rs
deleted file mode 100644
index 79339002..00000000
--- a/src/hacks/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod refcell;
diff --git a/src/hacks/refcell.rs b/src/hacks/refcell.rs
deleted file mode 100644
index 408e95d4..00000000
--- a/src/hacks/refcell.rs
+++ /dev/null
@@ -1,464 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers.
-// See http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A fork of std::cell::RefCell that makes `as_unsafe_cell` usable on stable Rust.
-//!
-//! FIXME(https://github.com/rust-lang/rust/issues/27708): Remove this
-//! (revert commit f7f81e0ed0b62402db291e28a9bb16f7194ebf78 / PR #11835)
-//! when `std::cell::RefCell::as_unsafe_cell` is in Rust’s stable channel.
-
-#![allow(unsafe_code, dead_code)]
-
-use std::cell::{UnsafeCell, Cell};
-use std::cmp::Ordering;
-use std::ops::{Deref, DerefMut};
-
-/// A fork of std::cell::RefCell that makes `as_unsafe_cell` usable on stable Rust.
-///
-/// FIXME(https://github.com/rust-lang/rust/issues/27708): Remove this
-/// (revert commit f7f81e0ed0b62402db291e28a9bb16f7194ebf78 / PR #11835)
-/// when `std::cell::RefCell::as_unsafe_cell` is in Rust’s stable channel.
-#[derive(Debug)]
-pub struct RefCell<T: ?Sized> {
- borrow: Cell<BorrowFlag>,
- value: UnsafeCell<T>,
-}
-type BorrowFlag = usize;
-
-/// An enumeration of values returned from the `state` method on a `RefCell<T>`.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum BorrowState {
- /// The cell is currently being read, there is at least one active `borrow`.
- Reading,
- /// The cell is currently being written to, there is an active `borrow_mut`.
- Writing,
- /// There are no outstanding borrows on this cell.
- Unused,
-}
-
-// Values [1, MAX-1] represent the number of `Ref` active
-// (will not outgrow its range since `usize` is the size of the address space)
-const UNUSED: BorrowFlag = 0;
-const WRITING: BorrowFlag = !0;
-
-impl<T> RefCell<T> {
- /// Creates a new `RefCell` containing `value`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::cell::RefCell;
- ///
- /// let c = RefCell::new(5);
- /// ```
- #[inline]
- pub fn new(value: T) -> RefCell<T> {
- RefCell {
- value: UnsafeCell::new(value),
- borrow: Cell::new(UNUSED),
- }
- }
-
- /// Consumes the `RefCell`, returning the wrapped value.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::cell::RefCell;
- ///
- /// let c = RefCell::new(5);
- ///
- /// let five = c.into_inner();
- /// ```
- #[inline]
- pub fn into_inner(self) -> T {
- // Since this function takes `self` (the `RefCell`) by value, the
- // compiler statically verifies that it is not currently borrowed.
- // Therefore the following assertion is just a `debug_assert!`.
- debug_assert!(self.borrow.get() == UNUSED);
- unsafe { self.value.into_inner() }
- }
-}
-
-impl<T: ?Sized> RefCell<T> {
- /// Query the current state of this `RefCell`
- ///
- /// The returned value can be dispatched on to determine if a call to
- /// `borrow` or `borrow_mut` would succeed.
- #[inline]
- pub fn borrow_state(&self) -> BorrowState {
- match self.borrow.get() {
- WRITING => BorrowState::Writing,
- UNUSED => BorrowState::Unused,
- _ => BorrowState::Reading,
- }
- }
-
- /// Immutably borrows the wrapped value.
- ///
- /// The borrow lasts until the returned `Ref` exits scope. Multiple
- /// immutable borrows can be taken out at the same time.
- ///
- /// # Panics
- ///
- /// Panics if the value is currently mutably borrowed.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::cell::RefCell;
- ///
- /// let c = RefCell::new(5);
- ///
- /// let borrowed_five = c.borrow();
- /// let borrowed_five2 = c.borrow();
- /// ```
- ///
- /// An example of panic:
- ///
- /// ```
- /// use std::cell::RefCell;
- /// use std::thread;
- ///
- /// let result = thread::spawn(move || {
- /// let c = RefCell::new(5);
- /// let m = c.borrow_mut();
- ///
- /// let b = c.borrow(); // this causes a panic
- /// }).join();
- ///
- /// assert!(result.is_err());
- /// ```
- #[inline]
- pub fn borrow(&self) -> Ref<T> {
- match BorrowRef::new(&self.borrow) {
- Some(b) => Ref {
- value: unsafe { &*self.value.get() },
- borrow: b,
- },
- None => panic!("RefCell<T> already mutably borrowed"),
- }
- }
-
- /// Mutably borrows the wrapped value.
- ///
- /// The borrow lasts until the returned `RefMut` exits scope. The value
- /// cannot be borrowed while this borrow is active.
- ///
- /// # Panics
- ///
- /// Panics if the value is currently borrowed.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::cell::RefCell;
- ///
- /// let c = RefCell::new(5);
- ///
- /// *c.borrow_mut() = 7;
- ///
- /// assert_eq!(*c.borrow(), 7);
- /// ```
- ///
- /// An example of panic:
- ///
- /// ```
- /// use std::cell::RefCell;
- /// use std::thread;
- ///
- /// let result = thread::spawn(move || {
- /// let c = RefCell::new(5);
- /// let m = c.borrow();
- ///
- /// let b = c.borrow_mut(); // this causes a panic
- /// }).join();
- ///
- /// assert!(result.is_err());
- /// ```
- #[inline]
- pub fn borrow_mut(&self) -> RefMut<T> {
- match BorrowRefMut::new(&self.borrow) {
- Some(b) => RefMut {
- value: unsafe { &mut *self.value.get() },
- borrow: b,
- },
- None => panic!("RefCell<T> already borrowed"),
- }
- }
-
- /// Returns a reference to the underlying `UnsafeCell`.
- ///
- /// This can be used to circumvent `RefCell`'s safety checks.
- ///
- /// This function is `unsafe` because `UnsafeCell`'s field is public.
- #[inline]
- pub unsafe fn as_unsafe_cell(&self) -> &UnsafeCell<T> {
- &self.value
- }
-
- /// Returns a mutable reference to the underlying data.
- ///
- /// This call borrows `RefCell` mutably (at compile-time) so there is no
- /// need for dynamic checks.
- #[inline]
- pub fn get_mut(&mut self) -> &mut T {
- unsafe {
- &mut *self.value.get()
- }
- }
-}
-
-unsafe impl<T: ?Sized> Send for RefCell<T> where T: Send {}
-
-impl<T: Clone> Clone for RefCell<T> {
- #[inline]
- fn clone(&self) -> RefCell<T> {
- RefCell::new(self.borrow().clone())
- }
-}
-
-impl<T: Default> Default for RefCell<T> {
- #[inline]
- fn default() -> RefCell<T> {
- RefCell::new(Default::default())
- }
-}
-
-impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> {
- #[inline]
- fn eq(&self, other: &RefCell<T>) -> bool {
- *self.borrow() == *other.borrow()
- }
-}
-
-impl<T: ?Sized + Eq> Eq for RefCell<T> {}
-
-impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> {
- #[inline]
- fn partial_cmp(&self, other: &RefCell<T>) -> Option<Ordering> {
- self.borrow().partial_cmp(&*other.borrow())
- }
-
- #[inline]
- fn lt(&self, other: &RefCell<T>) -> bool {
- *self.borrow() < *other.borrow()
- }
-
- #[inline]
- fn le(&self, other: &RefCell<T>) -> bool {
- *self.borrow() <= *other.borrow()
- }
-
- #[inline]
- fn gt(&self, other: &RefCell<T>) -> bool {
- *self.borrow() > *other.borrow()
- }
-
- #[inline]
- fn ge(&self, other: &RefCell<T>) -> bool {
- *self.borrow() >= *other.borrow()
- }
-}
-
-impl<T: ?Sized + Ord> Ord for RefCell<T> {
- #[inline]
- fn cmp(&self, other: &RefCell<T>) -> Ordering {
- self.borrow().cmp(&*other.borrow())
- }
-}
-
-struct BorrowRef<'b> {
- borrow: &'b Cell<BorrowFlag>,
-}
-
-impl<'b> BorrowRef<'b> {
- #[inline]
- fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> {
- match borrow.get() {
- WRITING => None,
- b => {
- borrow.set(b + 1);
- Some(BorrowRef { borrow: borrow })
- },
- }
- }
-}
-
-impl<'b> Drop for BorrowRef<'b> {
- #[inline]
- fn drop(&mut self) {
- let borrow = self.borrow.get();
- debug_assert!(borrow != WRITING && borrow != UNUSED);
- self.borrow.set(borrow - 1);
- }
-}
-
-impl<'b> Clone for BorrowRef<'b> {
- #[inline]
- fn clone(&self) -> BorrowRef<'b> {
- // Since this Ref exists, we know the borrow flag
- // is not set to WRITING.
- let borrow = self.borrow.get();
- debug_assert!(borrow != UNUSED);
- // Prevent the borrow counter from overflowing.
- assert!(borrow != WRITING);
- self.borrow.set(borrow + 1);
- BorrowRef { borrow: self.borrow }
- }
-}
-
-/// Wraps a borrowed reference to a value in a `RefCell` box.
-/// A wrapper type for an immutably borrowed value from a `RefCell<T>`.
-///
-/// See the [module-level documentation](index.html) for more.
-pub struct Ref<'b, T: ?Sized + 'b> {
- value: &'b T,
- borrow: BorrowRef<'b>,
-}
-
-impl<'b, T: ?Sized> Deref for Ref<'b, T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &T {
- self.value
- }
-}
-
-impl<'b, T: ?Sized> Ref<'b, T> {
- /// Copies a `Ref`.
- ///
- /// The `RefCell` is already immutably borrowed, so this cannot fail.
- ///
- /// This is an associated function that needs to be used as
- /// `Ref::clone(...)`. A `Clone` implementation or a method would interfere
- /// with the widespread use of `r.borrow().clone()` to clone the contents of
- /// a `RefCell`.
- #[inline]
- pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
- Ref {
- value: orig.value,
- borrow: orig.borrow.clone(),
- }
- }
-
- /// Make a new `Ref` for a component of the borrowed data.
- ///
- /// The `RefCell` is already immutably borrowed, so this cannot fail.
- ///
- /// This is an associated function that needs to be used as `Ref::map(...)`.
- /// A method would interfere with methods of the same name on the contents
- /// of a `RefCell` used through `Deref`.
- ///
- /// # Example
- ///
- /// ```
- /// use std::cell::{RefCell, Ref};
- ///
- /// let c = RefCell::new((5, 'b'));
- /// let b1: Ref<(u32, char)> = c.borrow();
- /// let b2: Ref<u32> = Ref::map(b1, |t| &t.0);
- /// assert_eq!(*b2, 5)
- /// ```
- #[inline]
- pub fn map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Ref<'b, U>
- where F: FnOnce(&T) -> &U
- {
- Ref {
- value: f(orig.value),
- borrow: orig.borrow,
- }
- }
-}
-
-impl<'b, T: ?Sized> RefMut<'b, T> {
- /// Make a new `RefMut` for a component of the borrowed data, e.g. an enum
- /// variant.
- ///
- /// The `RefCell` is already mutably borrowed, so this cannot fail.
- ///
- /// This is an associated function that needs to be used as
- /// `RefMut::map(...)`. A method would interfere with methods of the same
- /// name on the contents of a `RefCell` used through `Deref`.
- ///
- /// # Example
- ///
- /// ```
- /// use std::cell::{RefCell, RefMut};
- ///
- /// let c = RefCell::new((5, 'b'));
- /// {
- /// let b1: RefMut<(u32, char)> = c.borrow_mut();
- /// let mut b2: RefMut<u32> = RefMut::map(b1, |t| &mut t.0);
- /// assert_eq!(*b2, 5);
- /// *b2 = 42;
- /// }
- /// assert_eq!(*c.borrow(), (42, 'b'));
- /// ```
- #[inline]
- pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
- where F: FnOnce(&mut T) -> &mut U
- {
- RefMut {
- value: f(orig.value),
- borrow: orig.borrow,
- }
- }
-}
-
-struct BorrowRefMut<'b> {
- borrow: &'b Cell<BorrowFlag>,
-}
-
-impl<'b> Drop for BorrowRefMut<'b> {
- #[inline]
- fn drop(&mut self) {
- let borrow = self.borrow.get();
- debug_assert!(borrow == WRITING);
- self.borrow.set(UNUSED);
- }
-}
-
-impl<'b> BorrowRefMut<'b> {
- #[inline]
- fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
- match borrow.get() {
- UNUSED => {
- borrow.set(WRITING);
- Some(BorrowRefMut { borrow: borrow })
- },
- _ => None,
- }
- }
-}
-
-/// A wrapper type for a mutably borrowed value from a `RefCell<T>`.
-///
-/// See the [module-level documentation](index.html) for more.
-pub struct RefMut<'b, T: ?Sized + 'b> {
- value: &'b mut T,
- borrow: BorrowRefMut<'b>,
-}
-
-impl<'b, T: ?Sized> Deref for RefMut<'b, T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &T {
- self.value
- }
-}
-
-impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> {
- #[inline]
- fn deref_mut(&mut self) -> &mut T {
- self.value
- }
-}
diff --git a/src/ir/annotations.rs b/src/ir/annotations.rs
new file mode 100644
index 00000000..cc61dbfd
--- /dev/null
+++ b/src/ir/annotations.rs
@@ -0,0 +1,141 @@
+use clang;
+
+#[derive(Copy, PartialEq, Clone, Debug)]
+pub enum FieldAccessorKind {
+ None,
+ Regular,
+ Unsafe,
+ Immutable,
+}
+
+/// Annotations for a given item, or a field.
+#[derive(Clone, PartialEq, Debug)]
+pub struct Annotations {
+ /// Whether this item is marked as opaque. Only applies to types.
+ opaque: bool,
+ /// Whether this item should be hidden from the output. Only applies to
+ /// types.
+ hide: bool,
+ /// Whether this type should be replaced by another. The name must be the
+ /// canonical name that that type would get.
+ use_instead_of: Option<String>,
+ /// Manually disable deriving copy/clone on this type. Only applies to
+ /// struct or union types.
+ disallow_copy: bool,
+ /// Whether fields should be marked as private or not. You can set this on
+ /// structs (it will apply to all the fields), or individual fields.
+ private_fields: Option<bool>,
+ /// The kind of accessor this field will have. Also can be applied to
+ /// structs so all the fields inside share it by default.
+ accessor_kind: Option<FieldAccessorKind>,
+}
+
+fn parse_accessor(s: &str) -> FieldAccessorKind {
+ match s {
+ "false" => FieldAccessorKind::None,
+ "unsafe" => FieldAccessorKind::Unsafe,
+ "immutable" => FieldAccessorKind::Immutable,
+ _ => FieldAccessorKind::Regular,
+ }
+}
+
+impl Default for Annotations {
+ fn default() -> Self {
+ Annotations {
+ opaque: false,
+ hide: false,
+ use_instead_of: None,
+ disallow_copy: false,
+ private_fields: None,
+ accessor_kind: None
+ }
+ }
+}
+
+impl Annotations {
+ pub fn new(cursor: &clang::Cursor) -> Option<Annotations> {
+ let mut anno = Annotations::default();
+ let mut matched_one = false;
+ anno.parse(&cursor.comment(), &mut matched_one);
+
+ if matched_one {
+ Some(anno)
+ } else {
+ None
+ }
+ }
+
+ pub fn hide(&self) -> bool {
+ self.hide
+ }
+
+ pub fn opaque(&self) -> bool {
+ self.opaque
+ }
+
+ /// For a given type, indicates the type it should replace.
+ ///
+ /// For example, in the following code:
+ ///
+ /// ```cpp
+ ///
+ /// /** <div rustbindgen replaces="Bar"></div> */
+ /// struct Foo { int x; };
+ ///
+ /// struct Bar { char foo; };
+ /// ```
+ ///
+ /// the generated code would look something like:
+ ///
+ /// ```rust
+ /// /** <div rustbindgen replaces="Bar"></div> */
+ /// struct Bar {
+ /// int x;
+ /// };
+ /// ```
+ ///
+ /// That is, code for `Foo` is used to generate `Bar`.
+ pub fn use_instead_of(&self) -> Option<&str> {
+ self.use_instead_of.as_ref().map(|s| &**s)
+ }
+
+ pub fn disallow_copy(&self) -> bool {
+ self.disallow_copy
+ }
+
+ pub fn private_fields(&self) -> Option<bool> {
+ self.private_fields
+ }
+
+ pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
+ self.accessor_kind
+ }
+
+ fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) {
+ use clangll::CXComment_HTMLStartTag;
+ if comment.kind() == CXComment_HTMLStartTag &&
+ comment.get_tag_name() == "div" &&
+ comment.get_num_tag_attrs() > 1 &&
+ comment.get_tag_attr_name(0) == "rustbindgen" {
+ *matched = true;
+ for i in 0..comment.get_num_tag_attrs() {
+ let value = comment.get_tag_attr_value(i);
+ let name = comment.get_tag_attr_name(i);
+ match name.as_str() {
+ "opaque" => self.opaque = true,
+ "hide" => self.hide = true,
+ "nocopy" => self.disallow_copy = true,
+ "replaces" => self.use_instead_of = Some(value),
+ "private" => self.private_fields = Some(value != "false"),
+ "accessor"
+ => self.accessor_kind = Some(parse_accessor(&value)),
+ _ => {},
+ }
+ }
+ }
+
+ for i in 0..comment.num_children() {
+ self.parse(&comment.get_child(i), matched);
+ }
+ }
+}
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
new file mode 100644
index 00000000..1e6bf555
--- /dev/null
+++ b/src/ir/comp.rs
@@ -0,0 +1,718 @@
+use super::annotations::Annotations;
+use super::context::BindgenContext;
+use super::context::TypeResolver;
+use super::layout::Layout;
+use super::item::{Item, ItemId};
+use super::ty::{Type, RUST_DERIVE_IN_ARRAY_LIMIT};
+use std::cell::Cell;
+use std::cmp;
+use parse::{ClangItemParser, ParseError};
+use clang;
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub enum CompKind {
+ Struct,
+ Union,
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub enum MethodKind {
+ Static,
+ Normal,
+ Virtual,
+}
+
+/// A struct representing a C++ method, either static, normal, or virtual.
+#[derive(Debug)]
+pub struct Method {
+ kind: MethodKind,
+ /// The signature of the method. Take into account this is not a `Type`
+ /// item, but a `Function` one.
+ ///
+ /// This is tricky and probably this field should be renamed.
+ signature: ItemId,
+ is_const: bool,
+}
+
+impl Method {
+ fn new(kind: MethodKind, signature: ItemId, is_const: bool) -> Self {
+ Method {
+ kind: kind,
+ signature: signature,
+ is_const: is_const,
+ }
+ }
+
+ pub fn kind(&self) -> MethodKind {
+ self.kind
+ }
+
+ pub fn is_virtual(&self) -> bool {
+ self.kind == MethodKind::Virtual
+ }
+
+ pub fn is_static(&self) -> bool {
+ self.kind == MethodKind::Static
+ }
+
+ pub fn signature(&self) -> ItemId {
+ self.signature
+ }
+
+ pub fn is_const(&self) -> bool {
+ self.is_const
+ }
+}
+
+/// A struct representing a C++ field.
+#[derive(Clone, Debug)]
+pub struct Field {
+ /// The name of the field, empty if it's an unnamed bitfield width.
+ name: Option<String>,
+ /// The inner type.
+ ty: ItemId,
+ /// The doc comment on the field if any.
+ comment: Option<String>,
+ /// Annotations for this field, or the default.
+ annotations: Annotations,
+ /// If this field is a bitfield, and how many bits does it contain if it is.
+ bitfield: Option<u32>,
+ /// If the C++ field is marked as `mutable`
+ mutable: bool,
+}
+
+impl Field {
+ pub fn new(name: Option<String>,
+ ty: ItemId,
+ comment: Option<String>,
+ annotations: Option<Annotations>,
+ bitfield: Option<u32>,
+ mutable: bool) -> Field {
+ Field {
+ name: name,
+ ty: ty,
+ comment: comment,
+ annotations: annotations.unwrap_or_default(),
+ bitfield: bitfield,
+ mutable: mutable,
+ }
+ }
+
+ pub fn name(&self) -> Option<&str> {
+ self.name.as_ref().map(|n| &**n)
+ }
+
+ pub fn ty(&self) -> ItemId {
+ self.ty
+ }
+
+ pub fn comment(&self) -> Option<&str> {
+ self.comment.as_ref().map(|c| &**c)
+ }
+
+ pub fn bitfield(&self) -> Option<u32> {
+ self.bitfield
+ }
+
+ pub fn is_mutable(&self) -> bool {
+ self.mutable
+ }
+
+ pub fn annotations(&self) -> &Annotations {
+ &self.annotations
+ }
+}
+
+
+#[derive(Debug)]
+pub struct CompInfo {
+ /// Whether this is a struct or a union.
+ kind: CompKind,
+ /// The members of this struct or union.
+ fields: Vec<Field>,
+ /// The template parameters of this class. These are non-concrete, and
+ /// should always be a Type(TypeKind::Named(name)), but still they need to
+ /// be registered with an unique type id in the context.
+ template_args: Vec<ItemId>,
+ /// The method declarations inside this class, if in C++ mode.
+ methods: Vec<Method>,
+ /// Vector of classes this one inherits from.
+ base_members: Vec<ItemId>,
+ /// The parent reference template if any.
+ ref_template: Option<ItemId>,
+ /// The inner types that were declared inside this class, in something like:
+ ///
+ /// class Foo {
+ /// typedef int FooTy;
+ /// struct Bar {
+ /// int baz;
+ /// };
+ /// }
+ ///
+ /// static Foo::Bar const = {3};
+ inner_types: Vec<ItemId>,
+ /// Set of static constants declared inside this class.
+ inner_vars: Vec<ItemId>,
+ /// Whether this type should generate an vtable (TODO: Should be able to
+ /// look at the virtual methods and ditch this field).
+ has_vtable: bool,
+ /// Whether this type has destructor.
+ has_destructor: bool,
+ /// Whether this type has a base type with more than one member.
+ ///
+ /// TODO: We should be able to compute this.
+ has_nonempty_base: bool,
+ /// If this type has a template parameter which is not a type (e.g.: a size_t)
+ has_non_type_template_params: bool,
+ /// Whether this struct layout is packed.
+ packed: bool,
+ /// Whether this struct is anonymous.
+ is_anonymous: bool,
+ /// Used to know if we've found an opaque attribute that could cause us to
+ /// generate a type with invalid layout. This is explicitly used to avoid us
+ /// generating bad alignments when parsing types like max_align_t.
+ ///
+ /// It's not clear what the behavior should be here, if generating the item
+ /// and pray, or behave as an opaque type.
+ found_unknown_attr: bool,
+ /// Used to detect if we've run in a can_derive_debug cycle while cycling
+ /// around the template arguments.
+ detect_derive_debug_cycle: Cell<bool>,
+ /// Used to detect if we've run in a has_destructor cycle while cycling
+ /// around the template arguments.
+ detect_has_destructor_cycle: Cell<bool>,
+}
+
+impl CompInfo {
+ pub fn new(kind: CompKind) -> Self {
+ CompInfo {
+ kind: kind,
+ fields: vec![],
+ template_args: vec![],
+ methods: vec![],
+ base_members: vec![],
+ ref_template: None,
+ inner_types: vec![],
+ inner_vars: vec![],
+ has_vtable: false,
+ has_destructor: false,
+ has_nonempty_base: false,
+ has_non_type_template_params: false,
+ packed: false,
+ is_anonymous: false,
+ found_unknown_attr: false,
+ detect_derive_debug_cycle: Cell::new(false),
+ detect_has_destructor_cycle: Cell::new(false),
+ }
+ }
+
+ pub fn can_derive_debug(&self, type_resolver: &TypeResolver, layout: Option<Layout>) -> bool {
+ // We can reach here recursively via template parameters of a member,
+ // for example.
+ if self.detect_derive_debug_cycle.get() {
+ warn!("Derive debug cycle detected!");
+ return true;
+ }
+
+ if self.kind == CompKind::Union {
+ let layout = layout.unwrap_or_else(Layout::zero);
+ let size_divisor = cmp::max(1, layout.align);
+ return layout.size / size_divisor <= RUST_DERIVE_IN_ARRAY_LIMIT;
+ }
+
+ self.detect_derive_debug_cycle.set(true);
+
+ let can_derive_debug =
+ self.template_args.iter().all(|ty| {
+ type_resolver.resolve_type(*ty)
+ .can_derive_debug(type_resolver)
+ }) &&
+ self.fields.iter().all(|field| {
+ type_resolver.resolve_type(field.ty)
+ .can_derive_debug(type_resolver)
+ });
+
+ self.detect_derive_debug_cycle.set(false);
+
+ can_derive_debug
+ }
+
+ pub fn is_unsized(&self, type_resolver: &TypeResolver) -> bool {
+ !self.has_vtable(type_resolver) && self.fields.is_empty() &&
+ self.base_members.iter().all(|base| {
+ type_resolver
+ .resolve_type(*base)
+ .canonical_type(type_resolver)
+ .is_unsized(type_resolver)
+ }) &&
+ self.ref_template.map_or(true, |template| {
+ type_resolver.resolve_type(template).is_unsized(type_resolver)
+ })
+ }
+
+ pub fn has_destructor(&self, type_resolver: &TypeResolver) -> bool {
+ if self.detect_has_destructor_cycle.get() {
+ warn!("Cycle detected looking for destructors");
+ // Assume no destructor, since we don't have an explicit one.
+ return false;
+ }
+
+ self.detect_has_destructor_cycle.set(true);
+
+ let has_destructor = self.has_destructor || match self.kind {
+ CompKind::Union => false,
+ 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| {
+ type_resolver.resolve_type(*t).has_destructor(type_resolver)
+ }) ||
+ self.template_args.iter().any(|t| {
+ type_resolver.resolve_type(*t).has_destructor(type_resolver)
+ }) ||
+ self.base_members.iter().any(|t| {
+ type_resolver.resolve_type(*t).has_destructor(type_resolver)
+ }) ||
+ self.fields.iter().any(|field| {
+ type_resolver.resolve_type(field.ty)
+ .has_destructor(type_resolver)
+ })
+ }
+ };
+
+ self.detect_has_destructor_cycle.set(false);
+
+ has_destructor
+ }
+
+ pub fn can_derive_copy(&self, type_resolver: &TypeResolver) -> bool {
+ // NOTE: Take into account that while unions in C and C++ are copied by
+ // default, the may have an explicit destructor in C++, so we can't
+ // defer this check just for the union case.
+ if self.has_destructor(type_resolver) {
+ return false;
+ }
+
+ match self.kind {
+ CompKind::Union => true,
+ CompKind::Struct => {
+ // 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| {
+ type_resolver.resolve_type(*t).can_derive_copy(type_resolver)
+ }) &&
+ self.base_members.iter().all(|t| {
+ type_resolver.resolve_type(*t).can_derive_copy(type_resolver)
+ }) &&
+ self.fields.iter().all(|field| {
+ type_resolver.resolve_type(field.ty)
+ .can_derive_copy(type_resolver)
+ })
+ }
+ }
+ }
+
+ pub fn is_template_specialization(&self) -> bool {
+ self.ref_template.is_some()
+ }
+
+ pub fn specialized_template(&self) -> Option<ItemId> {
+ self.ref_template
+ }
+
+ // Computes the layout of this type.
+ //
+ // This is called as a fallback under some circumstances where LLVM doesn't
+ // give us the correct layout.
+ // If we're a union without known layout, we try to compute it from our
+ // members. This is not ideal, but clang fails to report the size for
+ // these kind of unions, see test/headers/template_union.hpp
+ pub fn layout(&self, type_resolver: &TypeResolver) -> Option<Layout> {
+ use std::cmp;
+
+ // We can't do better than clang here, sorry.
+ if self.kind == CompKind::Struct {
+ return None;
+ }
+
+ let mut max_size = 0;
+ let mut max_align = 0;
+ for field in &self.fields {
+ let field_layout = type_resolver.resolve_type(field.ty)
+ .layout(type_resolver);
+
+ if let Some(layout) = field_layout {
+ max_size = cmp::max(max_size, layout.size);
+ max_align = cmp::max(max_align, layout.align);
+ }
+ }
+
+ Some(Layout::new(max_size, max_align))
+ }
+
+ pub fn fields(&self) -> &[Field] {
+ &self.fields
+ }
+
+ pub fn template_args(&self) -> &[ItemId] {
+ &self.template_args
+ }
+
+ pub fn has_non_type_template_params(&self) -> bool {
+ self.has_non_type_template_params
+ }
+
+ pub fn has_vtable(&self, type_resolver: &TypeResolver) -> bool {
+ self.has_vtable || self.base_members().iter().any(|base| {
+ type_resolver
+ .resolve_type(*base)
+ .has_vtable(type_resolver)
+ }) || self.ref_template.map_or(false, |template| {
+ type_resolver.resolve_type(template).has_vtable(type_resolver)
+ })
+ }
+
+ pub fn methods(&self) -> &[Method] {
+ &self.methods
+ }
+
+ pub fn kind(&self) -> CompKind {
+ self.kind
+ }
+
+ pub fn base_members(&self) -> &[ItemId] {
+ &self.base_members
+ }
+
+ pub fn from_ty(potential_id: ItemId,
+ ty: &clang::Type,
+ location: Option<clang::Cursor>,
+ ctx: &mut BindgenContext) -> Result<Self, ParseError> {
+ use clangll::*;
+ // Sigh... For class templates we want the location, for
+ // specialisations, we want the declaration... So just try both.
+ //
+ // TODO: Yeah, this code reads really bad.
+ let mut cursor = ty.declaration();
+ let mut kind = Self::kind_from_cursor(&cursor);
+ if kind.is_err() {
+ if let Some(location) = location {
+ kind = Self::kind_from_cursor(&location);
+ cursor = location;
+ }
+ }
+
+ let kind = try!(kind);
+
+ debug!("CompInfo::from_ty({:?}, {:?})", kind, cursor);
+
+
+ let mut ci = CompInfo::new(kind);
+ ci.is_anonymous = cursor.is_anonymous();
+ ci.template_args = match ty.num_template_args() {
+ // In forward declarations and not specializations, etc, they are in
+ // the ast, we'll meet them in CXCursor_TemplateTypeParameter
+ -1 => vec![],
+ len => {
+ let mut list = Vec::with_capacity(len as usize);
+ for i in 0..len {
+ let arg_type = ty.template_arg_type(i);
+ if arg_type.kind() != CXType_Invalid {
+ let type_id =
+ Item::from_ty_or_ref(arg_type, None, None, ctx);
+
+ list.push(type_id);
+ } else {
+ ci.has_non_type_template_params = true;
+ warn!("warning: Template parameter is not a type");
+ }
+ }
+
+ list
+ }
+ };
+
+ ci.ref_template = Item::parse(cursor.specialized(), None, ctx).ok();
+
+ let mut maybe_anonymous_struct_field = None;
+ cursor.visit(|cur, _other| {
+ if cur.kind() != CXCursor_FieldDecl {
+ if let Some((ty, ref _clang_ty)) = maybe_anonymous_struct_field {
+ let field = Field::new(None, ty, None, None, None, false);
+ ci.fields.push(field);
+ }
+ maybe_anonymous_struct_field = None;
+ }
+
+ match cur.kind() {
+ CXCursor_FieldDecl => {
+ match maybe_anonymous_struct_field.take() {
+ Some((ty, clang_ty)) => {
+ let mut used = false;
+ cur.visit(|child, _| {
+ if child.cur_type() == clang_ty {
+ used = true;
+ }
+ CXChildVisit_Continue
+ });
+ if !used {
+ let field = Field::new(None, ty, None, None, None, false);
+ ci.fields.push(field);
+ }
+ },
+ None => {}
+ }
+
+ let bit_width = cur.bit_width();
+ let field_type =
+ Item::from_ty_or_ref(cur.cur_type(), Some(*cur), Some(potential_id), ctx);
+ let comment = cur.raw_comment();
+ let annotations = Annotations::new(cur);
+ let name = cur.spelling();
+ let is_mutable = cursor.is_mutable_field();
+
+ // Name can be empty if there are bitfields, for example,
+ // see tests/headers/struct_with_bitfields.h
+ assert!(!name.is_empty() || bit_width.is_some(),
+ "Empty field name?");
+
+ let name = if name.is_empty() { None } else { Some(name) };
+
+ let field = Field::new(name, field_type, comment,
+ annotations, bit_width, is_mutable);
+ ci.fields.push(field);
+
+ // No we look for things like attributes and stuff.
+ cur.visit(|cur, _| {
+ if cur.kind() == CXCursor_UnexposedAttr {
+ ci.found_unknown_attr = true;
+ }
+ CXChildVisit_Continue
+ });
+
+ }
+ CXCursor_UnexposedAttr => {
+ ci.found_unknown_attr = true;
+ }
+ CXCursor_EnumDecl |
+ CXCursor_TypeAliasDecl |
+ CXCursor_TypedefDecl |
+ CXCursor_StructDecl |
+ CXCursor_UnionDecl |
+ CXCursor_ClassTemplate |
+ CXCursor_ClassDecl => {
+ let inner = Item::parse(*cur, Some(potential_id), ctx)
+ .expect("Inner ClassDecl");
+ if !ci.inner_types.contains(&inner) {
+ ci.inner_types.push(inner);
+ }
+ // A declaration of an union or a struct without name could
+ // also be an unnamed field, unfortunately.
+ if cur.spelling().is_empty() && cur.kind() != CXCursor_EnumDecl {
+ maybe_anonymous_struct_field = Some((inner, cur.cur_type()));
+ }
+ }
+ CXCursor_PackedAttr => {
+ ci.packed = true;
+ }
+ CXCursor_TemplateTypeParameter => {
+ // Yes! You can arrive here with an empty template parameter
+ // name! Awesome, isn't it?
+ //
+ // see tests/headers/empty_template_param_name.hpp
+ if cur.spelling().is_empty() {
+ return CXChildVisit_Continue;
+ }
+
+ let default_type =
+ Item::from_ty(&cur.cur_type(), Some(*cur), Some(potential_id), ctx).ok();
+
+ let param = Item::named_type(cur.spelling(), default_type, potential_id, ctx);
+ ci.template_args.push(param);
+ }
+ CXCursor_CXXBaseSpecifier => {
+ if !ci.has_vtable {
+ ci.has_vtable = cur.is_virtual_base();
+ }
+ let type_id = Item::from_ty(&cur.cur_type(), None, None, ctx)
+ .expect("BaseSpecifier");
+ ci.base_members.push(type_id);
+ }
+ CXCursor_CXXMethod => {
+ let is_virtual = cur.method_is_virtual();
+ let is_static = cur.method_is_static();
+ debug_assert!(!(is_static && is_virtual), "How?");
+
+ if !ci.has_vtable {
+ ci.has_vtable = is_virtual;
+ }
+
+ let linkage = cur.linkage();
+ if linkage != CXLinkage_External {
+ return CXChildVisit_Continue;
+ }
+
+ if cur.access_specifier() == CX_CXXPrivate {
+ return CXChildVisit_Continue;
+ }
+
+ let visibility = cur.visibility();
+ if visibility != CXVisibility_Default {
+ return CXChildVisit_Continue;
+ }
+
+ if cur.is_inlined_function() {
+ return CXChildVisit_Continue;
+ }
+
+ let spelling = cur.spelling();
+ if spelling.starts_with("operator") {
+ return CXChildVisit_Continue;
+ }
+
+ // This used to not be here, but then I tried generating
+ // stylo bindings with this (without path filters), and
+ // cried a lot with a method in gfx/Point.h
+ // (ToUnknownPoint), that somehow was causing the same type
+ // to be inserted in the map two times.
+ //
+ // I couldn't make a reduced test case, but anyway...
+ // Methods of template functions not only use to be inlined,
+ // but also instantiated, and we wouldn't be able to call
+ // them, so just bail out.
+ if !ci.template_args.is_empty() {
+ return CXChildVisit_Continue;
+ }
+
+ // NB: This gets us an owned `Function`, not a `FunctionSig`.
+ let method_signature = Item::parse(*cur, Some(potential_id), ctx)
+ .expect("CXXMethod");
+ let is_const = cur.method_is_const();
+ let method_kind = if is_static {
+ MethodKind::Static
+ } else if is_virtual {
+ MethodKind::Virtual
+ } else {
+ MethodKind::Normal
+ };
+ ci.methods.push(Method::new(method_kind, method_signature, is_const));
+ }
+ CXCursor_Destructor => {
+ if cur.method_is_virtual() {
+ // FIXME: Push to the method list?
+ ci.has_vtable = true;
+ }
+ ci.has_destructor = true;
+ }
+ CXCursor_NonTypeTemplateParameter => {
+ ci.has_non_type_template_params = true;
+ }
+ CXCursor_VarDecl => {
+ let linkage = cur.linkage();
+ if linkage != CXLinkage_External && linkage != CXLinkage_UniqueExternal {
+ return CXChildVisit_Continue;
+ }
+
+ let visibility = cur.visibility();
+ if visibility != CXVisibility_Default {
+ return CXChildVisit_Continue;
+ }
+
+ let item = Item::parse(*cur, Some(potential_id), ctx)
+ .expect("VarDecl");
+ ci.inner_vars.push(item);
+ }
+ // Intentionally not handled
+ CXCursor_CXXAccessSpecifier |
+ CXCursor_CXXFinalAttr |
+ CXCursor_Constructor |
+ CXCursor_FunctionTemplate |
+ CXCursor_ConversionFunction => {}
+ _ => {
+ warn!("unhandled composite member `{}` (kind {}) in `{}` ({})",
+ cur.spelling(), cur.kind(), cursor.spelling(),
+ cur.location());
+ }
+ }
+ CXChildVisit_Continue
+ });
+
+ if let Some((ty, _)) = maybe_anonymous_struct_field {
+ let field = Field::new(None, ty, None, None, None, false);
+ ci.fields.push(field);
+ }
+
+ Ok(ci)
+ }
+
+ fn kind_from_cursor(cursor: &clang::Cursor) -> Result<CompKind, ParseError> {
+ use clangll::*;
+ Ok(match cursor.kind() {
+ CXCursor_UnionDecl => CompKind::Union,
+ CXCursor_ClassDecl |
+ CXCursor_StructDecl => CompKind::Struct,
+ CXCursor_ClassTemplatePartialSpecialization |
+ CXCursor_ClassTemplate => {
+ match cursor.template_kind() {
+ CXCursor_UnionDecl => CompKind::Union,
+ _ => CompKind::Struct,
+ }
+ }
+ _ => {
+ warn!("Unknown kind for comp type: {:?}", cursor);
+ return Err(ParseError::Continue);
+ }
+ })
+ }
+
+ pub fn signature_contains_named_type(&self,
+ type_resolver: &TypeResolver,
+ 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| {
+ type_resolver.resolve_type(*arg)
+ .signature_contains_named_type(type_resolver, ty)
+ })
+ }
+
+ pub fn inner_types(&self) -> &[ItemId] {
+ &self.inner_types
+ }
+
+ pub fn inner_vars(&self) -> &[ItemId] {
+ &self.inner_vars
+ }
+
+ pub fn found_unknown_attr(&self) -> bool {
+ self.found_unknown_attr
+ }
+
+ pub fn packed(&self) -> bool {
+ self.packed
+ }
+
+ /// Returns whether this type needs an explicit vtable because it has
+ /// virtual methods and none of its base classes has already a vtable.
+ pub fn needs_explicit_vtable(&self, type_resolver: &TypeResolver) -> bool {
+ self.has_vtable(type_resolver) && !self.base_members.iter().any(|base| {
+ // NB: Ideally, we could rely in all these types being `comp`, and
+ // life would be beautiful.
+ //
+ // Unfortunately, given the way we implement --match-pat, and also
+ // that you can inherit from templated types, we need to handle
+ // other cases here too.
+ type_resolver
+ .resolve_type(*base)
+ .canonical_type(type_resolver)
+ .as_comp().map_or(false, |ci| {
+ ci.has_vtable(type_resolver)
+ })
+ })
+ }
+}
diff --git a/src/ir/context.rs b/src/ir/context.rs
new file mode 100644
index 00000000..5ddedda0
--- /dev/null
+++ b/src/ir/context.rs
@@ -0,0 +1,685 @@
+use super::ty::{Type, TypeKind, FloatKind};
+use super::item::{Item, ItemCanonicalName, ItemId};
+use super::item_kind::ItemKind;
+use super::int::IntKind;
+use super::module::Module;
+use clang::{self, Cursor};
+use std::borrow::{Cow, Borrow};
+use std::collections::btree_map::{self, BTreeMap};
+use std::collections::{HashSet, HashMap};
+use std::fmt;
+use syntax::ast::Ident;
+use syntax::codemap::{DUMMY_SP, Span};
+use syntax::ext::base::ExtCtxt;
+use parse::ClangItemParser;
+use BindgenOptions;
+
+// This is just convenience to avoid creating a manual debug impl for the
+// context.
+struct GenContext<'ctx>(ExtCtxt<'ctx>);
+
+impl<'ctx> fmt::Debug for GenContext <'ctx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "GenContext {{ ... }}")
+ }
+}
+
+/// A context used during parsing and generation of structs.
+#[derive(Debug)]
+pub struct BindgenContext<'ctx> {
+ /// The map of all the items parsed so far.
+ ///
+ /// It's a BTreeMap because we want the keys to be sorted to have consistent
+ /// output.
+ items: BTreeMap<ItemId, Item>,
+
+ /// Clang cursor to type map. This is needed to be able to associate types
+ /// with item ids during parsing.
+ ///
+ /// The cursor used for storage is the definition cursor.
+ types: HashMap<Cursor, ItemId>,
+
+ /// A cursor to module map. Similar reason than above.
+ modules: HashMap<Cursor, ItemId>,
+
+ /// The root module, this is guaranteed to be an item of kind Module.
+ root_module: ItemId,
+
+ /// Current module being traversed.
+ current_module: ItemId,
+
+ /// A stack with the current type declarations and types we're parsing. This
+ /// is needed to avoid infinite recursion when parsing a type like:
+ ///
+ /// struct c { struct c* next; };
+ ///
+ /// This means effectively, that a type has a potential ID before knowing if
+ /// it's a correct type. But that's not important in practice.
+ ///
+ /// We could also use the `types` HashMap, but my intention with it is that
+ /// only valid types and declarations end up there, and this could
+ /// potentially break that assumption.
+ ///
+ /// FIXME: Should not be public, though... meh.
+ pub currently_parsed_types: Vec<(Cursor, ItemId)>,
+
+ /// A HashSet with all the already parsed macro names. This is done to avoid
+ /// hard errors while parsing duplicated macros.
+ parsed_macros: HashSet<String>,
+
+ /// The active replacements collected from replaces="xxx" annotations.
+ replacements: HashMap<String, ItemId>,
+
+ collected_typerefs: bool,
+
+ /// Dummy structures for code generation.
+ gen_ctx: Option<&'ctx GenContext<'ctx>>,
+ span: Span,
+
+ /// The clang index for parsing.
+ index: clang::Index,
+
+ /// The translation unit for parsing.
+ translation_unit: clang::TranslationUnit,
+
+ /// The options given by the user via cli or other medium.
+ options: BindgenOptions,
+}
+
+impl<'ctx> BindgenContext<'ctx> {
+ pub fn new(options: BindgenOptions) -> Self {
+ use clangll;
+
+ let index = clang::Index::new(false, true);
+
+ let translation_unit =
+ clang::TranslationUnit::parse(&index, "", &options.clang_args, &[],
+ clangll::CXTranslationUnit_DetailedPreprocessingRecord);
+
+ let root_module = Self::build_root_module();
+ let mut me = BindgenContext {
+ items: Default::default(),
+ types: Default::default(),
+ modules: Default::default(),
+ root_module: root_module.id(),
+ current_module: root_module.id(),
+ currently_parsed_types: vec![],
+ parsed_macros: Default::default(),
+ replacements: Default::default(),
+ collected_typerefs: false,
+ gen_ctx: None,
+ span: DUMMY_SP,
+ index: index,
+ translation_unit: translation_unit,
+ options: options,
+ };
+
+ me.add_item(root_module, None, None);
+
+ me
+ }
+
+ pub fn add_item(&mut self,
+ item: Item,
+ declaration: Option<Cursor>,
+ location: Option<Cursor>) {
+ use clangll::{CXCursor_ClassTemplate, CXCursor_ClassTemplatePartialSpecialization};
+ debug!("BindgenContext::add_item({:?}, declaration: {:?}, loc: {:?}", item, declaration, location);
+ debug_assert!(declaration.is_some() || !item.kind().is_type() ||
+ item.kind().expect_type().is_builtin_or_named(),
+ "Adding a type without declaration?");
+
+ let id = item.id();
+ let is_type = item.kind().is_type();
+ let old_item = self.items.insert(id, item);
+ assert!(old_item.is_none(), "Inserted type twice?");
+
+ if is_type && declaration.is_some() {
+ let declaration = declaration.unwrap();
+ debug_assert_eq!(declaration, declaration.canonical());
+ if declaration.is_valid() {
+ let old = self.types.insert(declaration, id);
+ debug_assert_eq!(old, None);
+ } else if location.is_some() &&
+ (location.unwrap().kind() == CXCursor_ClassTemplate ||
+ location.unwrap().kind() == CXCursor_ClassTemplatePartialSpecialization) {
+ let old = self.types.insert(location.unwrap().canonical(), id);
+ debug_assert_eq!(old, None);
+ } else {
+ // This could happen, for example, with types like `int*` or
+ // similar.
+ //
+ // Fortunately, we don't care about those types being
+ // duplicated, so we can just ignore them.
+ debug!("Invalid declaration {:?} found for type {:?}",
+ declaration, self.items.get(&id).unwrap().kind().expect_type());
+ }
+ }
+ }
+
+ // TODO: Move all this syntax crap to other part of the code.
+ pub fn ext_cx(&self) -> &ExtCtxt<'ctx> {
+ &self.gen_ctx.expect("Not in gen phase").0
+ }
+
+ pub fn span(&self) -> Span {
+ self.span
+ }
+
+ /// Mangles a name so it doesn't conflict with any keyword.
+ pub fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
+ use syntax::parse::token;
+ let ident = self.rust_ident_raw(&name);
+ let token = token::Ident(ident);
+ if token.is_any_keyword() ||
+ name.contains("@") ||
+ name.contains("?") ||
+ name.contains("$") ||
+ "bool" == name
+ {
+ let mut s = name.to_owned();
+ s = s.replace("@", "_");
+ s = s.replace("?", "_");
+ s = s.replace("$", "_");
+ s.push_str("_");
+ return Cow::Owned(s)
+ }
+ Cow::Borrowed(name)
+ }
+
+ /// Returns a mangled name as a rust identifier.
+ pub fn rust_ident(&self, name: &str) -> Ident {
+ self.rust_ident_raw(&self.rust_mangle(name))
+ }
+
+ pub fn rust_ident_raw<S>(&self, name: &S) -> Ident
+ where S: Borrow<str>,
+ {
+ self.ext_cx().ident_of(name.borrow())
+ }
+
+ pub fn items<'a>(&'a self) -> btree_map::Iter<'a, ItemId, Item> {
+ self.items.iter()
+ }
+
+ pub fn collected_typerefs(&self) -> bool {
+ self.collected_typerefs
+ }
+
+ fn collect_typerefs(&mut self) -> Vec<(ItemId, clang::Type, Option<clang::Cursor>)> {
+ debug_assert!(!self.collected_typerefs);
+ self.collected_typerefs = true;
+ let mut typerefs = vec![];
+ for (id, ref mut item) in &mut self.items {
+ let kind = item.kind();
+ let ty = match kind.as_type() {
+ Some(ty) => ty,
+ None => continue,
+ };
+
+ match *ty.kind() {
+ TypeKind::UnresolvedTypeRef(ref ty, loc) => {
+ typerefs.push((*id, ty.clone(), loc));
+ }
+ _ => {},
+ };
+ }
+ typerefs
+ }
+
+ fn resolve_typerefs(&mut self) {
+ let typerefs = self.collect_typerefs();
+
+ for (id, ty, loc) in typerefs {
+ let _resolved = {
+ let resolved = Item::from_ty(&ty, loc, None, self)
+ .expect("What happened?");
+ let mut item = self.items.get_mut(&id).unwrap();
+
+ *item.kind_mut().as_type_mut().unwrap().kind_mut() =
+ TypeKind::ResolvedTypeRef(resolved);
+ resolved
+ };
+
+ // Something in the STL is trolling me. I don't need this assertion
+ // right now, but worth investigating properly once this lands.
+ //
+ // debug_assert!(self.items.get(&resolved).is_some(), "How?");
+ }
+ }
+
+ fn process_replacements(&mut self) {
+ if self.replacements.is_empty() {
+ return;
+ }
+
+ // FIXME: This is linear, but the replaces="xxx" annotation was already
+ // there, and for better or worse it's useful, sigh...
+ //
+ // We leverage the ResolvedTypeRef thing, though, which is cool :P.
+
+ let mut replacements = vec![];
+
+ for (id, item) in self.items.iter() {
+ let ty = match item.kind().as_type() {
+ Some(ty) => ty,
+ None => continue,
+ };
+
+ // canonical_name calls are expensive.
+ let ci = match ty.as_comp() {
+ Some(ci) => ci,
+ None => continue,
+ };
+
+ if ci.is_template_specialization() {
+ continue;
+ }
+
+ if let Some(replacement) = self.replacements.get(&item.canonical_name(self)) {
+ if replacement != id {
+ // We set this just after parsing the annotation. It's
+ // very unlikely, but this can happen.
+ if self.items.get(replacement).is_some() {
+ replacements.push((*id, *replacement));
+ }
+ }
+ }
+ }
+
+ for (id, replacement) in replacements {
+ let mut item = self.items.get_mut(&id).unwrap();
+ *item.kind_mut().as_type_mut().unwrap().kind_mut() =
+ TypeKind::ResolvedTypeRef(replacement);
+ }
+ }
+
+ // Enters in the generation phase.
+ pub fn gen<F, Out>(&mut self, cb: F) -> Out
+ where F: FnOnce(&Self) -> Out
+ {
+ use syntax::ext::expand::ExpansionConfig;
+ use syntax::codemap::{ExpnInfo, MacroBang, NameAndSpan};
+ use syntax::ext::base;
+ use syntax::parse;
+ use std::mem;
+
+ let cfg = ExpansionConfig::default("xxx".to_owned());
+ let sess = parse::ParseSess::new();
+ let mut loader = base::DummyMacroLoader;
+ let mut ctx =
+ GenContext(base::ExtCtxt::new(&sess, vec![], cfg, &mut loader));
+
+ ctx.0.bt_push(ExpnInfo {
+ call_site: self.span,
+ callee: NameAndSpan {
+ format: MacroBang(parse::token::intern("")),
+ allow_internal_unstable: false,
+ span: None
+ }
+ });
+
+ // FIXME: This is evil, we should move code generation to use a wrapper
+ // of BindgenContext instead, I guess. Even though we know it's fine
+ // because we remove it before the end of this function.
+ self.gen_ctx = Some(unsafe { mem::transmute(&ctx) });
+
+ self.resolve_typerefs();
+ self.process_replacements();
+
+ let ret = cb(self);
+ self.gen_ctx = None;
+ ret
+ }
+
+ // This deserves a comment. Builtin types don't get a valid declaration, so
+ // we can't add it to the cursor->type map.
+ //
+ // That being said, they're not generated anyway, and are few, so the
+ // duplication and special-casing is fine.
+ //
+ // If at some point we care about the memory here, probably a map TypeKind
+ // -> builtin type ItemId would be the best to improve that.
+ fn add_builtin_item(&mut self, item: Item) {
+ debug_assert!(item.kind().is_type());
+ let id = item.id();
+ let old_item = self.items.insert(id, item);
+ assert!(old_item.is_none(), "Inserted type twice?");
+ }
+
+ fn build_root_module() -> Item {
+ let module = Module::new(Some("root".into()));
+ let id = ItemId::next();
+ Item::new(id, None, None, id, ItemKind::Module(module))
+ }
+
+ pub fn root_module(&self) -> ItemId {
+ self.root_module
+ }
+
+ pub fn resolve_type(&self, type_id: ItemId) -> &Type {
+ self.items.get(&type_id).unwrap().kind().expect_type()
+ }
+
+ pub fn safe_resolve_type(&self, type_id: ItemId) -> Option<&Type> {
+ self.items.get(&type_id).map(|t| t.kind().expect_type())
+ }
+
+ pub fn resolve_item_fallible(&self, item_id: ItemId) -> Option<&Item> {
+ self.items.get(&item_id)
+ }
+
+ pub fn resolve_item(&self, item_id: ItemId) -> &Item {
+ match self.items.get(&item_id) {
+ Some(item) => item,
+ None => panic!("Not an item: {:?}", item_id),
+ }
+ }
+
+ pub fn current_module(&self) -> ItemId {
+ self.current_module
+ }
+
+ /// This is one of the hackiest methods in all the parsing code. This method
+ /// is used to allow having templates with another argument names instead of
+ /// the canonical ones.
+ ///
+ /// This is surprisingly difficult to do with libclang, due to the fact that
+ /// partial template specializations don't provide explicit template
+ /// argument information.
+ ///
+ /// The only way to do this as far as I know, is inspecting manually the
+ /// AST, looking for TypeRefs inside. This, unfortunately, doesn't work for
+ /// more complex cases, see the comment on the assertion below.
+ ///
+ /// To see an example of what this handles:
+ ///
+ /// ```
+ /// template<typename T>
+ /// class Incomplete {
+ /// T p;
+ /// };
+ ///
+ /// template<typename U>
+ /// class Foo {
+ /// Incomplete<U> bar;
+ /// };
+ /// ```
+ fn build_template_wrapper(&mut self,
+ wrapping: ItemId,
+ parent_id: ItemId,
+ ty: &clang::Type,
+ location: clang::Cursor) -> ItemId {
+ use clangll::*;
+ let mut args = vec![];
+ let mut found_invalid_template_ref = false;
+ let self_id = ItemId::next();
+ location.visit(|c, _| {
+ if c.kind() == CXCursor_TemplateRef &&
+ c.cur_type().kind() == CXType_Invalid {
+ found_invalid_template_ref = true;
+ }
+ if c.kind() == CXCursor_TypeRef {
+ let new_ty =
+ Item::from_ty_or_ref(c.cur_type(), Some(*c), Some(self_id), self);
+ args.push(new_ty);
+ }
+ CXChildVisit_Continue
+ });
+
+ let item = {
+ let wrapping_type = self.resolve_type(wrapping);
+ let old_args = match *wrapping_type.kind() {
+ TypeKind::Comp(ref ci) => ci.template_args(),
+ _ => panic!("how?"),
+ };
+ // The following assertion actually fails with partial template
+ // specialization. But as far as I know there's no way at all to
+ // grab the specialized types from neither the AST or libclang.
+ //
+ // This flaw was already on the old parser, but I now think it has
+ // no clear solution.
+ //
+ // For an easy example in which there's no way at all of getting the
+ // `int` type, except manually parsing the spelling:
+ //
+ // template<typename T, typename U>
+ // class Incomplete {
+ // T d;
+ // U p;
+ // };
+ //
+ // template<typename U>
+ // class Foo {
+ // Incomplete<U, int> bar;
+ // };
+ //
+ // debug_assert_eq!(old_args.len(), args.len());
+ //
+ // That being said, this is not so common, so just error! and hope
+ // for the best, returning the previous type, who knows.
+ if old_args.len() != args.len() {
+ error!("Found partial template specialization, expect dragons!");
+ return wrapping;
+ }
+
+ let type_kind = TypeKind::TemplateRef(wrapping, args);
+ let name = ty.spelling();
+ let name = if name.is_empty() { None } else { Some(name) };
+ let ty = Type::new(name, ty.fallible_layout().ok(), type_kind, ty.is_const());
+ Item::new(self_id, None, None, parent_id, ItemKind::Type(ty))
+ };
+
+ // Bypass all the validations in add_item explicitly.
+ self.items.insert(self_id, item);
+ self_id
+ }
+
+ /// Looks up for an already resolved type, either because it's builtin, or
+ /// because we already have it in the map.
+ pub fn builtin_or_resolved_ty(&mut self,
+ parent_id: Option<ItemId>,
+ ty: &clang::Type,
+ location: Option<clang::Cursor>) -> Option<ItemId> {
+ use clangll::{CXCursor_ClassTemplate, CXCursor_ClassTemplatePartialSpecialization};
+ debug!("builtin_or_resolved_ty: {:?}, {:?}, {:?}", ty, location, parent_id);
+ let mut declaration = ty.declaration();
+ if !declaration.is_valid() {
+ if let Some(location) = location {
+ if location.kind() == CXCursor_ClassTemplate ||
+ location.kind() == CXCursor_ClassTemplatePartialSpecialization {
+ declaration = location;
+ }
+ }
+ }
+ let canonical_declaration = declaration.canonical();
+ if canonical_declaration.is_valid() {
+ // First lookup to see if we already have it resolved.
+ let id = self.types.get(&canonical_declaration).map(|id| *id);
+ if let Some(id) = id {
+ debug!("Already resolved ty {:?}, {:?}, {:?} {:?}",
+ id, declaration, ty, location);
+ // If the declaration existed, we *might* be done, but it's not
+ // the case for class templates, where the template arguments
+ // may vary.
+ //
+ // In this case, we create a TemplateRef with the new template
+ // arguments, pointing to the canonical template.
+ //
+ // Note that we only do it if parent_id is some, and we have a
+ // location for building the new arguments, the template
+ // argument names don't matter in the global context.
+ if (declaration.kind() == CXCursor_ClassTemplate ||
+ declaration.kind() == CXCursor_ClassTemplatePartialSpecialization) &&
+ *ty != canonical_declaration.cur_type() &&
+ location.is_some() && parent_id.is_some() {
+ return Some(
+ self.build_template_wrapper(id, parent_id.unwrap(), ty,
+ location.unwrap()));
+ }
+
+ return Some(self.build_ty_wrapper(id, parent_id, ty));
+ }
+ }
+
+ debug!("Not resolved, maybe builtin?");
+
+ // Else, build it.
+ self.build_builtin_ty(ty, declaration)
+ }
+
+ // This is unfortunately a lot of bloat, but is needed to properly track
+ // constness et. al.
+ //
+ // We should probably make the constness tracking separate, so it doesn't
+ // bloat that much, but hey, we already bloat the heck out of builtin types.
+ fn build_ty_wrapper(&mut self,
+ wrapped_id: ItemId,
+ parent_id: Option<ItemId>,
+ ty: &clang::Type) -> ItemId {
+ let id = ItemId::next();
+ let spelling = ty.spelling();
+ let is_const = ty.is_const();
+ let layout = ty.fallible_layout().ok();
+ let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
+ let ty = Type::new(Some(spelling), layout, type_kind, is_const);
+ let item = Item::new(id, None, None,
+ parent_id.unwrap_or(self.current_module), ItemKind::Type(ty));
+ self.add_builtin_item(item);
+ id
+ }
+
+ fn build_builtin_ty(&mut self,
+ ty: &clang::Type,
+ _declaration: Cursor) -> Option<ItemId> {
+ use clangll::*;
+ let type_kind = match ty.kind() {
+ CXType_NullPtr => TypeKind::NullPtr,
+ CXType_Void => TypeKind::Void,
+ CXType_Bool => TypeKind::Int(IntKind::Bool),
+ CXType_Int => TypeKind::Int(IntKind::Int),
+ CXType_UInt => TypeKind::Int(IntKind::UInt),
+ CXType_SChar |
+ CXType_Char_S => TypeKind::Int(IntKind::Char),
+ CXType_UChar |
+ CXType_Char_U => TypeKind::Int(IntKind::UChar),
+ CXType_Short => TypeKind::Int(IntKind::Short),
+ CXType_UShort => TypeKind::Int(IntKind::UShort),
+ CXType_WChar |
+ CXType_Char16 => TypeKind::Int(IntKind::U16),
+ CXType_Char32 => TypeKind::Int(IntKind::U32),
+ CXType_Long => TypeKind::Int(IntKind::Long),
+ CXType_ULong => TypeKind::Int(IntKind::ULong),
+ CXType_LongLong => TypeKind::Int(IntKind::LongLong),
+ CXType_ULongLong => TypeKind::Int(IntKind::ULongLong),
+ CXType_Float => TypeKind::Float(FloatKind::Float),
+ CXType_Double => TypeKind::Float(FloatKind::Double),
+ CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
+ _ => return None,
+ };
+
+ let spelling = ty.spelling();
+ let is_const = ty.is_const();
+ let layout = ty.fallible_layout().ok();
+ let ty = Type::new(Some(spelling), layout, type_kind, is_const);
+ let id = ItemId::next();
+ let item = Item::new(id, None, None, self.root_module, ItemKind::Type(ty));
+ self.add_builtin_item(item);
+ Some(id)
+ }
+
+ pub fn translation_unit(&self) -> &clang::TranslationUnit {
+ &self.translation_unit
+ }
+
+ pub fn parsed_macro(&self, macro_name: &str) -> bool {
+ self.parsed_macros.contains(macro_name)
+ }
+
+ pub fn note_parsed_macro(&mut self, macro_name: String) {
+ debug_assert!(!self.parsed_macros.contains(&macro_name));
+ self.parsed_macros.insert(macro_name);
+ }
+
+ pub fn in_codegen_phase(&self) -> bool {
+ self.gen_ctx.is_some()
+ }
+
+ /// This is a bit of a hack, but it's done so using the replaces="xxx"
+ /// annotation implies hide in the other type.
+ pub fn replace(&mut self, name: &str, potential_ty: ItemId) {
+ self.replacements.insert(name.into(), potential_ty);
+ }
+
+ pub fn hidden_by_name(&self, name: &str) -> bool {
+ debug_assert!(self.in_codegen_phase(),
+ "You're not supposed to call this yet");
+ self.options.hidden_types.contains(name)
+ }
+
+ pub fn opaque_by_name(&self, name: &str) -> bool {
+ debug_assert!(self.in_codegen_phase(),
+ "You're not supposed to call this yet");
+ self.options.opaque_types.contains(name)
+ }
+
+ pub fn options(&self) -> &BindgenOptions {
+ &self.options
+ }
+
+ /// Given a CXCursor_Namespace cursor, return the item id of the
+ /// corresponding module, or create one on the fly.
+ pub fn module(&mut self, cursor: clang::Cursor) -> ItemId {
+ use clangll::*;
+ assert!(cursor.kind() == CXCursor_Namespace, "Be a nice person");
+ let cursor = cursor.canonical();
+ let module_id = match self.modules.get(&cursor) {
+ Some(id) => return *id,
+ None => ItemId::next(),
+ };
+
+ let module_name = self.translation_unit
+ .tokens(&cursor).and_then(|tokens| {
+ if tokens.len() <= 1 {
+ None
+ } else {
+ match &*tokens[1].spelling {
+ "{" => None,
+ s => Some(s.to_owned()),
+ }
+ }
+ });
+
+ let module = Module::new(module_name);
+ let module = Item::new(module_id, None, None, self.current_module,
+ ItemKind::Module(module));
+
+ self.add_item(module, None, None);
+
+ module_id
+ }
+
+ pub fn with_module<F>(&mut self, module_id: ItemId, cb: F)
+ where F: FnOnce(&mut Self, &mut Vec<ItemId>)
+ {
+ debug_assert!(self.resolve_item(module_id).kind().is_module(), "Wat");
+
+ let previous_id = self.current_module;
+ self.current_module = module_id;
+
+ let mut children = vec![];
+ cb(self, &mut children);
+
+ self.items.get_mut(&module_id).unwrap()
+ .as_module_mut().expect("Not a module?")
+ .children_mut().extend(children.into_iter());
+
+ self.current_module = previous_id;
+ }
+}
+
+/// This was originally a type that only exposes the resolve_type operation to
+/// its consumers.
+///
+/// Later a made resolve_type public, so... meh. It should go away soon.
+pub type TypeResolver<'ctx> = BindgenContext<'ctx>;
diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs
new file mode 100644
index 00000000..c85ee07a
--- /dev/null
+++ b/src/ir/enum_ty.rs
@@ -0,0 +1,110 @@
+use super::item::{Item, ItemId};
+use super::ty::TypeKind;
+use super::context::BindgenContext;
+use parse::{ClangItemParser, ParseError};
+use clang;
+
+#[derive(Debug)]
+pub struct Enum {
+ /// The representation used for this enum.
+ /// Should be an IntKind type.
+ ///
+ /// It's None if the enum is a forward declaration and isn't defined
+ /// anywhere else, see tests/headers/func_ptr_in_struct.h
+ repr: Option<ItemId>,
+ /// The different variants, with explicit values.
+ variants: Vec<EnumVariant>,
+}
+
+impl Enum {
+ pub fn new(repr: Option<ItemId>, variants: Vec<EnumVariant>) -> Self {
+ Enum {
+ repr: repr,
+ variants: variants,
+ }
+ }
+
+ pub fn repr(&self) -> Option<ItemId> {
+ self.repr
+ }
+
+ pub fn variants(&self) -> &[EnumVariant] {
+ &self.variants
+ }
+
+ pub fn from_ty(ty: &clang::Type,
+ ctx: &mut BindgenContext) -> Result<Self, ParseError> {
+ use clangll::*;
+ if ty.kind() != CXType_Enum {
+ return Err(ParseError::Continue);
+ }
+
+ let declaration = ty.declaration().canonical();
+ let repr = Item::from_ty(&declaration.enum_type(), None, None, ctx).ok();
+ let mut variants = vec![];
+
+ let is_signed = match repr {
+ Some(repr) => {
+ let repr_type = ctx.resolve_type(repr);
+ match *repr_type.canonical_type(ctx).kind() {
+ TypeKind::Int(ref int_kind) => int_kind.is_signed(),
+ ref other => panic!("Since when enums can be non-integers? {:?}", other),
+ }
+ }
+ // Assume signedness since the default type by the C standard is an
+ // int.
+ None => true,
+ };
+
+ declaration.visit(|cursor, _| {
+ if cursor.kind() == CXCursor_EnumConstantDecl {
+ let name = cursor.spelling();
+ let comment = cursor.raw_comment();
+ let val = if is_signed {
+ EnumVariantValue::Signed(cursor.enum_val_signed())
+ } else {
+ EnumVariantValue::Unsigned(cursor.enum_val_unsigned())
+ };
+ variants.push(EnumVariant::new(name, comment, val));
+ }
+ CXChildVisit_Continue
+ });
+
+ Ok(Enum::new(repr, variants))
+ }
+}
+
+/// A single enum variant, to be contained only in an enum.
+#[derive(Debug)]
+pub struct EnumVariant {
+ /// The name of the variant.
+ name: String,
+ /// An optional doc comment.
+ comment: Option<String>,
+ /// The integer value of the variant.
+ val: EnumVariantValue,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum EnumVariantValue {
+ Signed(i64),
+ Unsigned(u64),
+}
+
+impl EnumVariant {
+ pub fn new(name: String, comment: Option<String>, val: EnumVariantValue) -> Self {
+ EnumVariant {
+ name: name,
+ comment: comment,
+ val: val,
+ }
+ }
+
+ pub fn name(&self) -> &str {
+ &self.name
+ }
+
+ pub fn val(&self) -> EnumVariantValue {
+ self.val
+ }
+}
diff --git a/src/ir/function.rs b/src/ir/function.rs
new file mode 100644
index 00000000..b95ac57b
--- /dev/null
+++ b/src/ir/function.rs
@@ -0,0 +1,220 @@
+use super::item::{Item, ItemId};
+use super::ty::TypeKind;
+use super::context::BindgenContext;
+use syntax::abi;
+use clang;
+use clangll::Enum_CXCallingConv;
+use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
+
+/// A function declaration , with a signature, arguments, and argument names.
+///
+/// The argument names vector must be the same length as the ones in the
+/// signature.
+#[derive(Debug)]
+pub struct Function {
+ name: String,
+ /// The mangled name, that is, the symbol.
+ mangled_name: Option<String>,
+ /// The id pointing to the current function signature.
+ signature: ItemId,
+ /// The doc comment on the function, if any.
+ comment: Option<String>,
+}
+
+impl Function {
+ pub fn new(name: String,
+ mangled_name: Option<String>,
+ sig: ItemId,
+ comment: Option<String>) -> Self {
+ Function {
+ name: name,
+ mangled_name: mangled_name,
+ signature: sig,
+ comment: comment,
+ }
+ }
+
+ pub fn name(&self) -> &str {
+ &self.name
+ }
+
+ pub fn mangled_name(&self) -> Option<&str> {
+ self.mangled_name.as_ref().map(|n| &**n)
+ }
+
+ pub fn signature(&self) -> ItemId {
+ self.signature
+ }
+}
+
+/// A function signature.
+#[derive(Debug)]
+pub struct FunctionSig {
+ /// The return type of the function.
+ return_type: ItemId,
+ /// The type of the arguments, optionally with the name of the argument when
+ /// declared.
+ argument_types: Vec<(Option<String>, ItemId)>,
+ /// Whether this function is variadic.
+ is_variadic: bool,
+ /// The abi of this function.
+ abi: abi::Abi,
+}
+
+fn get_abi(cc: Enum_CXCallingConv) -> abi::Abi {
+ use clangll::*;
+ match cc {
+ CXCallingConv_Default => abi::Abi::C,
+ CXCallingConv_C => abi::Abi::C,
+ CXCallingConv_X86StdCall => abi::Abi::Stdcall,
+ CXCallingConv_X86FastCall => abi::Abi::Fastcall,
+ CXCallingConv_AAPCS => abi::Abi::Aapcs,
+ CXCallingConv_X86_64Win64 => abi::Abi::Win64,
+ other => panic!("unsupported calling convention: {}", other),
+ }
+}
+
+pub fn cursor_mangling(cursor: &clang::Cursor) -> Option<String> {
+ let mut mangling = cursor.mangling();
+
+ // Try to undo backend linkage munging (prepended _, generally)
+ if cfg!(target_os = "macos") {
+ mangling.remove(0);
+ }
+
+ if mangling.is_empty() { None } else { Some(mangling) }
+}
+
+impl FunctionSig {
+ pub fn new(return_type: ItemId,
+ arguments: Vec<(Option<String>, ItemId)>,
+ is_variadic: bool,
+ abi: abi::Abi) -> Self {
+ FunctionSig {
+ return_type: return_type,
+ argument_types: arguments,
+ is_variadic: is_variadic,
+ abi: abi,
+ }
+ }
+
+ pub fn from_ty(ty: &clang::Type,
+ cursor: &clang::Cursor,
+ ctx: &mut BindgenContext) -> Result<Self, ParseError> {
+ use clangll::*;
+ debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor);
+
+ // Don't parse operatorxx functions in C++
+ let spelling = cursor.spelling();
+ if spelling.starts_with("operator") {
+ return Err(ParseError::Continue);
+ }
+
+ let cursor = if cursor.is_valid() {
+ *cursor
+ } else {
+ ty.declaration()
+ };
+ let mut args: Vec<_> = match cursor.kind() {
+ CXCursor_FunctionDecl |
+ CXCursor_CXXMethod => {
+ // For CXCursor_FunctionDecl, cursor.args() is the reliable way
+ // to get parameter names and types.
+ cursor.args().iter().map(|arg| {
+ let arg_ty = arg.cur_type();
+ let name = arg.spelling();
+ let name = if name.is_empty() { None } else { Some(name) };
+ let ty = Item::from_ty(&arg_ty, Some(*arg), None, ctx)
+ .expect("Argument?");
+ (name, ty)
+ }).collect()
+ }
+ _ => {
+ // For non-CXCursor_FunctionDecl, visiting the cursor's children
+ // is the only reliable way to get parameter names.
+ let mut args = vec![];
+ cursor.visit(|c, _| {
+ if c.kind() == CXCursor_ParmDecl {
+ let ty = Item::from_ty(&c.cur_type(), Some(*c), None, ctx)
+ .expect("ParmDecl?");
+ let name = c.spelling();
+ let name = if name.is_empty() { None } else { Some(name) };
+ args.push((name, ty));
+ }
+ CXChildVisit_Continue
+ });
+ args
+ }
+ };
+
+ if cursor.kind() == CXCursor_CXXMethod {
+ let is_const = cursor.method_is_const();
+ let is_virtual = cursor.method_is_virtual();
+ let is_static = cursor.method_is_static();
+ if !is_static && !is_virtual {
+ let class = Item::parse(cursor.semantic_parent(), None, ctx)
+ .expect("Expected to parse the class");
+ let ptr = Item::builtin_type(TypeKind::Pointer(class), is_const, ctx);
+ args.insert(0, (Some("this".into()), ptr));
+ } else if is_virtual {
+ let void = Item::builtin_type(TypeKind::Void, false, ctx);
+ let ptr = Item::builtin_type(TypeKind::Pointer(void), false, ctx);
+ args.insert(0, (Some("this".into()), ptr));
+ }
+ }
+
+ let ret = try!(Item::from_ty(&ty.ret_type(), None, None, ctx));
+ let abi = get_abi(ty.call_conv());
+
+ Ok(Self::new(ret, args, ty.is_variadic(), abi))
+ }
+
+ pub fn return_type(&self) -> ItemId {
+ self.return_type
+ }
+
+ pub fn argument_types(&self) -> &[(Option<String>, ItemId)] {
+ &self.argument_types
+ }
+
+ pub fn abi(&self) -> abi::Abi {
+ self.abi
+ }
+
+ pub fn is_variadic(&self) -> bool {
+ // Clang reports some functions as variadic when they *might* be
+ // variadic. We do the argument check because rust doesn't codegen well
+ // variadic functions without an initial argument.
+ self.is_variadic && !self.argument_types.is_empty()
+ }
+}
+
+impl ClangSubItemParser for Function {
+ fn parse(cursor: clang::Cursor,
+ context: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError> {
+ use clangll::*;
+ match cursor.kind() {
+ CXCursor_FunctionDecl |
+ CXCursor_CXXMethod => {},
+ _ => return Err(ParseError::Continue),
+ };
+
+ debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());
+
+ // Grab the signature using Item::from_ty.
+ let sig = try!(Item::from_ty(&cursor.cur_type(), Some(cursor), None, context));
+
+ let name = cursor.spelling();
+ assert!(!name.is_empty(), "Empty function name?");
+
+ let mut mangled_name = cursor_mangling(&cursor);
+ if mangled_name.as_ref() == Some(&name) {
+ mangled_name = None;
+ }
+
+ let comment = cursor.raw_comment();
+
+ let function = Self::new(name, mangled_name, sig, comment);
+ Ok(ParseResult::New(function, Some(cursor)))
+ }
+}
diff --git a/src/ir/int.rs b/src/ir/int.rs
new file mode 100644
index 00000000..d2769b77
--- /dev/null
+++ b/src/ir/int.rs
@@ -0,0 +1,30 @@
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum IntKind {
+ Bool,
+ Char,
+ UChar,
+ Short,
+ UShort,
+ Int,
+ UInt,
+ Long,
+ ULong,
+ LongLong,
+ ULongLong,
+ U16, // For Char16 and Wchar
+ U32, // For Char32
+ // Though now we're at it we could add equivalents for the rust types...
+}
+
+impl IntKind {
+ pub fn is_signed(&self) -> bool {
+ use self::IntKind::*;
+ match *self {
+ Bool | UChar | UShort |
+ UInt | ULong | ULongLong | U16 | U32 => false,
+
+ Char | Short | Int |
+ Long | LongLong => true,
+ }
+ }
+}
diff --git a/src/ir/item.rs b/src/ir/item.rs
new file mode 100644
index 00000000..c9ac71a4
--- /dev/null
+++ b/src/ir/item.rs
@@ -0,0 +1,681 @@
+use super::context::BindgenContext;
+use super::item_kind::ItemKind;
+use super::ty::{Type, TypeKind};
+use super::function::Function;
+use super::module::Module;
+use super::annotations::Annotations;
+use std::fmt;
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
+use clang;
+use clangll;
+
+/// A trait to get the canonical name from an item.
+///
+/// This is the trait that will eventually isolate all the logic related to name
+/// mangling and that kind of stuff.
+///
+/// This assumes no nested paths, at some point I'll have to make it a more
+/// complex thing.
+///
+/// This name is required to be safe for Rust, that is, is not expected to
+/// return any rust keyword from here.
+pub trait ItemCanonicalName {
+ fn canonical_name(&self, ctx: &BindgenContext) -> String;
+}
+
+/// The same, but specifies the path that needs to be followed to reach an item.
+///
+/// To contrast with canonical_name, here's an example:
+///
+/// ```
+/// namespace foo {
+/// const BAR = 3;
+/// }
+/// ```
+///
+/// For bar, the canonical path is foo::BAR, while the canonical name is just
+/// BAR.
+pub trait ItemCanonicalPath {
+ fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String>;
+}
+
+/// A single identifier for an item.
+///
+/// TODO: Build stronger abstractions on top of this, like TypeId(ItemId), ...
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct ItemId(usize);
+
+impl fmt::Display for ItemId {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(fmt, "_bindgen_id_"));
+ self.0.fmt(fmt)
+ }
+}
+
+pub static NEXT_ITEM_ID: AtomicUsize = ATOMIC_USIZE_INIT;
+
+impl ItemId {
+ pub fn next() -> Self {
+ ItemId(NEXT_ITEM_ID.fetch_add(1, Ordering::Relaxed))
+ }
+}
+
+// Pure convenience
+impl ItemCanonicalName for ItemId {
+ fn canonical_name(&self, ctx: &BindgenContext) -> String {
+ debug_assert!(ctx.in_codegen_phase(),
+ "You're not supposed to call this yet");
+ ctx.resolve_item(*self).canonical_name(ctx)
+ }
+}
+
+impl ItemCanonicalPath for ItemId {
+ fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
+ debug_assert!(ctx.in_codegen_phase(),
+ "You're not supposed to call this yet");
+ ctx.resolve_item(*self).canonical_path(ctx)
+ }
+}
+
+#[derive(Debug)]
+pub struct Item {
+ /// This item's id.
+ id: ItemId,
+ /// A doc comment over the item, if any.
+ comment: Option<String>,
+ /// Annotations extracted from the doc comment, or the default ones
+ /// otherwise.
+ annotations: Annotations,
+ /// An item's parent id. This will most likely be a class where this item
+ /// was declared, or a module, etc.
+ ///
+ /// All the items have a parent, except the root module, in which case the
+ /// parent id is its own id.
+ parent_id: ItemId,
+ /// The item kind.
+ kind: ItemKind,
+}
+
+impl Item {
+ pub fn new(id: ItemId,
+ comment: Option<String>,
+ annotations: Option<Annotations>,
+ parent_id: ItemId,
+ kind: ItemKind) -> Self {
+ debug_assert!(id != parent_id || kind.is_module());
+ Item {
+ id: id,
+ parent_id: parent_id,
+ comment: comment,
+ annotations: annotations.unwrap_or_default(),
+ kind: kind,
+ }
+ }
+
+ pub fn id(&self) -> ItemId {
+ self.id
+ }
+
+ pub fn parent_id(&self) -> ItemId {
+ self.parent_id
+ }
+
+ pub fn comment(&self) -> Option<&str> {
+ self.comment.as_ref().map(|c| &**c)
+ }
+
+ pub fn kind(&self) -> &ItemKind {
+ &self.kind
+ }
+
+ pub fn kind_mut(&mut self) -> &mut ItemKind {
+ &mut self.kind
+ }
+
+ pub fn is_toplevel(&self, ctx: &BindgenContext) -> bool {
+ // FIXME: Workaround for some types falling behind when parsing weird
+ // stl classes, for example.
+ if ctx.options().enable_cxx_namespaces &&
+ self.kind().is_module() &&
+ self.id() != ctx.root_module() {
+ return false;
+ }
+
+ let mut parent = self.parent_id;
+ loop {
+ let parent_item = match ctx.resolve_item_fallible(parent) {
+ Some(item) => item,
+ None => return false,
+ };
+
+ if parent_item.id() == ctx.root_module() {
+ return true;
+ } else if ctx.options().enable_cxx_namespaces || !parent_item.kind().is_module() {
+ return false;
+ }
+
+ parent = parent_item.parent_id();
+ }
+ }
+
+ pub fn expect_type(&self) -> &Type {
+ self.kind().expect_type()
+ }
+
+ pub fn expect_function(&self) -> &Function {
+ self.kind().expect_function()
+ }
+
+ 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(ref n, _), &TypeKind::Named(ref i, _)) => n == i,
+ _ => false,
+ }
+ })
+ }
+
+ match *ty.kind() {
+ TypeKind::Named(..) => vec![self.id()],
+ TypeKind::Array(inner, _) |
+ TypeKind::Pointer(inner) |
+ TypeKind::Reference(inner) |
+ TypeKind::Alias(_, inner) |
+ TypeKind::ResolvedTypeRef(inner) => {
+ ctx.resolve_item(inner).applicable_template_args(ctx)
+ }
+ // XXX Is this completely correct? Partial template specialization
+ // is hard anyways, sigh...
+ TypeKind::TemplateRef(_, 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![],
+ }
+ }
+
+ fn is_module(&self) -> bool {
+ match self.kind {
+ ItemKind::Module(..) => true,
+ _ => false,
+ }
+ }
+
+ pub fn annotations(&self) -> &Annotations {
+ &self.annotations
+ }
+
+ /// Whether this item should be hidden, either due to annotations, or due to
+ /// other kind of configuration.
+ pub fn is_hidden(&self, ctx: &BindgenContext) -> bool {
+ debug_assert!(ctx.in_codegen_phase(),
+ "You're not supposed to call this yet");
+ self.annotations.hide() ||
+ ctx.hidden_by_name(&self.real_canonical_name(ctx, false))
+ }
+
+ pub fn is_opaque(&self, ctx: &BindgenContext) -> bool {
+ debug_assert!(ctx.in_codegen_phase(),
+ "You're not supposed to call this yet");
+ self.annotations.opaque() ||
+ ctx.opaque_by_name(&self.real_canonical_name(ctx, false))
+ }
+
+ /// Get the canonical name without taking into account the replaces
+ /// annotation.
+ fn real_canonical_name(&self, ctx: &BindgenContext, count_namespaces: bool) -> String {
+ let base_name = match *self.kind() {
+ ItemKind::Type(ref ty) => {
+ match *ty.kind() {
+ // If we're a template specialization, our name is our parent's
+ TypeKind::Comp(ref ci) if ci.is_template_specialization() => {
+ return ci.specialized_template().unwrap().canonical_name(ctx);
+ },
+ // Same as above
+ TypeKind::ResolvedTypeRef(inner) |
+ TypeKind::TemplateRef(inner, _) => {
+ return inner.canonical_name(ctx);
+ }
+ // If we're a named type, we don't need to mangle it, and we
+ // should be able to assert we're not top level.
+ TypeKind::Named(ref name, _) => {
+ return name.to_owned();
+ }
+ _ => {}
+ }
+
+ ty.name().map(ToOwned::to_owned)
+ .unwrap_or_else(|| format!("_bindgen_ty{}", self.id()))
+ }
+ ItemKind::Function(ref fun) => {
+ let mut base = fun.name().to_owned();
+
+ // We might need to deduplicate if we're a method.
+ let parent = ctx.resolve_item(self.parent_id());
+ if let ItemKind::Type(ref ty) = *parent.kind() {
+ if let TypeKind::Comp(ref ci) = *ty.kind() {
+ let mut count = 0;
+ let mut found = false;
+ for method in ci.methods() {
+ if method.signature() == self.id() {
+ found = true;
+ break;
+ }
+ let fun = ctx.resolve_item(method.signature())
+ .expect_function();
+ if fun.name() == base {
+ count += 1;
+ }
+ }
+
+ assert!(found, "Method not found?");
+ if count != 0 {
+ base.push_str(&count.to_string());
+ }
+ }
+ }
+ base
+ }
+ ItemKind::Var(ref var) => {
+ var.name().to_owned()
+ }
+ ItemKind::Module(ref module) => {
+ module.name().map(ToOwned::to_owned)
+ .unwrap_or_else(|| format!("_bindgen_mod{}", self.id()))
+ }
+ };
+
+ let parent = ctx.resolve_item(self.parent_id());
+ let parent_is_namespace = parent.is_module();
+ if self.is_toplevel(ctx) || (parent_is_namespace && count_namespaces) {
+ return ctx.rust_mangle(&base_name).into_owned();
+ }
+
+ // TODO: allow modification of the mangling functions, maybe even per
+ // item type?
+ format!("{}_{}", parent.canonical_name(ctx), base_name)
+ }
+
+ pub fn as_module_mut(&mut self) -> Option<&mut Module> {
+ match self.kind {
+ ItemKind::Module(ref mut module) => Some(module),
+ _ => None,
+ }
+ }
+}
+
+impl ClangItemParser for Item {
+ fn builtin_type(kind: TypeKind, is_const: bool, ctx: &mut BindgenContext) -> ItemId {
+ // Feel free to add more here, I'm just lazy.
+ match kind {
+ TypeKind::Void |
+ TypeKind::Int(..) |
+ TypeKind::Pointer(..) |
+ TypeKind::Float(..) => {},
+ _ => panic!("Unsupported builtin type"),
+ }
+
+ let ty = Type::new(None, None, kind, is_const);
+ let id = ItemId::next();
+ let module = ctx.root_module();
+ ctx.add_item(Item::new(id, None, None, module, ItemKind::Type(ty)),
+ None, None);
+ id
+ }
+
+
+ fn parse(cursor: clang::Cursor,
+ parent_id: Option<ItemId>,
+ context: &mut BindgenContext) -> Result<ItemId, ParseError> {
+ use ir::function::Function;
+ use ir::module::Module;
+ use ir::var::Var;
+
+ if !cursor.is_valid() {
+ return Err(ParseError::Continue);
+ }
+
+ let comment = cursor.raw_comment();
+ let annotations = Annotations::new(&cursor);
+
+ // FIXME: The current_module logic is not really accurate. We should be
+ // able to index modules by their Cursor, and locate the proper module
+ // for a given item.
+ //
+ // We don't support modules properly though, so there's no rush for
+ // this.
+ let current_module = context.current_module();
+ macro_rules! try_parse {
+ ($what:ident) => {
+ match $what::parse(cursor, context) {
+ Ok(ParseResult::New(item, declaration)) => {
+ let id = ItemId::next();
+ context.add_item(Item::new(id, comment, annotations,
+ parent_id.unwrap_or(current_module),
+ ItemKind::$what(item)),
+ declaration,
+ Some(cursor));
+ return Ok(id);
+ }
+ Ok(ParseResult::AlreadyResolved(id)) => {
+ return Ok(id);
+ }
+ Err(ParseError::Recurse) => return Err(ParseError::Recurse),
+ Err(ParseError::Continue) => {},
+ }
+ }
+ }
+
+ try_parse!(Module);
+
+ // NOTE: Is extremely important to parse functions and vars **before**
+ // types. Otherwise we can parse a function declaration as a type
+ // (which is legal), and lose functions to generate.
+ //
+ // In general, I'm not totally confident this split between
+ // ItemKind::Function and TypeKind::FunctionSig is totally worth it, but
+ // I guess we can try.
+ try_parse!(Function);
+ try_parse!(Var);
+
+ // Types are sort of special, so to avoid parsing template classes
+ // twice, handle them separately.
+ {
+ let definition = cursor.definition();
+ let applicable_cursor = if definition.is_valid() {
+ definition
+ } else {
+ cursor
+ };
+ match Self::from_ty(&applicable_cursor.cur_type(),
+ Some(applicable_cursor), parent_id, context)
+ {
+ Ok(ty) => return Ok(ty),
+ Err(ParseError::Recurse) => return Err(ParseError::Recurse),
+ Err(ParseError::Continue) => {},
+ }
+ }
+
+ // Guess how does clang treat extern "C" blocks?
+ if cursor.kind() == clangll::CXCursor_UnexposedDecl {
+ Err(ParseError::Recurse)
+ } else {
+ error!("Unhandled cursor kind: {}", ::clang::kind_to_str(cursor.kind()));
+ Err(ParseError::Continue)
+ }
+ }
+
+ fn from_ty_or_ref(ty: clang::Type,
+ location: Option<clang::Cursor>,
+ parent_id: Option<ItemId>,
+ context: &mut BindgenContext) -> ItemId {
+ debug!("from_ty_or_ref: {:?}, {:?}, {:?}", ty, location, parent_id);
+
+ if context.collected_typerefs() {
+ debug!("refs already collected, resolving directly");
+ return Self::from_ty(&ty, location, parent_id, context)
+ .expect("Unable to resolve type");
+ }
+
+ if let Some(ty) = context.builtin_or_resolved_ty(parent_id, &ty, location) {
+ debug!("{:?} already resolved: {:?}", ty, location);
+ return ty;
+ }
+
+ debug!("New unresolved type reference: {:?}, {:?}", ty, location);
+
+ let is_const = ty.is_const();
+ let kind = TypeKind::UnresolvedTypeRef(ty, location);
+ let id = ItemId::next();
+ let current_module = context.current_module();
+ context.add_item(Item::new(id, None, None,
+ parent_id.unwrap_or(current_module),
+ ItemKind::Type(Type::new(None, None, kind, is_const))),
+ Some(clang::Cursor::null()),
+ None);
+ id
+ }
+
+
+ fn from_ty(ty: &clang::Type,
+ location: Option<clang::Cursor>,
+ parent_id: Option<ItemId>,
+ context: &mut BindgenContext) -> Result<ItemId, ParseError> {
+ Self::from_ty_with_id(ItemId::next(), ty, location, parent_id, context)
+ }
+
+ fn from_ty_with_id(id: ItemId,
+ ty: &clang::Type,
+ location: Option<clang::Cursor>,
+ parent_id: Option<ItemId>,
+ context: &mut BindgenContext) -> Result<ItemId, ParseError> {
+ use clangll::*;
+
+ let decl = {
+ let decl = ty.declaration();
+ let definition = decl.definition();
+ if definition.is_valid() {
+ definition
+ } else {
+ decl
+ }
+ };
+
+ let comment =
+ decl.raw_comment()
+ .or_else(|| location.as_ref().and_then(|l| l.raw_comment()));
+ let annotations =
+ Annotations::new(&decl)
+ .or_else(|| location.as_ref().and_then(|l| Annotations::new(l)));
+
+ if let Some(ref replaced) = annotations.as_ref().and_then(|a| a.use_instead_of()) {
+ context.replace(replaced, id);
+ }
+
+ if let Some(ty) = context.builtin_or_resolved_ty(parent_id, ty, location) {
+ return Ok(ty);
+ }
+
+ // First, check we're not recursing.
+ let mut valid_decl = decl.kind() != CXCursor_NoDeclFound;
+ let declaration_to_look_for = if valid_decl {
+ decl.canonical()
+ } else if location.is_some() && location.unwrap().kind() == CXCursor_ClassTemplate {
+ valid_decl = true;
+ location.unwrap()
+ } else {
+ decl
+ };
+
+ if valid_decl {
+ if let Some(&(_, item_id)) = context.currently_parsed_types.iter().find(|&&(d, _)| d == declaration_to_look_for) {
+ debug!("Avoiding recursion parsing type: {:?}", ty);
+ return Ok(item_id);
+ }
+ }
+
+ let current_module = context.current_module();
+ if valid_decl {
+ context.currently_parsed_types.push((declaration_to_look_for, id));
+ }
+
+ let result = Type::from_clang_ty(id, ty, location, parent_id, context);
+ let ret = match result {
+ Ok(ParseResult::AlreadyResolved(ty)) => Ok(ty),
+ Ok(ParseResult::New(item, declaration)) => {
+ context.add_item(Item::new(id, comment, annotations,
+ parent_id.unwrap_or(current_module),
+ ItemKind::Type(item)),
+ declaration,
+ location);
+ Ok(id)
+ }
+ Err(ParseError::Continue) => Err(ParseError::Continue),
+ Err(ParseError::Recurse) => {
+ debug!("Item::from_ty recursing in the ast");
+ 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 (popped_decl, _) = context.currently_parsed_types.pop().unwrap();
+ assert_eq!(popped_decl, declaration_to_look_for);
+ }
+
+ location.visit(|cur, _other| {
+ use clangll::*;
+ result = Item::from_ty_with_id(id, ty, Some(*cur), parent_id, context);
+ match result {
+ Ok(..) => CXChildVisit_Break,
+ Err(ParseError::Recurse) => CXChildVisit_Recurse,
+ Err(ParseError::Continue) => CXChildVisit_Continue,
+ }
+ });
+
+ if valid_decl {
+ context.currently_parsed_types.push((declaration_to_look_for, id));
+ }
+ }
+ // 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.
+ //
+ // 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 {
+ Ok(Self::named_type_with_id(id, ty.spelling(),
+ None,
+ parent_id.unwrap_or(context.current_module()),
+ context))
+ } else {
+ result
+ }
+ }
+ };
+
+ if valid_decl {
+ let (popped_decl, _) = context.currently_parsed_types.pop().unwrap();
+ assert_eq!(popped_decl, declaration_to_look_for);
+ }
+
+ ret
+ }
+
+ /// 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
+ /// a type.
+ ///
+ /// It must have an id, and must not be the current module id. Ideally we
+ /// could assert the parent id is a Comp(..) type, but that info isn't
+ /// available yet.
+ fn named_type_with_id<S>(id: ItemId,
+ name: S,
+ default: Option<ItemId>,
+ parent_id: ItemId,
+ context: &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(".", "");
+
+ context.add_item(Item::new(id, None, None, parent_id,
+ ItemKind::Type(Type::named(name, default))),
+ None,
+ None);
+
+ id
+ }
+
+ fn named_type<S>(name: S,
+ default: Option<ItemId>,
+ parent_id: ItemId,
+ context: &mut BindgenContext) -> ItemId
+ where S: Into<String>
+ {
+ Self::named_type_with_id(ItemId::next(), name, default, parent_id, context)
+ }
+}
+
+impl ItemCanonicalName for Item {
+ fn canonical_name(&self, ctx: &BindgenContext) -> String {
+ debug_assert!(ctx.in_codegen_phase(),
+ "You're not supposed to call this yet");
+ if let Some(other_canon_type) = self.annotations.use_instead_of() {
+ return other_canon_type.to_owned();
+ }
+ self.real_canonical_name(ctx, ctx.options().enable_cxx_namespaces)
+ }
+}
+
+impl ItemCanonicalPath for Item {
+ fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
+ if !ctx.options().enable_cxx_namespaces {
+ return vec![self.canonical_name(ctx)];
+ }
+
+ if self.id() == ctx.root_module() {
+ match self.kind {
+ ItemKind::Module(ref module) => {
+ return vec![module.name().unwrap().into()]
+ }
+ _ => panic!("Something has wrong horribly wrong"),
+ }
+ }
+
+ // TODO: This duplicates too much logic with real_canonical_name.
+ if let ItemKind::Type(ref ty) = *self.kind() {
+ match *ty.kind() {
+ TypeKind::Comp(ref ci) if ci.is_template_specialization() => {
+ return ci.specialized_template().unwrap().canonical_path(ctx);
+ },
+ TypeKind::ResolvedTypeRef(inner) |
+ TypeKind::TemplateRef(inner, _) => {
+ return inner.canonical_path(ctx);
+ }
+ TypeKind::Named(ref name, _) => {
+ return vec![name.clone()];
+ }
+ _ => {}
+ }
+ }
+
+ let mut parent_path = self.parent_id().canonical_path(&ctx);
+ parent_path.push(self.real_canonical_name(ctx, true));
+
+ parent_path
+ }
+}
diff --git a/src/ir/item_kind.rs b/src/ir/item_kind.rs
new file mode 100644
index 00000000..b6f317a7
--- /dev/null
+++ b/src/ir/item_kind.rs
@@ -0,0 +1,89 @@
+use super::function::Function;
+use super::module::Module;
+use super::ty::Type;
+use super::var::Var;
+
+/// A item we parse and translate.
+#[derive(Debug)]
+pub enum ItemKind {
+ /// A module, created implicitly once (the root module), or via C++
+ /// namespaces.
+ Module(Module),
+
+ /// A type declared in any of the multiple ways it can be declared.
+ Type(Type),
+
+ /// A function or method declaration.
+ Function(Function),
+ /// A variable declaration, most likely a static.
+ Var(Var),
+}
+
+impl ItemKind {
+ pub fn as_module(&self) -> Option<&Module> {
+ match *self {
+ ItemKind::Module(ref module) => Some(module),
+ _ => None,
+ }
+ }
+
+ pub fn is_module(&self) -> bool {
+ self.as_module().is_some()
+ }
+
+ pub fn expect_module(&self) -> &Module {
+ self.as_module().expect("Not a module")
+ }
+
+ pub fn as_function(&self) -> Option<&Function> {
+ match *self {
+ ItemKind::Function(ref func) => Some(func),
+ _ => None,
+ }
+ }
+
+ pub fn is_function(&self) -> bool {
+ self.as_function().is_some()
+ }
+
+ pub fn expect_function(&self) -> &Function {
+ self.as_function().expect("Not a function")
+ }
+
+ pub fn as_type(&self) -> Option<&Type> {
+ match *self {
+ ItemKind::Type(ref ty) => Some(ty),
+ _ => None,
+ }
+ }
+
+ pub fn as_type_mut(&mut self) -> Option<&mut Type> {
+ match *self {
+ ItemKind::Type(ref mut ty) => Some(ty),
+ _ => None,
+ }
+ }
+
+ pub fn is_type(&self) -> bool {
+ self.as_type().is_some()
+ }
+
+ pub fn expect_type(&self) -> &Type {
+ self.as_type().expect("Not a type")
+ }
+
+ pub fn as_var(&self) -> Option<&Var> {
+ match *self {
+ ItemKind::Var(ref v) => Some(v),
+ _ => None,
+ }
+ }
+
+ pub fn is_var(&self) -> bool {
+ self.as_var().is_some()
+ }
+
+ pub fn expect_var(&self) -> &Var {
+ self.as_var().expect("Not a var")
+ }
+}
diff --git a/src/ir/layout.rs b/src/ir/layout.rs
new file mode 100644
index 00000000..d672ebea
--- /dev/null
+++ b/src/ir/layout.rs
@@ -0,0 +1,26 @@
+
+/// A type that represents the struct layout of a type.
+#[derive(Debug, Clone, Copy)]
+pub struct Layout {
+ pub size: usize,
+ pub align: usize,
+ pub packed: bool,
+}
+
+impl Layout {
+ pub fn new(size: usize, align: usize) -> Self {
+ Layout {
+ size: size,
+ align: align,
+ packed: false,
+ }
+ }
+
+ pub fn is_zero(&self) -> bool {
+ self.size == 0 && self.align == 0
+ }
+
+ pub fn zero() -> Self {
+ Self::new(0, 0)
+ }
+}
diff --git a/src/ir/mod.rs b/src/ir/mod.rs
new file mode 100644
index 00000000..07ac3059
--- /dev/null
+++ b/src/ir/mod.rs
@@ -0,0 +1,12 @@
+pub mod annotations;
+pub mod comp;
+pub mod context;
+pub mod enum_ty;
+pub mod function;
+pub mod int;
+pub mod item;
+pub mod item_kind;
+pub mod layout;
+pub mod module;
+pub mod ty;
+pub mod var;
diff --git a/src/ir/module.rs b/src/ir/module.rs
new file mode 100644
index 00000000..77fee5ef
--- /dev/null
+++ b/src/ir/module.rs
@@ -0,0 +1,52 @@
+use super::context::BindgenContext;
+use super::item::ItemId;
+use clang;
+use parse::{ClangSubItemParser, ParseError, ParseResult};
+use parse_one;
+
+/// A module, as in, a C++ namespace.
+#[derive(Clone, Debug)]
+pub struct Module {
+ /// The name of the module, or none if it's anonymous.
+ name: Option<String>,
+ /// The children of this module, just here for convenience.
+ children_ids: Vec<ItemId>,
+}
+
+impl Module {
+ pub fn new(name: Option<String>) -> Self {
+ Module {
+ name: name,
+ children_ids: vec![],
+ }
+ }
+
+ pub fn name(&self) -> Option<&str> {
+ self.name.as_ref().map(|n| &**n)
+ }
+
+ pub fn children_mut(&mut self) -> &mut Vec<ItemId> {
+ &mut self.children_ids
+ }
+
+ pub fn children(&self) -> &[ItemId] {
+ &self.children_ids
+ }
+}
+
+impl ClangSubItemParser for Module {
+ fn parse(cursor: clang::Cursor, ctx: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError> {
+ use clangll::*;
+ match cursor.kind() {
+ CXCursor_Namespace => {
+ let module_id = ctx.module(cursor);
+ ctx.with_module(module_id, |ctx, children| {
+ cursor.visit(|cursor, _| parse_one(ctx, *cursor, Some(module_id), children))
+ });
+
+ Ok(ParseResult::AlreadyResolved(module_id))
+ }
+ _ => Err(ParseError::Continue)
+ }
+ }
+}
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
new file mode 100644
index 00000000..b0448437
--- /dev/null
+++ b/src/ir/ty.rs
@@ -0,0 +1,537 @@
+use super::comp::CompInfo;
+use super::enum_ty::Enum;
+use super::function::FunctionSig;
+use super::item::{Item, ItemId};
+use super::int::IntKind;
+use super::layout::Layout;
+use super::context::BindgenContext;
+use super::context::TypeResolver;
+use parse::{ClangItemParser, ParseResult, ParseError};
+use clang::{self, Cursor};
+
+#[derive(Debug)]
+pub struct Type {
+ /// The name of the type, or None if it was an unnamed struct or union.
+ name: Option<String>,
+ /// The layout of the type, if known.
+ layout: Option<Layout>,
+ /// Whether this type is marked as opaque.
+ opaque: bool,
+ /// Whether this type is marked as hidden.
+ hide: bool,
+ /// The inner kind of the type
+ kind: TypeKind,
+ /// Whether this type is const-qualified.
+ is_const: bool,
+}
+
+pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32usize;
+
+impl Type {
+ pub fn as_comp(&self) -> Option<&CompInfo> {
+ match self.kind {
+ TypeKind::Comp(ref ci) => Some(ci),
+ _ => None,
+ }
+ }
+
+ pub fn new(name: Option<String>,
+ layout: Option<Layout>,
+ kind: TypeKind,
+ is_const: bool) -> Self {
+ Type {
+ name: name,
+ layout: layout,
+ opaque: false,
+ hide: false,
+ kind: kind,
+ is_const: is_const,
+ }
+ }
+
+ pub fn kind(&self) -> &TypeKind {
+ &self.kind
+ }
+
+ pub fn kind_mut(&mut self) -> &mut TypeKind {
+ &mut self.kind
+ }
+
+ pub fn name(&self) -> Option<&str> {
+ self.name.as_ref().map(|name| &**name)
+ }
+
+ pub fn is_comp(&self) -> bool {
+ match self.kind {
+ TypeKind::Comp(..) => true,
+ _ => false,
+ }
+ }
+
+ pub fn is_named(&self) -> bool {
+ match self.kind {
+ TypeKind::Named(..) => true,
+ _ => false,
+ }
+ }
+
+ pub fn is_builtin_or_named(&self) -> bool {
+ match self.kind {
+ TypeKind::Void |
+ TypeKind::NullPtr |
+ TypeKind::Function(..) |
+ TypeKind::Array(..) |
+ TypeKind::Reference(..) |
+ TypeKind::Pointer(..) |
+ TypeKind::Int(..) |
+ TypeKind::Float(..) |
+ TypeKind::Named(..) => true,
+ _ => false,
+ }
+ }
+
+ /// Creates a new named type, with name `name`.
+ pub fn named(name: String, default: Option<ItemId>) -> Self {
+ assert!(!name.is_empty());
+ // TODO: stop duplicating the name, it's stupid.
+ let kind = TypeKind::Named(name.clone(), default);
+ Self::new(Some(name), None, kind, false)
+ }
+
+ pub fn is_integer_literal(&self) -> bool {
+ match *self.kind() {
+ TypeKind::Int(..) => true,
+ _ => false,
+ }
+ }
+
+ pub fn is_const(&self) -> bool {
+ self.is_const
+ }
+
+ pub fn layout(&self, type_resolver: &TypeResolver) -> Option<Layout> {
+ use std::mem;
+
+ self.layout.or_else(|| {
+ match self.kind {
+ TypeKind::Comp(ref ci)
+ => ci.layout(type_resolver),
+ // FIXME(emilio): This is a hack for anonymous union templates.
+ // Use the actual pointer size!
+ TypeKind::Pointer(..)
+ => Some(Layout::new(mem::size_of::<*mut ()>(), mem::align_of::<*mut ()>())),
+ TypeKind::ResolvedTypeRef(inner)
+ => type_resolver.resolve_type(inner).layout(type_resolver),
+ _ => None,
+ }
+ })
+ }
+
+ pub fn is_opaque(&self, _type_resolver: &TypeResolver) -> bool {
+ self.opaque
+ }
+
+ pub fn can_derive_debug(&self, type_resolver: &TypeResolver) -> bool {
+ !self.is_opaque(type_resolver) && match self.kind {
+ TypeKind::Array(t, len) => {
+ len <= RUST_DERIVE_IN_ARRAY_LIMIT &&
+ type_resolver.resolve_type(t).can_derive_debug(type_resolver)
+ }
+ TypeKind::ResolvedTypeRef(t) |
+ TypeKind::Alias(_, t) => {
+ type_resolver.resolve_type(t).can_derive_debug(type_resolver)
+ }
+ TypeKind::Comp(ref info) => {
+ info.can_derive_debug(type_resolver, self.layout(type_resolver))
+ }
+ _ => true,
+ }
+ }
+
+ // For some reason, deriving copies of an array of a type that is not known
+ // to be copy is a compile error. e.g.:
+ //
+ // #[derive(Copy)]
+ // struct A<T> {
+ // member: T,
+ // }
+ //
+ // is fine, while:
+ //
+ // #[derive(Copy)]
+ // struct A<T> {
+ // member: [T; 1],
+ // }
+ //
+ // is an error.
+ //
+ // That's the point of the existence of can_derive_copy_in_array().
+ pub fn can_derive_copy_in_array(&self, type_resolver: &TypeResolver) -> bool {
+ match self.kind {
+ TypeKind::ResolvedTypeRef(t) |
+ TypeKind::Alias(_, t) |
+ TypeKind::Array(t, _) => {
+ type_resolver.resolve_type(t)
+ .can_derive_copy_in_array(type_resolver)
+ }
+ TypeKind::Named(..) => false,
+ _ => self.can_derive_copy(type_resolver),
+ }
+ }
+
+ pub fn can_derive_copy(&self, type_resolver: &TypeResolver) -> bool {
+ !self.is_opaque(type_resolver) && match self.kind {
+ TypeKind::Array(t, len) => {
+ len <= RUST_DERIVE_IN_ARRAY_LIMIT &&
+ type_resolver.resolve_type(t).can_derive_copy_in_array(type_resolver)
+ }
+ TypeKind::ResolvedTypeRef(t) |
+ TypeKind::TemplateRef(t, _) |
+ TypeKind::Alias(_, t) => {
+ type_resolver.resolve_type(t).can_derive_copy(type_resolver)
+ }
+ TypeKind::Comp(ref info) => {
+ info.can_derive_copy(type_resolver)
+ }
+ _ => true,
+ }
+ }
+
+ pub fn has_vtable(&self, type_resolver: &TypeResolver) -> bool {
+ // FIXME: Can we do something about template parameters? Huh...
+ match self.kind {
+ TypeKind::TemplateRef(t, _) |
+ TypeKind::Alias(_, t) |
+ TypeKind::ResolvedTypeRef(t) |
+ TypeKind::Array(t, _) => {
+ type_resolver.resolve_type(t).has_vtable(type_resolver)
+ }
+ TypeKind::Comp(ref info) => {
+ info.has_vtable(type_resolver)
+ }
+ _ => false,
+ }
+
+ }
+
+ pub fn has_destructor(&self, type_resolver: &TypeResolver) -> bool {
+ self.is_opaque(type_resolver) || match self.kind {
+ TypeKind::TemplateRef(t, _) |
+ TypeKind::Alias(_, t) |
+ TypeKind::ResolvedTypeRef(t) |
+ TypeKind::Array(t, _) => {
+ type_resolver.resolve_type(t).has_destructor(type_resolver)
+ }
+ TypeKind::Comp(ref info) => {
+ info.has_destructor(type_resolver)
+ }
+ _ => false,
+ }
+ }
+
+ pub fn signature_contains_named_type(&self,
+ type_resolver: &TypeResolver,
+ ty: &Type) -> bool {
+ debug_assert!(ty.is_named());
+ let name = match *ty.kind() {
+ TypeKind::Named(ref name, _) => name,
+ _ => unreachable!(),
+ };
+
+ match self.kind {
+ TypeKind::Named(ref this_name, _)
+ => this_name == name,
+ TypeKind::ResolvedTypeRef(t) |
+ TypeKind::Array(t, _) |
+ TypeKind::Pointer(t)
+ => type_resolver.resolve_type(t)
+ .signature_contains_named_type(type_resolver, ty),
+ TypeKind::TemplateRef(_inner, ref template_args) => {
+ template_args.iter().any(|arg| {
+ type_resolver.resolve_type(*arg)
+ .signature_contains_named_type(type_resolver, ty)
+ })
+ }
+ TypeKind::Comp(ref ci)
+ => ci.signature_contains_named_type(type_resolver, ty),
+ _ => false,
+ }
+ }
+
+ pub fn canonical_type<'tr>(&'tr self, type_resolver: &'tr TypeResolver) -> &'tr Type {
+ match self.kind {
+ TypeKind::Named(..) |
+ TypeKind::Array(..) |
+ TypeKind::Comp(..) |
+ TypeKind::Int(..) |
+ TypeKind::Float(..) |
+ TypeKind::Function(..) |
+ TypeKind::Enum(..) |
+ TypeKind::Reference(..) |
+ TypeKind::Void |
+ TypeKind::NullPtr |
+ TypeKind::Pointer(..) => self,
+
+ TypeKind::ResolvedTypeRef(inner) |
+ TypeKind::Alias(_, inner) |
+ TypeKind::TemplateRef(inner, _)
+ => type_resolver.resolve_type(inner).canonical_type(type_resolver),
+
+ TypeKind::UnresolvedTypeRef(..)
+ => unreachable!("Should have been resolved after parsing!"),
+ }
+ }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub enum FloatKind {
+ Float,
+ Double,
+ LongDouble,
+}
+
+/// The different kinds of types that we can parse.
+///
+/// TODO: The name in the Alias and Named kinds is a bit unsound, should be in
+/// type.name?
+#[derive(Debug)]
+pub enum TypeKind {
+ /// The void type.
+ Void,
+ /// The nullptr_t type.
+ NullPtr,
+ /// A compound type, that is, a class, struct, or union.
+ Comp(CompInfo),
+ /// An integer type, of a given kind. `bool` and `char` are also considered
+ /// integers.
+ Int(IntKind),
+ /// A floating point type.
+ Float(FloatKind),
+ /// A type alias, with a name, that points to another type.
+ Alias(String, ItemId),
+ /// An array of a type and a lenght.
+ Array(ItemId, usize),
+ /// A function type, with a given signature.
+ Function(FunctionSig),
+ /// An enum type.
+ Enum(Enum),
+ /// A pointer to a type. The bool field represents whether it's const or
+ /// not.
+ Pointer(ItemId),
+ /// A reference to a type, as in: int& foo().
+ Reference(ItemId),
+ /// A reference to a template, with different template parameter names. To
+ /// see why this is needed, check out the creation of this variant in
+ /// `Type::from_clang_ty`.
+ TemplateRef(ItemId, Vec<ItemId>),
+
+ /// A reference to a yet-to-resolve type. This stores the clang cursor
+ /// itself, and postpones its resolution.
+ ///
+ /// These are gone in a phase after parsing where these are mapped to
+ /// already known types, and are converted to ResolvedTypeRef.
+ ///
+ /// see tests/headers/typeref.hpp to see somewhere where this is a problem.
+ UnresolvedTypeRef(clang::Type, Option<clang::Cursor>),
+ ResolvedTypeRef(ItemId),
+
+ /// A named type, that is, a template parameter, with an optional default
+ /// type.
+ Named(String, Option<ItemId>),
+}
+
+impl Type {
+ pub fn is_unsized(&self, type_resolver: &TypeResolver) -> bool {
+ match self.kind {
+ TypeKind::Void => true,
+ TypeKind::Comp(ref ci) => ci.is_unsized(type_resolver),
+ TypeKind::Array(inner, size) => {
+ size == 0 ||
+ type_resolver.resolve_type(inner).is_unsized(type_resolver)
+ }
+ TypeKind::ResolvedTypeRef(inner) |
+ TypeKind::Alias(_, inner) |
+ TypeKind::TemplateRef(inner, _)
+ => type_resolver.resolve_type(inner).is_unsized(type_resolver),
+ TypeKind::Named(..) |
+ TypeKind::Int(..) |
+ TypeKind::Float(..) |
+ TypeKind::Function(..) |
+ TypeKind::Enum(..) |
+ TypeKind::Reference(..) |
+ TypeKind::NullPtr |
+ TypeKind::Pointer(..) => false,
+
+ TypeKind::UnresolvedTypeRef(..)
+ => unreachable!("Should have been resolved after parsing!"),
+ }
+ }
+
+ pub fn from_clang_ty(potential_id: ItemId,
+ ty: &clang::Type,
+ location: Option<Cursor>,
+ parent_id: Option<ItemId>,
+ ctx: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError> {
+ use clangll::*;
+ if let Some(ty) = ctx.builtin_or_resolved_ty(parent_id, ty, location) {
+ debug!("{:?} already resolved: {:?}", ty, location);
+ return Ok(ParseResult::AlreadyResolved(ty));
+ }
+
+ let layout = ty.fallible_layout().ok();
+ let cursor = ty.declaration();
+ let mut name = cursor.spelling();
+
+ debug!("from_clang_ty: {:?}, ty: {:?}, loc: {:?}", potential_id, ty, location);
+ debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types);
+
+ let canonical_ty = ty.canonical_type();
+ let kind = match ty.kind() {
+ CXType_Unexposed if *ty != canonical_ty &&
+ canonical_ty.kind() != CXType_Invalid => {
+ debug!("Looking for canonical type: {:?}", canonical_ty);
+ return Self::from_clang_ty(potential_id, &canonical_ty,
+ location, parent_id, ctx);
+ }
+ CXType_Unexposed |
+ CXType_Invalid => {
+ // For some reason Clang doesn't give us any hint
+ // in some situations where we should generate a
+ // function pointer (see
+ // tests/headers/func_ptr_in_struct.h), so we do a
+ // guess here trying to see if it has a valid return
+ // type.
+ if ty.ret_type().kind() != CXType_Invalid {
+ let signature =
+ try!(FunctionSig::from_ty(ty, &location.unwrap_or(cursor), ctx));
+ TypeKind::Function(signature)
+ // Same here, with template specialisations we can safely assume
+ // this is a Comp(..)
+ } else if ty.num_template_args() > 0 {
+ debug!("Template specialization: {:?}", ty);
+ let complex =
+ CompInfo::from_ty(potential_id, ty, location, ctx)
+ .expect("C'mon");
+ TypeKind::Comp(complex)
+ } else if let Some(location) = location {
+ match location.kind() {
+ CXCursor_ClassTemplatePartialSpecialization |
+ CXCursor_ClassTemplate => {
+ name = location.spelling();
+ let complex =
+ CompInfo::from_ty(potential_id, ty, Some(location), ctx)
+ .expect("C'mon");
+ TypeKind::Comp(complex)
+ }
+ CXCursor_TemplateRef => {
+ let referenced = location.referenced();
+ return Self::from_clang_ty(potential_id,
+ &referenced.cur_type(),
+ Some(referenced),
+ parent_id,
+ ctx);
+ }
+ CXCursor_TypeRef => {
+ let referenced = location.referenced();
+ // FIXME: use potential id?
+ return Ok(ParseResult::AlreadyResolved(
+ Item::from_ty_or_ref(referenced.cur_type(),
+ Some(referenced),
+ parent_id,
+ ctx)));
+ }
+ _ => {
+ if ty.kind() == CXType_Unexposed {
+ warn!("Unexposed type {:?}, recursing inside, loc: {:?}", ty, location);
+ return Err(ParseError::Recurse);
+ }
+
+ error!("invalid type {:?}", ty);
+ return Err(ParseError::Continue);
+ }
+ }
+ } else {
+ // TODO: Don't duplicate this!
+ if ty.kind() == CXType_Unexposed {
+ warn!("Unexposed type {:?}, recursing inside", ty);
+ return Err(ParseError::Recurse);
+ }
+
+ error!("invalid type `{}`", ty.spelling());
+ return Err(ParseError::Continue);
+ }
+ }
+ // NOTE: We don't resolve pointers eagerly because the pointee type
+ // might not have been parsed, and if it contains templates or
+ // something else we might get confused, see the comment inside
+ // TypeRef.
+ //
+ // We might need to, though, if the context is already in the
+ // process of resolving them.
+ CXType_MemberPointer |
+ CXType_Pointer => {
+ let inner =
+ Item::from_ty_or_ref(ty.pointee_type(), Some(ty.pointee_type().declaration()), parent_id, ctx);
+ TypeKind::Pointer(inner)
+ }
+ // XXX: RValueReference is most likely wrong, but I don't think we
+ // can even add bindings for that, so huh.
+ CXType_RValueReference |
+ CXType_LValueReference => {
+ let inner =
+ Item::from_ty_or_ref(ty.pointee_type(), Some(ty.pointee_type().declaration()), parent_id, ctx);
+ TypeKind::Reference(inner)
+ }
+ // XXX DependentSizedArray is wrong
+ CXType_VariableArray |
+ CXType_DependentSizedArray |
+ CXType_IncompleteArray => {
+ let inner = Item::from_ty(&ty.elem_type(), location, parent_id, ctx)
+ .expect("Not able to resolve array element?");
+ TypeKind::Pointer(inner)
+ }
+ CXType_FunctionNoProto |
+ CXType_FunctionProto => {
+ let signature = try!(FunctionSig::from_ty(ty, &location.unwrap_or(cursor), ctx));
+ TypeKind::Function(signature)
+ }
+ CXType_Typedef => {
+ let inner = cursor.typedef_type();
+ let inner =
+ Item::from_ty_or_ref(inner, location, parent_id, ctx);
+ TypeKind::Alias(ty.spelling(), inner)
+ }
+ CXType_Enum => {
+ let enum_ = Enum::from_ty(ty, ctx)
+ .expect("Not an enum?");
+ TypeKind::Enum(enum_)
+ }
+ CXType_Record => {
+ let complex = CompInfo::from_ty(potential_id, ty, location, ctx)
+ .expect("Not a complex type?");
+ TypeKind::Comp(complex)
+ }
+ CXType_ConstantArray => {
+ let inner = Item::from_ty(&ty.elem_type(), location, parent_id, ctx)
+ .expect("Not able to resolve array element?");
+ TypeKind::Array(inner, ty.array_size())
+ }
+ #[cfg(not(feature="llvm_stable"))]
+ CXType_Elaborated => {
+ return Self::from_clang_ty(potential_id, &ty.named(),
+ location, parent_id, ctx);
+ }
+ _ => {
+ error!("unsupported type {:?} at {:?}", ty, location);
+ return Err(ParseError::Continue);
+ }
+ };
+
+ let name = if name.is_empty() { None } else { Some(name) };
+ let is_const = ty.is_const();
+
+ let ty = Type::new(name, layout, kind, is_const);
+ // TODO: maybe declaration.canonical()?
+ Ok(ParseResult::New(ty, Some(cursor.canonical())))
+ }
+}
diff --git a/src/ir/var.rs b/src/ir/var.rs
new file mode 100644
index 00000000..ac59973b
--- /dev/null
+++ b/src/ir/var.rs
@@ -0,0 +1,160 @@
+use super::item::{Item, ItemId};
+use super::context::BindgenContext;
+use super::ty::TypeKind;
+use super::int::IntKind;
+use super::function::cursor_mangling;
+use parse::{ClangItemParser, ClangSubItemParser, ParseResult, ParseError};
+use clang;
+
+#[derive(Debug)]
+pub struct Var {
+ /// The name of the variable.
+ name: String,
+ /// The mangled name of the variable.
+ mangled_name: Option<String>,
+ /// The type of the variable.
+ ty: ItemId,
+ /// TODO: support non-integer constants?
+ /// The integer value of the variable.
+ val: Option<i64>,
+ /// Whether this variable is const.
+ is_const: bool,
+}
+
+impl Var {
+ pub fn new(name: String,
+ mangled: Option<String>,
+ ty: ItemId,
+ val: Option<i64>,
+ is_const: bool) -> Var {
+ assert!(!name.is_empty());
+ Var {
+ name: name,
+ mangled_name: mangled,
+ ty: ty,
+ val: val,
+ is_const: is_const,
+ }
+ }
+
+ pub fn is_const(&self) -> bool {
+ self.is_const
+ }
+
+ pub fn val(&self) -> Option<i64> {
+ self.val
+ }
+
+ pub fn ty(&self) -> ItemId {
+ self.ty
+ }
+
+ pub fn name(&self) -> &str {
+ &self.name
+ }
+
+ pub fn mangled_name(&self) -> Option<&str> {
+ self.mangled_name.as_ref().map(|n| &**n)
+ }
+}
+
+impl ClangSubItemParser for Var {
+ fn parse(cursor: clang::Cursor,
+ context: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError> {
+ use clangll::*;
+ match cursor.kind() {
+ CXCursor_MacroDefinition => {
+ let value = match parse_int_literal_tokens(&cursor, context.translation_unit(), 1) {
+ None => return Err(ParseError::Continue),
+ Some(v) => v,
+ };
+
+ let name = cursor.spelling();
+ if name.is_empty() {
+ warn!("Empty macro name?");
+ return Err(ParseError::Continue);
+ }
+
+ if context.parsed_macro(&name) {
+ warn!("Duplicated macro definition: {}", name);
+ return Err(ParseError::Continue);
+ }
+ context.note_parsed_macro(name.clone());
+
+ let ty = if value.abs() > u32::max_value() as i64 {
+ Item::builtin_type(TypeKind::Int(IntKind::ULongLong), true, context)
+ } else {
+ Item::builtin_type(TypeKind::Int(IntKind::UInt), true, context)
+ };
+
+ Ok(ParseResult::New(Var::new(name, None, ty, Some(value), true), Some(cursor)))
+ }
+ CXCursor_VarDecl => {
+ let name = cursor.spelling();
+ if name.is_empty() {
+ warn!("Empty constant name?");
+ return Err(ParseError::Continue);
+ }
+
+ let ty = cursor.cur_type();
+
+ // XXX this is redundant, remove!
+ let is_const = ty.is_const();
+
+ let ty = Item::from_ty(&ty, Some(cursor), None, context)
+ .expect("Unable to resolve constant type?");
+
+ let mut value = None;
+
+ // Note: Ty might not be totally resolved yet, see
+ // tests/headers/inner_const.hpp
+ //
+ // That's fine because in that case we know it's not a literal.
+ if context.safe_resolve_type(ty).map_or(false, |t| t.is_integer_literal()) {
+ // Try to parse a literal token value
+ cursor.visit(|c, _| {
+ if c.kind() == CXCursor_IntegerLiteral {
+ value =
+ parse_int_literal_tokens(&c,
+ context.translation_unit(),
+ 0);
+ }
+ CXChildVisit_Continue
+ });
+ }
+
+ let mangling = cursor_mangling(&cursor);
+
+ let var = Var::new(name, mangling, ty, value, is_const);
+ Ok(ParseResult::New(var, Some(cursor)))
+
+ }
+ _ => {
+ /* TODO */
+ Err(ParseError::Continue)
+ }
+ }
+ }
+}
+
+fn parse_int_literal_tokens(cursor: &clang::Cursor,
+ unit: &clang::TranslationUnit,
+ which: usize) -> Option<i64> {
+ use clangll::CXToken_Literal;
+ let tokens = match unit.tokens(cursor) {
+ None => return None,
+ Some(tokens) => tokens,
+ };
+
+ if tokens.len() <= which || tokens[which].kind != CXToken_Literal {
+ return None;
+ }
+
+ let s = &tokens[which].spelling;
+ // TODO: try to preserve hex literals?
+ if s.starts_with("0x") {
+ i64::from_str_radix(&s[2..], 16).ok()
+ } else {
+ s.parse().ok()
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index a6b33c8e..33bd66e7 100755
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,19 +4,34 @@
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
+// To avoid rather annoying warnings when matching with CXCursor_xxx as a
+// constant.
+#![allow(non_upper_case_globals)]
+
extern crate syntex_syntax as syntax;
extern crate aster;
extern crate quasi;
extern crate clang_sys;
extern crate libc;
+extern crate regex;
#[macro_use]
extern crate log;
-use std::collections::HashSet;
-use std::default::Default;
-use std::io::{Write, self};
+mod clangll;
+mod clang;
+mod ir;
+mod parse;
+mod regex_set;
+mod codegen {
+ include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
+}
+
+use std::borrow::Borrow;
+use std::io::{self, Write};
use std::fs::OpenOptions;
use std::path::Path;
+use std::marker;
+use std::collections::HashSet;
use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
@@ -24,21 +39,16 @@ use syntax::print::pprust;
use syntax::print::pp::eof;
use syntax::ptr::P;
-use types::ModuleMap;
+use ir::context::BindgenContext;
+use ir::item::{Item, ItemId};
+use parse::{ClangItemParser, ParseError};
+use regex_set::RegexSet;
-mod types;
-mod clangll;
-mod clang;
-mod parser;
-mod hacks;
-mod gen {
- include!(concat!(env!("OUT_DIR"), "/gen.rs"));
-}
-
-#[derive(Clone)]
+#[derive(Debug)]
pub struct Builder<'a> {
options: BindgenOptions,
- logger: Option<&'a Logger>
+ // TODO: Before the logger was here, do we still want the lifetime?
+ phantom: marker::PhantomData<&'a ()>,
}
pub fn builder<'a>() -> Builder<'a> {
@@ -51,17 +61,22 @@ impl<'a> Builder<'a> {
}
pub fn match_pat<T: Into<String>>(&mut self, arg: T) -> &mut Self {
- self.options.match_pat.push(arg.into());
+ self.options.match_pat.insert(arg.into());
self
}
- pub fn blacklist_type<T: Into<String>>(&mut self, arg: T) -> &mut Self {
- self.options.blacklist_type.push(arg.into());
+ pub fn hide_type<T: Into<String>>(&mut self, arg: T) -> &mut Self {
+ self.options.hidden_types.insert(arg.into());
self
}
pub fn opaque_type<T: Into<String>>(&mut self, arg: T) -> &mut Self {
- self.options.opaque_types.push(arg.into());
+ self.options.opaque_types.insert(arg.into());
+ self
+ }
+
+ pub fn whitelisted_type<T: Borrow<str>>(&mut self, arg: &T) -> &mut Self {
+ self.options.whitelisted_types.insert(arg);
self
}
@@ -124,36 +139,34 @@ impl<'a> Builder<'a> {
self
}
- pub fn log(&mut self, logger: &'a Logger) -> &mut Self {
- self.logger = Some(logger);
- self
- }
-
pub fn disable_class_constants(&mut self) -> &mut Self {
self.options.class_constants = false;
self
}
- pub fn generate(&self) -> Result<Bindings, ()> {
- Bindings::generate(&self.options, self.logger, None)
+ pub fn generate(self) -> Result<Bindings, ()> {
+ Bindings::generate(self.options, None)
}
}
impl<'a> Default for Builder<'a> {
fn default() -> Builder<'a> {
Builder {
- logger: None,
- options: Default::default()
+ options: Default::default(),
+ phantom: marker::PhantomData,
}
}
}
-#[derive(Clone)]
/// Deprecated - use a `Builder` instead
+#[derive(Debug)]
pub struct BindgenOptions {
- pub match_pat: Vec<String>,
- pub blacklist_type: Vec<String>,
- pub opaque_types: Vec<String>,
+ pub match_pat: HashSet<String>,
+ pub hidden_types: HashSet<String>,
+ pub opaque_types: HashSet<String>,
+ pub whitelisted_types: RegexSet,
+ pub whitelisted_functions: RegexSet,
+ pub whitelisted_vars: RegexSet,
pub builtins: bool,
pub rust_enums: bool,
pub links: Vec<(String, LinkType)>,
@@ -171,7 +184,7 @@ pub struct BindgenOptions {
pub class_constants: bool,
/// Wether to generate names that are **directly** under namespaces.
pub namespaced_constants: bool,
- // whether to use msvc mangling rules
+ /// Whether to use msvc mangling rules
pub msvc_mangling: bool,
pub override_enum_ty: String,
pub raw_lines: Vec<String>,
@@ -183,9 +196,12 @@ pub struct BindgenOptions {
impl Default for BindgenOptions {
fn default() -> BindgenOptions {
BindgenOptions {
- match_pat: vec![],
- blacklist_type: vec![],
- opaque_types: vec![],
+ match_pat: Default::default(),
+ hidden_types: Default::default(),
+ opaque_types: Default::default(),
+ whitelisted_types: Default::default(),
+ whitelisted_functions: Default::default(),
+ whitelisted_vars: Default::default(),
builtins: false,
rust_enums: true,
links: vec![],
@@ -216,11 +232,6 @@ pub enum LinkType {
Framework
}
-pub trait Logger {
- fn error(&self, msg: &str);
- fn warn(&self, msg: &str);
-}
-
#[derive(Debug, Clone)]
pub struct Bindings {
module: ast::Mod,
@@ -229,25 +240,20 @@ pub struct Bindings {
impl Bindings {
/// Deprecated - use a `Builder` instead
- pub fn generate(options: &BindgenOptions, logger: Option<&Logger>, span: Option<Span>) -> Result<Bindings, ()> {
- let l = DummyLogger;
- let logger = logger.unwrap_or(&l as &Logger);
-
+ pub fn generate(options: BindgenOptions, span: Option<Span>) -> Result<Bindings, ()> {
let span = span.unwrap_or(DUMMY_SP);
- let module_map = try!(parse_headers(options, logger));
+ let mut context = BindgenContext::new(options);
+ parse(&mut context);
let module = ast::Mod {
inner: span,
- items: gen::gen_mods(&options.links[..],
- module_map,
- options.clone(),
- span)
+ items: codegen::codegen(&mut context),
};
Ok(Bindings {
module: module,
- raw_lines: options.raw_lines.clone(),
+ raw_lines: context.options().raw_lines.clone(),
})
}
@@ -290,68 +296,6 @@ impl Bindings {
}
}
-
-struct DummyLogger;
-
-impl Logger for DummyLogger {
- fn error(&self, _msg: &str) { }
- fn warn(&self, _msg: &str) { }
-}
-
-fn parse_headers(options: &BindgenOptions, logger: &Logger) -> Result<ModuleMap, ()> {
- fn str_to_ikind(s: &str) -> Option<types::IKind> {
- match s {
- "uchar" => Some(types::IUChar),
- "schar" => Some(types::ISChar),
- "ushort" => Some(types::IUShort),
- "sshort" => Some(types::IShort),
- "uint" => Some(types::IUInt),
- "sint" => Some(types::IInt),
- "ulong" => Some(types::IULong),
- "slong" => Some(types::ILong),
- "ulonglong" => Some(types::IULongLong),
- "slonglong" => Some(types::ILongLong),
- _ => None,
- }
- }
-
- // TODO: Unify most of these with BindgenOptions?
- let clang_opts = parser::ClangParserOptions {
- builtin_names: builtin_names(),
- builtins: options.builtins,
- match_pat: options.match_pat.clone(),
- emit_ast: options.emit_ast,
- class_constants: options.class_constants,
- namespaced_constants: options.namespaced_constants,
- ignore_functions: options.ignore_functions,
- ignore_methods: options.ignore_methods,
- fail_on_unknown_type: options.fail_on_unknown_type,
- enable_cxx_namespaces: options.enable_cxx_namespaces,
- override_enum_ty: str_to_ikind(&options.override_enum_ty),
- clang_args: options.clang_args.clone(),
- opaque_types: options.opaque_types.clone(),
- blacklist_type: options.blacklist_type.clone(),
- msvc_mangling: options.msvc_mangling,
- };
-
- parser::parse(clang_opts, logger)
-}
-
-fn builtin_names() -> HashSet<String> {
- let mut names = HashSet::new();
- let keys = [
- "__va_list_tag",
- "__va_list",
- "__builtin_va_list",
- ];
-
- for s in &keys {
- names.insert((*s).to_owned());
- }
-
- names
-}
-
#[test]
fn builder_state() {
let logger = DummyLogger;
@@ -365,3 +309,57 @@ fn builder_state() {
assert!(build.options.clang_args.binary_search(&"example.h".to_owned()).is_ok());
assert!(build.options.links.binary_search(&("m".to_owned(), LinkType::Static)).is_ok());
}
+
+/// Determines whether the given cursor is in any of the files matched by the
+/// options.
+fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
+ let (file, _, _, _) = cursor.location().location();
+
+ match file.name() {
+ None => ctx.options().builtins,
+ Some(..) => true,
+ }
+}
+
+pub fn parse_one(ctx: &mut BindgenContext,
+ cursor: clang::Cursor,
+ parent: Option<ItemId>,
+ children: &mut Vec<ItemId>) -> clangll::Enum_CXVisitorResult {
+ if !filter_builtins(ctx, &cursor) {
+ return CXChildVisit_Continue
+ }
+
+ use clangll::CXChildVisit_Continue;
+ match Item::parse(cursor, parent, ctx) {
+ Ok(id) => children.push(id),
+ Err(ParseError::Continue) => {},
+ Err(ParseError::Recurse) => {
+ cursor.visit(|child, _| parse_one(ctx, *child, parent, children));
+ }
+ }
+ CXChildVisit_Continue
+}
+
+fn parse(context: &mut BindgenContext) {
+ use clang::Diagnostic;
+ use clangll::*;
+
+ for d in context.translation_unit().diags().iter() {
+ let msg = d.format(Diagnostic::default_opts());
+ let is_err = d.severity() >= CXDiagnostic_Error;
+ println!("{}, err: {}", msg, is_err);
+ }
+
+ let cursor = context.translation_unit().cursor();
+ if context.options().emit_ast {
+ cursor.visit(|cur, _| clang::ast_dump(cur, 0));
+ }
+
+ let root = context.root_module();
+ context.with_module(root, |context, children| {
+ cursor.visit(|cursor, _| parse_one(context, *cursor, None, children))
+ });
+
+ assert!(context.current_module() == context.root_module(),
+ "How did this happen?");
+}
diff --git a/src/parse.rs b/src/parse.rs
new file mode 100644
index 00000000..39d2644a
--- /dev/null
+++ b/src/parse.rs
@@ -0,0 +1,48 @@
+use clang;
+use ir::ty::TypeKind;
+use ir::item::ItemId;
+use ir::context::BindgenContext;
+
+#[derive(Debug)]
+pub enum ParseError {
+ Recurse,
+ Continue,
+}
+
+#[derive(Debug)]
+pub enum ParseResult<T> {
+ AlreadyResolved(ItemId),
+ New(T, Option<clang::Cursor>),
+}
+
+pub trait ClangSubItemParser : Sized {
+ /// The fact that is a reference guarantees it's holded by the context, and
+ /// allow returning already existing types.
+ fn parse(cursor: clang::Cursor, context: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError>;
+}
+
+pub trait ClangItemParser: Sized {
+ fn parse(cursor: clang::Cursor,
+ parent: Option<ItemId>,
+ context: &mut BindgenContext) -> Result<ItemId, ParseError>;
+ fn from_ty_or_ref(ty: clang::Type,
+ location: Option<clang::Cursor>,
+ parent_id: Option<ItemId>,
+ context: &mut BindgenContext) -> ItemId;
+ fn from_ty_with_id(id: ItemId,
+ ty: &clang::Type,
+ location: Option<clang::Cursor>,
+ parent: Option<ItemId>,
+ ctx: &mut BindgenContext) -> Result<ItemId, ParseError>;
+ fn from_ty(ty: &clang::Type,
+ location: Option<clang::Cursor>,
+ parent: Option<ItemId>,
+ ctx: &mut BindgenContext) -> Result<ItemId, ParseError>;
+ fn named_type<S>(name: S, default: Option<ItemId>, parent: ItemId,
+ context: &mut BindgenContext) -> ItemId
+ where S: Into<String>;
+ fn named_type_with_id<S>(id: ItemId, name: S, default: Option<ItemId>,
+ parent: ItemId, context: &mut BindgenContext) -> ItemId
+ where S: Into<String>;
+ fn builtin_type(kind: TypeKind, is_const: bool, context: &mut BindgenContext) -> ItemId;
+}
diff --git a/src/parser.rs b/src/parser.rs
deleted file mode 100644
index 0e531420..00000000
--- a/src/parser.rs
+++ /dev/null
@@ -1,1516 +0,0 @@
-#![allow(non_upper_case_globals)]
-
-use std::collections::{HashMap, HashSet};
-use hacks::refcell::RefCell;
-use std::rc::Rc;
-use std::path::Path;
-use std::cmp;
-
-use syntax::abi;
-
-use types as il;
-use types::*;
-use clang as cx;
-use clang::{ast_dump, Comment, Cursor, Diagnostic, TranslationUnit, type_to_str, kind_to_str};
-use clangll::*;
-
-use super::Logger;
-
-#[derive(Clone)]
-pub struct ClangParserOptions {
- pub builtin_names: HashSet<String>,
- pub builtins: bool,
- pub match_pat: Vec<String>,
- pub emit_ast: bool,
- pub fail_on_unknown_type: bool,
- pub ignore_functions: bool,
- pub ignore_methods: bool,
- pub enable_cxx_namespaces: bool,
- pub class_constants: bool,
- pub namespaced_constants: bool,
- pub override_enum_ty: Option<il::IKind>,
- pub clang_args: Vec<String>,
- pub opaque_types: Vec<String>,
- pub blacklist_type: Vec<String>,
- pub msvc_mangling: bool,
-}
-
-struct ClangParserCtx<'a> {
- options: ClangParserOptions,
- name: HashMap<Cursor, Global>,
- builtin_defs: Vec<Cursor>,
- module_map: ModuleMap,
- current_module_id: ModuleId,
- /// This member is used to track down if we're in a namespace if the
- /// enable_cxx_namespaces option is disabled.
- namespace_depth: usize,
- current_translation_unit: TranslationUnit,
- logger: &'a (Logger+'a),
- err_count: i32,
- anonymous_modules_found: usize,
-}
-
-impl<'a> ClangParserCtx<'a> {
- fn module(&self, id: &ModuleId) -> &Module {
- self.module_map.get(id).expect("Module not found!")
- }
-
- fn current_module(&self) -> &Module {
- self.module(&self.current_module_id)
- }
-
- fn in_root_namespace(&self) -> bool {
- self.namespace_depth == 0
- }
-
- fn current_module_mut(&mut self) -> &mut Module {
- self.module_map.get_mut(&self.current_module_id).expect("Module not found!")
- }
-}
-
-fn cursor_link_name(_: &mut ClangParserCtx, cursor: &Cursor) -> String {
- // Try to undo backend linkage munging (prepended _, generally)
- let mut mangling = cursor.mangling();
- if cfg!(target_os = "macos") {
- mangling.remove(0);
- }
- mangling
-}
-
-fn match_pattern(ctx: &mut ClangParserCtx, cursor: &Cursor) -> bool {
- let (file, _, _, _) = cursor.location().location();
-
- let name = match file.name() {
- None => return ctx.options.builtins,
- Some(name) => name,
- };
-
- if ctx.options.match_pat.is_empty() {
- return true;
- }
-
- let name = name.replace("\\", "/");
- ctx.options.match_pat.iter().any(|pat| name.contains(pat))
-}
-
-fn conv_template_type_parameter(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Type {
- assert_eq!(cursor.kind(), CXCursor_TemplateTypeParameter);
- let ty = conv_ty(ctx, &cursor.cur_type(), cursor);
- let layout = Layout::new(ty.size(), ty.align());
- TNamed(Rc::new(RefCell::new(TypeInfo::new(cursor.spelling(), ctx.current_module_id, TVoid, layout))))
-}
-
-fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
- let cursor = cursor.canonical();
- let override_enum_ty = ctx.options.override_enum_ty;
- let new_decl = !ctx.name.contains_key(&cursor);
-
- let decl = if new_decl {
- let spelling = cursor.spelling();
- let comment = cursor.raw_comment();
- let (file, _, _, _) = cursor.location().location();
- let ty = cursor.cur_type();
- let layout = Layout::from_ty(&ty);
- let filename = match Path::new(&file.name().unwrap_or("".to_owned())).file_name() {
- Some(name) => name.to_string_lossy().replace(".", "_"),
- _ => "".to_string()
- };
- let glob_decl = match cursor.kind() {
- CXCursor_UnionDecl |
- CXCursor_ClassTemplate |
- CXCursor_ClassDecl |
- CXCursor_StructDecl => {
- let anno = Annotations::new(&cursor);
-
- let kind = match cursor.kind() {
- CXCursor_UnionDecl => CompKind::Union,
- CXCursor_ClassTemplate => {
- match cursor.template_kind() {
- CXCursor_UnionDecl => CompKind::Union,
- _ => CompKind::Struct,
- }
- }
- _ => CompKind::Struct,
- };
-
- let opaque = ctx.options.opaque_types.iter().any(|name| *name == spelling);
- let hide = ctx.options.blacklist_type.iter().any(|name| *name == spelling);
-
- let mut has_non_type_template_params = false;
- let args = match ty.num_template_args() {
- // In forward declarations, etc, they are in the ast... sigh
- -1 => {
- let mut args = vec![];
- cursor.visit(|c, _| {
- if c.kind() == CXCursor_TemplateTypeParameter {
- args.push(conv_template_type_parameter(ctx, c));
- }
- CXChildVisit_Continue
- });
- args
- }
- len => {
- let mut list = Vec::with_capacity(len as usize);
- for i in 0..len {
- let arg_type = ty.template_arg_type(i);
- if arg_type.kind() != CXType_Invalid {
- list.push(conv_ty(ctx, &arg_type, &cursor));
- } else {
- has_non_type_template_params = true;
- ctx.logger.warn("warning: Template parameter is not a type");
- }
- }
- list
- }
- };
-
- let mut ci = CompInfo::new(spelling, ctx.current_module_id,
- filename, comment, kind, vec![],
- layout, anno);
- ci.parser_cursor = Some(cursor);
-
- // If it's an instantiation of another template,
- // find the canonical declaration to find the module
- // it belongs to and if it's opaque.
- let parent = cursor.specialized();
- if let Some(parent) = ctx.name.get(&parent) {
- ci.ref_template = Some(parent.clone().to_type())
- }
-
- ci.opaque = opaque;
- ci.hide = hide;
- ci.args = args;
- ci.has_non_type_template_params = has_non_type_template_params;
-
- let ci = Rc::new(RefCell::new(ci));
- GCompDecl(ci)
- }
- CXCursor_EnumDecl => {
- let kind = match override_enum_ty {
- Some(t) => t,
- None => match cursor.enum_type().kind() {
- CXType_SChar | CXType_Char_S => ISChar,
- CXType_UChar | CXType_Char_U => IUChar,
- CXType_UShort => IUShort,
- CXType_UInt => IUInt,
- CXType_ULong => IULong,
- CXType_ULongLong => IULongLong,
- CXType_Short => IShort,
- CXType_Int => IInt,
- CXType_Long => ILong,
- CXType_LongLong => ILongLong,
- _ => IInt,
- }
- };
-
- let ei = Rc::new(RefCell::new(EnumInfo::new(spelling, ctx.current_module_id, filename, kind, vec!(), layout)));
- GEnumDecl(ei)
- }
- CXCursor_TypeAliasDecl | CXCursor_TypedefDecl => {
- let opaque = ctx.options.opaque_types.iter().any(|name| *name == spelling);
- let hide = ctx.options.blacklist_type.iter().any(|name| *name == spelling);
- let mut ti = TypeInfo::new(spelling, ctx.current_module_id, TVoid, layout);
- ti.opaque = opaque;
- ti.hide = hide;
-
- let ti = Rc::new(RefCell::new(ti));
- GType(ti)
- }
- CXCursor_VarDecl => {
- let mangled = cursor_link_name(ctx, &cursor);
- let is_const = ty.is_const();
- let ty = conv_ty_resolving_typedefs(ctx, &ty, &cursor, true);
- let mut vi = VarInfo::new(spelling, mangled, comment, ty);
- vi.is_const = is_const;
- cursor.visit(|c, _: &Cursor| {
- vi.val = visit_literal(c, &ctx.current_translation_unit);
- CXChildVisit_Continue
- });
- GVar(Rc::new(RefCell::new(vi)))
- }
- CXCursor_MacroDefinition => {
- let vi = Rc::new(RefCell::new(VarInfo::new(spelling, String::new(), comment, TVoid)));
- GVar(vi)
- }
- CXCursor_FunctionDecl => {
- let mangled = cursor_link_name(ctx, &cursor);
- let vi = Rc::new(RefCell::new(VarInfo::new(spelling, mangled, comment, TVoid)));
- GFunc(vi)
- }
- _ => GOther,
- };
-
- ctx.name.insert(cursor, glob_decl.clone());
- glob_decl
- } else {
- ctx.name.get(&cursor).unwrap().clone()
- };
-
- if new_decl && ctx.options.builtin_names.contains(&cursor.spelling()) {
- ctx.builtin_defs.push(cursor);
- }
-
- decl
-}
-
-fn opaque_decl(ctx: &mut ClangParserCtx, decl: &Cursor) {
- let spelling = decl.spelling();
- let hide = ctx.options.blacklist_type.iter().any(|name| *name == spelling);
-
- if hide {
- return;
- }
-
- let name = decl_name(ctx, decl);
- ctx.current_module_mut().globals.push(name);
-}
-
-fn fwd_decl<F: FnOnce(&mut ClangParserCtx)->()>(ctx: &mut ClangParserCtx, cursor: &Cursor, f: F) {
- let def = cursor.definition();
- if cursor == &def {
- f(ctx);
- } else if def.kind() == CXCursor_NoDeclFound ||
- def.kind() == CXCursor_InvalidFile {
- opaque_decl(ctx, cursor);
- }
-}
-
-fn get_abi(cc: Enum_CXCallingConv) -> abi::Abi {
- match cc {
- CXCallingConv_Default => abi::Abi::C,
- CXCallingConv_C => abi::Abi::C,
- CXCallingConv_X86StdCall => abi::Abi::Stdcall,
- CXCallingConv_X86FastCall => abi::Abi::Fastcall,
- CXCallingConv_AAPCS => abi::Abi::Aapcs,
- CXCallingConv_X86_64Win64 => abi::Abi::Win64,
- other => panic!("unsupported calling convention: {}", other),
- }
-}
-
-fn conv_ptr_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
- ty: &cx::Type,
- cursor: &Cursor,
- is_ref: bool,
- layout: Layout,
- resolve_typedefs: bool) -> il::Type {
- let is_const = ty.is_const();
- match ty.kind() {
- CXType_Void => {
- return TPtr(Box::new(TVoid), is_const, is_ref, layout)
- }
- CXType_Unexposed |
- CXType_FunctionProto |
- CXType_FunctionNoProto => {
- let ret_ty = ty.ret_type();
- return if ret_ty.kind() != CXType_Invalid {
- TFuncPtr(mk_fn_sig(ctx, ty, cursor))
- } else if cursor.kind() == CXCursor_VarDecl {
- let can_ty = ty.canonical_type();
- conv_ty_resolving_typedefs(ctx, &can_ty, cursor, resolve_typedefs)
- } else {
- TPtr(Box::new(conv_decl_ty_resolving_typedefs(ctx, ty, cursor, resolve_typedefs)), ty.is_const(), is_ref, layout)
- };
- }
- CXType_Typedef => {
- let decl = ty.declaration();
- let def_ty = decl.typedef_type();
- if def_ty.kind() == CXType_FunctionProto ||
- def_ty.kind() == CXType_FunctionNoProto {
- return TPtr(Box::new(conv_ptr_ty_resolving_typedefs(ctx, &def_ty, cursor, is_ref, layout, resolve_typedefs)), is_const, is_ref, layout);
- } else {
- return TPtr(Box::new(conv_ty_resolving_typedefs(ctx, ty, cursor, resolve_typedefs)), is_const, is_ref, layout);
- }
- }
- _ => return TPtr(Box::new(conv_ty_resolving_typedefs(ctx, ty, cursor, resolve_typedefs)), is_const, is_ref, layout),
- }
-}
-
-fn mk_fn_sig(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor) -> il::FuncSig {
- mk_fn_sig_resolving_typedefs(ctx, ty, cursor, &[])
-}
-
-fn mk_fn_sig_resolving_typedefs(ctx: &mut ClangParserCtx,
- ty: &cx::Type,
- cursor: &Cursor,
- typedefs: &[String]) -> il::FuncSig {
- let args_lst: Vec<(String, il::Type)> = match cursor.kind() {
- CXCursor_FunctionDecl | CXCursor_CXXMethod => {
- // For CXCursor_FunctionDecl, cursor.args() is the reliable way to
- // get parameter names and types.
- cursor.args().iter().map(|arg| {
- let arg_name = arg.spelling();
- let arg_ty = arg.cur_type();
- let is_class_typedef = arg_ty.sanitized_spelling_in(typedefs);
- (arg_name, conv_ty_resolving_typedefs(ctx, &arg_ty, arg, is_class_typedef))
- }).collect()
- }
- _ => {
- // For non-CXCursor_FunctionDecl, visiting the cursor's children is
- // the only reliable way to get parameter names.
- let mut args_lst = vec!();
- cursor.visit(|c: &Cursor, _: &Cursor| {
- if c.kind() == CXCursor_ParmDecl {
- let is_class_typedef = c.cur_type().sanitized_spelling_in(typedefs);
- args_lst.push((c.spelling(), conv_ty_resolving_typedefs(ctx, &c.cur_type(), c, is_class_typedef)));
- }
- CXChildVisit_Continue
- });
- args_lst
- }
- };
-
- let ret_ty = Box::new(conv_ty(ctx, &ty.ret_type(), cursor));
- let abi = get_abi(ty.call_conv());
-
- // Function is presumed unsafe if it takes a pointer argument.
- let is_unsafe = args_lst.iter().any(|arg| match arg.1 {
- TPtr(..) => true,
- _ => false
- });
-
- il::FuncSig {
- ret_ty: ret_ty,
- args: args_lst,
- is_variadic: ty.is_variadic(),
- is_safe: !is_unsafe,
- abi: abi,
- }
-}
-
-fn conv_decl_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
- ty: &cx::Type,
- cursor: &Cursor,
- resolve_typedefs: bool) -> il::Type {
- let ty_decl = ty.declaration();
- // println!("conv_ty_decl: `{}`, ty kind {}: {}, decl `{}` kind {}: {}", cursor.spelling(), ty.kind(), type_to_str(ty.kind()), ty_decl.spelling(), ty_decl.kind(), kind_to_str(ty_decl.kind()));
- return match ty_decl.kind() {
- CXCursor_StructDecl |
- CXCursor_UnionDecl |
- CXCursor_ClassTemplate |
- CXCursor_ClassDecl => {
- let decl = decl_name(ctx, &ty_decl);
- // NB: This will only return a number greater than 0 if this is a **full** class
- // template specialization.
- //
- // If the cursor kind is CXCursor_ClassTemplate, this will still return -1
- // and we'll have to keep traversing the cursor.
- let args = match ty.num_template_args() {
- -1 => vec![],
- len => {
- let mut list = Vec::with_capacity(len as usize);
- for i in 0..len {
- let arg_type = ty.template_arg_type(i);
- if arg_type.kind() != CXType_Invalid {
- list.push(conv_ty(ctx, &arg_type, &cursor));
- } else {
- ctx.logger.warn("warning: Template parameter is not a type");
- }
- }
- list
- }
- };
-
- let ci = decl.compinfo();
- // NB: Args might be filled from decl_name,
- // it's important not to override
- //
- // We might incur in double borrows here. If that's the case, we're
- // already scanning the compinfo, and we'd get the args from the
- // ast.
- use hacks::refcell::BorrowState;
- if !args.is_empty() && ci.borrow_state() == BorrowState::Unused {
- ci.borrow_mut().args = args;
-
- // XXX: This is a super-dumb way to get the spesialisation,
- // but it seems to be the only one that'd work here...
- cursor.visit(|c, _: &Cursor| {
- if c.kind() == CXCursor_TemplateRef {
- let decl = decl_name(ctx, &c.referenced());
- ci.borrow_mut().ref_template = Some(decl.to_type());
- }
- CXChildVisit_Continue
- });
- }
-
- TComp(ci)
- }
- CXCursor_EnumDecl => {
- let decl = decl_name(ctx, &ty_decl);
- let ei = decl.enuminfo();
- TEnum(ei)
- }
- CXCursor_TypeAliasDecl |
- CXCursor_TypedefDecl => {
- if resolve_typedefs {
- return conv_ty_resolving_typedefs(ctx, &ty_decl.typedef_type(), &ty_decl.typedef_type().declaration(), resolve_typedefs);
- }
-
- let decl = decl_name(ctx, &ty_decl);
- let ti = decl.typeinfo();
- TNamed(ti)
- }
- CXCursor_NoDeclFound => {
- let canonical = ty.canonical_type();
- let kind = canonical.kind();
- if kind != CXType_Invalid && kind != CXType_Unexposed {
- conv_ty_resolving_typedefs(ctx, &canonical, &ty_decl, resolve_typedefs)
- } else {
- let layout = Layout::from_ty(ty);
- TNamed(Rc::new(RefCell::new(TypeInfo::new(ty.spelling().replace("const ", ""), ctx.current_module_id, TVoid, layout))))
- }
- }
- _ => {
- let fail = ctx.options.fail_on_unknown_type;
- log_err_warn(ctx,
- &format!("unsupported decl `{}` ({})",
- kind_to_str(ty_decl.kind()), ty_decl.location()
- ),
- fail
- );
- TVoid
- }
- };
-}
-
-fn conv_ty(ctx: &mut ClangParserCtx,
- ty: &cx::Type,
- cursor: &Cursor) -> il::Type {
- conv_ty_resolving_typedefs(ctx, ty, cursor, false)
-}
-
-fn conv_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
- ty: &cx::Type,
- cursor: &Cursor,
- resolve_typedefs: bool) -> il::Type {
- let layout = Layout::from_ty(&ty);
- // println!("conv_ty: `{}` layout: {:?}, kind {}: {}", cursor.spelling(), layout, ty.kind(), type_to_str(ty.kind()));
-
- match ty.kind() {
- CXType_Void => TVoid,
- CXType_Invalid => {
- log_err_warn(ctx,
- &format!("invalid type `{}` ({})",
- cursor.spelling(), cursor.location()
- ),
- false
- );
- TVoid
- }
- CXType_Bool => TInt(IBool, layout),
- CXType_SChar |
- CXType_Char_S => TInt(ISChar, layout),
- CXType_UChar |
- CXType_Char_U => TInt(IUChar, layout),
- CXType_WChar => TInt(IShort, layout),
- CXType_Char16 |
- CXType_UShort => TInt(IUShort, layout),
- CXType_UInt => TInt(IUInt, layout),
- CXType_ULong => TInt(IULong, layout),
- CXType_ULongLong => TInt(IULongLong, layout),
- CXType_Short => TInt(IShort, layout),
- CXType_Int => TInt(IInt, layout),
- CXType_Long => TInt(ILong, layout),
- CXType_LongLong => TInt(ILongLong, layout),
- CXType_Float => TFloat(FFloat, layout),
- CXType_Double => TFloat(FDouble, layout),
- CXType_LongDouble => TFloat(FDouble, layout),
- CXType_Pointer => conv_ptr_ty_resolving_typedefs(ctx, &ty.pointee_type(), cursor, false, layout, resolve_typedefs),
- CXType_LValueReference => conv_ptr_ty_resolving_typedefs(ctx, &ty.pointee_type(), cursor, true, layout, resolve_typedefs),
- // XXX DependentSizedArray is wrong
- CXType_VariableArray |
- CXType_DependentSizedArray |
- CXType_IncompleteArray => {
- conv_ptr_ty_resolving_typedefs(ctx, &ty.elem_type(), cursor, false, layout, resolve_typedefs)
- }
- CXType_FunctionProto => TFuncProto(mk_fn_sig(ctx, ty, cursor)),
- CXType_Record |
- CXType_Typedef |
- CXType_Unexposed |
- CXType_Enum => conv_decl_ty_resolving_typedefs(ctx, ty, cursor, resolve_typedefs),
- CXType_ConstantArray => TArray(Box::new(conv_ty_resolving_typedefs(ctx, &ty.elem_type(), cursor, resolve_typedefs)), ty.array_size(), layout),
- #[cfg(not(feature="llvm_stable"))]
- CXType_Elaborated => conv_ty_resolving_typedefs(ctx, &ty.named(), cursor, resolve_typedefs),
- _ => {
- let fail = ctx.options.fail_on_unknown_type;
- log_err_warn(ctx,
- &format!("unsupported type `{}` ({})",
- type_to_str(ty.kind()), cursor.location()
- ),
- fail
- );
- TVoid
- },
- }
-}
-
-fn opaque_ty(ctx: &mut ClangParserCtx, ty: &cx::Type) {
- if ty.kind() == CXType_Record || ty.kind() == CXType_Enum {
- let decl = ty.declaration();
- let def = decl.definition();
- if def.kind() == CXCursor_NoDeclFound ||
- def.kind() == CXCursor_InvalidFile {
- opaque_decl(ctx, &decl);
- }
- }
-}
-
-#[derive(Copy, PartialEq, Clone, Debug)]
-pub enum Accessor {
- None,
- Regular,
- Unsafe,
- Immutable,
-}
-
-#[derive(Clone, PartialEq, Debug)]
-pub struct Annotations {
- opaque: bool,
- hide: bool,
- use_as: Option<String>,
- /// Disable deriving copy/clone on this struct.
- no_copy: bool,
- // In the None case we fall back to the value specified
- // in the enclosing decl
- private: Option<bool>,
- accessor: Option<Accessor>,
-}
-
-fn parse_accessor(s: &str) -> Accessor {
- match s {
- "false" => Accessor::None,
- "unsafe" => Accessor::Unsafe,
- "immutable" => Accessor::Immutable,
- _ => Accessor::Regular,
- }
-}
-
-impl Annotations {
- fn new(cursor: &Cursor) -> Annotations {
- let mut anno = Annotations {
- opaque: false,
- hide: false,
- use_as: None,
- no_copy: false,
- private: None,
- accessor: None
- };
-
- anno.parse(&cursor.comment());
- anno
- }
-
- fn parse(&mut self, comment: &Comment) {
- if comment.kind() == CXComment_HTMLStartTag &&
- comment.get_tag_name() == "div" &&
- comment.get_num_tag_attrs() > 1 &&
- comment.get_tag_attr_name(0) == "rustbindgen" {
- for i in 0..comment.get_num_tag_attrs() {
- let name = comment.get_tag_attr_name(i);
- match name.as_str() {
- "opaque" => self.opaque = true,
- "hide" => self.hide = true,
- "replaces" => self.use_as = Some(comment.get_tag_attr_value(i)),
- "nocopy" => self.no_copy = true,
- "private" => self.private = Some(comment.get_tag_attr_value(i) != "false"),
- "accessor" => {
- self.accessor = Some(parse_accessor(&comment.get_tag_attr_value(i)))
- },
- _ => (),
- }
- }
- }
-
- for i in 0..comment.num_children() {
- self.parse(&comment.get_child(i));
- }
- }
-}
-
-/// Recursively visits a cursor that represents a composite (struct or union)
-/// type and fills members with CompMember instances representing the fields and
-/// nested composites that make up the visited composite.
-fn visit_composite(cursor: &Cursor, parent: &Cursor,
- ctx: &mut ClangParserCtx,
- ci: &mut CompInfo) -> Enum_CXVisitorResult {
- assert!(ci.parser_cursor.is_some());
- fn is_bitfield_continuation(field: &il::FieldInfo, _ty: &il::Type, width: u32) -> bool {
- match (&field.bitfields, field.ty.layout()) {
- (&Some(ref bitfields), Some(layout)) => {
- let actual_width = bitfields.iter().map(|&(_, w)| w).fold(0u32, |acc, w| acc + w);
- actual_width + width <= (layout.size * 8) as u32
- },
- _ => false
- }
- }
-
- match cursor.kind() {
- CXCursor_TypeAliasDecl | CXCursor_TypedefDecl => {
- ci.typedefs.push(cursor.spelling().to_owned());
- }
- CXCursor_FieldDecl => {
- let anno = Annotations::new(cursor);
- if anno.hide {
- return CXChildVisit_Continue;
- }
-
- let is_class_typedef = cursor.cur_type().sanitized_spelling_in(&ci.typedefs);
- let mutable = cursor.is_mutable_field();
-
- let cursor_ty = cursor.cur_type();
-
- // NB: Overwritten in the case of non-integer bitfield
- let mut ty = conv_ty_resolving_typedefs(ctx,
- &cursor_ty,
- cursor,
- is_class_typedef);
-
-
- use hacks::refcell::BorrowState;
- if let Some(child_ci) = ty.get_outermost_composite() {
- if let BorrowState::Unused = child_ci.borrow_state() {
- let mut child_ci = child_ci.borrow_mut();
- let child_cursor = child_ci.parser_cursor.unwrap();
-
- // TODO: This is lame, ideally we should use cursors.
- // The problem this loop is trying to solve is
- // tests/headers/inner_template_self.hpp, and templates with
- // incomplete types.
- //
- // The problem with this is that, in the first case (see the
- // CXCursor_ClassDecl branch below) clang treats the *prev*
- // field as a Class Declaration instead of a Class Template,
- // so we have to check now for the name and the module id.
- //
- // Ideally, some method like `semantic_parent` or
- // `lexical_parent` should return the reference to the
- // class, but I've tried everything I could think about and
- // failed miserably.
- //
- // Also, there could be more complex cases, like a templated
- // type in an inner type declaration, that this is
- // completely unable to catch.
- //
- // In the second case (the CXCursor_ClassTemplate branch),
- // we're not able to retrieve the template parameters of an
- // incomplete type via the declaration or anything like
- // that. We can inspect the AST and deduct them though,
- // since there's a leading CXCursor_TemplateRef.
- if child_ci.args.is_empty() && child_cursor.kind() == CXCursor_ClassDecl {
- // println!("child: {:?} {:?}, {:?}, {:?}", cursor.spelling(),
- // type_to_str(cursor_ty.kind()),
- // type_to_str(child_cursor.cur_type().kind()),
- // kind_to_str(child_cursor.kind()));
- if child_ci.name == ci.name &&
- child_ci.module_id == ci.module_id {
- child_ci.args = ci.args.clone();
- }
- }
-
- if child_cursor.kind() == CXCursor_ClassTemplate {
- // We need to take into account the possibly different
- // type template names, so we need to clear them and
- // re-scan.
- child_ci.args.clear();
- let mut found_invalid_template_ref = false;
- cursor.visit(|c, _| {
- // println!("ichild: {:?} {:?}, {:?}", c.spelling(),
- // kind_to_str(c.kind()),
- // type_to_str(c.cur_type().kind()));
- if c.kind() == CXCursor_TemplateRef &&
- c.cur_type().kind() == CXType_Invalid {
- found_invalid_template_ref = true;
- }
- if found_invalid_template_ref &&
- c.kind() == CXCursor_TypeRef {
- child_ci.args.push(TNamed(Rc::new(RefCell::new(
- TypeInfo::new(c.spelling(),
- ctx.current_module_id,
- TVoid,
- Layout::zero())))));
- }
- CXChildVisit_Continue
- })
- }
- }
- }
-
- let comment = cursor.raw_comment();
-
- let (name, bitfields) = match (cursor.bit_width(), ci.members.last_mut()) {
- // The field is a continuation of an exising bitfield
- (Some(width), Some(&mut il::CompMember::Field(ref mut field)))
- if is_bitfield_continuation(field, &ty, width) => {
-
- // println!("found bitfield continuation {} (width: {})", cursor.spelling(), width);
-
- field.bitfields.as_mut().unwrap().push((cursor.spelling(), width));
- return CXChildVisit_Continue;
- },
- // The field is the start of a new bitfield
- (Some(width), _) => {
- // Bitfields containing enums are not supported by the c standard
- // https://stackoverflow.com/questions/11983231/is-it-safe-to-use-an-enum-in-a-bit-field
-
- match ty {
- il::TInt(..) => {},
- _ => {
- // NOTE: We rely on the name of the type converted
- // to rust types, and on the alignment.
- let bits = cmp::max(width, ty.size() as u32 * 8);
- let layout_size = cmp::max(1, bits.next_power_of_two() / 8) as usize;
-
- let msg = format!("Enums in bitfields are not supported ({}::{}). Trying to recover with width: {}",
- parent.spelling(), cursor.spelling(), layout_size * 8);
- ctx.logger.warn(&msg);
-
- let name = match layout_size {
- 1 => "uint8_t",
- 2 => "uint16_t",
- 4 => "uint32_t",
- 8 => "uint64_t",
- _ => panic!("bitfield width not supported: {}", layout_size),
- };
-
- // NB: We rely on the ULongLong not being translated
- // (using the common uintxx_t name)
- let ti = TypeInfo::new(name.into(),
- ctx.current_module_id,
- TInt(IKind::IULongLong, Layout::new(layout_size, layout_size)),
- Layout::new(layout_size, layout_size));
- ty = TNamed(Rc::new(RefCell::new(ti)))
- }
- }
- ("".to_owned(), Some(vec![(cursor.spelling(), width)]))
- },
- // The field is not a bitfield
- (None, _) => (cursor.spelling(), None)
- };
-
- // The Clang C api does not fully expose composite fields, but it
- // does expose them in a way that can be detected. When the current
- // field kind is TComp, TPtr or TArray and the previous member is a
- // composite type - the same type as this field - then this is a
- // composite field. e.g.:
- //
- // struct foo {
- // union {
- // int a;
- // char b;
- // } bar;
- // };
- //
- // struct foo {
- // union {
- // int a;
- // char b;
- // } **bar;
- // };
- //
- // struct foo {
- // union {
- // int a;
- // char b;
- // } bar[3][2];
- // };
- //
-
- //let is_composite = match (inner_composite(&ty), ci.members.last()) {
- // (Some(ty_compinfo), Some(&CompMember::Comp(ref c))) => {
- // c.borrow().deref() as *const _ == ty_compinfo.borrow().deref() as *const _
- // },
- // _ => false
- //};
-
- if let Some(&mut CompMember::Field(ref mut info)) = ci.members.last_mut() {
- if bitfields.is_none() && info.bitfields.is_none() {
- let should_replace = if let TComp(ref ci) = info.ty {
- if ci.borrow().was_unnamed && ty.was_unnamed() &&
- Some(&ci.borrow().name) == ty.name().as_ref() {
- true
- } else {
- false
- }
- } else {
- false
- };
-
- if should_replace {
- *info = FieldInfo::new(name, ty, comment, bitfields, mutable);
- info.private = anno.private.unwrap_or(ci.anno.private.unwrap_or(false));
- info.accessor = anno.accessor.unwrap_or(ci.anno.accessor.unwrap_or(Accessor::None));
- return CXChildVisit_Continue;
- }
- }
- }
-
- let mut field = FieldInfo::new(name, ty, comment, bitfields, mutable);
- field.private = anno.private.unwrap_or(ci.anno.private.unwrap_or(false));
- field.accessor = anno.accessor.unwrap_or(ci.anno.accessor.unwrap_or(Accessor::None));
- ci.members.push(CompMember::Field(field));
- }
- CXCursor_StructDecl |
- CXCursor_UnionDecl |
- CXCursor_ClassTemplate |
- CXCursor_ClassDecl => {
- fwd_decl(ctx, cursor, |ctx_| {
- // If the struct is anonymous (i.e. declared here) then it
- // cannot be used elsewhere and so does not need to be added
- // to globals otherwise it will be declared later and a global.
- let decl = decl_name(ctx_, cursor);
- let ci2 = decl.compinfo();
-
- // Mangle the name to prevent multiple definitions
- // of the same inner type to cause conflicts
- let new_name = [&*ci.name, &*ci2.borrow().name].join("_").to_owned();
- ci2.borrow_mut().name = new_name;
-
- // This clear() is needed because of the speculation we do on
- // incomplete types inside visit_composite() members.
- //
- // If this type ends up being complete, we're going to really
- // parse them now, so we should reset them.
- ci2.borrow_mut().args.clear();
-
- // Propagate template arguments and typedefs to inner structs
- ci2.borrow_mut().args.extend(ci.args.clone().into_iter());
- ci2.borrow_mut().typedefs.extend(ci.typedefs.clone().into_iter());
-
- cursor.visit(|c, p| {
- let mut ci_ = ci2.borrow_mut();
- visit_composite(c, p, ctx_, &mut ci_)
- });
-
- ci.members.push(CompMember::Comp(decl.compinfo()));
-
- // Anonymous structs are legal in both C++ and C11
- if ci2.borrow().was_unnamed {
- let ci2b = ci2.borrow();
- let field = FieldInfo::new(ci2b.name.clone(), TComp(ci2.clone()), ci2b.comment.clone(), None, false);
- ci.members.push(CompMember::Field(field));
- }
- });
- }
- CXCursor_PackedAttr => {
- ci.set_packed(true);
- }
- CXCursor_TemplateTypeParameter => {
- ci.args.push(conv_template_type_parameter(ctx, cursor));
- }
- CXCursor_EnumDecl => {
- let anno = Annotations::new(cursor);
-
- fwd_decl(ctx, cursor, |ctx_| {
- let decl = decl_name(ctx_, cursor);
- let ei = decl.enuminfo();
- // Mangle the name to avoid name conflicts with inner types
- let new_name = [&*ci.name, &*ei.borrow().name].join("_").to_owned();
- ei.borrow_mut().name = new_name;
- ei.borrow_mut().comment = cursor.raw_comment();
- cursor.visit(|c, _: &Cursor| {
- let mut ei_ = ei.borrow_mut();
- visit_enum(c, &mut ei_.items)
- });
- if anno.opaque {
- ei.borrow_mut().items = vec!();
- }
- ci.members.push(CompMember::Enum(ei));
- });
- }
- CXCursor_CXXBaseSpecifier => {
- let ty = conv_ty(ctx, &cursor.cur_type(), cursor);
- let fieldname = if ci.members.is_empty() {
- "_base".to_string()
- } else {
- format!("_base{}", ci.members.len())
- };
- let found_virtual_base = if ci.members.is_empty() {
- false
- } else if let CompMember::Field(ref fi) = ci.members[0] {
- if let TComp(ref ci2) = fi.ty {
- ci2.borrow().has_vtable
- } else {
- false
- }
- } else {
- false
- };
-
- if let TComp(ref info) = ty {
- ci.has_nonempty_base |= !info.borrow().members.is_empty();
- ci.has_destructor |= info.borrow().has_destructor;
- ci.typedefs.extend(info.borrow().typedefs.clone().into_iter());
- }
-
- let field = FieldInfo::new(fieldname, ty, "".to_owned(), None, false);
- if !found_virtual_base && cursor.is_virtual_base() {
- ci.members.insert(0, CompMember::Field(field));
- ci.has_vtable = true;
- } else {
- ci.members.push(CompMember::Field(field));
- }
- ci.base_members += 1;
- }
- CXCursor_CXXMethod => {
- // Make sure to mark has_vtable properly, even if we
- // would otherwise skip this method due to linkage/visibility.
- if cursor.method_is_virtual() {
- ci.has_vtable = true;
- }
-
- let linkage = cursor.linkage();
- if linkage != CXLinkage_External {
- return CXChildVisit_Continue;
- }
-
- let visibility = cursor.visibility();
- if visibility != CXVisibility_Default {
- return CXChildVisit_Continue;
- }
-
- if cursor.is_inlined_function() {
- return CXChildVisit_Continue;
- }
-
- // XXX no methods yet for templates
- if !ci.args.is_empty() {
- return CXChildVisit_Continue;
- }
-
- if cursor.access_specifier() == CX_CXXPrivate {
- return CXChildVisit_Continue;
- }
-
- let spelling = cursor.spelling();
- if spelling.len() > 8 &&
- &(spelling)[..8] == "operator" {
- return CXChildVisit_Continue;
- }
-
- fn is_override(ci: &CompInfo, sig: &Type, name: &str) -> bool {
- for vm in ci.vmethods.iter() {
- if vm.name == name && &vm.ty == sig {
- return true;
- }
- }
- for base in ci.members[..ci.base_members].iter() {
- let base = match *base {
- CompMember::Field(ref fi) => {
- match fi.ty {
- TComp(ref ci) => ci.clone(),
- _ => continue,
- }
- },
- _ => unreachable!()
- };
- if is_override(&*base.borrow(), sig, name) {
- return true;
- }
- }
- return false;
- }
-
- let mut sig = mk_fn_sig_resolving_typedefs(ctx, &cursor.cur_type(), cursor, &ci.typedefs);
- if !cursor.method_is_static() {
- // XXX what have i done
- if cursor.method_is_virtual() {
- sig.args.insert(0, ("this".to_string(),TPtr(Box::new(TVoid), cursor.cur_type().is_const(), false, Layout::zero())));
- } else {
- // XXX This is weak and doesn't work if names are mangled further, but...
- // We can't have access to the current Rc from here, so we can't pass the type
- // here.
- //
- // Also, it would form an rc cycle.
- //
- // Possibly marking the "this" attribute with TOther or a similar marked value
- // would be a better choice.
- sig.args.insert(0, ("this".to_string(),
- TPtr(Box::new(TNamed(Rc::new(RefCell::new(TypeInfo::new(ci.name.clone(), ctx.current_module_id, TVoid, Layout::zero()))))), cursor.cur_type().is_const(), false, Layout::zero())));
- }
- }
-
- // XXX with final classes we can optimize a bit
- let sig = TFuncPtr(sig);
- if is_override(ci, &sig, &spelling) {
- return CXChildVisit_Continue;
- }
-
- let mut vi = VarInfo::new(spelling, cursor_link_name(ctx, &cursor), cursor.raw_comment(), sig);
- vi.is_static = cursor.method_is_static();
- vi.is_const = cursor.cur_type().is_const();
-
- if ctx.options.ignore_methods {
- return CXChildVisit_Continue;
- }
-
- if cursor.method_is_virtual() {
- ci.vmethods.push(vi);
- } else {
- ci.methods.push(vi);
- }
- }
- CXCursor_Destructor => {
- ci.has_destructor = true;
- // Propagate the change to the parent
- if let Some(ref t) = ci.ref_template {
- match *t {
- TComp(ref parent_ci) => parent_ci.borrow_mut().has_destructor = true,
- _ => {}
- }
- }
- }
- CXCursor_NonTypeTemplateParameter => {
- log_err_warn(ctx, &format!("warning: Non-type template parameter in composite member could affect layout: `{}` (kind {}) in `{}` ({})",
- cursor.spelling(), cursor.kind(), parent.spelling(),
- cursor.location()), false);
- ci.has_non_type_template_params = true;
- }
- CXCursor_VarDecl => {
- if !ctx.options.class_constants {
- return CXChildVisit_Continue;
- }
-
- let linkage = cursor.linkage();
- if linkage != CXLinkage_External && linkage != CXLinkage_UniqueExternal {
- return CXChildVisit_Continue;
- }
-
- let visibility = cursor.visibility();
- if visibility != CXVisibility_Default {
- return CXChildVisit_Continue;
- }
-
- let var = decl_name(ctx, cursor);
- ci.vars.push(var);
- }
- // Intentionally not handled
- CXCursor_CXXAccessSpecifier |
- CXCursor_CXXFinalAttr |
- CXCursor_Constructor |
- CXCursor_FunctionTemplate |
- CXCursor_ConversionFunction => {}
- _ => {
- // XXX: Some kind of warning would be nice, but this produces far
- // too many.
- log_err_warn(ctx, &format!("unhandled composite member `{}` (kind {}) in `{}` ({})",
- cursor.spelling(), cursor.kind(), parent.spelling(),
- cursor.location()), false);
- }
- }
- CXChildVisit_Continue
-}
-
-fn visit_enum(cursor: &Cursor,
- items: &mut Vec<EnumItem>) -> Enum_CXVisitorResult {
- if cursor.kind() == CXCursor_EnumConstantDecl {
- let name = cursor.spelling();
- let comment = cursor.raw_comment();
- let val = cursor.enum_val();
- let item = EnumItem::new(name, comment, val);
- items.push(item);
- }
- CXChildVisit_Continue
-}
-
-fn parse_int_literal_tokens(cursor: &Cursor, unit: &TranslationUnit, which: usize) -> Option<i64> {
- match unit.tokens(cursor) {
- None => None,
- Some(tokens) => {
- if tokens.len() <= which || tokens[which].kind != CXToken_Literal {
- None
- } else {
- let ref s = tokens[which].spelling;
- let parsed = {
- //TODO: try to preserve hex literals?
- if s.starts_with("0x") {
- i64::from_str_radix(&s[2..], 16)
- } else {
- s.parse()
- }
- };
- match parsed {
- Ok(i) => Some(i),
- Err(_) => None,
- }
- }
- }
- }
-}
-
-fn visit_literal(cursor: &Cursor, unit: &TranslationUnit) -> Option<i64> {
- if cursor.kind() == CXCursor_IntegerLiteral {
- return parse_int_literal_tokens(cursor, unit, 0);
- }
- return None;
-}
-
-fn visit_top(cursor: &Cursor,
- mut ctx: &mut ClangParserCtx) -> Enum_CXVisitorResult {
- if !match_pattern(ctx, cursor) {
- return CXChildVisit_Continue;
- }
-
- match cursor.kind() {
- CXCursor_UnexposedDecl => {
- return CXChildVisit_Recurse;
- }
- CXCursor_StructDecl
- | CXCursor_UnionDecl
- | CXCursor_ClassDecl
- | CXCursor_ClassTemplate => {
- let anno = Annotations::new(cursor);
- fwd_decl(ctx, cursor, move |ctx_| {
- let decl = decl_name(ctx_, cursor);
- let ci = decl.compinfo();
- // This clear() is needed because of the speculation we do
- // on incomplete types inside visit_composite() members.
- ci.borrow_mut().args.clear();
- cursor.visit(|c, p| {
- let mut ci_ = ci.borrow_mut();
- visit_composite(c, p, ctx_, &mut ci_)
- });
-
- if anno.opaque {
- ci.borrow_mut().opaque = true;
- }
-
- if anno.hide {
- ci.borrow_mut().hide = true;
- }
-
- if anno.no_copy {
- ci.borrow_mut().no_copy = true;
- }
-
- // If we find a previous translation, we take it now and carry
- // on.
- //
- // XXX: This clone is spurious and could be avoided with another
- // scope I think.
- let name = ci.borrow().name.clone();
- if let Some(translation) = ctx_.current_module_mut().translations.remove(&name) {
- println!("*** {}: found previous translation", name);
- if let GComp(ref translated) = translation {
- *ci.borrow_mut() = translated.borrow().clone();
- }
- }
-
- if let Some(other_type_name) = anno.use_as {
- ci.borrow_mut().name = other_type_name.clone();
- // if the translated type already existed, and we can
- // replace it, just do it (tm).
- //
- // We'll still need the translations map for not found
- // translations and stuff like that.
- //
- // This is a linear search, which is crap, but fwiw it's not
- // too common (just when a type marked as translation is
- // found).
- //
- // NB: We have to also loop through the `name` map to take
- // declarations in files that haven't been matched into
- // account (since they won't appear in globals).
- let mut found_in_globals = false;
- for v in ctx_.current_module_mut().globals.iter_mut() {
- match *v {
- GComp(ref mut other_ci) => {
- if other_ci.borrow().name == other_type_name {
- *other_ci.borrow_mut() = ci.borrow().clone();
- found_in_globals = true;
- }
- },
- _ => {},
- }
- }
-
- for (cursor, v) in ctx_.name.iter_mut() {
- // We can find ourselves here, and that's no fun at
- // all.
- if *cursor == ci.borrow().parser_cursor.unwrap() {
- continue;
- }
- match *v {
- GComp(ref mut other_ci) |
- GCompDecl(ref mut other_ci) => {
- if other_ci.borrow().name == other_type_name {
- // We have to preserve template parameter
- // names here if we want to survive.
- let args = other_ci.borrow().args.clone();
- *other_ci.borrow_mut() = ci.borrow().clone();
- other_ci.borrow_mut().args = args;
- }
- }
- _ => {}
- }
- }
-
- if !found_in_globals {
- ctx_.current_module_mut().translations
- .insert(other_type_name, GComp(ci));
- }
- } else {
- ctx_.current_module_mut().globals.push(GComp(ci));
- }
- });
- CXChildVisit_Continue
- }
- CXCursor_EnumDecl => {
- fwd_decl(ctx, cursor, |ctx_| {
- let decl = decl_name(ctx_, cursor);
- let ei = decl.enuminfo();
- ei.borrow_mut().comment = cursor.raw_comment();
- cursor.visit(|c, _: &Cursor| {
- let mut ei_ = ei.borrow_mut();
- visit_enum(c, &mut ei_.items)
- });
- ctx_.current_module_mut().globals.push(GEnum(ei));
- });
- CXChildVisit_Continue
- }
- CXCursor_FunctionDecl => {
- if ctx.options.ignore_functions {
- return CXChildVisit_Continue;
- }
-
- let linkage = cursor.linkage();
- if linkage != CXLinkage_External && linkage != CXLinkage_UniqueExternal {
- return CXChildVisit_Continue;
- }
-
- let visibility = cursor.visibility();
- if visibility != CXVisibility_Default {
- return CXChildVisit_Continue;
- }
-
- if cursor.is_inlined_function() {
- return CXChildVisit_Continue;
- }
-
- let spelling = cursor.spelling();
- if spelling.len() > 8 &&
- &(spelling)[..8] == "operator" {
- return CXChildVisit_Continue;
- }
-
- let func = decl_name(ctx, cursor);
- let vi = func.varinfo();
- let mut vi = vi.borrow_mut();
-
- vi.ty = TFuncPtr(mk_fn_sig(ctx, &cursor.cur_type(), cursor));
- ctx.current_module_mut().globals.push(func);
-
- CXChildVisit_Continue
- }
- CXCursor_VarDecl => {
- // TODO: At some point we might want to mangle them instead?
- // We already have a bunch of that logic.
- if !ctx.in_root_namespace() && !ctx.options.namespaced_constants {
- return CXChildVisit_Continue;
- }
-
- let linkage = cursor.linkage();
- if linkage != CXLinkage_External && linkage != CXLinkage_UniqueExternal {
- return CXChildVisit_Continue;
- }
-
- let visibility = cursor.visibility();
- if visibility != CXVisibility_Default {
- return CXChildVisit_Continue;
- }
- let val = decl_name(ctx, cursor);
- ctx.current_module_mut().globals.push(val);
-
- CXChildVisit_Continue
- }
- CXCursor_TypeAliasDecl | CXCursor_TypedefDecl => {
- let anno = Annotations::new(cursor);
- if anno.hide {
- return CXChildVisit_Continue;
- }
-
- let mut under_ty = cursor.typedef_type();
- if under_ty.kind() == CXType_Unexposed {
- under_ty = under_ty.canonical_type();
- }
-
- if cursor.spelling() ==
- cursor.typedef_type().declaration().spelling() {
- // XXX: This is a real hack, but in the common idiom of:
- // typedef struct xxx { ... } xxx;
- //
- // The annotation arrives here, so...
- if anno.opaque {
- ctx.options.opaque_types.push(cursor.spelling());
- }
- return CXChildVisit_Continue;
- }
- let ty = conv_ty(ctx, &under_ty, cursor);
- let typedef = decl_name(ctx, cursor);
- let ti = typedef.typeinfo();
- let mut ti = ti.borrow_mut();
- ti.ty = ty.clone();
-
- if anno.opaque {
- ti.opaque = true;
- }
-
- ti.comment = cursor.raw_comment();
- ctx.current_module_mut().globals.push(typedef);
-
- opaque_ty(ctx, &under_ty);
-
- CXChildVisit_Continue
- }
- CXCursor_FieldDecl => {
- CXChildVisit_Continue
- }
- CXCursor_Namespace => {
- if !ctx.options.enable_cxx_namespaces {
- ctx.namespace_depth += 1;
- cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx));
- ctx.namespace_depth -= 1;
- return CXChildVisit_Continue;
- }
-
- let namespace_name = match ctx.current_translation_unit.tokens(cursor) {
- None => None,
- Some(tokens) => {
- if tokens.len() <= 1 {
- None
- } else {
- match &*tokens[1].spelling {
- "{" => None,
- s => Some(s.to_owned()),
- }
- }
- }
- }.unwrap_or_else(|| {
- ctx.anonymous_modules_found += 1;
- format!("__anonymous{}", ctx.anonymous_modules_found)
- });
-
- // Find an existing namespace children of the current one
- let mod_id = ctx.current_module()
- .children_ids.iter()
- .find(|id| ctx.module_map.get(id).unwrap().name == namespace_name)
- .map(|id| *id);
-
- let mod_id = match mod_id {
- Some(id) => id,
- None => {
- let parent_id = ctx.current_module_id;
- let id = ModuleId::next();
- ctx.module_map.get_mut(&parent_id).unwrap().children_ids.push(id);
- ctx.module_map.insert(id, Module::new(namespace_name, Some(parent_id)));
- id
- }
- };
-
- let previous_id = ctx.current_module_id;
-
- ctx.current_module_id = mod_id;
- ctx.namespace_depth += 1;
- cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx));
- ctx.namespace_depth -= 1;
- ctx.current_module_id = previous_id;
-
- return CXChildVisit_Continue;
- }
- CXCursor_MacroDefinition => {
- let val = parse_int_literal_tokens(cursor, &ctx.current_translation_unit, 1);
- let val = match val {
- None => return CXChildVisit_Continue, // Not an integer literal.
- Some(v) => v,
- };
- let var = decl_name(ctx, cursor);
- let vi = var.varinfo();
- let mut vi = vi.borrow_mut();
- vi.ty = if val.abs() > u32::max_value() as i64 {
- TInt(IULongLong, Layout::new(8, 8))
- } else {
- TInt(IUInt, Layout::new(4, 4))
- };
- vi.is_const = true;
- vi.val = Some(val);
- ctx.current_module_mut().globals.push(var);
-
- return CXChildVisit_Continue;
- }
- _ => {
- // println!("Not handled cursor: {}", cursor.kind());
- return CXChildVisit_Continue;
- }
- }
-}
-
-fn log_err_warn(ctx: &mut ClangParserCtx, msg: &str, is_err: bool) {
- if is_err {
- ctx.err_count += 1;
- ctx.logger.error(msg);
- } else {
- ctx.logger.warn(msg);
- }
-}
-
-pub fn parse(options: ClangParserOptions, logger: &Logger) -> Result<ModuleMap, ()> {
- let ix = cx::Index::create(false, true);
- if ix.is_null() {
- logger.error("Clang failed to create index");
- return Err(())
- }
-
- let unit = TranslationUnit::parse(&ix, "", &options.clang_args, &[], CXTranslationUnit_DetailedPreprocessingRecord);
- if unit.is_null() {
- logger.error("No input files given");
- return Err(())
- }
-
- let mut ctx = ClangParserCtx {
- options: options,
- name: HashMap::new(),
- builtin_defs: vec!(),
- module_map: ModuleMap::new(),
- namespace_depth: 0,
- current_module_id: ROOT_MODULE_ID,
- current_translation_unit: unit,
- logger: logger,
- err_count: 0,
- anonymous_modules_found: 0,
- };
-
- ctx.module_map.insert(ROOT_MODULE_ID, Module::new("root".to_owned(), None));
-
- let diags = ctx.current_translation_unit.diags();
- for d in &diags {
- let msg = d.format(Diagnostic::default_opts());
- let is_err = d.severity() >= CXDiagnostic_Error;
- log_err_warn(&mut ctx, &msg, is_err);
- }
-
- if ctx.err_count > 0 {
- logger.error(&format!("{} errors after diagnostics", ctx.err_count));
- return Err(())
- }
-
- let cursor = ctx.current_translation_unit.cursor();
-
- if ctx.options.emit_ast {
- cursor.visit(|cur, _: &Cursor| ast_dump(cur, 0));
- }
-
- cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx));
-
- while !ctx.builtin_defs.is_empty() {
- let c = ctx.builtin_defs.remove(0);
- visit_top(&c.definition(), &mut ctx);
- }
-
- ctx.current_translation_unit.dispose();
- ix.dispose();
-
- if ctx.err_count > 0 {
- logger.error(&format!("{} errors after translation", ctx.err_count));
- return Err(())
- }
-
- Ok(ctx.module_map)
-}
diff --git a/src/regex_set.rs b/src/regex_set.rs
new file mode 100644
index 00000000..20bc56bf
--- /dev/null
+++ b/src/regex_set.rs
@@ -0,0 +1,58 @@
+use std::borrow::Borrow;
+use regex::Regex;
+
+// Yeah, I'm aware this is sorta crappy, should be cheaper to compile a regex
+// ORing all the patterns, I guess...
+#[derive(Debug)]
+pub struct RegexSet {
+ items: Vec<Regex>
+}
+
+impl RegexSet {
+ pub fn is_empty(&self) -> bool {
+ self.items.is_empty()
+ }
+
+ pub fn extend<I>(&mut self, iter: I)
+ where I: IntoIterator<Item=String>
+ {
+ for s in iter.into_iter() {
+ self.insert(&s)
+ }
+ }
+
+ pub fn insert<S>(&mut self, string: &S)
+ where S: Borrow<str>
+ {
+ let s = string.borrow();
+ match Regex::new(&format!("^{}$", s)) {
+ Ok(r) => {
+ self.items.push(r);
+ }
+ Err(err) => {
+ error!("Invalid pattern provided: {}, {:?}", s, err);
+ }
+ }
+ }
+
+ pub fn matches<S>(&self, string: &S) -> bool
+ where S: Borrow<str>
+ {
+ let s = string.borrow();
+ for r in &self.items {
+ if r.is_match(s) {
+ return true;
+ }
+ }
+
+ false
+ }
+}
+
+impl Default for RegexSet {
+ fn default() -> Self {
+ RegexSet {
+ items: vec![],
+ }
+ }
+}
diff --git a/src/types.rs b/src/types.rs
deleted file mode 100644
index 60af3f59..00000000
--- a/src/types.rs
+++ /dev/null
@@ -1,882 +0,0 @@
-use std::cell::Cell;
-use hacks::refcell::RefCell;
-use std::fmt;
-use std::rc::Rc;
-use std::collections::HashMap;
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
-
-use syntax::abi;
-
-pub use self::Global::*;
-pub use self::Type::*;
-pub use self::IKind::*;
-pub use self::FKind::*;
-use clang::{self, Cursor};
-
-use parser::{Annotations, Accessor};
-
-static NEXT_MODULE_ID: AtomicUsize = ATOMIC_USIZE_INIT;
-
-#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
-pub struct ModuleId(usize);
-pub static ROOT_MODULE_ID: ModuleId = ModuleId(0);
-
-impl ModuleId {
- pub fn next() -> ModuleId {
- ModuleId(NEXT_MODULE_ID.fetch_add(1, Ordering::SeqCst) + 1)
- }
-}
-
-pub type ModuleMap = HashMap<ModuleId, Module>;
-
-#[derive(Clone)]
-pub struct Module {
- pub name: String,
- pub globals: Vec<Global>,
- pub parent_id: Option<ModuleId>,
- // Just for convenience
- pub children_ids: Vec<ModuleId>,
- /// Types that must be substituted in this module,
- /// in the form original_name -> substituted_type
- pub translations: HashMap<String, Global>,
-}
-
-impl Module {
- pub fn new(name: String, parent_id: Option<ModuleId>) -> Self {
- Module {
- name: name,
- globals: vec![],
- parent_id: parent_id,
- children_ids: vec![],
- translations: HashMap::new(),
- }
- }
-
- #[allow(dead_code)]
- pub fn add_global(&mut self, g: Global) {
- self.globals.push(g)
- }
-}
-
-#[derive(Clone, PartialEq)]
-pub enum Global {
- GType(Rc<RefCell<TypeInfo>>),
- GComp(Rc<RefCell<CompInfo>>),
- GCompDecl(Rc<RefCell<CompInfo>>),
- GEnum(Rc<RefCell<EnumInfo>>),
- GEnumDecl(Rc<RefCell<EnumInfo>>),
- GVar(Rc<RefCell<VarInfo>>),
- GFunc(Rc<RefCell<VarInfo>>),
- GOther
-}
-
-impl Global {
- // XXX prevent this dumb to_owned()... didn't want to deal with the borrowed lifetime
- pub fn name(&self) -> String {
- match *self {
- GType(ref info) => info.borrow().name.to_owned(),
- GComp(ref info)
- | GCompDecl(ref info) => info.borrow().name.to_owned(),
- GEnum(ref info)
- | GEnumDecl(ref info) => info.borrow().name.to_owned(),
- GVar(ref info)
- | GFunc(ref info) => info.borrow().name.to_owned(),
- GOther => "".to_owned(),
- }
- }
-
- pub fn layout(&self) -> Option<Layout> {
- Some(match *self {
- GType(ref info) => info.borrow().layout,
- GComp(ref info)
- | GCompDecl(ref info) => info.borrow().layout,
- GEnum(ref info)
- | GEnumDecl(ref info) => info.borrow().layout,
- GVar(_)
- | GFunc(_)
- | GOther => return None,
- })
- }
-
- pub fn compinfo(&self) -> Rc<RefCell<CompInfo>> {
- match *self {
- GComp(ref i)
- | GCompDecl(ref i) => i.clone(),
- _ => panic!("global_compinfo")
- }
- }
-
- pub fn enuminfo(&self) -> Rc<RefCell<EnumInfo>> {
- match *self {
- GEnum(ref i)
- | GEnumDecl(ref i) => i.clone(),
- _ => panic!("global_enuminfo")
- }
- }
-
- pub fn typeinfo(&self) -> Rc<RefCell<TypeInfo>> {
- match *self {
- GType(ref i) => i.clone(),
- _ => panic!("global_typeinfo")
- }
- }
-
- pub fn varinfo(&self) -> Rc<RefCell<VarInfo>> {
- match *self {
- GVar(ref i)
- | GFunc(ref i) => i.clone(),
- _ => panic!("global_varinfo")
- }
- }
-
- pub fn to_type(self) -> Type {
- match self {
- GType(ti) => TNamed(ti),
- GComp(ci)
- | GCompDecl(ci) => TComp(ci),
- GEnum(ei)
- | GEnumDecl(ei) => TEnum(ei),
- GVar(_)
- | GFunc(_)
- | GOther => TVoid,
- }
- }
-}
-
-impl fmt::Debug for Global {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- GType(ref ti) => ti.borrow().fmt(f),
- GComp(ref ci)
- | GCompDecl(ref ci) => ci.borrow().fmt(f),
- GEnum(ref ei)
- | GEnumDecl(ref ei) => ei.borrow().fmt(f),
- GVar(ref vi)
- | GFunc(ref vi) => vi.borrow().fmt(f),
- GOther => "*".fmt(f),
- }
- }
-}
-
-#[derive(Debug, Clone, PartialEq)]
-pub struct FuncSig {
- pub ret_ty: Box<Type>,
- pub args: Vec<(String, Type)>,
- pub is_variadic: bool,
- pub is_safe: bool,
- pub abi: abi::Abi,
-}
-
-// NOTE: Remember to add your new variant to the PartialEq implementation below!
-#[derive(Clone, Debug)]
-pub enum Type {
- TVoid,
- TInt(IKind, Layout),
- TFloat(FKind, Layout),
- TPtr(Box<Type>, bool, bool, Layout),
- TArray(Box<Type>, usize, Layout),
- TFuncProto(FuncSig),
- TFuncPtr(FuncSig),
- TNamed(Rc<RefCell<TypeInfo>>),
- TComp(Rc<RefCell<CompInfo>>),
- TEnum(Rc<RefCell<EnumInfo>>)
-}
-
-/// Compares to Rc<T> types looking first at the value they point to.
-///
-/// This is needed to avoid infinite recursion in things like virtual function
-/// signatures.
-fn ref_ptr_aware_eq<T: PartialEq>(one: &Rc<T>, other: &Rc<T>) -> bool {
- &**one as *const T == &**other as *const T ||
- **one == **other
-}
-
-impl PartialEq for Type {
- fn eq(&self, other: &Self) -> bool {
- match (self, other) {
- (&TVoid, &TVoid)
- => true,
- (&TInt(ref kind, ref l), &TInt(ref o_kind, ref o_l))
- => kind == o_kind && l == o_l,
- (&TFloat(ref kind, ref l), &TFloat(ref o_kind, ref o_l))
- => kind == o_kind && l == o_l,
- (&TPtr(ref ty, is_const, is_ref, ref l), &TPtr(ref o_ty, o_is_const, o_is_ref, ref o_l))
- => is_const == o_is_const && is_ref == o_is_ref && l == o_l && ty == o_ty,
- (&TArray(ref ty, count, ref l), &TArray(ref o_ty, o_count, ref o_l))
- => count == o_count && l == o_l && ty == o_ty,
- (&TFuncProto(ref sig), &TFuncProto(ref o_sig))
- => sig == o_sig,
- (&TNamed(ref ti), &TNamed(ref o_ti))
- => ref_ptr_aware_eq(ti, o_ti),
- (&TComp(ref ci), &TComp(ref o_ci))
- => ref_ptr_aware_eq(ci, o_ci),
- (&TEnum(ref ei), &TEnum(ref o_ei))
- => ref_ptr_aware_eq(ei, o_ei),
- _ => false,
- }
- }
-}
-
-impl Type {
- #[allow(dead_code)]
- pub fn name(&self) -> Option<String> {
- match *self {
- TNamed(ref info) => Some(info.borrow().name.clone()),
- TComp(ref info) => Some(info.borrow().name.clone()),
- TEnum(ref info) => Some(info.borrow().name.clone()),
- TArray(ref t, _, _) => t.name(),
- TPtr(ref t, _, _, _) => t.name(),
- _ => None
- }
- }
-
- pub fn signature_contains_type(&self, other: &Type) -> bool {
- self == other || match *self {
- TPtr(ref t, _, _, _) => t.signature_contains_type(other),
- TArray(ref t, _, _) => t.signature_contains_type(other),
- TComp(ref info) => info.borrow().signature_contains_type(other),
- _ => false,
- }
- }
-
- // XXX Add this info to enums?
- pub fn was_unnamed(&self) -> bool {
- match *self {
- TComp(ref ci) => ci.borrow().was_unnamed,
- TArray(ref t, _, _) => t.was_unnamed(),
- TPtr(ref t, _, _, _) => t.was_unnamed(),
- _ => false,
- }
- }
-
- pub fn get_outermost_composite(&self) -> Option<Rc<RefCell<CompInfo>>> {
- match *self {
- TComp(ref ci) => Some(ci.clone()),
- TArray(ref t, _, _) => t.get_outermost_composite(),
- TPtr(ref t, _, _, _) => t.get_outermost_composite(),
- _ => None,
- }
- }
-
- pub fn size(&self) -> usize {
- self.layout().map(|l| l.size).unwrap_or(0)
- }
-
- pub fn align(&self) -> usize {
- self.layout().map(|l| l.align).unwrap_or(0)
- }
-
- pub fn layout(&self) -> Option<Layout> {
- Some(match *self {
- TInt(_, l) => l.clone(),
- TFloat(_, l) => l.clone(),
- TPtr(_, _, _, l) => l.clone(),
- TArray(_, _, l) => l.clone(),
- TComp(ref ci) => ci.borrow().layout.clone(),
- TEnum(ref ei) => ei.borrow().layout.clone(),
- // Test first with the underlying type layout, else with the reported one
- // This fixes a weird bug in SM when it can't find layout for uint32_t
- TNamed(ref ti) => ti.borrow().ty.layout().unwrap_or(ti.borrow().layout.clone()),
- TVoid |
- TFuncProto(..) |
- TFuncPtr(..) => return None,
- })
- }
-
- pub fn can_derive_debug(&self) -> bool {
- !self.is_opaque() && match *self {
- TArray(ref t, size, _) => size <= 32 && t.can_derive_debug(),
- TNamed(ref ti) => ti.borrow().ty.can_derive_debug(),
- TComp(ref comp) => comp.borrow().can_derive_debug(),
- _ => true,
- }
- }
-
- // For some reason, deriving copies of an array of a type that is not known to be copy
- // is a compile error. e.g.:
- //
- // #[derive(Copy)]
- // struct A<T> {
- // member: T,
- // }
- //
- // is fine, while:
- //
- // #[derive(Copy)]
- // struct A<T> {
- // member: [T; 1],
- // }
- //
- // is an error.
- //
- // That's the point of the existance of can_derive_copy_in_array().
- pub fn can_derive_copy_in_array(&self) -> bool {
- match *self {
- TVoid => false,
- TNamed(ref ti) => ti.borrow().ty.can_derive_copy_in_array(),
- TArray(ref t, _, _) => t.can_derive_copy_in_array(),
- ref t => t.can_derive_copy(),
- }
- }
-
- pub fn can_derive_copy(&self) -> bool {
- !self.is_opaque() && match *self {
- TArray(ref t, _, _) => t.can_derive_copy_in_array(),
- TNamed(ref ti) => ti.borrow().ty.can_derive_copy(),
- TComp(ref comp) => comp.borrow().can_derive_copy(),
- _ => true,
- }
- }
-
- pub fn is_opaque(&self) -> bool {
- match *self {
- TArray(ref t, _, _) => t.is_opaque(),
- TPtr(ref t, _, _, _) => t.is_opaque(),
- TNamed(ref ti) => ti.borrow().opaque || ti.borrow().ty.is_opaque(),
- TComp(ref ci) => ci.borrow().is_opaque(),
- _ => false,
- }
- }
-
- #[allow(dead_code)]
- pub fn is_union_like(&self) -> bool {
- match *self {
- TArray(ref t, _, _) => t.is_union_like(),
- TPtr(ref t, _, _, _) => t.is_union_like(),
- TNamed(ref ti) => ti.borrow().ty.is_union_like(),
- TComp(ref ci) => ci.borrow().kind == CompKind::Union,
- _ => false,
- }
- }
-
- // If a type is opaque we conservatively
- // assume it has destructor
- pub fn has_destructor(&self) -> bool {
- self.is_opaque() || match *self {
- TArray(ref t, _, _) => t.has_destructor(),
- TNamed(ref ti) => ti.borrow().ty.has_destructor(),
- TComp(ref ci) => ci.borrow().has_destructor(),
- _ => false,
- }
- }
-
- pub fn is_translatable(&self) -> bool {
- match *self {
- TVoid => false,
- TArray(ref t, _, _) => t.is_translatable(),
- TComp(ref ci) => ci.borrow().is_translatable(),
- // NB: TNamed explicitely ommited here
- _ => true,
- }
- }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq)]
-pub struct Layout {
- pub size: usize,
- pub align: usize,
- pub packed: bool,
-}
-
-impl Layout {
- pub fn new(size: usize, align: usize) -> Self {
- Layout { size: size, align: align, packed: false }
- }
-
- // TODO: make this fallible using fallible_size().
- pub fn from_ty(ty: &clang::Type) -> Self {
- Self::new(ty.size(), ty.align())
- }
-
- pub fn zero() -> Layout {
- Layout { size: 0, align: 0, packed: false }
- }
-
- pub fn is_zero(&self) -> bool {
- *self == Self::zero()
- }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub enum IKind {
- IBool,
- ISChar,
- IUChar,
- IShort,
- IUShort,
- IInt,
- IUInt,
- ILong,
- IULong,
- ILongLong,
- IULongLong
-}
-
-impl IKind {
- #[allow(dead_code)]
- pub fn is_signed(self) -> bool {
- match self {
- IBool => false,
- ISChar => true,
- IUChar => false,
- IShort => true,
- IUShort => false,
- IInt => true,
- IUInt => false,
- ILong => true,
- IULong => false,
- ILongLong => true,
- IULongLong => false,
- }
- }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub enum FKind {
- FFloat,
- FDouble
-}
-
-#[derive(Clone, PartialEq, Debug)]
-pub enum CompMember {
- Field(FieldInfo),
- Comp(Rc<RefCell<CompInfo>>),
- Enum(Rc<RefCell<EnumInfo>>),
-}
-
-#[derive(Copy, Clone, PartialEq)]
-pub enum CompKind {
- Struct,
- Union,
-}
-
-#[derive(Clone, PartialEq)]
-pub struct CompInfo {
- pub kind: CompKind,
- pub name: String,
- pub module_id: ModuleId,
- pub filename: String,
- pub comment: String,
- pub members: Vec<CompMember>,
- pub args: Vec<Type>,
- pub methods: Vec<VarInfo>,
- pub vmethods: Vec<VarInfo>,
- pub ref_template: Option<Type>,
- pub has_vtable: bool,
- pub has_destructor: bool,
- pub has_nonempty_base: bool,
- pub hide: bool,
- pub parser_cursor: Option<Cursor>,
- /// If this struct should be replaced by an opaque blob.
- ///
- /// This is useful if for some reason we can't generate
- /// the correct layout.
- pub opaque: bool,
- pub base_members: usize,
- layout: Layout,
- /// If this struct is explicitely marked as non-copiable.
- pub no_copy: bool,
- /// Typedef'd types names, that we'll resolve early to avoid name conflicts
- pub typedefs: Vec<String>,
- /// If this type has a template parameter which is not a type (e.g.: a size_t)
- pub has_non_type_template_params: bool,
- /// If this type was unnamed when parsed
- pub was_unnamed: bool,
- /// Set of static vars declared inside this class.
- pub vars: Vec<Global>,
- /// Used to detect if we've run in a can_derive_debug cycle while cycling
- /// around the template arguments.
- detect_derive_debug_cycle: Cell<bool>,
- /// Used to detect if we've run in a has_destructor cycle while cycling
- /// around the template arguments.
- detect_has_destructor_cycle: Cell<bool>,
-
- /// Annotations on the decl
- pub anno: Annotations,
-}
-
-static mut UNNAMED_COUNTER: u32 = 0;
-
-fn unnamed_name(name: String, filename: &String) -> String {
- if name.is_empty() {
- let n = unsafe { UNNAMED_COUNTER += 1; UNNAMED_COUNTER };
- format!("{}_unnamed_{}", filename, n)
- } else {
- name
- }
-}
-
-impl CompInfo {
- pub fn new(name: String,
- module_id: ModuleId,
- filename: String,
- comment: String,
- kind: CompKind,
- members: Vec<CompMember>,
- layout: Layout,
- anno: Annotations) -> CompInfo {
- let was_unnamed = name.is_empty();
- CompInfo {
- kind: kind,
- module_id: module_id,
- name: unnamed_name(name, &filename),
- filename: filename,
- comment: comment,
- members: members,
- args: vec![],
- methods: vec![],
- vmethods: vec![],
- ref_template: None,
- has_vtable: false,
- has_destructor: false,
- has_nonempty_base: false,
- hide: false,
- parser_cursor: None,
- opaque: false,
- no_copy: false,
- base_members: 0,
- layout: layout,
- typedefs: vec![],
- vars: vec![],
- has_non_type_template_params: false,
- was_unnamed: was_unnamed,
- detect_derive_debug_cycle: Cell::new(false),
- detect_has_destructor_cycle: Cell::new(false),
- anno: anno,
- }
- }
-
- // Gets or computes the layout as appropriately.
- pub fn layout(&self) -> Layout {
- use std::cmp;
- // The returned layout from clang is zero as of right now, but we should
- // change it to be fallible to distinguish correctly between zero-sized
- // types and unknown layout.
- if !self.layout.is_zero() {
- return self.layout.clone();
- }
-
- if self.args.is_empty() {
- return self.layout.clone();
- }
-
- if self.kind == CompKind::Struct {
- return self.layout.clone();
- }
-
- // If we're a union without known layout, we try to compute it from our
- // members. This is not ideal, but clang fails to report the size for
- // these kind of unions, see test/headers/template_union.hpp
- let mut max_size = 0;
- let mut max_align = 0;
- for member in &self.members {
- let layout = match *member {
- CompMember::Field(ref f) => f.ty.layout().unwrap_or(Layout::zero()),
- CompMember::Comp(ref ci) => ci.borrow().layout(),
- CompMember::Enum(ref ei) => ei.borrow().layout.clone(),
- };
-
- max_size = cmp::max(max_size, layout.size);
- max_align = cmp::max(max_align, layout.align);
- }
-
- Layout::new(max_size, max_align)
- }
-
- pub fn set_packed(&mut self, packed: bool) {
- self.layout.packed = packed
- }
-
- // Return the module id or the class declaration module id.
- pub fn module_id(&self) -> ModuleId {
- self.ref_template.as_ref().and_then(|t| if let TComp(ref ci) = *t {
- Some(ci.borrow().module_id)
- } else {
- None
- }).unwrap_or(self.module_id)
- }
-
- pub fn can_derive_debug(&self) -> bool {
- if self.hide || self.is_opaque() {
- return false;
- }
-
- if self.detect_derive_debug_cycle.get() {
- println!("Derive debug cycle detected: {}!", self.name);
- return true;
- }
-
- match self.kind {
- CompKind::Union => {
- let size_divisor = if self.layout.align == 0 { 1 } else { self.layout.align };
- if self.layout.size / size_divisor > 32 {
- return false;
- }
-
- true
- }
- CompKind::Struct => {
- self.detect_derive_debug_cycle.set(true);
-
- let can_derive_debug = self.args.iter().all(|ty| ty.can_derive_debug()) &&
- self.members.iter()
- .all(|member| match *member {
- CompMember::Field(ref f) => f.ty.can_derive_debug(),
- _ => true,
- });
- self.detect_derive_debug_cycle.set(false);
-
- can_derive_debug
- }
- }
- }
-
- pub fn is_opaque(&self) -> bool {
- if let Some(ref template) = self.ref_template {
- if template.is_opaque() {
- return true;
- }
- }
- self.opaque
- }
-
- pub fn has_destructor(&self) -> bool {
- if self.detect_has_destructor_cycle.get() {
- warn!("Cycle detected looking for destructors: {}!", self.name);
- // Assume no destructor, since we don't have an explicit one.
- return false;
- }
-
- self.detect_has_destructor_cycle.set(true);
-
- let has_destructor = self.has_destructor || match self.kind {
- CompKind::Union => false,
- 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| t.has_destructor()) ||
- self.args.iter().any(|t| t.has_destructor()) ||
- self.members.iter().enumerate().any(|(index, m)| match *m {
- CompMember::Field(ref f) => {
- // Base members may not be resolved yet
- if index < self.base_members {
- f.ty.has_destructor()
- } else {
- f.ty.has_destructor() || !f.ty.is_translatable()
- }
- },
- _ => false,
- })
- }
- };
-
- self.detect_has_destructor_cycle.set(false);
-
- has_destructor
- }
-
- pub fn can_derive_copy(&self) -> bool {
- if self.no_copy {
- return false;
- }
-
- // NOTE: Take into account that while unions in C and C++ are copied by
- // default, the may have an explicit destructor in C++, so we can't
- // defer this check just for the union case.
- if self.has_destructor() {
- return false;
- }
-
- match self.kind {
- CompKind::Union => true,
- CompKind::Struct => {
- // 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()) &&
- self.members.iter().all(|m| match *m {
- CompMember::Field(ref f) => f.ty.can_derive_copy(),
- _ => true,
- })
- }
- }
- }
-
- pub fn is_translatable(&self) -> bool {
- match self.kind {
- CompKind::Union => true,
- CompKind::Struct => {
- self.args.iter().all(|t| t != &TVoid) && !self.has_non_type_template_params
- }
- }
- }
-
- pub fn signature_contains_type(&self, other: &Type) -> bool {
- self.args.iter().any(|t| t.signature_contains_type(other))
- }
-}
-
-impl fmt::Debug for CompInfo {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "CompInfo({}, ref: {:?}, args: {:?}, members: {:?}", self.name, self.ref_template, self.args, self.members)
- }
-}
-
-#[derive(Clone, PartialEq)]
-pub struct FieldInfo {
- pub name: String,
- pub ty: Type,
- pub comment: String,
- pub bitfields: Option<Vec<(String, u32)>>,
- /// If the C++ field is marked as `mutable`
- pub mutable: bool,
- /// True when field or enclosing struct
- /// has a `<div rust-bindgen private>` annotation
- pub private: bool,
- /// Set by the `<div rust-bindgen accessor="..">`
- /// annotation on a field or enclosing struct
- pub accessor: Accessor,
-}
-
-impl FieldInfo {
- pub fn new(name: String,
- ty: Type,
- comment: String,
- bitfields: Option<Vec<(String, u32)>>,
- mutable: bool) -> FieldInfo {
- FieldInfo {
- name: name,
- ty: ty,
- comment: comment,
- bitfields: bitfields,
- mutable: mutable,
- private: false,
- accessor: Accessor::None,
- }
- }
-}
-
-impl fmt::Debug for FieldInfo {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.name.fmt(f)
- }
-}
-
-#[derive(Clone, PartialEq)]
-pub struct EnumInfo {
- pub name: String,
- pub module_id: ModuleId,
- pub comment: String,
- pub filename: String,
- pub items: Vec<EnumItem>,
- pub kind: IKind,
- pub layout: Layout,
-}
-
-impl EnumInfo {
- pub fn new(name: String, module_id: ModuleId, filename: String, kind: IKind, items: Vec<EnumItem>, layout: Layout) -> EnumInfo {
- EnumInfo {
- name: unnamed_name(name, &filename),
- module_id: module_id,
- comment: String::new(),
- filename: filename,
- items: items,
- kind: kind,
- layout: layout,
- }
- }
-}
-
-impl fmt::Debug for EnumInfo {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.name.fmt(f)
- }
-}
-
-#[derive(Clone, PartialEq)]
-pub struct EnumItem {
- pub name: String,
- pub comment: String,
- pub val: i64
-}
-
-impl EnumItem {
- pub fn new(name: String, comment: String, val: i64) -> EnumItem {
- EnumItem {
- name: name,
- comment: comment,
- val: val
- }
- }
-}
-
-#[derive(Clone, PartialEq)]
-pub struct TypeInfo {
- pub name: String,
- pub module_id: ModuleId,
- pub comment: String,
- pub ty: Type,
- pub layout: Layout,
- // TODO: Is this really useful?
- // You can just make opaque the underlying type
- pub opaque: bool,
- pub hide: bool,
-}
-
-impl TypeInfo {
- pub fn new(name: String, module_id: ModuleId, ty: Type, layout: Layout) -> TypeInfo {
- TypeInfo {
- name: name,
- module_id: module_id,
- comment: String::new(),
- ty: ty,
- layout: layout,
- opaque: false,
- hide: false,
- }
- }
-}
-
-impl fmt::Debug for TypeInfo {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.name.fmt(f)
- }
-}
-
-#[derive(Clone, PartialEq)]
-pub struct VarInfo {
- pub name: String,
- pub mangled: String,
- pub comment: String,
- pub ty: Type,
- //TODO: support non-integer constants
- pub val: Option<i64>,
- pub is_const: bool,
- pub is_static: bool,
-}
-
-impl VarInfo {
- pub fn new(name: String, mangled: String, comment: String, ty: Type) -> VarInfo {
- let mangled = if name == mangled {
- String::new()
- } else {
- mangled
- };
- VarInfo {
- name: name,
- mangled: mangled,
- comment: comment,
- ty: ty,
- val: None,
- is_const: false,
- is_static: false,
- }
- }
-}
-
-impl fmt::Debug for VarInfo {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.name.fmt(f)
- }
-}
diff --git a/tests/expectations/accessors.rs b/tests/expectations/accessors.rs
index 8d314878..b721980c 100644
--- a/tests/expectations/accessors.rs
+++ b/tests/expectations/accessors.rs
@@ -6,7 +6,7 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_SomeAccessors {
+pub struct SomeAccessors {
pub mNoAccessor: ::std::os::raw::c_int,
/** <div rustbindgen accessor></div> */
pub mBothAccessors: ::std::os::raw::c_int,
@@ -15,11 +15,20 @@ pub struct Struct_SomeAccessors {
/** <div rustbindgen accessor="immutable"></div> */
pub mImmutableAccessor: ::std::os::raw::c_int,
}
-impl Struct_SomeAccessors {
+#[test]
+fn bindgen_test_layout_SomeAccessors() {
+ assert_eq!(::std::mem::size_of::<SomeAccessors>() , 16usize);
+ assert_eq!(::std::mem::align_of::<SomeAccessors>() , 4usize);
+}
+impl Clone for SomeAccessors {
+ fn clone(&self) -> Self { *self }
+}
+impl SomeAccessors {
#[inline]
pub fn get_mBothAccessors(&self) -> &::std::os::raw::c_int {
&self.mBothAccessors
}
+ #[inline]
pub fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int {
&mut self.mBothAccessors
}
@@ -27,6 +36,7 @@ impl Struct_SomeAccessors {
pub unsafe fn get_mUnsafeAccessors(&self) -> &::std::os::raw::c_int {
&self.mUnsafeAccessors
}
+ #[inline]
pub unsafe fn get_mUnsafeAccessors_mut(&mut self)
-> &mut ::std::os::raw::c_int {
&mut self.mUnsafeAccessors
@@ -36,26 +46,27 @@ impl Struct_SomeAccessors {
&self.mImmutableAccessor
}
}
-impl ::std::clone::Clone for Struct_SomeAccessors {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Struct_SomeAccessors() {
- assert_eq!(::std::mem::size_of::<Struct_SomeAccessors>() , 16usize);
- assert_eq!(::std::mem::align_of::<Struct_SomeAccessors>() , 4usize);
-}
/** <div rustbindgen accessor></div> */
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_AllAccessors {
+pub struct AllAccessors {
pub mBothAccessors: ::std::os::raw::c_int,
pub mAlsoBothAccessors: ::std::os::raw::c_int,
}
-impl Struct_AllAccessors {
+#[test]
+fn bindgen_test_layout_AllAccessors() {
+ assert_eq!(::std::mem::size_of::<AllAccessors>() , 8usize);
+ assert_eq!(::std::mem::align_of::<AllAccessors>() , 4usize);
+}
+impl Clone for AllAccessors {
+ fn clone(&self) -> Self { *self }
+}
+impl AllAccessors {
#[inline]
pub fn get_mBothAccessors(&self) -> &::std::os::raw::c_int {
&self.mBothAccessors
}
+ #[inline]
pub fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int {
&mut self.mBothAccessors
}
@@ -63,31 +74,33 @@ impl Struct_AllAccessors {
pub fn get_mAlsoBothAccessors(&self) -> &::std::os::raw::c_int {
&self.mAlsoBothAccessors
}
+ #[inline]
pub fn get_mAlsoBothAccessors_mut(&mut self)
-> &mut ::std::os::raw::c_int {
&mut self.mAlsoBothAccessors
}
}
-impl ::std::clone::Clone for Struct_AllAccessors {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Struct_AllAccessors() {
- assert_eq!(::std::mem::size_of::<Struct_AllAccessors>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_AllAccessors>() , 4usize);
-}
/** <div rustbindgen accessor="unsafe"></div> */
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_AllUnsafeAccessors {
+pub struct AllUnsafeAccessors {
pub mBothAccessors: ::std::os::raw::c_int,
pub mAlsoBothAccessors: ::std::os::raw::c_int,
}
-impl Struct_AllUnsafeAccessors {
+#[test]
+fn bindgen_test_layout_AllUnsafeAccessors() {
+ assert_eq!(::std::mem::size_of::<AllUnsafeAccessors>() , 8usize);
+ assert_eq!(::std::mem::align_of::<AllUnsafeAccessors>() , 4usize);
+}
+impl Clone for AllUnsafeAccessors {
+ fn clone(&self) -> Self { *self }
+}
+impl AllUnsafeAccessors {
#[inline]
pub unsafe fn get_mBothAccessors(&self) -> &::std::os::raw::c_int {
&self.mBothAccessors
}
+ #[inline]
pub unsafe fn get_mBothAccessors_mut(&mut self)
-> &mut ::std::os::raw::c_int {
&mut self.mBothAccessors
@@ -96,23 +109,16 @@ impl Struct_AllUnsafeAccessors {
pub unsafe fn get_mAlsoBothAccessors(&self) -> &::std::os::raw::c_int {
&self.mAlsoBothAccessors
}
+ #[inline]
pub unsafe fn get_mAlsoBothAccessors_mut(&mut self)
-> &mut ::std::os::raw::c_int {
&mut self.mAlsoBothAccessors
}
}
-impl ::std::clone::Clone for Struct_AllUnsafeAccessors {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Struct_AllUnsafeAccessors() {
- assert_eq!(::std::mem::size_of::<Struct_AllUnsafeAccessors>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_AllUnsafeAccessors>() , 4usize);
-}
/** <div rustbindgen accessor></div> */
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_ContradictAccessors {
+pub struct ContradictAccessors {
pub mBothAccessors: ::std::os::raw::c_int,
/** <div rustbindgen accessor="false"></div> */
pub mNoAccessors: ::std::os::raw::c_int,
@@ -121,11 +127,20 @@ pub struct Struct_ContradictAccessors {
/** <div rustbindgen accessor="immutable"></div> */
pub mImmutableAccessor: ::std::os::raw::c_int,
}
-impl Struct_ContradictAccessors {
+#[test]
+fn bindgen_test_layout_ContradictAccessors() {
+ assert_eq!(::std::mem::size_of::<ContradictAccessors>() , 16usize);
+ assert_eq!(::std::mem::align_of::<ContradictAccessors>() , 4usize);
+}
+impl Clone for ContradictAccessors {
+ fn clone(&self) -> Self { *self }
+}
+impl ContradictAccessors {
#[inline]
pub fn get_mBothAccessors(&self) -> &::std::os::raw::c_int {
&self.mBothAccessors
}
+ #[inline]
pub fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int {
&mut self.mBothAccessors
}
@@ -133,6 +148,7 @@ impl Struct_ContradictAccessors {
pub unsafe fn get_mUnsafeAccessors(&self) -> &::std::os::raw::c_int {
&self.mUnsafeAccessors
}
+ #[inline]
pub unsafe fn get_mUnsafeAccessors_mut(&mut self)
-> &mut ::std::os::raw::c_int {
&mut self.mUnsafeAccessors
@@ -142,53 +158,47 @@ impl Struct_ContradictAccessors {
&self.mImmutableAccessor
}
}
-impl ::std::clone::Clone for Struct_ContradictAccessors {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Struct_ContradictAccessors() {
- assert_eq!(::std::mem::size_of::<Struct_ContradictAccessors>() , 16usize);
- assert_eq!(::std::mem::align_of::<Struct_ContradictAccessors>() , 4usize);
-}
/** <div rustbindgen accessor replaces="Replaced"></div> */
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_Replaced {
+pub struct Replaced {
pub mAccessor: ::std::os::raw::c_int,
}
-impl Struct_Replaced {
+#[test]
+fn bindgen_test_layout_Replaced() {
+ assert_eq!(::std::mem::size_of::<Replaced>() , 4usize);
+ assert_eq!(::std::mem::align_of::<Replaced>() , 4usize);
+}
+impl Clone for Replaced {
+ fn clone(&self) -> Self { *self }
+}
+impl Replaced {
#[inline]
pub fn get_mAccessor(&self) -> &::std::os::raw::c_int { &self.mAccessor }
+ #[inline]
pub fn get_mAccessor_mut(&mut self) -> &mut ::std::os::raw::c_int {
&mut self.mAccessor
}
}
-impl ::std::clone::Clone for Struct_Replaced {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Struct_Replaced() {
- assert_eq!(::std::mem::size_of::<Struct_Replaced>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_Replaced>() , 4usize);
-}
/** <div rustbindgen accessor></div> */
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_Wrapper {
- pub mReplaced: Struct_Replaced,
+pub struct Wrapper {
+ pub mReplaced: Replaced,
}
-impl Struct_Wrapper {
- #[inline]
- pub fn get_mReplaced(&self) -> &Struct_Replaced { &self.mReplaced }
- pub fn get_mReplaced_mut(&mut self) -> &mut Struct_Replaced {
- &mut self.mReplaced
- }
+#[test]
+fn bindgen_test_layout_Wrapper() {
+ assert_eq!(::std::mem::size_of::<Wrapper>() , 4usize);
+ assert_eq!(::std::mem::align_of::<Wrapper>() , 4usize);
}
-impl ::std::clone::Clone for Struct_Wrapper {
+impl Clone for Wrapper {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Struct_Wrapper() {
- assert_eq!(::std::mem::size_of::<Struct_Wrapper>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_Wrapper>() , 4usize);
+impl Wrapper {
+ #[inline]
+ pub fn get_mReplaced(&self) -> &Replaced { &self.mReplaced }
+ #[inline]
+ pub fn get_mReplaced_mut(&mut self) -> &mut Replaced {
+ &mut self.mReplaced
+ }
}
diff --git a/tests/expectations/annotation_hide.rs b/tests/expectations/annotation_hide.rs
index 14ba8310..dcaf7997 100644
--- a/tests/expectations/annotation_hide.rs
+++ b/tests/expectations/annotation_hide.rs
@@ -4,8 +4,11 @@
#![allow(non_snake_case)]
-pub enum Struct_C { }
+/**
+ * <div rustbindgen opaque></div>
+ */
#[repr(C)]
+#[derive(Debug, Copy)]
pub struct D {
pub _bindgen_opaque_blob: u32,
}
@@ -14,16 +17,19 @@ fn bindgen_test_layout_D() {
assert_eq!(::std::mem::size_of::<D>() , 4usize);
assert_eq!(::std::mem::align_of::<D>() , 4usize);
}
+impl Clone for D {
+ fn clone(&self) -> Self { *self }
+}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_NotAnnotated {
+pub struct NotAnnotated {
pub f: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_NotAnnotated {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_NotAnnotated() {
- assert_eq!(::std::mem::size_of::<Struct_NotAnnotated>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_NotAnnotated>() , 4usize);
+fn bindgen_test_layout_NotAnnotated() {
+ assert_eq!(::std::mem::size_of::<NotAnnotated>() , 4usize);
+ assert_eq!(::std::mem::align_of::<NotAnnotated>() , 4usize);
+}
+impl Clone for NotAnnotated {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/anon_enum.rs b/tests/expectations/anon_enum.rs
new file mode 100644
index 00000000..6b8688e1
--- /dev/null
+++ b/tests/expectations/anon_enum.rs
@@ -0,0 +1,23 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Test {
+ pub foo: ::std::os::raw::c_int,
+ pub bar: f32,
+}
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Test__bindgen_ty_bindgen_id_4 { T_NONE = 0, }
+#[test]
+fn bindgen_test_layout_Test() {
+ assert_eq!(::std::mem::size_of::<Test>() , 8usize);
+ assert_eq!(::std::mem::align_of::<Test>() , 4usize);
+}
+impl Clone for Test {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/expectations/anon_enum_whitelist.rs b/tests/expectations/anon_enum_whitelist.rs
new file mode 100644
index 00000000..62c1f1a5
--- /dev/null
+++ b/tests/expectations/anon_enum_whitelist.rs
@@ -0,0 +1,13 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+pub const NODE_FLAG_FOO: _bindgen_ty_bindgen_id_1 =
+ _bindgen_ty_bindgen_id_1::NODE_FLAG_FOO;
+pub const NODE_FLAG_BAR: _bindgen_ty_bindgen_id_1 =
+ _bindgen_ty_bindgen_id_1::NODE_FLAG_BAR;
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum _bindgen_ty_bindgen_id_1 { NODE_FLAG_FOO = 0, NODE_FLAG_BAR = 1, }
diff --git a/tests/expectations/anon_union.rs b/tests/expectations/anon_union.rs
new file mode 100644
index 00000000..66963f40
--- /dev/null
+++ b/tests/expectations/anon_union.rs
@@ -0,0 +1,73 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[derive(Debug)]
+#[repr(C)]
+pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
+impl <T> __BindgenUnionField<T> {
+ #[inline]
+ pub fn new() -> Self { __BindgenUnionField(::std::marker::PhantomData) }
+ #[inline]
+ pub unsafe fn as_ref(&self) -> &T { ::std::mem::transmute(self) }
+ #[inline]
+ pub unsafe fn as_mut(&mut self) -> &mut T { ::std::mem::transmute(self) }
+}
+impl <T> ::std::default::Default for __BindgenUnionField<T> {
+ #[inline]
+ fn default() -> Self { Self::new() }
+}
+impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
+ #[inline]
+ fn clone(&self) -> Self { Self::new() }
+}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct TErrorResult<T> {
+ pub mResult: ::std::os::raw::c_int,
+ pub __bindgen_anon_1: TErrorResult__bindgen_ty_bindgen_id_9<T>,
+ pub mMightHaveUnreported: bool,
+ pub mUnionState: TErrorResult_UnionState,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
+pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState =
+ TErrorResult_UnionState::HasMessage;
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum TErrorResult_UnionState { HasMessage = 0, }
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct TErrorResult_Message<T> {
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct TErrorResult_DOMExceptionInfo<T> {
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct TErrorResult__bindgen_ty_bindgen_id_9<T> {
+ pub mMessage: __BindgenUnionField<*mut TErrorResult_Message<T>>,
+ pub mDOMExceptionInfo: __BindgenUnionField<*mut TErrorResult_DOMExceptionInfo<T>>,
+ pub bindgen_union_field: u64,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct ErrorResult {
+ pub _base: TErrorResult<::std::os::raw::c_int>,
+}
+#[test]
+fn bindgen_test_layout_ErrorResult() {
+ assert_eq!(::std::mem::size_of::<ErrorResult>() , 24usize);
+ assert_eq!(::std::mem::align_of::<ErrorResult>() , 8usize);
+}
+impl Clone for ErrorResult {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/expectations/arg_keyword.rs b/tests/expectations/arg_keyword.rs
new file mode 100644
index 00000000..cb1cc432
--- /dev/null
+++ b/tests/expectations/arg_keyword.rs
@@ -0,0 +1,10 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+extern "C" {
+ #[link_name = "_Z3fooPKc"]
+ pub fn foo(type_: *const ::std::os::raw::c_char);
+}
diff --git a/tests/expectations/class.rs b/tests/expectations/class.rs
index 450a57a6..5951e0e6 100644
--- a/tests/expectations/class.rs
+++ b/tests/expectations/class.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,65 +23,52 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
-#[derive(Copy)]
-pub struct Struct_C {
+pub struct C {
pub a: ::std::os::raw::c_int,
pub big_array: [::std::os::raw::c_char; 33usize],
}
-impl ::std::clone::Clone for Struct_C {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_C() {
- assert_eq!(::std::mem::size_of::<Struct_C>() , 40usize);
- assert_eq!(::std::mem::align_of::<Struct_C>() , 4usize);
+fn bindgen_test_layout_C() {
+ assert_eq!(::std::mem::size_of::<C>() , 40usize);
+ assert_eq!(::std::mem::align_of::<C>() , 4usize);
}
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_WithDtor {
+pub struct WithDtor {
pub b: ::std::os::raw::c_int,
}
#[test]
-fn bindgen_test_layout_Struct_WithDtor() {
- assert_eq!(::std::mem::size_of::<Struct_WithDtor>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_WithDtor>() , 4usize);
+fn bindgen_test_layout_WithDtor() {
+ assert_eq!(::std::mem::size_of::<WithDtor>() , 4usize);
+ assert_eq!(::std::mem::align_of::<WithDtor>() , 4usize);
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_Union {
+pub struct Union {
pub d: __BindgenUnionField<f32>,
pub i: __BindgenUnionField<::std::os::raw::c_int>,
- pub _bindgen_data_: u32,
+ pub bindgen_union_field: u32,
}
-impl Union_Union {
- pub unsafe fn d(&mut self) -> *mut f32 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn i(&mut self) -> *mut ::std::os::raw::c_int {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout_Union() {
+ assert_eq!(::std::mem::size_of::<Union>() , 4usize);
+ assert_eq!(::std::mem::align_of::<Union>() , 4usize);
}
-impl ::std::clone::Clone for Union_Union {
+impl Clone for Union {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Union_Union() {
- assert_eq!(::std::mem::size_of::<Union_Union>() , 4usize);
- assert_eq!(::std::mem::align_of::<Union_Union>() , 4usize);
-}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_WithUnion {
- pub data: Union_Union,
-}
-impl ::std::clone::Clone for Struct_WithUnion {
- fn clone(&self) -> Self { *self }
+pub struct WithUnion {
+ pub data: Union,
}
#[test]
-fn bindgen_test_layout_Struct_WithUnion() {
- assert_eq!(::std::mem::size_of::<Struct_WithUnion>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_WithUnion>() , 4usize);
+fn bindgen_test_layout_WithUnion() {
+ assert_eq!(::std::mem::size_of::<WithUnion>() , 4usize);
+ assert_eq!(::std::mem::align_of::<WithUnion>() , 4usize);
+}
+impl Clone for WithUnion {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/class_nested.rs b/tests/expectations/class_nested.rs
index 22e72209..593e156d 100644
--- a/tests/expectations/class_nested.rs
+++ b/tests/expectations/class_nested.rs
@@ -6,53 +6,54 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_A {
+pub struct A {
pub member_a: ::std::os::raw::c_int,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_A_B {
+pub struct A_B {
pub member_b: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_A_B {
+#[test]
+fn bindgen_test_layout_A_B() {
+ assert_eq!(::std::mem::size_of::<A_B>() , 4usize);
+ assert_eq!(::std::mem::align_of::<A_B>() , 4usize);
+}
+impl Clone for A_B {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_A_B() {
- assert_eq!(::std::mem::size_of::<Struct_A_B>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_A_B>() , 4usize);
+fn bindgen_test_layout_A() {
+ assert_eq!(::std::mem::size_of::<A>() , 4usize);
+ assert_eq!(::std::mem::align_of::<A>() , 4usize);
}
-impl ::std::clone::Clone for Struct_A {
+impl Clone for A {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Struct_A() {
- assert_eq!(::std::mem::size_of::<Struct_A>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_A>() , 4usize);
+extern "C" {
+ #[link_name = "var"]
+ pub static mut var: A_B;
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_D {
- pub member: Struct_A_B,
-}
-impl ::std::clone::Clone for Struct_D {
- fn clone(&self) -> Self { *self }
+pub struct D {
+ pub member: A_B,
}
#[test]
-fn bindgen_test_layout_Struct_D() {
- assert_eq!(::std::mem::size_of::<Struct_D>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_D>() , 4usize);
+fn bindgen_test_layout_D() {
+ assert_eq!(::std::mem::size_of::<D>() , 4usize);
+ assert_eq!(::std::mem::align_of::<D>() , 4usize);
+}
+impl Clone for D {
+ fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_Templated<T> {
+pub struct Templated<T> {
pub member: T,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_Templated_Templated_inner<T> {
+pub struct Templated_Templated_inner<T> {
pub member_ptr: *mut T,
}
-extern "C" {
- pub static mut var: Struct_A_B;
-}
diff --git a/tests/expectations/class_no_members.rs b/tests/expectations/class_no_members.rs
index 8468c02b..017f7c22 100644
--- a/tests/expectations/class_no_members.rs
+++ b/tests/expectations/class_no_members.rs
@@ -6,31 +6,40 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_whatever;
-impl ::std::clone::Clone for Struct_whatever {
+pub struct whatever {
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_whatever() {
+ assert_eq!(::std::mem::size_of::<whatever>() , 1usize);
+ assert_eq!(::std::mem::align_of::<whatever>() , 1usize);
+}
+impl Clone for whatever {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_whatever_child {
- pub _base: Struct_whatever,
+pub struct whatever_child {
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_whatever_child() {
+ assert_eq!(::std::mem::size_of::<whatever_child>() , 1usize);
+ assert_eq!(::std::mem::align_of::<whatever_child>() , 1usize);
}
-impl ::std::clone::Clone for Struct_whatever_child {
+impl Clone for whatever_child {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_whatever_child_with_member {
- pub _base: Struct_whatever,
+pub struct whatever_child_with_member {
pub m_member: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_whatever_child_with_member {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_whatever_child_with_member() {
- assert_eq!(::std::mem::size_of::<Struct_whatever_child_with_member>() ,
- 4usize);
- assert_eq!(::std::mem::align_of::<Struct_whatever_child_with_member>() ,
- 4usize);
+fn bindgen_test_layout_whatever_child_with_member() {
+ assert_eq!(::std::mem::size_of::<whatever_child_with_member>() , 4usize);
+ assert_eq!(::std::mem::align_of::<whatever_child_with_member>() , 4usize);
+}
+impl Clone for whatever_child_with_member {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/class_static.rs b/tests/expectations/class_static.rs
index 8aa156d8..8108be2d 100644
--- a/tests/expectations/class_static.rs
+++ b/tests/expectations/class_static.rs
@@ -6,15 +6,27 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_MyClass;
-impl ::std::clone::Clone for Struct_MyClass {
- fn clone(&self) -> Self { *self }
+pub struct MyClass {
+ pub _address: u8,
}
extern "C" {
#[link_name = "_ZN7MyClass7exampleE"]
- pub static mut Struct_MyClass_consts_example:
- *const ::std::os::raw::c_int;
+ pub static mut MyClass_example: *const ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "_ZN7MyClass26example_check_no_collisionE"]
- pub static mut Struct_MyClass_consts_example_check_no_collision:
+ pub static mut MyClass_example_check_no_collision:
*const ::std::os::raw::c_int;
}
+#[test]
+fn bindgen_test_layout_MyClass() {
+ assert_eq!(::std::mem::size_of::<MyClass>() , 1usize);
+ assert_eq!(::std::mem::align_of::<MyClass>() , 1usize);
+}
+impl Clone for MyClass {
+ fn clone(&self) -> Self { *self }
+}
+extern "C" {
+ #[link_name = "_ZL26example_check_no_collision"]
+ pub static mut example_check_no_collision: *const ::std::os::raw::c_int;
+}
diff --git a/tests/expectations/class_use_as.rs b/tests/expectations/class_use_as.rs
index 4d06feca..c3843b31 100644
--- a/tests/expectations/class_use_as.rs
+++ b/tests/expectations/class_use_as.rs
@@ -9,27 +9,27 @@
*/
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_whatever {
+pub struct whatever {
pub replacement: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_whatever {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_whatever() {
- assert_eq!(::std::mem::size_of::<Struct_whatever>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_whatever>() , 4usize);
+fn bindgen_test_layout_whatever() {
+ assert_eq!(::std::mem::size_of::<whatever>() , 4usize);
+ assert_eq!(::std::mem::align_of::<whatever>() , 4usize);
+}
+impl Clone for whatever {
+ fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_container {
- pub c: Struct_whatever,
-}
-impl ::std::clone::Clone for Struct_container {
- fn clone(&self) -> Self { *self }
+pub struct container {
+ pub c: whatever,
}
#[test]
-fn bindgen_test_layout_Struct_container() {
- assert_eq!(::std::mem::size_of::<Struct_container>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_container>() , 4usize);
+fn bindgen_test_layout_container() {
+ assert_eq!(::std::mem::size_of::<container>() , 4usize);
+ assert_eq!(::std::mem::align_of::<container>() , 4usize);
+}
+impl Clone for container {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/class_with_dtor.rs b/tests/expectations/class_with_dtor.rs
index 3cc48dfb..8ed1ddf9 100644
--- a/tests/expectations/class_with_dtor.rs
+++ b/tests/expectations/class_with_dtor.rs
@@ -6,17 +6,17 @@
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_HandleWithDtor<T> {
+pub struct HandleWithDtor<T> {
pub ptr: *mut T,
}
-pub type HandleValue = Struct_HandleWithDtor<::std::os::raw::c_int>;
+pub type HandleValue = HandleWithDtor<::std::os::raw::c_int>;
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_WithoutDtor {
+pub struct WithoutDtor {
pub shouldBeWithDtor: HandleValue,
}
#[test]
-fn bindgen_test_layout_Struct_WithoutDtor() {
- assert_eq!(::std::mem::size_of::<Struct_WithoutDtor>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_WithoutDtor>() , 8usize);
+fn bindgen_test_layout_WithoutDtor() {
+ assert_eq!(::std::mem::size_of::<WithoutDtor>() , 8usize);
+ assert_eq!(::std::mem::align_of::<WithoutDtor>() , 8usize);
}
diff --git a/tests/expectations/class_with_inner_struct.rs b/tests/expectations/class_with_inner_struct.rs
index b465a183..464c622d 100644
--- a/tests/expectations/class_with_inner_struct.rs
+++ b/tests/expectations/class_with_inner_struct.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,109 +23,94 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_A {
+pub struct A {
pub c: ::std::os::raw::c_uint,
- pub named_union: Union_A_class_with_inner_struct_hpp_unnamed_1,
- pub A_class_with_inner_struct_hpp_unnamed_2: Union_A_class_with_inner_struct_hpp_unnamed_2,
+ pub named_union: A__bindgen_ty_bindgen_id_6,
+ pub __bindgen_anon_1: A__bindgen_ty_bindgen_id_9,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_A_Segment {
+pub struct A_Segment {
pub begin: ::std::os::raw::c_int,
pub end: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_A_Segment {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_A_Segment() {
- assert_eq!(::std::mem::size_of::<Struct_A_Segment>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_A_Segment>() , 4usize);
+fn bindgen_test_layout_A_Segment() {
+ assert_eq!(::std::mem::size_of::<A_Segment>() , 8usize);
+ assert_eq!(::std::mem::align_of::<A_Segment>() , 4usize);
+}
+impl Clone for A_Segment {
+ fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_A_class_with_inner_struct_hpp_unnamed_1 {
+pub struct A__bindgen_ty_bindgen_id_6 {
pub f: __BindgenUnionField<::std::os::raw::c_int>,
- pub _bindgen_data_: u32,
+ pub bindgen_union_field: u32,
}
-impl Union_A_class_with_inner_struct_hpp_unnamed_1 {
- pub unsafe fn f(&mut self) -> *mut ::std::os::raw::c_int {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout_A__bindgen_ty_bindgen_id_6() {
+ assert_eq!(::std::mem::size_of::<A__bindgen_ty_bindgen_id_6>() , 4usize);
+ assert_eq!(::std::mem::align_of::<A__bindgen_ty_bindgen_id_6>() , 4usize);
}
-impl ::std::clone::Clone for Union_A_class_with_inner_struct_hpp_unnamed_1 {
+impl Clone for A__bindgen_ty_bindgen_id_6 {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Union_A_class_with_inner_struct_hpp_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Union_A_class_with_inner_struct_hpp_unnamed_1>()
- , 4usize);
- assert_eq!(::std::mem::align_of::<Union_A_class_with_inner_struct_hpp_unnamed_1>()
- , 4usize);
-}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_A_class_with_inner_struct_hpp_unnamed_2 {
+pub struct A__bindgen_ty_bindgen_id_9 {
pub d: __BindgenUnionField<::std::os::raw::c_int>,
- pub _bindgen_data_: u32,
+ pub bindgen_union_field: u32,
}
-impl Union_A_class_with_inner_struct_hpp_unnamed_2 {
- pub unsafe fn d(&mut self) -> *mut ::std::os::raw::c_int {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout_A__bindgen_ty_bindgen_id_9() {
+ assert_eq!(::std::mem::size_of::<A__bindgen_ty_bindgen_id_9>() , 4usize);
+ assert_eq!(::std::mem::align_of::<A__bindgen_ty_bindgen_id_9>() , 4usize);
}
-impl ::std::clone::Clone for Union_A_class_with_inner_struct_hpp_unnamed_2 {
+impl Clone for A__bindgen_ty_bindgen_id_9 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Union_A_class_with_inner_struct_hpp_unnamed_2() {
- assert_eq!(::std::mem::size_of::<Union_A_class_with_inner_struct_hpp_unnamed_2>()
- , 4usize);
- assert_eq!(::std::mem::align_of::<Union_A_class_with_inner_struct_hpp_unnamed_2>()
- , 4usize);
+fn bindgen_test_layout_A() {
+ assert_eq!(::std::mem::size_of::<A>() , 12usize);
+ assert_eq!(::std::mem::align_of::<A>() , 4usize);
}
-impl ::std::clone::Clone for Struct_A {
+impl Clone for A {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Struct_A() {
- assert_eq!(::std::mem::size_of::<Struct_A>() , 12usize);
- assert_eq!(::std::mem::align_of::<Struct_A>() , 4usize);
-}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_B {
+pub struct B {
pub d: ::std::os::raw::c_uint,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_B_Segment {
+pub struct B_Segment {
pub begin: ::std::os::raw::c_int,
pub end: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_B_Segment {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_B_Segment() {
- assert_eq!(::std::mem::size_of::<Struct_B_Segment>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_B_Segment>() , 4usize);
+fn bindgen_test_layout_B_Segment() {
+ assert_eq!(::std::mem::size_of::<B_Segment>() , 8usize);
+ assert_eq!(::std::mem::align_of::<B_Segment>() , 4usize);
}
-impl ::std::clone::Clone for Struct_B {
+impl Clone for B_Segment {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_B() {
- assert_eq!(::std::mem::size_of::<Struct_B>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_B>() , 4usize);
+fn bindgen_test_layout_B() {
+ assert_eq!(::std::mem::size_of::<B>() , 4usize);
+ assert_eq!(::std::mem::align_of::<B>() , 4usize);
+}
+impl Clone for B {
+ fn clone(&self) -> Self { *self }
}
#[repr(i32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_StepSyntax {
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum StepSyntax {
Keyword = 0,
FunctionalWithoutKeyword = 1,
FunctionalWithStartKeyword = 2,
@@ -133,98 +118,80 @@ pub enum Enum_StepSyntax {
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_C {
+pub struct C {
pub d: ::std::os::raw::c_uint,
- pub C_class_with_inner_struct_hpp_unnamed_3: Union_C_class_with_inner_struct_hpp_unnamed_3,
+ pub __bindgen_anon_1: C__bindgen_ty_bindgen_id_21,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_C_class_with_inner_struct_hpp_unnamed_3 {
- pub mFunc: __BindgenUnionField<Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_4>,
- pub C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_5: __BindgenUnionField<Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_5>,
- pub _bindgen_data_: [u32; 4usize],
-}
-impl Union_C_class_with_inner_struct_hpp_unnamed_3 {
- pub unsafe fn mFunc(&mut self)
- ->
- *mut Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_4 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_5(&mut self)
- ->
- *mut Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_5 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for Union_C_class_with_inner_struct_hpp_unnamed_3 {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Union_C_class_with_inner_struct_hpp_unnamed_3() {
- assert_eq!(::std::mem::size_of::<Union_C_class_with_inner_struct_hpp_unnamed_3>()
- , 16usize);
- assert_eq!(::std::mem::align_of::<Union_C_class_with_inner_struct_hpp_unnamed_3>()
- , 4usize);
+pub struct C__bindgen_ty_bindgen_id_21 {
+ pub mFunc: __BindgenUnionField<C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_22>,
+ pub __bindgen_anon_1: __BindgenUnionField<C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_28>,
+ pub bindgen_union_field: [u32; 4usize],
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_4 {
+pub struct C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_22 {
pub mX1: f32,
pub mY1: f32,
pub mX2: f32,
pub mY2: f32,
}
-impl ::std::clone::Clone for
- Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_4
- {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_4() {
- assert_eq!(::std::mem::size_of::<Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_4>()
+fn bindgen_test_layout_C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_22() {
+ assert_eq!(::std::mem::size_of::<C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_22>()
, 16usize);
- assert_eq!(::std::mem::align_of::<Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_4>()
+ assert_eq!(::std::mem::align_of::<C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_22>()
, 4usize);
}
+impl Clone for C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_22 {
+ fn clone(&self) -> Self { *self }
+}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_5 {
- pub mStepSyntax: Enum_StepSyntax,
+pub struct C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_28 {
+ pub mStepSyntax: StepSyntax,
pub mSteps: ::std::os::raw::c_uint,
}
-impl ::std::clone::Clone for
- Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_5
- {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_5() {
- assert_eq!(::std::mem::size_of::<Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_5>()
+fn bindgen_test_layout_C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_28() {
+ assert_eq!(::std::mem::size_of::<C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_28>()
, 8usize);
- assert_eq!(::std::mem::align_of::<Struct_C_class_with_inner_struct_hpp_unnamed_3_class_with_inner_struct_hpp_unnamed_5>()
+ assert_eq!(::std::mem::align_of::<C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_28>()
, 4usize);
}
+impl Clone for C__bindgen_ty_bindgen_id_21__bindgen_ty_bindgen_id_28 {
+ fn clone(&self) -> Self { *self }
+}
+#[test]
+fn bindgen_test_layout_C__bindgen_ty_bindgen_id_21() {
+ assert_eq!(::std::mem::size_of::<C__bindgen_ty_bindgen_id_21>() ,
+ 16usize);
+ assert_eq!(::std::mem::align_of::<C__bindgen_ty_bindgen_id_21>() ,
+ 4usize);
+}
+impl Clone for C__bindgen_ty_bindgen_id_21 {
+ fn clone(&self) -> Self { *self }
+}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_C_Segment {
+pub struct C_Segment {
pub begin: ::std::os::raw::c_int,
pub end: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_C_Segment {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_C_Segment() {
- assert_eq!(::std::mem::size_of::<Struct_C_Segment>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_C_Segment>() , 4usize);
+fn bindgen_test_layout_C_Segment() {
+ assert_eq!(::std::mem::size_of::<C_Segment>() , 8usize);
+ assert_eq!(::std::mem::align_of::<C_Segment>() , 4usize);
}
-impl ::std::clone::Clone for Struct_C {
+impl Clone for C_Segment {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_C() {
- assert_eq!(::std::mem::size_of::<Struct_C>() , 20usize);
- assert_eq!(::std::mem::align_of::<Struct_C>() , 4usize);
+fn bindgen_test_layout_C() {
+ assert_eq!(::std::mem::size_of::<C>() , 20usize);
+ assert_eq!(::std::mem::align_of::<C>() , 4usize);
+}
+impl Clone for C {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/class_with_typedef.rs b/tests/expectations/class_with_typedef.rs
index 44bce6d7..bc19f2bd 100644
--- a/tests/expectations/class_with_typedef.rs
+++ b/tests/expectations/class_with_typedef.rs
@@ -8,57 +8,65 @@ pub type AnotherInt = ::std::os::raw::c_int;
#[repr(C)]
#[derive(Debug, Copy)]
pub struct C {
- pub c: ::std::os::raw::c_int,
- pub ptr: *mut ::std::os::raw::c_int,
- pub arr: [::std::os::raw::c_int; 10usize],
+ pub c: C_MyInt,
+ pub ptr: *mut C_MyInt,
+ pub arr: [C_MyInt; 10usize],
pub d: AnotherInt,
pub other_ptr: *mut AnotherInt,
}
-impl ::std::clone::Clone for C {
- fn clone(&self) -> Self { *self }
-}
+pub type C_MyInt = ::std::os::raw::c_int;
+pub type C_Lookup = *const ::std::os::raw::c_char;
#[test]
fn bindgen_test_layout_C() {
assert_eq!(::std::mem::size_of::<C>() , 72usize);
assert_eq!(::std::mem::align_of::<C>() , 8usize);
}
extern "C" {
- fn _ZN1C6methodEi(this: *mut C, c: ::std::os::raw::c_int);
- fn _ZN1C9methodRefERi(this: *mut C, c: *mut ::std::os::raw::c_int);
- fn _ZN1C16complexMethodRefERPKc(this: *mut C,
- c: *mut *const ::std::os::raw::c_char);
- fn _ZN1C13anotherMethodEi(this: *mut C, c: AnotherInt);
+ #[link_name = "_ZN1C6methodEi"]
+ pub fn C_method(this: *mut C, c: C_MyInt);
+}
+extern "C" {
+ #[link_name = "_ZN1C9methodRefERi"]
+ pub fn C_methodRef(this: *mut C, c: *mut C_MyInt);
+}
+extern "C" {
+ #[link_name = "_ZN1C16complexMethodRefERPKc"]
+ pub fn C_complexMethodRef(this: *mut C, c: *mut C_Lookup);
+}
+extern "C" {
+ #[link_name = "_ZN1C13anotherMethodEi"]
+ pub fn C_anotherMethod(this: *mut C, c: AnotherInt);
+}
+impl Clone for C {
+ fn clone(&self) -> Self { *self }
}
impl C {
#[inline]
- pub unsafe fn method(&mut self, c: ::std::os::raw::c_int) {
- _ZN1C6methodEi(&mut *self, c)
- }
+ pub unsafe fn method(&mut self, c: C_MyInt) { C_method(&mut *self, c) }
#[inline]
- pub unsafe fn methodRef(&mut self, c: *mut ::std::os::raw::c_int) {
- _ZN1C9methodRefERi(&mut *self, c)
+ pub unsafe fn methodRef(&mut self, c: *mut C_MyInt) {
+ C_methodRef(&mut *self, c)
}
#[inline]
- pub unsafe fn complexMethodRef(&mut self,
- c: *mut *const ::std::os::raw::c_char) {
- _ZN1C16complexMethodRefERPKc(&mut *self, c)
+ pub unsafe fn complexMethodRef(&mut self, c: *mut C_Lookup) {
+ C_complexMethodRef(&mut *self, c)
}
#[inline]
pub unsafe fn anotherMethod(&mut self, c: AnotherInt) {
- _ZN1C13anotherMethodEi(&mut *self, c)
+ C_anotherMethod(&mut *self, c)
}
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct D {
pub _base: C,
- pub ptr: *mut ::std::os::raw::c_int,
-}
-impl ::std::clone::Clone for D {
- fn clone(&self) -> Self { *self }
+ pub ptr: *mut C_MyInt,
}
#[test]
fn bindgen_test_layout_D() {
assert_eq!(::std::mem::size_of::<D>() , 80usize);
assert_eq!(::std::mem::align_of::<D>() , 8usize);
}
+impl Clone for D {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/expectations/const_ptr.rs b/tests/expectations/const_ptr.rs
new file mode 100644
index 00000000..89400df1
--- /dev/null
+++ b/tests/expectations/const_ptr.rs
@@ -0,0 +1,9 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+extern "C" {
+ pub fn foo(bar: *const ::std::os::raw::c_void);
+}
diff --git a/tests/expectations/const_resolved_ty.rs b/tests/expectations/const_resolved_ty.rs
new file mode 100644
index 00000000..77d8f438
--- /dev/null
+++ b/tests/expectations/const_resolved_ty.rs
@@ -0,0 +1,9 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+extern "C" {
+ pub fn foo(foo: *const u8);
+}
diff --git a/tests/expectations/const_tparam.rs b/tests/expectations/const_tparam.rs
new file mode 100644
index 00000000..59649626
--- /dev/null
+++ b/tests/expectations/const_tparam.rs
@@ -0,0 +1,11 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct C<T> {
+ pub foo: *mut T,
+}
diff --git a/tests/expectations/crtp.rs b/tests/expectations/crtp.rs
index c6964524..e4a86b24 100644
--- a/tests/expectations/crtp.rs
+++ b/tests/expectations/crtp.rs
@@ -7,23 +7,37 @@
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Base<T> {
- pub _phantom0: ::std::marker::PhantomData<T>,
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct Derived {
- pub _base: Base<Derived>,
+ pub _address: u8,
}
-impl ::std::clone::Clone for Derived {
+#[test]
+fn bindgen_test_layout_Derived() {
+ assert_eq!(::std::mem::size_of::<Derived>() , 1usize);
+ assert_eq!(::std::mem::align_of::<Derived>() , 1usize);
+}
+impl Clone for Derived {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug)]
pub struct BaseWithDestructor<T> {
- pub _phantom0: ::std::marker::PhantomData<T>,
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
#[repr(C)]
#[derive(Debug)]
pub struct DerivedFromBaseWithDestructor {
- pub _base: BaseWithDestructor<DerivedFromBaseWithDestructor>,
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_DerivedFromBaseWithDestructor() {
+ assert_eq!(::std::mem::size_of::<DerivedFromBaseWithDestructor>() ,
+ 1usize);
+ assert_eq!(::std::mem::align_of::<DerivedFromBaseWithDestructor>() ,
+ 1usize);
}
diff --git a/tests/expectations/decl_ptr_to_array.rs b/tests/expectations/decl_ptr_to_array.rs
index e7dabeee..b8abedb5 100644
--- a/tests/expectations/decl_ptr_to_array.rs
+++ b/tests/expectations/decl_ptr_to_array.rs
@@ -5,5 +5,6 @@
extern "C" {
- pub static mut foo: [::std::os::raw::c_int; 1usize];
+ #[link_name = "foo"]
+ pub static mut foo: *mut [::std::os::raw::c_int; 1usize];
}
diff --git a/tests/expectations/duplicated_constants_in_ns.rs b/tests/expectations/duplicated_constants_in_ns.rs
index b4b7b2bc..cb69890c 100644
--- a/tests/expectations/duplicated_constants_in_ns.rs
+++ b/tests/expectations/duplicated_constants_in_ns.rs
@@ -4,4 +4,14 @@
#![allow(non_snake_case)]
-
+pub mod root {
+ use root;
+ pub mod foo {
+ use root;
+ pub const FOO: ::std::os::raw::c_int = 4;
+ }
+ pub mod bar {
+ use root;
+ pub const FOO: ::std::os::raw::c_int = 5;
+ }
+}
diff --git a/tests/expectations/empty_template_param_name.rs b/tests/expectations/empty_template_param_name.rs
new file mode 100644
index 00000000..d165df80
--- /dev/null
+++ b/tests/expectations/empty_template_param_name.rs
@@ -0,0 +1,12 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct __iterator_traits<_Iterator> {
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<_Iterator>,
+}
diff --git a/tests/expectations/enum.rs b/tests/expectations/enum.rs
index f6f510dd..8138d697 100644
--- a/tests/expectations/enum.rs
+++ b/tests/expectations/enum.rs
@@ -5,8 +5,8 @@
#[repr(u32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Foo { Bar = 0, Qux = 1, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Foo { Bar = 0, Qux = 1, }
#[repr(i32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Neg { MinusOne = -1, One = 1, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Neg { MinusOne = -1, One = 1, }
diff --git a/tests/expectations/enum_alias.rs b/tests/expectations/enum_alias.rs
new file mode 100644
index 00000000..7ea85598
--- /dev/null
+++ b/tests/expectations/enum_alias.rs
@@ -0,0 +1,9 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(u8)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Bar { VAL = 0, }
diff --git a/tests/expectations/enum_and_vtable_mangling.rs b/tests/expectations/enum_and_vtable_mangling.rs
index c68dc102..3c7d5370 100644
--- a/tests/expectations/enum_and_vtable_mangling.rs
+++ b/tests/expectations/enum_and_vtable_mangling.rs
@@ -4,27 +4,26 @@
#![allow(non_snake_case)]
+pub const match_: _bindgen_ty_bindgen_id_1 = _bindgen_ty_bindgen_id_1::match_;
+pub const whatever_else: _bindgen_ty_bindgen_id_1 =
+ _bindgen_ty_bindgen_id_1::whatever_else;
#[repr(u32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_enum_and_vtable_mangling_hpp_unnamed_1 {
- match_ = 0,
- whatever_else = 1,
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum _bindgen_ty_bindgen_id_1 { match_ = 0, whatever_else = 1, }
+#[repr(C)]
+pub struct bindgen_vtable__bindgen_id_4 {
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_C {
- pub _vftable: *const _vftable_Struct_C,
+pub struct C {
+ pub vtable_: *const bindgen_vtable__bindgen_id_4,
pub i: ::std::os::raw::c_int,
}
-#[repr(C)]
-pub struct _vftable_Struct_C {
- pub match_: unsafe extern "C" fn(this: *mut ::std::os::raw::c_void),
+#[test]
+fn bindgen_test_layout_C() {
+ assert_eq!(::std::mem::size_of::<C>() , 16usize);
+ assert_eq!(::std::mem::align_of::<C>() , 8usize);
}
-impl ::std::clone::Clone for Struct_C {
+impl Clone for C {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Struct_C() {
- assert_eq!(::std::mem::size_of::<Struct_C>() , 16usize);
- assert_eq!(::std::mem::align_of::<Struct_C>() , 8usize);
-}
diff --git a/tests/expectations/enum_dupe.rs b/tests/expectations/enum_dupe.rs
index 10464881..322b89fc 100644
--- a/tests/expectations/enum_dupe.rs
+++ b/tests/expectations/enum_dupe.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-pub const Dupe: Enum_Foo = Enum_Foo::Bar;
+pub const Foo_Dupe: Foo = Foo::Bar;
#[repr(u32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Foo { Bar = 1, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Foo { Bar = 1, }
diff --git a/tests/expectations/enum_explicit_type.rs b/tests/expectations/enum_explicit_type.rs
index 1b94c284..352f4ea9 100644
--- a/tests/expectations/enum_explicit_type.rs
+++ b/tests/expectations/enum_explicit_type.rs
@@ -5,17 +5,17 @@
#[repr(u8)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Foo { Bar = 0, Qux = 1, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Foo { Bar = 0, Qux = 1, }
#[repr(i8)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Neg { MinusOne = -1, One = 1, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Neg { MinusOne = -1, One = 1, }
#[repr(u16)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Bigger { Much = 255, Larger = 256, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Bigger { Much = 255, Larger = 256, }
#[repr(i64)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_MuchLong { MuchLow = -4294967296, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum MuchLong { MuchLow = -4294967296, }
#[repr(u64)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_MuchLongLong { MuchHigh = 4294967296, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum MuchLongLong { MuchHigh = 4294967296, }
diff --git a/tests/expectations/enum_negative.rs b/tests/expectations/enum_negative.rs
index 03db5709..74cf4f16 100644
--- a/tests/expectations/enum_negative.rs
+++ b/tests/expectations/enum_negative.rs
@@ -5,5 +5,5 @@
#[repr(i32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Foo { Bar = -2, Qux = 1, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Foo { Bar = -2, Qux = 1, }
diff --git a/tests/expectations/enum_packed.rs b/tests/expectations/enum_packed.rs
index 7684a26d..963763e1 100644
--- a/tests/expectations/enum_packed.rs
+++ b/tests/expectations/enum_packed.rs
@@ -5,11 +5,11 @@
#[repr(u8)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Foo { Bar = 0, Qux = 1, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Foo { Bar = 0, Qux = 1, }
#[repr(i8)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Neg { MinusOne = -1, One = 1, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Neg { MinusOne = -1, One = 1, }
#[repr(u16)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Bigger { Much = 255, Larger = 256, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Bigger { Much = 255, Larger = 256, }
diff --git a/tests/expectations/extern.rs b/tests/expectations/extern.rs
index 8f122341..e7ac7504 100644
--- a/tests/expectations/extern.rs
+++ b/tests/expectations/extern.rs
@@ -5,4 +5,5 @@
pub type foo =
- unsafe extern "C" fn(bar: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
+ ::std::option::Option<unsafe extern "C" fn(bar: ::std::os::raw::c_int)
+ -> ::std::os::raw::c_int>;
diff --git a/tests/expectations/forward_declared_struct.rs b/tests/expectations/forward_declared_struct.rs
index 3a812c0d..5c2764e1 100644
--- a/tests/expectations/forward_declared_struct.rs
+++ b/tests/expectations/forward_declared_struct.rs
@@ -6,27 +6,27 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_a {
+pub struct a {
pub b: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_a {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_a() {
- assert_eq!(::std::mem::size_of::<Struct_a>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_a>() , 4usize);
+fn bindgen_test_layout_a() {
+ assert_eq!(::std::mem::size_of::<a>() , 4usize);
+ assert_eq!(::std::mem::align_of::<a>() , 4usize);
+}
+impl Clone for a {
+ fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_c {
+pub struct c {
pub d: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_c {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_c() {
- assert_eq!(::std::mem::size_of::<Struct_c>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_c>() , 4usize);
+fn bindgen_test_layout_c() {
+ assert_eq!(::std::mem::size_of::<c>() , 4usize);
+ assert_eq!(::std::mem::align_of::<c>() , 4usize);
+}
+impl Clone for c {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/func_proto.rs b/tests/expectations/func_proto.rs
index 8f122341..e7ac7504 100644
--- a/tests/expectations/func_proto.rs
+++ b/tests/expectations/func_proto.rs
@@ -5,4 +5,5 @@
pub type foo =
- unsafe extern "C" fn(bar: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
+ ::std::option::Option<unsafe extern "C" fn(bar: ::std::os::raw::c_int)
+ -> ::std::os::raw::c_int>;
diff --git a/tests/expectations/func_ptr.rs b/tests/expectations/func_ptr.rs
index 01e413a6..c62e532d 100644
--- a/tests/expectations/func_ptr.rs
+++ b/tests/expectations/func_ptr.rs
@@ -5,10 +5,8 @@
extern "C" {
+ #[link_name = "foo"]
pub static mut foo:
- ::std::option::Option<unsafe extern "C" fn(x:
- ::std::os::raw::c_int,
- y:
- ::std::os::raw::c_int)
- -> ::std::os::raw::c_int>;
+ *mut ::std::option::Option<unsafe extern "C" fn()
+ -> ::std::os::raw::c_int>;
}
diff --git a/tests/expectations/func_ptr_in_struct.rs b/tests/expectations/func_ptr_in_struct.rs
index 3d7b5f68..0d4ccdbf 100644
--- a/tests/expectations/func_ptr_in_struct.rs
+++ b/tests/expectations/func_ptr_in_struct.rs
@@ -4,23 +4,18 @@
#![allow(non_snake_case)]
-#[repr(i32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_baz { _BindgenOpaqueEnum = 0, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum baz { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_Foo {
- pub bar: ::std::option::Option<unsafe extern "C" fn(x:
- ::std::os::raw::c_int,
- y:
- ::std::os::raw::c_int)
- -> Enum_baz>,
-}
-impl ::std::clone::Clone for Struct_Foo {
- fn clone(&self) -> Self { *self }
+pub struct Foo {
+ pub bar: *mut ::std::option::Option<unsafe extern "C" fn() -> baz>,
}
#[test]
-fn bindgen_test_layout_Struct_Foo() {
- assert_eq!(::std::mem::size_of::<Struct_Foo>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_Foo>() , 8usize);
+fn bindgen_test_layout_Foo() {
+ assert_eq!(::std::mem::size_of::<Foo>() , 8usize);
+ assert_eq!(::std::mem::align_of::<Foo>() , 8usize);
+}
+impl Clone for Foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/func_with_func_ptr_arg.rs b/tests/expectations/func_with_func_ptr_arg.rs
index 4ac25286..b6e345f6 100644
--- a/tests/expectations/func_with_func_ptr_arg.rs
+++ b/tests/expectations/func_with_func_ptr_arg.rs
@@ -5,5 +5,5 @@
extern "C" {
- pub fn foo(bar: ::std::option::Option<unsafe extern "C" fn()>);
+ pub fn foo(bar: *mut ::std::option::Option<unsafe extern "C" fn()>);
}
diff --git a/tests/expectations/in_class_typedef.rs b/tests/expectations/in_class_typedef.rs
new file mode 100644
index 00000000..4e95ca8c
--- /dev/null
+++ b/tests/expectations/in_class_typedef.rs
@@ -0,0 +1,21 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Foo<T> {
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
+pub type Foo_elem_type<T> = T;
+pub type Foo_ptr_type<T> = *mut T;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Foo_Bar<T> {
+ pub x: ::std::os::raw::c_int,
+ pub y: ::std::os::raw::c_int,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
diff --git a/tests/expectations/inherit_named.rs b/tests/expectations/inherit_named.rs
new file mode 100644
index 00000000..8081c649
--- /dev/null
+++ b/tests/expectations/inherit_named.rs
@@ -0,0 +1,17 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Wohoo<T> {
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Weeee<T> {
+ pub _base: T,
+}
diff --git a/tests/expectations/inherit_typedef.rs b/tests/expectations/inherit_typedef.rs
new file mode 100644
index 00000000..ca9041e2
--- /dev/null
+++ b/tests/expectations/inherit_typedef.rs
@@ -0,0 +1,33 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Foo {
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_Foo() {
+ assert_eq!(::std::mem::size_of::<Foo>() , 1usize);
+ assert_eq!(::std::mem::align_of::<Foo>() , 1usize);
+}
+impl Clone for Foo {
+ fn clone(&self) -> Self { *self }
+}
+pub type TypedefedFoo = Foo;
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Bar {
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_Bar() {
+ assert_eq!(::std::mem::size_of::<Bar>() , 1usize);
+ assert_eq!(::std::mem::align_of::<Bar>() , 1usize);
+}
+impl Clone for Bar {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/expectations/inner_const.rs b/tests/expectations/inner_const.rs
new file mode 100644
index 00000000..666b8ce2
--- /dev/null
+++ b/tests/expectations/inner_const.rs
@@ -0,0 +1,27 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Foo {
+ pub bar: ::std::os::raw::c_int,
+}
+extern "C" {
+ #[link_name = "_ZN3Foo3BOOE"]
+ pub static mut Foo_BOO: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "_ZN3Foo8whateverE"]
+ pub static mut Foo_whatever: Foo;
+}
+#[test]
+fn bindgen_test_layout_Foo() {
+ assert_eq!(::std::mem::size_of::<Foo>() , 4usize);
+ assert_eq!(::std::mem::align_of::<Foo>() , 4usize);
+}
+impl Clone for Foo {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/expectations/inner_template_self.rs b/tests/expectations/inner_template_self.rs
index 60af23ee..b965b92d 100644
--- a/tests/expectations/inner_template_self.rs
+++ b/tests/expectations/inner_template_self.rs
@@ -6,20 +6,20 @@
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_LinkedList<T> {
- pub next: *mut Struct_LinkedList<T>,
- pub prev: *mut Struct_LinkedList<T>,
+pub struct LinkedList<T> {
+ pub next: *mut LinkedList<T>,
+ pub prev: *mut LinkedList<T>,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_InstantiateIt {
- pub m_list: Struct_LinkedList<::std::os::raw::c_int>,
-}
-impl ::std::clone::Clone for Struct_InstantiateIt {
- fn clone(&self) -> Self { *self }
+pub struct InstantiateIt {
+ pub m_list: LinkedList<::std::os::raw::c_int>,
}
#[test]
-fn bindgen_test_layout_Struct_InstantiateIt() {
- assert_eq!(::std::mem::size_of::<Struct_InstantiateIt>() , 16usize);
- assert_eq!(::std::mem::align_of::<Struct_InstantiateIt>() , 8usize);
+fn bindgen_test_layout_InstantiateIt() {
+ assert_eq!(::std::mem::size_of::<InstantiateIt>() , 16usize);
+ assert_eq!(::std::mem::align_of::<InstantiateIt>() , 8usize);
+}
+impl Clone for InstantiateIt {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/jsval_layout_opaque.rs b/tests/expectations/jsval_layout_opaque.rs
index fa9b89b9..69fe54dc 100644
--- a/tests/expectations/jsval_layout_opaque.rs
+++ b/tests/expectations/jsval_layout_opaque.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,9 +23,10 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
pub const JSVAL_TAG_SHIFT: ::std::os::raw::c_uint = 47;
#[repr(u8)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSValueType {
JSVAL_TYPE_DOUBLE = 0,
JSVAL_TYPE_INT32 = 1,
@@ -40,7 +41,7 @@ pub enum JSValueType {
JSVAL_TYPE_MISSING = 33,
}
#[repr(u32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSValueTag {
JSVAL_TAG_MAX_DOUBLE = 131056,
JSVAL_TAG_INT32 = 131057,
@@ -53,7 +54,7 @@ pub enum JSValueTag {
JSVAL_TAG_OBJECT = 131064,
}
#[repr(u64)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSValueShiftedTag {
JSVAL_SHIFTED_TAG_MAX_DOUBLE = 18444492278190833663,
JSVAL_SHIFTED_TAG_INT32 = 18444633011384221696,
@@ -66,7 +67,7 @@ pub enum JSValueShiftedTag {
JSVAL_SHIFTED_TAG_OBJECT = 18445618173802708992,
}
#[repr(u32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSWhyMagic {
JS_ELEMENTS_HOLE = 0,
JS_NO_ITER_VALUE = 1,
@@ -92,155 +93,107 @@ pub enum JSWhyMagic {
#[derive(Debug, Copy)]
pub struct jsval_layout {
pub asBits: __BindgenUnionField<u64>,
- pub debugView: __BindgenUnionField<jsval_layout_jsval_layout_opaque_hpp_unnamed_1>,
- pub s: __BindgenUnionField<jsval_layout_jsval_layout_opaque_hpp_unnamed_2>,
+ pub debugView: __BindgenUnionField<jsval_layout__bindgen_ty_bindgen_id_81>,
+ pub s: __BindgenUnionField<jsval_layout__bindgen_ty_bindgen_id_85>,
pub asDouble: __BindgenUnionField<f64>,
pub asPtr: __BindgenUnionField<*mut ::std::os::raw::c_void>,
pub asWord: __BindgenUnionField<usize>,
pub asUIntPtr: __BindgenUnionField<usize>,
- pub _bindgen_data_: u64,
-}
-impl jsval_layout {
- pub unsafe fn asBits(&mut self) -> *mut u64 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn debugView(&mut self)
- -> *mut jsval_layout_jsval_layout_opaque_hpp_unnamed_1 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn s(&mut self)
- -> *mut jsval_layout_jsval_layout_opaque_hpp_unnamed_2 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn asDouble(&mut self) -> *mut f64 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn asPtr(&mut self) -> *mut *mut ::std::os::raw::c_void {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn asWord(&mut self) -> *mut usize {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn asUIntPtr(&mut self) -> *mut usize {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for jsval_layout {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_jsval_layout() {
- assert_eq!(::std::mem::size_of::<jsval_layout>() , 8usize);
- assert_eq!(::std::mem::align_of::<jsval_layout>() , 8usize);
+ pub bindgen_union_field: u64,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct jsval_layout_jsval_layout_opaque_hpp_unnamed_1 {
+pub struct jsval_layout__bindgen_ty_bindgen_id_81 {
pub _bitfield_1: u64,
}
-impl jsval_layout_jsval_layout_opaque_hpp_unnamed_1 {
+#[test]
+fn bindgen_test_layout_jsval_layout__bindgen_ty_bindgen_id_81() {
+ assert_eq!(::std::mem::size_of::<jsval_layout__bindgen_ty_bindgen_id_81>()
+ , 8usize);
+ assert_eq!(::std::mem::align_of::<jsval_layout__bindgen_ty_bindgen_id_81>()
+ , 8usize);
+}
+impl Clone for jsval_layout__bindgen_ty_bindgen_id_81 {
+ fn clone(&self) -> Self { *self }
+}
+impl jsval_layout__bindgen_ty_bindgen_id_81 {
#[inline]
pub fn payload47(&self) -> u64 {
- (self._bitfield_1 & (140737488355327usize as u64)) >> 0usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 &
+ (140737488355327usize as u64)) >>
+ 0u32) as u64)
+ }
}
#[inline]
- pub fn set_payload47(&mut self, val: u32) {
+ pub fn set_payload47(&mut self, val: u64) {
self._bitfield_1 &= !(140737488355327usize as u64);
self._bitfield_1 |=
- ((val as u64) << 0usize) & (140737488355327usize as u64);
+ ((val as u64 as u64) << 0u32) & (140737488355327usize as u64);
}
#[inline]
- pub fn tag(&self) -> u64 {
- (self._bitfield_1 & (18446603336221196288usize as u64)) >> 47usize
+ pub fn tag(&self) -> JSValueTag {
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 &
+ (18446603336221196288usize as u64)) >>
+ 47u32) as u32)
+ }
}
#[inline]
- pub fn set_tag(&mut self, val: u32) {
+ pub fn set_tag(&mut self, val: JSValueTag) {
self._bitfield_1 &= !(18446603336221196288usize as u64);
self._bitfield_1 |=
- ((val as u64) << 47usize) & (18446603336221196288usize as u64);
- }
- #[inline]
- pub fn new_bitfield_1(payload47: u32, tag: u32) -> u64 {
- 0 | ((payload47 as u64) << 0u32) | ((tag as u64) << 47u32)
+ ((val as u32 as u64) << 47u32) &
+ (18446603336221196288usize as u64);
}
}
-impl ::std::clone::Clone for jsval_layout_jsval_layout_opaque_hpp_unnamed_1 {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_jsval_layout_jsval_layout_opaque_hpp_unnamed_1() {
- assert_eq!(::std::mem::size_of::<jsval_layout_jsval_layout_opaque_hpp_unnamed_1>()
- , 8usize);
- assert_eq!(::std::mem::align_of::<jsval_layout_jsval_layout_opaque_hpp_unnamed_1>()
- , 8usize);
-}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct jsval_layout_jsval_layout_opaque_hpp_unnamed_2 {
- pub payload: jsval_layout_jsval_layout_opaque_hpp_unnamed_2_jsval_layout_opaque_hpp_unnamed_3,
+pub struct jsval_layout__bindgen_ty_bindgen_id_85 {
+ pub payload: jsval_layout__bindgen_ty_bindgen_id_85__bindgen_ty_bindgen_id_86,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct jsval_layout_jsval_layout_opaque_hpp_unnamed_2_jsval_layout_opaque_hpp_unnamed_3 {
+pub struct jsval_layout__bindgen_ty_bindgen_id_85__bindgen_ty_bindgen_id_86 {
pub i32: __BindgenUnionField<i32>,
pub u32: __BindgenUnionField<u32>,
pub why: __BindgenUnionField<JSWhyMagic>,
- pub _bindgen_data_: u32,
-}
-impl jsval_layout_jsval_layout_opaque_hpp_unnamed_2_jsval_layout_opaque_hpp_unnamed_3
- {
- pub unsafe fn i32(&mut self) -> *mut i32 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn u32(&mut self) -> *mut u32 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn why(&mut self) -> *mut JSWhyMagic {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for
- jsval_layout_jsval_layout_opaque_hpp_unnamed_2_jsval_layout_opaque_hpp_unnamed_3
- {
- fn clone(&self) -> Self { *self }
+ pub bindgen_union_field: u32,
}
#[test]
-fn bindgen_test_layout_jsval_layout_jsval_layout_opaque_hpp_unnamed_2_jsval_layout_opaque_hpp_unnamed_3() {
- assert_eq!(::std::mem::size_of::<jsval_layout_jsval_layout_opaque_hpp_unnamed_2_jsval_layout_opaque_hpp_unnamed_3>()
+fn bindgen_test_layout_jsval_layout__bindgen_ty_bindgen_id_85__bindgen_ty_bindgen_id_86() {
+ assert_eq!(::std::mem::size_of::<jsval_layout__bindgen_ty_bindgen_id_85__bindgen_ty_bindgen_id_86>()
, 4usize);
- assert_eq!(::std::mem::align_of::<jsval_layout_jsval_layout_opaque_hpp_unnamed_2_jsval_layout_opaque_hpp_unnamed_3>()
+ assert_eq!(::std::mem::align_of::<jsval_layout__bindgen_ty_bindgen_id_85__bindgen_ty_bindgen_id_86>()
, 4usize);
}
-impl ::std::clone::Clone for jsval_layout_jsval_layout_opaque_hpp_unnamed_2 {
+impl Clone for
+ jsval_layout__bindgen_ty_bindgen_id_85__bindgen_ty_bindgen_id_86 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_jsval_layout_jsval_layout_opaque_hpp_unnamed_2() {
- assert_eq!(::std::mem::size_of::<jsval_layout_jsval_layout_opaque_hpp_unnamed_2>()
+fn bindgen_test_layout_jsval_layout__bindgen_ty_bindgen_id_85() {
+ assert_eq!(::std::mem::size_of::<jsval_layout__bindgen_ty_bindgen_id_85>()
, 4usize);
- assert_eq!(::std::mem::align_of::<jsval_layout_jsval_layout_opaque_hpp_unnamed_2>()
+ assert_eq!(::std::mem::align_of::<jsval_layout__bindgen_ty_bindgen_id_85>()
, 4usize);
}
+impl Clone for jsval_layout__bindgen_ty_bindgen_id_85 {
+ fn clone(&self) -> Self { *self }
+}
+impl Clone for jsval_layout {
+ fn clone(&self) -> Self { *self }
+}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct Value {
pub data: jsval_layout,
}
-impl ::std::clone::Clone for Value {
- fn clone(&self) -> Self { *self }
-}
#[test]
fn bindgen_test_layout_Value() {
assert_eq!(::std::mem::size_of::<Value>() , 8usize);
assert_eq!(::std::mem::align_of::<Value>() , 8usize);
}
+impl Clone for Value {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/expectations/keywords.rs b/tests/expectations/keywords.rs
index 12e9b5c2..5b75389e 100644
--- a/tests/expectations/keywords.rs
+++ b/tests/expectations/keywords.rs
@@ -5,90 +5,198 @@
extern "C" {
+ #[link_name = "u8"]
pub static mut u8: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "u16"]
pub static mut u16: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "u32"]
pub static mut u32: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "u64"]
pub static mut u64: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "i8"]
pub static mut i8: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "i16"]
pub static mut i16: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "i32"]
pub static mut i32: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "i64"]
pub static mut i64: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "f32"]
pub static mut f32: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "f64"]
pub static mut f64: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "usize"]
pub static mut usize: ::std::os::raw::c_int;
+}
+extern "C" {
+ #[link_name = "isize"]
pub static mut isize: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "as"]
pub static mut as_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "box"]
pub static mut box_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "crate"]
pub static mut crate_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "false"]
pub static mut false_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "fn"]
pub static mut fn_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "impl"]
pub static mut impl_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "in"]
pub static mut in_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "let"]
pub static mut let_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "loop"]
pub static mut loop_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "match"]
pub static mut match_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "mod"]
pub static mut mod_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "move"]
pub static mut move_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "mut"]
pub static mut mut_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "pub"]
pub static mut pub_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "ref"]
pub static mut ref_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "self"]
pub static mut self_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "Self"]
pub static mut Self_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "super"]
pub static mut super_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "trait"]
pub static mut trait_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "true"]
pub static mut true_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "type"]
pub static mut type_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "unsafe"]
pub static mut unsafe_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "use"]
pub static mut use_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "where"]
pub static mut where_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "abstract"]
pub static mut abstract_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "alignof"]
pub static mut alignof_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "become"]
pub static mut become_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "final"]
pub static mut final_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "macro"]
pub static mut macro_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "offsetof"]
pub static mut offsetof_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "override"]
pub static mut override_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "priv"]
pub static mut priv_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "proc"]
pub static mut proc_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "pure"]
pub static mut pure_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "unsized"]
pub static mut unsized_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "virtual"]
pub static mut virtual_: ::std::os::raw::c_int;
+}
+extern "C" {
#[link_name = "yield"]
pub static mut yield_: ::std::os::raw::c_int;
}
diff --git a/tests/expectations/moar_bitfields.rs b/tests/expectations/moar_bitfields.rs
new file mode 100644
index 00000000..7c034120
--- /dev/null
+++ b/tests/expectations/moar_bitfields.rs
@@ -0,0 +1,48 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(u32)]
+pub enum WhenToScroll {
+ SCROLL_ALWAYS = 0,
+ SCROLL_IF_NOT_VISIBLE = 1,
+ SCROLL_IF_NOT_FULLY_VISIBLE = 2,
+}
+#[repr(C)]
+pub struct ScrollAxis {
+ pub mWhereToScroll: ::std::os::raw::c_short,
+ pub _bitfield_1: u16,
+}
+#[test]
+fn bindgen_test_layout_ScrollAxis() {
+ assert_eq!(::std::mem::size_of::<ScrollAxis>() , 4usize);
+ assert_eq!(::std::mem::align_of::<ScrollAxis>() , 4usize);
+}
+impl ScrollAxis {
+ #[inline]
+ pub fn mWhenToScroll(&self) -> WhenToScroll {
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (255usize as u16)) >>
+ 0u32) as u32)
+ }
+ }
+ #[inline]
+ pub fn set_mWhenToScroll(&mut self, val: WhenToScroll) {
+ self._bitfield_1 &= !(255usize as u16);
+ self._bitfield_1 |= ((val as u32 as u16) << 0u32) & (255usize as u16);
+ }
+ #[inline]
+ pub fn mOnlyIfPerceivedScrollableDirection(&self) -> bool {
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (256usize as u16)) >>
+ 8u32) as u8)
+ }
+ }
+ #[inline]
+ pub fn set_mOnlyIfPerceivedScrollableDirection(&mut self, val: bool) {
+ self._bitfield_1 &= !(256usize as u16);
+ self._bitfield_1 |= ((val as u8 as u16) << 8u32) & (256usize as u16);
+ }
+}
diff --git a/tests/expectations/mutable.rs b/tests/expectations/mutable.rs
index cf2c5937..0d0d6ea3 100644
--- a/tests/expectations/mutable.rs
+++ b/tests/expectations/mutable.rs
@@ -6,37 +6,37 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_C {
+pub struct C {
pub m_member: ::std::os::raw::c_int,
pub m_other: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_C {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_C() {
- assert_eq!(::std::mem::size_of::<Struct_C>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_C>() , 4usize);
+fn bindgen_test_layout_C() {
+ assert_eq!(::std::mem::size_of::<C>() , 8usize);
+ assert_eq!(::std::mem::align_of::<C>() , 4usize);
+}
+impl Clone for C {
+ fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_NonCopiable {
- pub m_member: ::std::cell::Cell<::std::os::raw::c_int>,
+pub struct NonCopiable {
+ pub m_member: ::std::os::raw::c_int,
}
#[test]
-fn bindgen_test_layout_Struct_NonCopiable() {
- assert_eq!(::std::mem::size_of::<Struct_NonCopiable>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_NonCopiable>() , 4usize);
+fn bindgen_test_layout_NonCopiable() {
+ assert_eq!(::std::mem::size_of::<NonCopiable>() , 4usize);
+ assert_eq!(::std::mem::align_of::<NonCopiable>() , 4usize);
}
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_NonCopiableWithNonCopiableMutableMember {
- pub m_member: ::std::cell::UnsafeCell<Struct_NonCopiable>,
+pub struct NonCopiableWithNonCopiableMutableMember {
+ pub m_member: NonCopiable,
}
#[test]
-fn bindgen_test_layout_Struct_NonCopiableWithNonCopiableMutableMember() {
- assert_eq!(::std::mem::size_of::<Struct_NonCopiableWithNonCopiableMutableMember>()
+fn bindgen_test_layout_NonCopiableWithNonCopiableMutableMember() {
+ assert_eq!(::std::mem::size_of::<NonCopiableWithNonCopiableMutableMember>()
, 4usize);
- assert_eq!(::std::mem::align_of::<Struct_NonCopiableWithNonCopiableMutableMember>()
+ assert_eq!(::std::mem::align_of::<NonCopiableWithNonCopiableMutableMember>()
, 4usize);
}
diff --git a/tests/expectations/namespace.rs b/tests/expectations/namespace.rs
index 36113536..0bd6e8e0 100644
--- a/tests/expectations/namespace.rs
+++ b/tests/expectations/namespace.rs
@@ -4,17 +4,8 @@
#![allow(non_snake_case)]
-pub use root::*;
pub mod root {
- #[repr(C)]
- #[derive(Debug)]
- pub struct Struct_C<T> {
- pub _base: __anonymous1::Struct_A,
- pub m_c: T,
- pub m_c_ptr: *mut T,
- pub m_c_arr: [T; 10usize],
- pub _phantom0: ::std::marker::PhantomData<T>,
- }
+ use root;
extern "C" {
#[link_name = "_Z9top_levelv"]
pub fn top_level();
@@ -27,44 +18,68 @@ pub mod root {
pub fn in_whatever();
}
}
- pub mod __anonymous1 {
+ pub mod _bindgen_mod_bindgen_id_12 {
use root;
+ pub mod empty {
+ use root;
+ }
+ extern "C" {
+ #[link_name = "_ZN12_GLOBAL__N_13fooEv"]
+ pub fn foo();
+ }
#[repr(C)]
#[derive(Debug, Copy)]
- pub struct Struct_A {
+ pub struct A {
pub b: root::whatever::whatever_int_t,
}
- impl ::std::clone::Clone for Struct_A {
- fn clone(&self) -> Self { *self }
- }
#[test]
- fn bindgen_test_layout_Struct_A() {
- assert_eq!(::std::mem::size_of::<Struct_A>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_A>() , 4usize);
- }
- extern "C" {
- #[link_name = "_ZN12_GLOBAL__N_13fooEv"]
- pub fn foo();
+ fn bindgen_test_layout_A() {
+ assert_eq!(::std::mem::size_of::<A>() , 4usize);
+ assert_eq!(::std::mem::align_of::<A>() , 4usize);
}
- pub mod empty {
- use root;
+ impl Clone for A {
+ fn clone(&self) -> Self { *self }
}
}
+ #[repr(C)]
+ #[derive(Debug)]
+ pub struct C<T> {
+ pub _base: root::_bindgen_mod_bindgen_id_12::A,
+ pub m_c: T,
+ pub m_c_ptr: *mut T,
+ pub m_c_arr: [T; 10usize],
+ }
pub mod w {
use root;
pub type whatever_int_t = ::std::os::raw::c_uint;
#[repr(C)]
#[derive(Debug)]
- pub struct Struct_D<T> {
- pub m_c: root::Struct_C<T>,
+ pub struct D<T> {
+ pub m_c: root::C<T>,
}
extern "C" {
#[link_name = "_ZN1w3hehEv"]
pub fn heh() -> root::w::whatever_int_t;
+ }
+ extern "C" {
#[link_name = "_ZN1w3fooEv"]
- pub fn foo() -> root::Struct_C<::std::os::raw::c_int>;
+ pub fn foo() -> root::C<::std::os::raw::c_int>;
+ }
+ extern "C" {
#[link_name = "_ZN1w4barrEv"]
- pub fn barr() -> root::Struct_C<f32>;
+ pub fn barr() -> root::C<f32>;
}
}
}
+extern "C" {
+ #[link_name = "_Z9top_levelv"]
+ pub fn top_level();
+}
+#[repr(C)]
+#[derive(Debug)]
+pub struct C<T> {
+ pub _base: root::_bindgen_mod_bindgen_id_12::A,
+ pub m_c: T,
+ pub m_c_ptr: *mut T,
+ pub m_c_arr: [T; 10usize],
+}
diff --git a/tests/expectations/nested.rs b/tests/expectations/nested.rs
index 2f7fae9a..fdd435aa 100644
--- a/tests/expectations/nested.rs
+++ b/tests/expectations/nested.rs
@@ -6,47 +6,54 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_Calc {
+pub struct Calc {
pub w: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_Calc {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_Calc() {
- assert_eq!(::std::mem::size_of::<Struct_Calc>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_Calc>() , 4usize);
+fn bindgen_test_layout_Calc() {
+ assert_eq!(::std::mem::size_of::<Calc>() , 4usize);
+ assert_eq!(::std::mem::align_of::<Calc>() , 4usize);
+}
+impl Clone for Calc {
+ fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_Test;
+pub struct Test {
+ pub _address: u8,
+}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_Test_Size {
- pub mWidth: Struct_Test_Size_Dimension,
- pub mHeight: Struct_Test_Size_Dimension,
+pub struct Test_Size {
+ pub mWidth: Test_Size_Dimension,
+ pub mHeight: Test_Size_Dimension,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_Test_Size_Dimension {
- pub _base: Struct_Calc,
+pub struct Test_Size_Dimension {
+ pub _base: Calc,
+}
+#[test]
+fn bindgen_test_layout_Test_Size_Dimension() {
+ assert_eq!(::std::mem::size_of::<Test_Size_Dimension>() , 4usize);
+ assert_eq!(::std::mem::align_of::<Test_Size_Dimension>() , 4usize);
}
-impl ::std::clone::Clone for Struct_Test_Size_Dimension {
+impl Clone for Test_Size_Dimension {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_Test_Size_Dimension() {
- assert_eq!(::std::mem::size_of::<Struct_Test_Size_Dimension>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_Test_Size_Dimension>() , 4usize);
+fn bindgen_test_layout_Test_Size() {
+ assert_eq!(::std::mem::size_of::<Test_Size>() , 8usize);
+ assert_eq!(::std::mem::align_of::<Test_Size>() , 4usize);
}
-impl ::std::clone::Clone for Struct_Test_Size {
+impl Clone for Test_Size {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_Test_Size() {
- assert_eq!(::std::mem::size_of::<Struct_Test_Size>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_Test_Size>() , 4usize);
+fn bindgen_test_layout_Test() {
+ assert_eq!(::std::mem::size_of::<Test>() , 1usize);
+ assert_eq!(::std::mem::align_of::<Test>() , 1usize);
}
-impl ::std::clone::Clone for Struct_Test {
+impl Clone for Test {
fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/nested_vtable.rs b/tests/expectations/nested_vtable.rs
new file mode 100644
index 00000000..0c4f7dbe
--- /dev/null
+++ b/tests/expectations/nested_vtable.rs
@@ -0,0 +1,48 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+pub struct bindgen_vtable__bindgen_id_1 {
+}
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct nsISupports {
+ pub vtable_: *const bindgen_vtable__bindgen_id_1,
+}
+#[test]
+fn bindgen_test_layout_nsISupports() {
+ assert_eq!(::std::mem::size_of::<nsISupports>() , 8usize);
+ assert_eq!(::std::mem::align_of::<nsISupports>() , 8usize);
+}
+impl Clone for nsISupports {
+ fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct nsIRunnable {
+ pub _base: nsISupports,
+}
+#[test]
+fn bindgen_test_layout_nsIRunnable() {
+ assert_eq!(::std::mem::size_of::<nsIRunnable>() , 8usize);
+ assert_eq!(::std::mem::align_of::<nsIRunnable>() , 8usize);
+}
+impl Clone for nsIRunnable {
+ fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Runnable {
+ pub _base: nsIRunnable,
+}
+#[test]
+fn bindgen_test_layout_Runnable() {
+ assert_eq!(::std::mem::size_of::<Runnable>() , 8usize);
+ assert_eq!(::std::mem::align_of::<Runnable>() , 8usize);
+}
+impl Clone for Runnable {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/expectations/no_copy.rs b/tests/expectations/no_copy.rs
index 601b65c8..53ab9677 100644
--- a/tests/expectations/no_copy.rs
+++ b/tests/expectations/no_copy.rs
@@ -7,7 +7,7 @@
/** <div rustbindgen nocopy></div> */
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_CopiableButWait<T> {
+pub struct CopiableButWait<T> {
pub whatever: ::std::os::raw::c_int,
- pub _phantom0: ::std::marker::PhantomData<T>,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
diff --git a/tests/expectations/nsStyleAutoArray.rs b/tests/expectations/nsStyleAutoArray.rs
index 8acfa150..c150ec46 100644
--- a/tests/expectations/nsStyleAutoArray.rs
+++ b/tests/expectations/nsStyleAutoArray.rs
@@ -6,17 +6,17 @@
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_nsTArray<T> {
+pub struct nsTArray<T> {
pub mBuff: *mut T,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_nsStyleAutoArray<T> {
+pub struct nsStyleAutoArray<T> {
pub mFirstElement: T,
- pub mOtherElements: Struct_nsTArray<T>,
+ pub mOtherElements: nsTArray<T>,
}
#[repr(i32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsStyleAutoArray_WithSingleInitialElement {
WITH_SINGLE_INITIAL_ELEMENT = 0,
}
diff --git a/tests/expectations/only_bitfields.rs b/tests/expectations/only_bitfields.rs
index d46a1f83..68968826 100644
--- a/tests/expectations/only_bitfields.rs
+++ b/tests/expectations/only_bitfields.rs
@@ -6,34 +6,40 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_C {
+pub struct C {
pub _bitfield_1: u8,
}
-impl Struct_C {
+#[test]
+fn bindgen_test_layout_C() {
+ assert_eq!(::std::mem::size_of::<C>() , 1usize);
+ assert_eq!(::std::mem::align_of::<C>() , 1usize);
+}
+impl Clone for C {
+ fn clone(&self) -> Self { *self }
+}
+impl C {
#[inline]
- pub fn a(&self) -> u8 { (self._bitfield_1 & (1usize as u8)) >> 0usize }
+ pub fn a(&self) -> bool {
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (1usize as u8)) >>
+ 0u32) as u8)
+ }
+ }
#[inline]
pub fn set_a(&mut self, val: bool) {
self._bitfield_1 &= !(1usize as u8);
- self._bitfield_1 |= ((val as u8) << 0usize) & (1usize as u8);
+ self._bitfield_1 |= ((val as u8 as u8) << 0u32) & (1usize as u8);
}
#[inline]
- pub fn b(&self) -> u8 { (self._bitfield_1 & (254usize as u8)) >> 1usize }
- #[inline]
- pub fn set_b(&mut self, val: u8) {
- self._bitfield_1 &= !(254usize as u8);
- self._bitfield_1 |= ((val as u8) << 1usize) & (254usize as u8);
+ pub fn b(&self) -> bool {
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (254usize as u8)) >>
+ 1u32) as u8)
+ }
}
#[inline]
- pub fn new_bitfield_1(a: bool, b: u8) -> u8 {
- 0 | ((a as u8) << 0u32) | ((b as u8) << 1u32)
+ pub fn set_b(&mut self, val: bool) {
+ self._bitfield_1 &= !(254usize as u8);
+ self._bitfield_1 |= ((val as u8 as u8) << 1u32) & (254usize as u8);
}
}
-impl ::std::clone::Clone for Struct_C {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Struct_C() {
- assert_eq!(::std::mem::size_of::<Struct_C>() , 1usize);
- assert_eq!(::std::mem::align_of::<Struct_C>() , 1usize);
-}
diff --git a/tests/expectations/opaque_in_struct.rs b/tests/expectations/opaque_in_struct.rs
index a5e3dff6..d537f5c7 100644
--- a/tests/expectations/opaque_in_struct.rs
+++ b/tests/expectations/opaque_in_struct.rs
@@ -4,7 +4,9 @@
#![allow(non_snake_case)]
+/** <div rustbindgen opaque> */
#[repr(C)]
+#[derive(Debug, Copy)]
pub struct opaque {
pub _bindgen_opaque_blob: u32,
}
@@ -13,12 +15,19 @@ fn bindgen_test_layout_opaque() {
assert_eq!(::std::mem::size_of::<opaque>() , 4usize);
assert_eq!(::std::mem::align_of::<opaque>() , 4usize);
}
+impl Clone for opaque {
+ fn clone(&self) -> Self { *self }
+}
#[repr(C)]
-pub struct Struct_container {
+#[derive(Debug, Copy)]
+pub struct container {
pub contained: u32,
}
#[test]
-fn bindgen_test_layout_Struct_container() {
- assert_eq!(::std::mem::size_of::<Struct_container>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_container>() , 4usize);
+fn bindgen_test_layout_container() {
+ assert_eq!(::std::mem::size_of::<container>() , 4usize);
+ assert_eq!(::std::mem::align_of::<container>() , 4usize);
+}
+impl Clone for container {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/opaque_pointer.rs b/tests/expectations/opaque_pointer.rs
index eb5f09cd..067f55bd 100644
--- a/tests/expectations/opaque_pointer.rs
+++ b/tests/expectations/opaque_pointer.rs
@@ -4,7 +4,11 @@
#![allow(non_snake_case)]
+/**
+ * <div rustbindgen opaque></div>
+ */
#[repr(C)]
+#[derive(Debug, Copy)]
pub struct OtherOpaque {
pub _bindgen_opaque_blob: u32,
}
@@ -13,16 +17,29 @@ fn bindgen_test_layout_OtherOpaque() {
assert_eq!(::std::mem::size_of::<OtherOpaque>() , 4usize);
assert_eq!(::std::mem::align_of::<OtherOpaque>() , 4usize);
}
+impl Clone for OtherOpaque {
+ fn clone(&self) -> Self { *self }
+}
+/**
+ * <div rustbindgen opaque></div>
+ */
#[repr(C)]
-pub struct Opaque;
+#[derive(Debug, Copy, Clone)]
+pub struct Opaque<T> {
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
#[repr(C)]
-pub struct Struct_WithOpaquePtr {
- pub whatever: u64,
+#[derive(Debug, Copy)]
+pub struct WithOpaquePtr {
+ pub whatever: *mut Opaque<::std::os::raw::c_int>,
pub other: u32,
pub t: u32,
}
#[test]
-fn bindgen_test_layout_Struct_WithOpaquePtr() {
- assert_eq!(::std::mem::size_of::<Struct_WithOpaquePtr>() , 16usize);
- assert_eq!(::std::mem::align_of::<Struct_WithOpaquePtr>() , 8usize);
+fn bindgen_test_layout_WithOpaquePtr() {
+ assert_eq!(::std::mem::size_of::<WithOpaquePtr>() , 16usize);
+ assert_eq!(::std::mem::align_of::<WithOpaquePtr>() , 8usize);
+}
+impl Clone for WithOpaquePtr {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/opaque_typedef.rs b/tests/expectations/opaque_typedef.rs
index a54ac881..c45cbc6f 100644
--- a/tests/expectations/opaque_typedef.rs
+++ b/tests/expectations/opaque_typedef.rs
@@ -6,11 +6,10 @@
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_RandomTemplate<T> {
- pub _phantom0: ::std::marker::PhantomData<T>,
+pub struct RandomTemplate<T> {
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
-pub enum Struct_Wat { }
-pub enum Struct_Wat3 { }
-#[repr(C)]
-pub struct ShouldBeOpaque;
-pub type ShouldNotBeOpaque = Struct_RandomTemplate<::std::os::raw::c_int>;
+/** <div rustbindgen opaque></div> */
+pub type ShouldBeOpaque = [u8; 0usize];
+pub type ShouldNotBeOpaque = RandomTemplate<f32>;
diff --git a/tests/expectations/overflowed_enum.rs b/tests/expectations/overflowed_enum.rs
index 2228e44b..9e1f8a7f 100644
--- a/tests/expectations/overflowed_enum.rs
+++ b/tests/expectations/overflowed_enum.rs
@@ -5,12 +5,12 @@
#[repr(u32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Foo {
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Foo {
BAP_ARM = 9698489,
BAP_X86 = 11960045,
BAP_X86_64 = 3128633167,
}
#[repr(u16)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_Bar { One = 1, Big = 2, }
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Bar { One = 1, Big = 2, }
diff --git a/tests/expectations/private.rs b/tests/expectations/private.rs
index 7263e3ee..c4ac37d1 100644
--- a/tests/expectations/private.rs
+++ b/tests/expectations/private.rs
@@ -6,47 +6,47 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_HasPrivate {
+pub struct HasPrivate {
pub mNotPrivate: ::std::os::raw::c_int,
/** <div rustbindgen private></div> */
mIsPrivate: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_HasPrivate {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_HasPrivate() {
- assert_eq!(::std::mem::size_of::<Struct_HasPrivate>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_HasPrivate>() , 4usize);
+fn bindgen_test_layout_HasPrivate() {
+ assert_eq!(::std::mem::size_of::<HasPrivate>() , 8usize);
+ assert_eq!(::std::mem::align_of::<HasPrivate>() , 4usize);
+}
+impl Clone for HasPrivate {
+ fn clone(&self) -> Self { *self }
}
/** <div rustbindgen private></div> */
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_VeryPrivate {
+pub struct VeryPrivate {
mIsPrivate: ::std::os::raw::c_int,
mIsAlsoPrivate: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_VeryPrivate {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_VeryPrivate() {
- assert_eq!(::std::mem::size_of::<Struct_VeryPrivate>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_VeryPrivate>() , 4usize);
+fn bindgen_test_layout_VeryPrivate() {
+ assert_eq!(::std::mem::size_of::<VeryPrivate>() , 8usize);
+ assert_eq!(::std::mem::align_of::<VeryPrivate>() , 4usize);
+}
+impl Clone for VeryPrivate {
+ fn clone(&self) -> Self { *self }
}
/** <div rustbindgen private></div> */
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_ContradictPrivate {
- /** <div rustbindgen private=false></div> */
- mNotPrivate: ::std::os::raw::c_int,
+pub struct ContradictPrivate {
+ /** <div rustbindgen private="false"></div> */
+ pub mNotPrivate: ::std::os::raw::c_int,
mIsPrivate: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_ContradictPrivate {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_ContradictPrivate() {
- assert_eq!(::std::mem::size_of::<Struct_ContradictPrivate>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_ContradictPrivate>() , 4usize);
+fn bindgen_test_layout_ContradictPrivate() {
+ assert_eq!(::std::mem::size_of::<ContradictPrivate>() , 8usize);
+ assert_eq!(::std::mem::align_of::<ContradictPrivate>() , 4usize);
+}
+impl Clone for ContradictPrivate {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/redeclaration.rs b/tests/expectations/redeclaration.rs
new file mode 100644
index 00000000..0d7e585c
--- /dev/null
+++ b/tests/expectations/redeclaration.rs
@@ -0,0 +1,9 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+extern "C" {
+ pub fn foo();
+}
diff --git a/tests/expectations/ref_argument_array.rs b/tests/expectations/ref_argument_array.rs
index 9660fbf2..5cfac9d8 100644
--- a/tests/expectations/ref_argument_array.rs
+++ b/tests/expectations/ref_argument_array.rs
@@ -6,22 +6,18 @@
pub const NSID_LENGTH: ::std::os::raw::c_uint = 10;
#[repr(C)]
-#[derive(Debug, Copy)]
-pub struct Struct_nsID {
- pub _vftable: *const _vftable_Struct_nsID,
+pub struct bindgen_vtable__bindgen_id_4 {
}
#[repr(C)]
-pub struct _vftable_Struct_nsID {
- pub ToProvidedString: unsafe extern "C" fn(this:
- *mut ::std::os::raw::c_void,
- aDest:
- *mut [::std::os::raw::c_char; 10usize]),
-}
-impl ::std::clone::Clone for Struct_nsID {
- fn clone(&self) -> Self { *self }
+#[derive(Debug, Copy)]
+pub struct nsID {
+ pub vtable_: *const bindgen_vtable__bindgen_id_4,
}
#[test]
-fn bindgen_test_layout_Struct_nsID() {
- assert_eq!(::std::mem::size_of::<Struct_nsID>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_nsID>() , 8usize);
+fn bindgen_test_layout_nsID() {
+ assert_eq!(::std::mem::size_of::<nsID>() , 8usize);
+ assert_eq!(::std::mem::align_of::<nsID>() , 8usize);
+}
+impl Clone for nsID {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/size_t_template.rs b/tests/expectations/size_t_template.rs
index 6f249ae5..78351ecc 100644
--- a/tests/expectations/size_t_template.rs
+++ b/tests/expectations/size_t_template.rs
@@ -5,12 +5,15 @@
#[repr(C)]
-#[derive(Debug)]
-pub struct Struct_C {
+#[derive(Debug, Copy)]
+pub struct C {
pub arr: [u32; 3usize],
}
#[test]
-fn bindgen_test_layout_Struct_C() {
- assert_eq!(::std::mem::size_of::<Struct_C>() , 12usize);
- assert_eq!(::std::mem::align_of::<Struct_C>() , 4usize);
+fn bindgen_test_layout_C() {
+ assert_eq!(::std::mem::size_of::<C>() , 12usize);
+ assert_eq!(::std::mem::align_of::<C>() , 4usize);
+}
+impl Clone for C {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/struct_containing_forward_declared_struct.rs b/tests/expectations/struct_containing_forward_declared_struct.rs
index 11ca55b8..388cc595 100644
--- a/tests/expectations/struct_containing_forward_declared_struct.rs
+++ b/tests/expectations/struct_containing_forward_declared_struct.rs
@@ -6,27 +6,27 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_a {
- pub val_a: *mut Struct_b,
-}
-impl ::std::clone::Clone for Struct_a {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Struct_a() {
- assert_eq!(::std::mem::size_of::<Struct_a>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_a>() , 8usize);
+pub struct a {
+ pub val_a: *mut a_b,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_b {
+pub struct a_b {
pub val_b: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_b {
+#[test]
+fn bindgen_test_layout_a_b() {
+ assert_eq!(::std::mem::size_of::<a_b>() , 4usize);
+ assert_eq!(::std::mem::align_of::<a_b>() , 4usize);
+}
+impl Clone for a_b {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_b() {
- assert_eq!(::std::mem::size_of::<Struct_b>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_b>() , 4usize);
+fn bindgen_test_layout_a() {
+ assert_eq!(::std::mem::size_of::<a>() , 8usize);
+ assert_eq!(::std::mem::align_of::<a>() , 8usize);
+}
+impl Clone for a {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/struct_with_anon_struct.rs b/tests/expectations/struct_with_anon_struct.rs
index 52495279..e28c4fc0 100644
--- a/tests/expectations/struct_with_anon_struct.rs
+++ b/tests/expectations/struct_with_anon_struct.rs
@@ -6,30 +6,30 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo {
- pub bar: Struct_foo_struct_with_anon_struct_h_unnamed_1,
+pub struct foo {
+ pub bar: foo__bindgen_ty_bindgen_id_2,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo_struct_with_anon_struct_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_2 {
pub a: ::std::os::raw::c_int,
pub b: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for Struct_foo_struct_with_anon_struct_h_unnamed_1 {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_foo_struct_with_anon_struct_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Struct_foo_struct_with_anon_struct_h_unnamed_1>()
- , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_struct_with_anon_struct_h_unnamed_1>()
- , 4usize);
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_2() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 8usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
}
-impl ::std::clone::Clone for Struct_foo {
+impl Clone for foo__bindgen_ty_bindgen_id_2 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_foo() {
- assert_eq!(::std::mem::size_of::<Struct_foo>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo>() , 4usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 8usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/struct_with_anon_struct_array.rs b/tests/expectations/struct_with_anon_struct_array.rs
index 19a16cd6..48cc71d2 100644
--- a/tests/expectations/struct_with_anon_struct_array.rs
+++ b/tests/expectations/struct_with_anon_struct_array.rs
@@ -6,49 +6,47 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo {
- pub bar: [Struct_foo_struct_with_anon_struct_array_h_unnamed_1; 2usize],
- pub baz: [[[Struct_foo_struct_with_anon_struct_array_h_unnamed_2; 4usize]; 3usize]; 2usize],
+pub struct foo {
+ pub bar: [foo__bindgen_ty_bindgen_id_2; 2usize],
+ pub baz: [[[foo__bindgen_ty_bindgen_id_6; 4usize]; 3usize]; 2usize],
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo_struct_with_anon_struct_array_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_2 {
pub a: ::std::os::raw::c_int,
pub b: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for
- Struct_foo_struct_with_anon_struct_array_h_unnamed_1 {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_foo_struct_with_anon_struct_array_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Struct_foo_struct_with_anon_struct_array_h_unnamed_1>()
- , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_struct_with_anon_struct_array_h_unnamed_1>()
- , 4usize);
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_2() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 8usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
+}
+impl Clone for foo__bindgen_ty_bindgen_id_2 {
+ fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo_struct_with_anon_struct_array_h_unnamed_2 {
+pub struct foo__bindgen_ty_bindgen_id_6 {
pub a: ::std::os::raw::c_int,
pub b: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for
- Struct_foo_struct_with_anon_struct_array_h_unnamed_2 {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_foo_struct_with_anon_struct_array_h_unnamed_2() {
- assert_eq!(::std::mem::size_of::<Struct_foo_struct_with_anon_struct_array_h_unnamed_2>()
- , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_struct_with_anon_struct_array_h_unnamed_2>()
- , 4usize);
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_6() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_6>() ,
+ 8usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_6>() ,
+ 4usize);
}
-impl ::std::clone::Clone for Struct_foo {
+impl Clone for foo__bindgen_ty_bindgen_id_6 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_foo() {
- assert_eq!(::std::mem::size_of::<Struct_foo>() , 208usize);
- assert_eq!(::std::mem::align_of::<Struct_foo>() , 4usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 208usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/struct_with_anon_struct_pointer.rs b/tests/expectations/struct_with_anon_struct_pointer.rs
index 84aa0f15..a4b693a7 100644
--- a/tests/expectations/struct_with_anon_struct_pointer.rs
+++ b/tests/expectations/struct_with_anon_struct_pointer.rs
@@ -6,31 +6,30 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo {
- pub bar: *mut Struct_foo_struct_with_anon_struct_pointer_h_unnamed_1,
+pub struct foo {
+ pub bar: *mut foo__bindgen_ty_bindgen_id_2,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo_struct_with_anon_struct_pointer_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_2 {
pub a: ::std::os::raw::c_int,
pub b: ::std::os::raw::c_int,
}
-impl ::std::clone::Clone for
- Struct_foo_struct_with_anon_struct_pointer_h_unnamed_1 {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_foo_struct_with_anon_struct_pointer_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Struct_foo_struct_with_anon_struct_pointer_h_unnamed_1>()
- , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_struct_with_anon_struct_pointer_h_unnamed_1>()
- , 4usize);
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_2() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 8usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
}
-impl ::std::clone::Clone for Struct_foo {
+impl Clone for foo__bindgen_ty_bindgen_id_2 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_foo() {
- assert_eq!(::std::mem::size_of::<Struct_foo>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo>() , 8usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 8usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 8usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/struct_with_anon_union.rs b/tests/expectations/struct_with_anon_union.rs
index 04883f78..889bccf7 100644
--- a/tests/expectations/struct_with_anon_union.rs
+++ b/tests/expectations/struct_with_anon_union.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,43 +23,34 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo {
- pub bar: Union_foo_struct_with_anon_union_h_unnamed_1,
+pub struct foo {
+ pub bar: foo__bindgen_ty_bindgen_id_2,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo_struct_with_anon_union_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_2 {
pub a: __BindgenUnionField<::std::os::raw::c_uint>,
pub b: __BindgenUnionField<::std::os::raw::c_ushort>,
- pub _bindgen_data_: u32,
+ pub bindgen_union_field: u32,
}
-impl Union_foo_struct_with_anon_union_h_unnamed_1 {
- pub unsafe fn a(&mut self) -> *mut ::std::os::raw::c_uint {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn b(&mut self) -> *mut ::std::os::raw::c_ushort {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_2() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
}
-impl ::std::clone::Clone for Union_foo_struct_with_anon_union_h_unnamed_1 {
+impl Clone for foo__bindgen_ty_bindgen_id_2 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Union_foo_struct_with_anon_union_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Union_foo_struct_with_anon_union_h_unnamed_1>()
- , 4usize);
- assert_eq!(::std::mem::align_of::<Union_foo_struct_with_anon_union_h_unnamed_1>()
- , 4usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 4usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
}
-impl ::std::clone::Clone for Struct_foo {
+impl Clone for foo {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Struct_foo() {
- assert_eq!(::std::mem::size_of::<Struct_foo>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_foo>() , 4usize);
-}
diff --git a/tests/expectations/struct_with_anon_unnamed_struct.rs b/tests/expectations/struct_with_anon_unnamed_struct.rs
index 6f7afeae..ca590b1b 100644
--- a/tests/expectations/struct_with_anon_unnamed_struct.rs
+++ b/tests/expectations/struct_with_anon_unnamed_struct.rs
@@ -6,31 +6,30 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo {
- pub foo_struct_with_anon_unnamed_struct_h_unnamed_1: Struct_foo_struct_with_anon_unnamed_struct_h_unnamed_1,
+pub struct foo {
+ pub __bindgen_anon_1: foo__bindgen_ty_bindgen_id_2,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo_struct_with_anon_unnamed_struct_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_2 {
pub a: ::std::os::raw::c_uint,
pub b: ::std::os::raw::c_uint,
}
-impl ::std::clone::Clone for
- Struct_foo_struct_with_anon_unnamed_struct_h_unnamed_1 {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_foo_struct_with_anon_unnamed_struct_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Struct_foo_struct_with_anon_unnamed_struct_h_unnamed_1>()
- , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_struct_with_anon_unnamed_struct_h_unnamed_1>()
- , 4usize);
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_2() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 8usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
}
-impl ::std::clone::Clone for Struct_foo {
+impl Clone for foo__bindgen_ty_bindgen_id_2 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_foo() {
- assert_eq!(::std::mem::size_of::<Struct_foo>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo>() , 4usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 8usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/struct_with_anon_unnamed_union.rs b/tests/expectations/struct_with_anon_unnamed_union.rs
index 73bd0111..013a9184 100644
--- a/tests/expectations/struct_with_anon_unnamed_union.rs
+++ b/tests/expectations/struct_with_anon_unnamed_union.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,44 +23,34 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo {
- pub foo_struct_with_anon_unnamed_union_h_unnamed_1: Union_foo_struct_with_anon_unnamed_union_h_unnamed_1,
+pub struct foo {
+ pub __bindgen_anon_1: foo__bindgen_ty_bindgen_id_2,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo_struct_with_anon_unnamed_union_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_2 {
pub a: __BindgenUnionField<::std::os::raw::c_uint>,
pub b: __BindgenUnionField<::std::os::raw::c_ushort>,
- pub _bindgen_data_: u32,
+ pub bindgen_union_field: u32,
}
-impl Union_foo_struct_with_anon_unnamed_union_h_unnamed_1 {
- pub unsafe fn a(&mut self) -> *mut ::std::os::raw::c_uint {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn b(&mut self) -> *mut ::std::os::raw::c_ushort {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_2() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
}
-impl ::std::clone::Clone for
- Union_foo_struct_with_anon_unnamed_union_h_unnamed_1 {
+impl Clone for foo__bindgen_ty_bindgen_id_2 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Union_foo_struct_with_anon_unnamed_union_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Union_foo_struct_with_anon_unnamed_union_h_unnamed_1>()
- , 4usize);
- assert_eq!(::std::mem::align_of::<Union_foo_struct_with_anon_unnamed_union_h_unnamed_1>()
- , 4usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 4usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
}
-impl ::std::clone::Clone for Struct_foo {
+impl Clone for foo {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Struct_foo() {
- assert_eq!(::std::mem::size_of::<Struct_foo>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_foo>() , 4usize);
-}
diff --git a/tests/expectations/struct_with_bitfields.rs b/tests/expectations/struct_with_bitfields.rs
index c2bfc543..3fb83a47 100644
--- a/tests/expectations/struct_with_bitfields.rs
+++ b/tests/expectations/struct_with_bitfields.rs
@@ -6,127 +6,117 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_bitfield {
- pub _bitfield_1: ::std::os::raw::c_ushort,
+pub struct bitfield {
+ pub _bitfield_1: u8,
pub e: ::std::os::raw::c_int,
- pub _bitfield_2: ::std::os::raw::c_uint,
- pub _bitfield_3: ::std::os::raw::c_uint,
+ pub _bitfield_2: u8,
+ pub _bitfield_3: u32,
}
-impl Struct_bitfield {
+#[test]
+fn bindgen_test_layout_bitfield() {
+ assert_eq!(::std::mem::size_of::<bitfield>() , 16usize);
+ assert_eq!(::std::mem::align_of::<bitfield>() , 4usize);
+}
+impl Clone for bitfield {
+ fn clone(&self) -> Self { *self }
+}
+impl bitfield {
#[inline]
pub fn a(&self) -> ::std::os::raw::c_ushort {
- (self._bitfield_1 & (1usize as ::std::os::raw::c_ushort)) >> 0usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (1usize as u8)) >>
+ 0u32) as u16)
+ }
}
#[inline]
- pub fn set_a(&mut self, val: bool) {
- self._bitfield_1 &= !(1usize as ::std::os::raw::c_ushort);
- self._bitfield_1 |=
- ((val as ::std::os::raw::c_ushort) << 0usize) &
- (1usize as ::std::os::raw::c_ushort);
+ pub fn set_a(&mut self, val: ::std::os::raw::c_ushort) {
+ self._bitfield_1 &= !(1usize as u8);
+ self._bitfield_1 |= ((val as u16 as u8) << 0u32) & (1usize as u8);
}
#[inline]
pub fn b(&self) -> ::std::os::raw::c_ushort {
- (self._bitfield_1 & (2usize as ::std::os::raw::c_ushort)) >> 1usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (2usize as u8)) >>
+ 1u32) as u16)
+ }
}
#[inline]
- pub fn set_b(&mut self, val: bool) {
- self._bitfield_1 &= !(2usize as ::std::os::raw::c_ushort);
- self._bitfield_1 |=
- ((val as ::std::os::raw::c_ushort) << 1usize) &
- (2usize as ::std::os::raw::c_ushort);
+ pub fn set_b(&mut self, val: ::std::os::raw::c_ushort) {
+ self._bitfield_1 &= !(2usize as u8);
+ self._bitfield_1 |= ((val as u16 as u8) << 1u32) & (2usize as u8);
}
#[inline]
pub fn c(&self) -> ::std::os::raw::c_ushort {
- (self._bitfield_1 & (4usize as ::std::os::raw::c_ushort)) >> 2usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (4usize as u8)) >>
+ 2u32) as u16)
+ }
}
#[inline]
- pub fn set_c(&mut self, val: bool) {
- self._bitfield_1 &= !(4usize as ::std::os::raw::c_ushort);
- self._bitfield_1 |=
- ((val as ::std::os::raw::c_ushort) << 2usize) &
- (4usize as ::std::os::raw::c_ushort);
+ pub fn set_c(&mut self, val: ::std::os::raw::c_ushort) {
+ self._bitfield_1 &= !(4usize as u8);
+ self._bitfield_1 |= ((val as u16 as u8) << 2u32) & (4usize as u8);
}
#[inline]
pub fn at_offset_3(&self) -> ::std::os::raw::c_ushort {
- (self._bitfield_1 & (8usize as ::std::os::raw::c_ushort)) >> 3usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (8usize as u8)) >>
+ 3u32) as u16)
+ }
}
#[inline]
- pub fn set_at_offset_3(&mut self, val: bool) {
- self._bitfield_1 &= !(8usize as ::std::os::raw::c_ushort);
- self._bitfield_1 |=
- ((val as ::std::os::raw::c_ushort) << 3usize) &
- (8usize as ::std::os::raw::c_ushort);
+ pub fn set_at_offset_3(&mut self, val: ::std::os::raw::c_ushort) {
+ self._bitfield_1 &= !(8usize as u8);
+ self._bitfield_1 |= ((val as u16 as u8) << 3u32) & (8usize as u8);
}
#[inline]
pub fn at_offset_4(&self) -> ::std::os::raw::c_ushort {
- (self._bitfield_1 & (48usize as ::std::os::raw::c_ushort)) >> 4usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (48usize as u8)) >>
+ 4u32) as u16)
+ }
}
#[inline]
- pub fn set_at_offset_4(&mut self, val: u8) {
- self._bitfield_1 &= !(48usize as ::std::os::raw::c_ushort);
- self._bitfield_1 |=
- ((val as ::std::os::raw::c_ushort) << 4usize) &
- (48usize as ::std::os::raw::c_ushort);
+ pub fn set_at_offset_4(&mut self, val: ::std::os::raw::c_ushort) {
+ self._bitfield_1 &= !(48usize as u8);
+ self._bitfield_1 |= ((val as u16 as u8) << 4u32) & (48usize as u8);
}
#[inline]
pub fn d(&self) -> ::std::os::raw::c_ushort {
- (self._bitfield_1 & (192usize as ::std::os::raw::c_ushort)) >> 6usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (192usize as u8)) >>
+ 6u32) as u16)
+ }
}
#[inline]
- pub fn set_d(&mut self, val: u8) {
- self._bitfield_1 &= !(192usize as ::std::os::raw::c_ushort);
- self._bitfield_1 |=
- ((val as ::std::os::raw::c_ushort) << 6usize) &
- (192usize as ::std::os::raw::c_ushort);
- }
- #[inline]
- pub fn new_bitfield_1(a: bool, b: bool, c: bool, unnamed_bitfield1: bool,
- unnamed_bitfield2: u8, d: u8)
- -> ::std::os::raw::c_ushort {
- 0 | ((a as ::std::os::raw::c_ushort) << 0u32) |
- ((b as ::std::os::raw::c_ushort) << 1u32) |
- ((c as ::std::os::raw::c_ushort) << 2u32) |
- ((unnamed_bitfield1 as ::std::os::raw::c_ushort) << 3u32) |
- ((unnamed_bitfield2 as ::std::os::raw::c_ushort) << 4u32) |
- ((d as ::std::os::raw::c_ushort) << 6u32)
+ pub fn set_d(&mut self, val: ::std::os::raw::c_ushort) {
+ self._bitfield_1 &= !(192usize as u8);
+ self._bitfield_1 |= ((val as u16 as u8) << 6u32) & (192usize as u8);
}
#[inline]
pub fn f(&self) -> ::std::os::raw::c_uint {
- (self._bitfield_2 & (3usize as ::std::os::raw::c_uint)) >> 0usize
- }
- #[inline]
- pub fn set_f(&mut self, val: u8) {
- self._bitfield_2 &= !(3usize as ::std::os::raw::c_uint);
- self._bitfield_2 |=
- ((val as ::std::os::raw::c_uint) << 0usize) &
- (3usize as ::std::os::raw::c_uint);
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_2 & (3usize as u8)) >>
+ 0u32) as u32)
+ }
}
#[inline]
- pub fn new_bitfield_2(f: u8) -> ::std::os::raw::c_uint {
- 0 | ((f as ::std::os::raw::c_uint) << 0u32)
+ pub fn set_f(&mut self, val: ::std::os::raw::c_uint) {
+ self._bitfield_2 &= !(3usize as u8);
+ self._bitfield_2 |= ((val as u32 as u8) << 0u32) & (3usize as u8);
}
#[inline]
pub fn g(&self) -> ::std::os::raw::c_uint {
- (self._bitfield_3 & (4294967295usize as ::std::os::raw::c_uint)) >>
- 0usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_3 &
+ (4294967295usize as u32)) >> 0u32) as
+ u32)
+ }
}
#[inline]
- pub fn set_g(&mut self, val: u32) {
- self._bitfield_3 &= !(4294967295usize as ::std::os::raw::c_uint);
+ pub fn set_g(&mut self, val: ::std::os::raw::c_uint) {
+ self._bitfield_3 &= !(4294967295usize as u32);
self._bitfield_3 |=
- ((val as ::std::os::raw::c_uint) << 0usize) &
- (4294967295usize as ::std::os::raw::c_uint);
- }
- #[inline]
- pub fn new_bitfield_3(g: u32) -> ::std::os::raw::c_uint {
- 0 | ((g as ::std::os::raw::c_uint) << 0u32)
+ ((val as u32 as u32) << 0u32) & (4294967295usize as u32);
}
}
-impl ::std::clone::Clone for Struct_bitfield {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Struct_bitfield() {
- assert_eq!(::std::mem::size_of::<Struct_bitfield>() , 16usize);
- assert_eq!(::std::mem::align_of::<Struct_bitfield>() , 4usize);
-}
diff --git a/tests/expectations/struct_with_derive_debug.rs b/tests/expectations/struct_with_derive_debug.rs
index f89d9d72..52906a81 100644
--- a/tests/expectations/struct_with_derive_debug.rs
+++ b/tests/expectations/struct_with_derive_debug.rs
@@ -6,53 +6,45 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_LittleArray {
+pub struct LittleArray {
pub a: [::std::os::raw::c_int; 32usize],
}
-impl ::std::clone::Clone for Struct_LittleArray {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_LittleArray() {
- assert_eq!(::std::mem::size_of::<Struct_LittleArray>() , 128usize);
- assert_eq!(::std::mem::align_of::<Struct_LittleArray>() , 4usize);
+fn bindgen_test_layout_LittleArray() {
+ assert_eq!(::std::mem::size_of::<LittleArray>() , 128usize);
+ assert_eq!(::std::mem::align_of::<LittleArray>() , 4usize);
+}
+impl Clone for LittleArray {
+ fn clone(&self) -> Self { *self }
}
#[repr(C)]
-#[derive(Copy)]
-pub struct Struct_BigArray {
+pub struct BigArray {
pub a: [::std::os::raw::c_int; 33usize],
}
-impl ::std::clone::Clone for Struct_BigArray {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_BigArray() {
- assert_eq!(::std::mem::size_of::<Struct_BigArray>() , 132usize);
- assert_eq!(::std::mem::align_of::<Struct_BigArray>() , 4usize);
+fn bindgen_test_layout_BigArray() {
+ assert_eq!(::std::mem::size_of::<BigArray>() , 132usize);
+ assert_eq!(::std::mem::align_of::<BigArray>() , 4usize);
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_WithLittleArray {
- pub a: Struct_LittleArray,
-}
-impl ::std::clone::Clone for Struct_WithLittleArray {
- fn clone(&self) -> Self { *self }
+pub struct WithLittleArray {
+ pub a: LittleArray,
}
#[test]
-fn bindgen_test_layout_Struct_WithLittleArray() {
- assert_eq!(::std::mem::size_of::<Struct_WithLittleArray>() , 128usize);
- assert_eq!(::std::mem::align_of::<Struct_WithLittleArray>() , 4usize);
-}
-#[repr(C)]
-#[derive(Copy)]
-pub struct Struct_WithBigArray {
- pub a: Struct_BigArray,
+fn bindgen_test_layout_WithLittleArray() {
+ assert_eq!(::std::mem::size_of::<WithLittleArray>() , 128usize);
+ assert_eq!(::std::mem::align_of::<WithLittleArray>() , 4usize);
}
-impl ::std::clone::Clone for Struct_WithBigArray {
+impl Clone for WithLittleArray {
fn clone(&self) -> Self { *self }
}
+#[repr(C)]
+pub struct WithBigArray {
+ pub a: BigArray,
+}
#[test]
-fn bindgen_test_layout_Struct_WithBigArray() {
- assert_eq!(::std::mem::size_of::<Struct_WithBigArray>() , 132usize);
- assert_eq!(::std::mem::align_of::<Struct_WithBigArray>() , 4usize);
+fn bindgen_test_layout_WithBigArray() {
+ assert_eq!(::std::mem::size_of::<WithBigArray>() , 132usize);
+ assert_eq!(::std::mem::align_of::<WithBigArray>() , 4usize);
}
diff --git a/tests/expectations/struct_with_nesting.rs b/tests/expectations/struct_with_nesting.rs
index 2de481ea..ca5ec09e 100644
--- a/tests/expectations/struct_with_nesting.rs
+++ b/tests/expectations/struct_with_nesting.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,89 +23,70 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo {
+pub struct foo {
pub a: ::std::os::raw::c_uint,
- pub foo_struct_with_nesting_h_unnamed_1: Union_foo_struct_with_nesting_h_unnamed_1,
+ pub __bindgen_anon_1: foo__bindgen_ty_bindgen_id_3,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo_struct_with_nesting_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_3 {
pub b: __BindgenUnionField<::std::os::raw::c_uint>,
- pub foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_2: __BindgenUnionField<Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_2>,
- pub foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_3: __BindgenUnionField<Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_3>,
- pub _bindgen_data_: u32,
-}
-impl Union_foo_struct_with_nesting_h_unnamed_1 {
- pub unsafe fn b(&mut self) -> *mut ::std::os::raw::c_uint {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_2(&mut self)
- ->
- *mut Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_2 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_3(&mut self)
- ->
- *mut Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_3 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for Union_foo_struct_with_nesting_h_unnamed_1 {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Union_foo_struct_with_nesting_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Union_foo_struct_with_nesting_h_unnamed_1>()
- , 4usize);
- assert_eq!(::std::mem::align_of::<Union_foo_struct_with_nesting_h_unnamed_1>()
- , 4usize);
+ pub __bindgen_anon_1: __BindgenUnionField<foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_5>,
+ pub __bindgen_anon_2: __BindgenUnionField<foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_8>,
+ pub bindgen_union_field: u32,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_2 {
+pub struct foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_5 {
pub c1: ::std::os::raw::c_ushort,
pub c2: ::std::os::raw::c_ushort,
}
-impl ::std::clone::Clone for
- Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_2 {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_2() {
- assert_eq!(::std::mem::size_of::<Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_2>()
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_5() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_5>()
, 4usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_2>()
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_5>()
, 2usize);
}
+impl Clone for foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_5 {
+ fn clone(&self) -> Self { *self }
+}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_3 {
+pub struct foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_8 {
pub d1: ::std::os::raw::c_uchar,
pub d2: ::std::os::raw::c_uchar,
pub d3: ::std::os::raw::c_uchar,
pub d4: ::std::os::raw::c_uchar,
}
-impl ::std::clone::Clone for
- Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_3 {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_3() {
- assert_eq!(::std::mem::size_of::<Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_3>()
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_8() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_8>()
, 4usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_struct_with_nesting_h_unnamed_1_struct_with_nesting_h_unnamed_3>()
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_8>()
, 1usize);
}
-impl ::std::clone::Clone for Struct_foo {
+impl Clone for foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_8 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_foo() {
- assert_eq!(::std::mem::size_of::<Struct_foo>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo>() , 4usize);
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_3() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_3>() ,
+ 4usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_3>() ,
+ 4usize);
+}
+impl Clone for foo__bindgen_ty_bindgen_id_3 {
+ fn clone(&self) -> Self { *self }
+}
+#[test]
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 8usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/struct_with_packing.rs b/tests/expectations/struct_with_packing.rs
index 9f997435..93fc3f11 100644
--- a/tests/expectations/struct_with_packing.rs
+++ b/tests/expectations/struct_with_packing.rs
@@ -6,15 +6,15 @@
#[repr(C, packed)]
#[derive(Debug, Copy)]
-pub struct Struct_a {
+pub struct a {
pub b: ::std::os::raw::c_char,
pub c: ::std::os::raw::c_short,
}
-impl ::std::clone::Clone for Struct_a {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_a() {
- assert_eq!(::std::mem::size_of::<Struct_a>() , 3usize);
- assert_eq!(::std::mem::align_of::<Struct_a>() , 1usize);
+fn bindgen_test_layout_a() {
+ assert_eq!(::std::mem::size_of::<a>() , 3usize);
+ assert_eq!(::std::mem::align_of::<a>() , 1usize);
+}
+impl Clone for a {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/struct_with_struct.rs b/tests/expectations/struct_with_struct.rs
index 0c6ab122..27ff4795 100644
--- a/tests/expectations/struct_with_struct.rs
+++ b/tests/expectations/struct_with_struct.rs
@@ -6,30 +6,30 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo {
- pub bar: Struct_foo_struct_with_struct_h_unnamed_1,
+pub struct foo {
+ pub bar: foo__bindgen_ty_bindgen_id_2,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo_struct_with_struct_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_2 {
pub x: ::std::os::raw::c_uint,
pub y: ::std::os::raw::c_uint,
}
-impl ::std::clone::Clone for Struct_foo_struct_with_struct_h_unnamed_1 {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_foo_struct_with_struct_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Struct_foo_struct_with_struct_h_unnamed_1>()
- , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_struct_with_struct_h_unnamed_1>()
- , 4usize);
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_2() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 8usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
}
-impl ::std::clone::Clone for Struct_foo {
+impl Clone for foo__bindgen_ty_bindgen_id_2 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_foo() {
- assert_eq!(::std::mem::size_of::<Struct_foo>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo>() , 4usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 8usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/template.rs b/tests/expectations/template.rs
index 2f3f9a21..76afc879 100644
--- a/tests/expectations/template.rs
+++ b/tests/expectations/template.rs
@@ -6,110 +6,129 @@
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_Foo<T, U> {
+pub struct Foo<T, U> {
pub m_member: T,
pub m_member_ptr: *mut T,
pub m_member_arr: [T; 1usize],
- pub _phantom0: ::std::marker::PhantomData<U>,
+ pub _phantom_1: ::std::marker::PhantomData<U>,
+}
+extern "C" {
+ #[link_name = "_Z3bar3FooIiiE"]
+ pub fn bar(foo: Foo<::std::os::raw::c_int, ::std::os::raw::c_int>);
}
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_D<T> {
- pub m_foo: Struct_Foo<::std::os::raw::c_int, ::std::os::raw::c_int>,
- pub _phantom0: ::std::marker::PhantomData<T>,
+pub struct D<T> {
+ 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>;
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_D_U<T, Z> {
- pub m_nested_foo: Struct_Foo<::std::os::raw::c_int,
- ::std::os::raw::c_int>,
+pub struct D_U<T, Z> {
+ pub m_nested_foo: D_MyFoo,
pub m_baz: Z,
- pub _phantom0: ::std::marker::PhantomData<T>,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_Rooted<T> {
+pub struct Rooted<T> {
pub prev: *mut T,
- pub next: *mut Struct_Rooted<*mut ::std::os::raw::c_void>,
+ pub next: *mut Rooted<*mut ::std::os::raw::c_void>,
pub ptr: T,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_RootedContainer {
- pub root: Struct_Rooted<*mut ::std::os::raw::c_void>,
-}
-impl ::std::clone::Clone for Struct_RootedContainer {
- fn clone(&self) -> Self { *self }
+pub struct RootedContainer {
+ pub root: Rooted<*mut ::std::os::raw::c_void>,
}
#[test]
-fn bindgen_test_layout_Struct_RootedContainer() {
- assert_eq!(::std::mem::size_of::<Struct_RootedContainer>() , 24usize);
- assert_eq!(::std::mem::align_of::<Struct_RootedContainer>() , 8usize);
+fn bindgen_test_layout_RootedContainer() {
+ assert_eq!(::std::mem::size_of::<RootedContainer>() , 24usize);
+ assert_eq!(::std::mem::align_of::<RootedContainer>() , 8usize);
+}
+impl Clone for RootedContainer {
+ fn clone(&self) -> Self { *self }
}
-pub type WithDtorIntFwd = Struct_WithDtor<::std::os::raw::c_int>;
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_WithDtor<T> {
+pub struct WithDtor<T> {
pub member: T,
}
+pub type WithDtorIntFwd = WithDtor<::std::os::raw::c_int>;
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_PODButContainsDtor {
+pub struct PODButContainsDtor {
pub member: WithDtorIntFwd,
}
#[test]
-fn bindgen_test_layout_Struct_PODButContainsDtor() {
- assert_eq!(::std::mem::size_of::<Struct_PODButContainsDtor>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_PODButContainsDtor>() , 4usize);
+fn bindgen_test_layout_PODButContainsDtor() {
+ assert_eq!(::std::mem::size_of::<PODButContainsDtor>() , 4usize);
+ assert_eq!(::std::mem::align_of::<PODButContainsDtor>() , 4usize);
}
+/** <div rustbindgen opaque> */
#[repr(C)]
-pub struct Opaque;
+#[derive(Debug, Copy, Clone)]
+pub struct Opaque<T> {
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
#[repr(C)]
-pub struct Struct_POD {
+#[derive(Debug, Copy)]
+pub struct POD {
pub opaque_member: u32,
}
#[test]
-fn bindgen_test_layout_Struct_POD() {
- assert_eq!(::std::mem::size_of::<Struct_POD>() , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_POD>() , 4usize);
+fn bindgen_test_layout_POD() {
+ assert_eq!(::std::mem::size_of::<POD>() , 4usize);
+ assert_eq!(::std::mem::align_of::<POD>() , 4usize);
}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct Struct_NestedBase<T, U> {
- pub buff: *mut T,
- pub _phantom0: ::std::marker::PhantomData<U>,
+impl Clone for POD {
+ fn clone(&self) -> Self { *self }
}
/**
* <div rustbindgen replaces="NestedReplaced"></div>
*/
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_NestedReplaced<T> {
+pub struct NestedReplaced<T> {
pub buff: *mut T,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_NestedContainer<T> {
- pub c: T,
- pub nested: Struct_NestedReplaced<T>,
- pub inc: Struct_Incomplete<T>,
+pub struct NestedBase<T, U> {
+ pub buff: *mut T,
+ pub _phantom_1: ::std::marker::PhantomData<U>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_Incomplete<T> {
+pub struct Incomplete<T> {
pub d: T,
}
#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct NestedContainer<T> {
+ pub c: T,
+ pub nested: NestedReplaced<T>,
+ pub inc: Incomplete<T>,
+}
+#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_Untemplated;
-impl ::std::clone::Clone for Struct_Untemplated {
+pub struct Untemplated {
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_Untemplated() {
+ assert_eq!(::std::mem::size_of::<Untemplated>() , 1usize);
+ assert_eq!(::std::mem::align_of::<Untemplated>() , 1usize);
+}
+impl Clone for Untemplated {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_Templated<T> {
- pub m_untemplated: Struct_Untemplated,
- pub _phantom0: ::std::marker::PhantomData<T>,
+pub struct Templated<T> {
+ pub m_untemplated: Untemplated,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
/**
* If the replacement doesn't happen at the parse level the container would be
@@ -119,9 +138,19 @@ pub struct Struct_Templated<T> {
*/
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_ReplacedWithoutDestructor<T> {
+pub struct ReplacedWithoutDestructor<T> {
pub buff: *mut T,
}
+#[repr(C)]
+#[derive(Debug)]
+pub struct ShouldNotBeCopiable<T> {
+ pub m_member: ReplacedWithoutDestructor<T>,
+}
+#[repr(C)]
+#[derive(Debug)]
+pub struct ShouldNotBeCopiableAsWell<U> {
+ pub m_member: ReplacedWithoutDestructorFwd<U>,
+}
/**
* If the replacement doesn't happen at the parse level the container would be
* copy and the replacement wouldn't, so this wouldn't compile.
@@ -130,25 +159,12 @@ pub struct Struct_ReplacedWithoutDestructor<T> {
*/
#[repr(C)]
#[derive(Debug)]
-pub struct Struct_ReplacedWithoutDestructorFwd<T> {
+pub struct ReplacedWithoutDestructorFwd<T> {
pub buff: *mut T,
}
#[repr(C)]
-#[derive(Debug)]
-pub struct Struct_ShouldNotBeCopiable<T> {
- pub m_member: Struct_ReplacedWithoutDestructor<T>,
-}
-#[repr(C)]
-#[derive(Debug)]
-pub struct Struct_ShouldNotBeCopiableAsWell<U> {
- pub m_member: Struct_ReplacedWithoutDestructorFwd<U>,
-}
-#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_TemplateWithVar<T> {
- pub _phantom0: ::std::marker::PhantomData<T>,
-}
-extern "C" {
- #[link_name = "_Z3bar3FooIiiE"]
- pub fn bar(foo: Struct_Foo<::std::os::raw::c_int, ::std::os::raw::c_int>);
+pub struct TemplateWithVar<T> {
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
diff --git a/tests/expectations/typeref.rs b/tests/expectations/typeref.rs
new file mode 100644
index 00000000..35a873c9
--- /dev/null
+++ b/tests/expectations/typeref.rs
@@ -0,0 +1,92 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[derive(Debug)]
+#[repr(C)]
+pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
+impl <T> __BindgenUnionField<T> {
+ #[inline]
+ pub fn new() -> Self { __BindgenUnionField(::std::marker::PhantomData) }
+ #[inline]
+ pub unsafe fn as_ref(&self) -> &T { ::std::mem::transmute(self) }
+ #[inline]
+ pub unsafe fn as_mut(&mut self) -> &mut T { ::std::mem::transmute(self) }
+}
+impl <T> ::std::default::Default for __BindgenUnionField<T> {
+ #[inline]
+ fn default() -> Self { Self::new() }
+}
+impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
+ #[inline]
+ fn clone(&self) -> Self { Self::new() }
+}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct nsFoo {
+ pub mBar: StyleShapeSource<::std::os::raw::c_int>,
+}
+#[test]
+fn bindgen_test_layout_nsFoo() {
+ assert_eq!(::std::mem::size_of::<nsFoo>() , 8usize);
+ assert_eq!(::std::mem::align_of::<nsFoo>() , 8usize);
+}
+impl Clone for nsFoo {
+ fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct FragmentOrURL {
+ pub mIsLocalRef: bool,
+}
+#[test]
+fn bindgen_test_layout_FragmentOrURL() {
+ assert_eq!(::std::mem::size_of::<FragmentOrURL>() , 1usize);
+ assert_eq!(::std::mem::align_of::<FragmentOrURL>() , 1usize);
+}
+impl Clone for FragmentOrURL {
+ fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Position {
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_Position() {
+ assert_eq!(::std::mem::size_of::<Position>() , 1usize);
+ assert_eq!(::std::mem::align_of::<Position>() , 1usize);
+}
+impl Clone for Position {
+ fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Bar {
+ pub mFoo: *mut nsFoo,
+}
+#[test]
+fn bindgen_test_layout_Bar() {
+ assert_eq!(::std::mem::size_of::<Bar>() , 8usize);
+ assert_eq!(::std::mem::align_of::<Bar>() , 8usize);
+}
+impl Clone for Bar {
+ fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct StyleShapeSource<ReferenceBox> {
+ pub __bindgen_anon_1: StyleShapeSource__bindgen_ty_bindgen_id_13<ReferenceBox>,
+ pub _phantom_0: ::std::marker::PhantomData<ReferenceBox>,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct StyleShapeSource__bindgen_ty_bindgen_id_13<ReferenceBox> {
+ pub mPosition: __BindgenUnionField<*mut Position>,
+ pub mFragmentOrURL: __BindgenUnionField<*mut FragmentOrURL>,
+ pub bindgen_union_field: u64,
+ pub _phantom_0: ::std::marker::PhantomData<ReferenceBox>,
+}
diff --git a/tests/expectations/union_dtor.rs b/tests/expectations/union_dtor.rs
index c1e260da..4d1fa25a 100644
--- a/tests/expectations/union_dtor.rs
+++ b/tests/expectations/union_dtor.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,25 +23,16 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug)]
-pub struct Union_UnionWithDtor {
+pub struct UnionWithDtor {
pub mFoo: __BindgenUnionField<::std::os::raw::c_int>,
pub mBar: __BindgenUnionField<*mut ::std::os::raw::c_void>,
- pub _bindgen_data_: u64,
-}
-impl Union_UnionWithDtor {
- pub unsafe fn mFoo(&mut self) -> *mut ::std::os::raw::c_int {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn mBar(&mut self) -> *mut *mut ::std::os::raw::c_void {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+ pub bindgen_union_field: u64,
}
#[test]
-fn bindgen_test_layout_Union_UnionWithDtor() {
- assert_eq!(::std::mem::size_of::<Union_UnionWithDtor>() , 8usize);
- assert_eq!(::std::mem::align_of::<Union_UnionWithDtor>() , 8usize);
+fn bindgen_test_layout_UnionWithDtor() {
+ assert_eq!(::std::mem::size_of::<UnionWithDtor>() , 8usize);
+ assert_eq!(::std::mem::align_of::<UnionWithDtor>() , 8usize);
}
diff --git a/tests/expectations/union_fields.rs b/tests/expectations/union_fields.rs
index 1a957eaa..684a9e04 100644
--- a/tests/expectations/union_fields.rs
+++ b/tests/expectations/union_fields.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,36 +23,21 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_union_fields_hpp_unnamed_1 {
+pub struct _bindgen_ty_bindgen_id_1 {
pub mInt: __BindgenUnionField<::std::os::raw::c_int>,
pub mFloat: __BindgenUnionField<f32>,
pub mPointer: __BindgenUnionField<*mut ::std::os::raw::c_void>,
- pub _bindgen_data_: u64,
+ pub bindgen_union_field: u64,
}
-impl Union_union_fields_hpp_unnamed_1 {
- pub unsafe fn mInt(&mut self) -> *mut ::std::os::raw::c_int {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn mFloat(&mut self) -> *mut f32 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn mPointer(&mut self) -> *mut *mut ::std::os::raw::c_void {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout__bindgen_ty_bindgen_id_1() {
+ assert_eq!(::std::mem::size_of::<_bindgen_ty_bindgen_id_1>() , 8usize);
+ assert_eq!(::std::mem::align_of::<_bindgen_ty_bindgen_id_1>() , 8usize);
}
-impl ::std::clone::Clone for Union_union_fields_hpp_unnamed_1 {
+impl Clone for _bindgen_ty_bindgen_id_1 {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Union_union_fields_hpp_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Union_union_fields_hpp_unnamed_1>() ,
- 8usize);
- assert_eq!(::std::mem::align_of::<Union_union_fields_hpp_unnamed_1>() ,
- 8usize);
-}
-pub type nsStyleUnion = Union_union_fields_hpp_unnamed_1;
+pub type nsStyleUnion = _bindgen_ty_bindgen_id_1;
diff --git a/tests/expectations/union_template.rs b/tests/expectations/union_template.rs
index eb6705f0..f07087de 100644
--- a/tests/expectations/union_template.rs
+++ b/tests/expectations/union_template.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,64 +23,36 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_NastyStruct<T> {
+pub struct NastyStruct<T> {
pub mIsSome: bool,
- pub mStorage: Union_NastyStruct_union_template_hpp_unnamed_1<T>,
- pub NastyStruct_union_template_hpp_unnamed_2: Union_NastyStruct_union_template_hpp_unnamed_2<T>,
+ pub mStorage: NastyStruct__bindgen_ty_bindgen_id_5<T>,
+ pub __bindgen_anon_1: NastyStruct__bindgen_ty_bindgen_id_9<T>,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Union_NastyStruct_union_template_hpp_unnamed_1<T> {
+pub struct NastyStruct__bindgen_ty_bindgen_id_5<T> {
pub mFoo: __BindgenUnionField<*mut ::std::os::raw::c_void>,
pub mDummy: __BindgenUnionField<::std::os::raw::c_ulong>,
- pub _bindgen_data_: u64,
- pub _phantom0: ::std::marker::PhantomData<T>,
-}
-impl <T> Union_NastyStruct_union_template_hpp_unnamed_1<T> {
- pub unsafe fn mFoo(&mut self) -> *mut *mut ::std::os::raw::c_void {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn mDummy(&mut self) -> *mut ::std::os::raw::c_ulong {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+ pub bindgen_union_field: u64,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Union_NastyStruct_union_template_hpp_unnamed_2<T> {
+pub struct NastyStruct__bindgen_ty_bindgen_id_9<T> {
pub wat: __BindgenUnionField<::std::os::raw::c_short>,
pub wut: __BindgenUnionField<*mut ::std::os::raw::c_int>,
- pub _bindgen_data_: u64,
- pub _phantom0: ::std::marker::PhantomData<T>,
-}
-impl <T> Union_NastyStruct_union_template_hpp_unnamed_2<T> {
- pub unsafe fn wat(&mut self) -> *mut ::std::os::raw::c_short {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn wut(&mut self) -> *mut *mut ::std::os::raw::c_int {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+ pub bindgen_union_field: u64,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Union_Whatever<T> {
+pub struct Whatever<T> {
pub mTPtr: __BindgenUnionField<*mut ::std::os::raw::c_void>,
pub mInt: __BindgenUnionField<::std::os::raw::c_int>,
- pub _bindgen_data_: u64,
- pub _phantom0: ::std::marker::PhantomData<T>,
-}
-impl <T> Union_Whatever<T> {
- pub unsafe fn mTPtr(&mut self) -> *mut *mut ::std::os::raw::c_void {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn mInt(&mut self) -> *mut ::std::os::raw::c_int {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+ pub bindgen_union_field: u64,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
}
diff --git a/tests/expectations/union_with_anon_struct.rs b/tests/expectations/union_with_anon_struct.rs
index 850f39bc..f216b0bf 100644
--- a/tests/expectations/union_with_anon_struct.rs
+++ b/tests/expectations/union_with_anon_struct.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,40 +23,34 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo {
- pub bar: __BindgenUnionField<Struct_foo_union_with_anon_struct_h_unnamed_1>,
- pub _bindgen_data_: [u32; 2usize],
-}
-impl Union_foo {
- pub unsafe fn bar(&mut self)
- -> *mut Struct_foo_union_with_anon_struct_h_unnamed_1 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for Union_foo {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Union_foo() {
- assert_eq!(::std::mem::size_of::<Union_foo>() , 8usize);
- assert_eq!(::std::mem::align_of::<Union_foo>() , 4usize);
+pub struct foo {
+ pub bar: __BindgenUnionField<foo__bindgen_ty_bindgen_id_2>,
+ pub bindgen_union_field: [u32; 2usize],
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo_union_with_anon_struct_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_2 {
pub a: ::std::os::raw::c_uint,
pub b: ::std::os::raw::c_uint,
}
-impl ::std::clone::Clone for Struct_foo_union_with_anon_struct_h_unnamed_1 {
+#[test]
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_2() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 8usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
+}
+impl Clone for foo__bindgen_ty_bindgen_id_2 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_foo_union_with_anon_struct_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Struct_foo_union_with_anon_struct_h_unnamed_1>()
- , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_union_with_anon_struct_h_unnamed_1>()
- , 4usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 8usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/union_with_anon_struct_bitfield.rs b/tests/expectations/union_with_anon_struct_bitfield.rs
index ce59836e..80be0e55 100644
--- a/tests/expectations/union_with_anon_struct_bitfield.rs
+++ b/tests/expectations/union_with_anon_struct_bitfield.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,75 +23,62 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo {
+pub struct foo {
pub a: __BindgenUnionField<::std::os::raw::c_int>,
- pub foo_union_with_anon_struct_bitfield_h_unnamed_1: __BindgenUnionField<Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1>,
- pub _bindgen_data_: u32,
+ pub __bindgen_anon_1: __BindgenUnionField<foo__bindgen_ty_bindgen_id_3>,
+ pub bindgen_union_field: u32,
}
-impl Union_foo {
- pub unsafe fn a(&mut self) -> *mut ::std::os::raw::c_int {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn foo_union_with_anon_struct_bitfield_h_unnamed_1(&mut self)
- -> *mut Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for Union_foo {
- fn clone(&self) -> Self { *self }
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct foo__bindgen_ty_bindgen_id_3 {
+ pub _bitfield_1: u32,
}
#[test]
-fn bindgen_test_layout_Union_foo() {
- assert_eq!(::std::mem::size_of::<Union_foo>() , 4usize);
- assert_eq!(::std::mem::align_of::<Union_foo>() , 4usize);
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_3() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_3>() ,
+ 4usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_3>() ,
+ 4usize);
}
-#[repr(C)]
-#[derive(Debug, Copy)]
-pub struct Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1 {
- pub _bitfield_1: ::std::os::raw::c_int,
+impl Clone for foo__bindgen_ty_bindgen_id_3 {
+ fn clone(&self) -> Self { *self }
}
-impl Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1 {
+impl foo__bindgen_ty_bindgen_id_3 {
#[inline]
pub fn b(&self) -> ::std::os::raw::c_int {
- (self._bitfield_1 & (127usize as ::std::os::raw::c_int)) >> 0usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (127usize as u32)) >>
+ 0u32) as u32)
+ }
}
#[inline]
- pub fn set_b(&mut self, val: u8) {
- self._bitfield_1 &= !(127usize as ::std::os::raw::c_int);
- self._bitfield_1 |=
- ((val as ::std::os::raw::c_int) << 0usize) &
- (127usize as ::std::os::raw::c_int);
+ pub fn set_b(&mut self, val: ::std::os::raw::c_int) {
+ self._bitfield_1 &= !(127usize as u32);
+ self._bitfield_1 |= ((val as u32 as u32) << 0u32) & (127usize as u32);
}
#[inline]
pub fn c(&self) -> ::std::os::raw::c_int {
- (self._bitfield_1 & (4294967168usize as ::std::os::raw::c_int)) >>
- 7usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 &
+ (4294967168usize as u32)) >> 7u32) as
+ u32)
+ }
}
#[inline]
- pub fn set_c(&mut self, val: u32) {
- self._bitfield_1 &= !(4294967168usize as ::std::os::raw::c_int);
+ pub fn set_c(&mut self, val: ::std::os::raw::c_int) {
+ self._bitfield_1 &= !(4294967168usize as u32);
self._bitfield_1 |=
- ((val as ::std::os::raw::c_int) << 7usize) &
- (4294967168usize as ::std::os::raw::c_int);
- }
- #[inline]
- pub fn new_bitfield_1(b: u8, c: u32) -> ::std::os::raw::c_int {
- 0 | ((b as ::std::os::raw::c_int) << 0u32) |
- ((c as ::std::os::raw::c_int) << 7u32)
+ ((val as u32 as u32) << 7u32) & (4294967168usize as u32);
}
}
-impl ::std::clone::Clone for
- Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1 {
- fn clone(&self) -> Self { *self }
-}
#[test]
-fn bindgen_test_layout_Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1>()
- , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1>()
- , 4usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 4usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/union_with_anon_union.rs b/tests/expectations/union_with_anon_union.rs
index f610342d..e7f43cbe 100644
--- a/tests/expectations/union_with_anon_union.rs
+++ b/tests/expectations/union_with_anon_union.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,51 +23,35 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo {
- pub bar: __BindgenUnionField<Union_foo_union_with_anon_union_h_unnamed_1>,
- pub _bindgen_data_: u32,
-}
-impl Union_foo {
- pub unsafe fn bar(&mut self)
- -> *mut Union_foo_union_with_anon_union_h_unnamed_1 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for Union_foo {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Union_foo() {
- assert_eq!(::std::mem::size_of::<Union_foo>() , 4usize);
- assert_eq!(::std::mem::align_of::<Union_foo>() , 4usize);
+pub struct foo {
+ pub bar: __BindgenUnionField<foo__bindgen_ty_bindgen_id_2>,
+ pub bindgen_union_field: u32,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo_union_with_anon_union_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_2 {
pub a: __BindgenUnionField<::std::os::raw::c_uint>,
pub b: __BindgenUnionField<::std::os::raw::c_ushort>,
- pub _bindgen_data_: u32,
+ pub bindgen_union_field: u32,
}
-impl Union_foo_union_with_anon_union_h_unnamed_1 {
- pub unsafe fn a(&mut self) -> *mut ::std::os::raw::c_uint {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn b(&mut self) -> *mut ::std::os::raw::c_ushort {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_2() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_2>() ,
+ 4usize);
}
-impl ::std::clone::Clone for Union_foo_union_with_anon_union_h_unnamed_1 {
+impl Clone for foo__bindgen_ty_bindgen_id_2 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Union_foo_union_with_anon_union_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Union_foo_union_with_anon_union_h_unnamed_1>()
- , 4usize);
- assert_eq!(::std::mem::align_of::<Union_foo_union_with_anon_union_h_unnamed_1>()
- , 4usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 4usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/union_with_anon_unnamed_struct.rs b/tests/expectations/union_with_anon_unnamed_struct.rs
index cdc760c4..80b3e97a 100644
--- a/tests/expectations/union_with_anon_unnamed_struct.rs
+++ b/tests/expectations/union_with_anon_unnamed_struct.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,48 +23,37 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_pixel {
+pub struct pixel {
pub rgba: __BindgenUnionField<::std::os::raw::c_uint>,
- pub pixel_union_with_anon_unnamed_struct_h_unnamed_1: __BindgenUnionField<Struct_pixel_union_with_anon_unnamed_struct_h_unnamed_1>,
- pub _bindgen_data_: u32,
-}
-impl Union_pixel {
- pub unsafe fn rgba(&mut self) -> *mut ::std::os::raw::c_uint {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn pixel_union_with_anon_unnamed_struct_h_unnamed_1(&mut self)
- -> *mut Struct_pixel_union_with_anon_unnamed_struct_h_unnamed_1 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for Union_pixel {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Union_pixel() {
- assert_eq!(::std::mem::size_of::<Union_pixel>() , 4usize);
- assert_eq!(::std::mem::align_of::<Union_pixel>() , 4usize);
+ pub __bindgen_anon_1: __BindgenUnionField<pixel__bindgen_ty_bindgen_id_3>,
+ pub bindgen_union_field: u32,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_pixel_union_with_anon_unnamed_struct_h_unnamed_1 {
+pub struct pixel__bindgen_ty_bindgen_id_3 {
pub r: ::std::os::raw::c_uchar,
pub g: ::std::os::raw::c_uchar,
pub b: ::std::os::raw::c_uchar,
pub a: ::std::os::raw::c_uchar,
}
-impl ::std::clone::Clone for
- Struct_pixel_union_with_anon_unnamed_struct_h_unnamed_1 {
+#[test]
+fn bindgen_test_layout_pixel__bindgen_ty_bindgen_id_3() {
+ assert_eq!(::std::mem::size_of::<pixel__bindgen_ty_bindgen_id_3>() ,
+ 4usize);
+ assert_eq!(::std::mem::align_of::<pixel__bindgen_ty_bindgen_id_3>() ,
+ 1usize);
+}
+impl Clone for pixel__bindgen_ty_bindgen_id_3 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_pixel_union_with_anon_unnamed_struct_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Struct_pixel_union_with_anon_unnamed_struct_h_unnamed_1>()
- , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_pixel_union_with_anon_unnamed_struct_h_unnamed_1>()
- , 1usize);
+fn bindgen_test_layout_pixel() {
+ assert_eq!(::std::mem::size_of::<pixel>() , 4usize);
+ assert_eq!(::std::mem::align_of::<pixel>() , 4usize);
+}
+impl Clone for pixel {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/union_with_anon_unnamed_union.rs b/tests/expectations/union_with_anon_unnamed_union.rs
index 50dfc8d0..3ddea69e 100644
--- a/tests/expectations/union_with_anon_unnamed_union.rs
+++ b/tests/expectations/union_with_anon_unnamed_union.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,57 +23,36 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo {
+pub struct foo {
pub a: __BindgenUnionField<::std::os::raw::c_uint>,
- pub foo_union_with_anon_unnamed_union_h_unnamed_1: __BindgenUnionField<Union_foo_union_with_anon_unnamed_union_h_unnamed_1>,
- pub _bindgen_data_: u32,
-}
-impl Union_foo {
- pub unsafe fn a(&mut self) -> *mut ::std::os::raw::c_uint {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn foo_union_with_anon_unnamed_union_h_unnamed_1(&mut self)
- -> *mut Union_foo_union_with_anon_unnamed_union_h_unnamed_1 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for Union_foo {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Union_foo() {
- assert_eq!(::std::mem::size_of::<Union_foo>() , 4usize);
- assert_eq!(::std::mem::align_of::<Union_foo>() , 4usize);
+ pub __bindgen_anon_1: __BindgenUnionField<foo__bindgen_ty_bindgen_id_3>,
+ pub bindgen_union_field: u32,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo_union_with_anon_unnamed_union_h_unnamed_1 {
+pub struct foo__bindgen_ty_bindgen_id_3 {
pub b: __BindgenUnionField<::std::os::raw::c_ushort>,
pub c: __BindgenUnionField<::std::os::raw::c_uchar>,
- pub _bindgen_data_: u16,
+ pub bindgen_union_field: u16,
}
-impl Union_foo_union_with_anon_unnamed_union_h_unnamed_1 {
- pub unsafe fn b(&mut self) -> *mut ::std::os::raw::c_ushort {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn c(&mut self) -> *mut ::std::os::raw::c_uchar {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_3() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_3>() ,
+ 2usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_3>() ,
+ 2usize);
}
-impl ::std::clone::Clone for
- Union_foo_union_with_anon_unnamed_union_h_unnamed_1 {
+impl Clone for foo__bindgen_ty_bindgen_id_3 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Union_foo_union_with_anon_unnamed_union_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Union_foo_union_with_anon_unnamed_union_h_unnamed_1>()
- , 2usize);
- assert_eq!(::std::mem::align_of::<Union_foo_union_with_anon_unnamed_union_h_unnamed_1>()
- , 2usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 4usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/union_with_big_member.rs b/tests/expectations/union_with_big_member.rs
index d1cd63d4..521a5ff4 100644
--- a/tests/expectations/union_with_big_member.rs
+++ b/tests/expectations/union_with_big_member.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,53 +23,34 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Copy)]
-pub struct Union_WithBigArray {
+pub struct WithBigArray {
pub a: __BindgenUnionField<::std::os::raw::c_int>,
pub b: __BindgenUnionField<[::std::os::raw::c_int; 33usize]>,
- pub _bindgen_data_: [u32; 33usize],
+ pub bindgen_union_field: [u32; 33usize],
}
-impl Union_WithBigArray {
- pub unsafe fn a(&mut self) -> *mut ::std::os::raw::c_int {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn b(&mut self) -> *mut [::std::os::raw::c_int; 33usize] {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout_WithBigArray() {
+ assert_eq!(::std::mem::size_of::<WithBigArray>() , 132usize);
+ assert_eq!(::std::mem::align_of::<WithBigArray>() , 4usize);
}
-impl ::std::clone::Clone for Union_WithBigArray {
+impl Clone for WithBigArray {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Union_WithBigArray() {
- assert_eq!(::std::mem::size_of::<Union_WithBigArray>() , 132usize);
- assert_eq!(::std::mem::align_of::<Union_WithBigArray>() , 4usize);
-}
#[repr(C)]
#[derive(Copy)]
-pub struct Union_WithBigMember {
+pub struct WithBigMember {
pub a: __BindgenUnionField<::std::os::raw::c_int>,
- pub b: __BindgenUnionField<Union_WithBigArray>,
- pub _bindgen_data_: [u32; 33usize],
+ pub b: __BindgenUnionField<WithBigArray>,
+ pub bindgen_union_field: [u32; 33usize],
}
-impl Union_WithBigMember {
- pub unsafe fn a(&mut self) -> *mut ::std::os::raw::c_int {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn b(&mut self) -> *mut Union_WithBigArray {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout_WithBigMember() {
+ assert_eq!(::std::mem::size_of::<WithBigMember>() , 132usize);
+ assert_eq!(::std::mem::align_of::<WithBigMember>() , 4usize);
}
-impl ::std::clone::Clone for Union_WithBigMember {
+impl Clone for WithBigMember {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Union_WithBigMember() {
- assert_eq!(::std::mem::size_of::<Union_WithBigMember>() , 132usize);
- assert_eq!(::std::mem::align_of::<Union_WithBigMember>() , 4usize);
-}
diff --git a/tests/expectations/union_with_nesting.rs b/tests/expectations/union_with_nesting.rs
index 4117786d..6b8d318d 100644
--- a/tests/expectations/union_with_nesting.rs
+++ b/tests/expectations/union_with_nesting.rs
@@ -4,7 +4,7 @@
#![allow(non_snake_case)]
-#[derive(Copy, Debug)]
+#[derive(Debug)]
#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
@@ -23,101 +23,69 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
#[inline]
fn clone(&self) -> Self { Self::new() }
}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo {
+pub struct foo {
pub a: __BindgenUnionField<::std::os::raw::c_uint>,
- pub foo_union_with_nesting_h_unnamed_1: __BindgenUnionField<Struct_foo_union_with_nesting_h_unnamed_1>,
- pub _bindgen_data_: u32,
-}
-impl Union_foo {
- pub unsafe fn a(&mut self) -> *mut ::std::os::raw::c_uint {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn foo_union_with_nesting_h_unnamed_1(&mut self)
- -> *mut Struct_foo_union_with_nesting_h_unnamed_1 {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for Union_foo {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Union_foo() {
- assert_eq!(::std::mem::size_of::<Union_foo>() , 4usize);
- assert_eq!(::std::mem::align_of::<Union_foo>() , 4usize);
+ pub __bindgen_anon_1: __BindgenUnionField<foo__bindgen_ty_bindgen_id_3>,
+ pub bindgen_union_field: u32,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_foo_union_with_nesting_h_unnamed_1 {
- pub foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_2: Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_2,
- pub foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_3: Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_3,
+pub struct foo__bindgen_ty_bindgen_id_3 {
+ pub __bindgen_anon_1: foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_4,
+ pub __bindgen_anon_2: foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_7,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_2 {
+pub struct foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_4 {
pub b1: __BindgenUnionField<::std::os::raw::c_ushort>,
pub b2: __BindgenUnionField<::std::os::raw::c_ushort>,
- pub _bindgen_data_: u16,
-}
-impl Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_2 {
- pub unsafe fn b1(&mut self) -> *mut ::std::os::raw::c_ushort {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn b2(&mut self) -> *mut ::std::os::raw::c_ushort {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
-}
-impl ::std::clone::Clone for
- Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_2 {
- fn clone(&self) -> Self { *self }
+ pub bindgen_union_field: u16,
}
#[test]
-fn bindgen_test_layout_Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_2() {
- assert_eq!(::std::mem::size_of::<Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_2>()
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_4() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_4>()
, 2usize);
- assert_eq!(::std::mem::align_of::<Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_2>()
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_4>()
, 2usize);
}
+impl Clone for foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_4 {
+ fn clone(&self) -> Self { *self }
+}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_3 {
+pub struct foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_7 {
pub c1: __BindgenUnionField<::std::os::raw::c_ushort>,
pub c2: __BindgenUnionField<::std::os::raw::c_ushort>,
- pub _bindgen_data_: u16,
+ pub bindgen_union_field: u16,
}
-impl Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_3 {
- pub unsafe fn c1(&mut self) -> *mut ::std::os::raw::c_ushort {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
- pub unsafe fn c2(&mut self) -> *mut ::std::os::raw::c_ushort {
- let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
- ::std::mem::transmute(raw.offset(0))
- }
+#[test]
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_7() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_7>()
+ , 2usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_7>()
+ , 2usize);
}
-impl ::std::clone::Clone for
- Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_3 {
+impl Clone for foo__bindgen_ty_bindgen_id_3__bindgen_ty_bindgen_id_7 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_3() {
- assert_eq!(::std::mem::size_of::<Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_3>()
- , 2usize);
- assert_eq!(::std::mem::align_of::<Union_foo_union_with_nesting_h_unnamed_1_union_with_nesting_h_unnamed_3>()
- , 2usize);
+fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_3() {
+ assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_3>() ,
+ 4usize);
+ assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_3>() ,
+ 2usize);
}
-impl ::std::clone::Clone for Struct_foo_union_with_nesting_h_unnamed_1 {
+impl Clone for foo__bindgen_ty_bindgen_id_3 {
fn clone(&self) -> Self { *self }
}
#[test]
-fn bindgen_test_layout_Struct_foo_union_with_nesting_h_unnamed_1() {
- assert_eq!(::std::mem::size_of::<Struct_foo_union_with_nesting_h_unnamed_1>()
- , 4usize);
- assert_eq!(::std::mem::align_of::<Struct_foo_union_with_nesting_h_unnamed_1>()
- , 2usize);
+fn bindgen_test_layout_foo() {
+ assert_eq!(::std::mem::size_of::<foo>() , 4usize);
+ assert_eq!(::std::mem::align_of::<foo>() , 4usize);
+}
+impl Clone for foo {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/unknown_attr.rs b/tests/expectations/unknown_attr.rs
new file mode 100644
index 00000000..06da6a3c
--- /dev/null
+++ b/tests/expectations/unknown_attr.rs
@@ -0,0 +1,16 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct _bindgen_ty_bindgen_id_1 {
+ pub __clang_max_align_nonce1: ::std::os::raw::c_longlong,
+ pub __clang_max_align_nonce2: f64,
+}
+impl Clone for _bindgen_ty_bindgen_id_1 {
+ fn clone(&self) -> Self { *self }
+}
+pub type max_align_t = _bindgen_ty_bindgen_id_1;
diff --git a/tests/expectations/using.rs b/tests/expectations/using.rs
index adc1e61b..dbb6c84f 100644
--- a/tests/expectations/using.rs
+++ b/tests/expectations/using.rs
@@ -6,9 +6,9 @@
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct Struct_Point<T> {
+pub struct Point<T> {
pub x: T,
pub y: T,
}
-pub type IntPoint2D = Struct_Point<::std::os::raw::c_int>;
-pub type IntVec2D = Struct_Point<::std::os::raw::c_int>;
+pub type IntPoint2D = Point<::std::os::raw::c_int>;
+pub type IntVec2D = Point<::std::os::raw::c_int>;
diff --git a/tests/expectations/variadic_template_args.rs b/tests/expectations/variadic_template_args.rs
new file mode 100644
index 00000000..f0c68106
--- /dev/null
+++ b/tests/expectations/variadic_template_args.rs
@@ -0,0 +1,21 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+pub struct RefPtr<T> {
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
+#[repr(C)]
+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 =
+ *mut ::std::option::Option<unsafe extern "C" fn(arg1: Args)
+ -> type-parameter-1-0>;
diff --git a/tests/expectations/virtual_dtor.rs b/tests/expectations/virtual_dtor.rs
new file mode 100644
index 00000000..99e0a535
--- /dev/null
+++ b/tests/expectations/virtual_dtor.rs
@@ -0,0 +1,19 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+pub struct bindgen_vtable__bindgen_id_1 {
+}
+#[repr(C)]
+#[derive(Debug)]
+pub struct nsSlots {
+ pub vtable_: *const bindgen_vtable__bindgen_id_1,
+}
+#[test]
+fn bindgen_test_layout_nsSlots() {
+ assert_eq!(::std::mem::size_of::<nsSlots>() , 8usize);
+ assert_eq!(::std::mem::align_of::<nsSlots>() , 8usize);
+}
diff --git a/tests/expectations/virtual_overloaded.rs b/tests/expectations/virtual_overloaded.rs
index a59f9c27..d395fed0 100644
--- a/tests/expectations/virtual_overloaded.rs
+++ b/tests/expectations/virtual_overloaded.rs
@@ -5,22 +5,18 @@
#[repr(C)]
-#[derive(Debug, Copy)]
-pub struct Struct_C {
- pub _vftable: *const _vftable_Struct_C,
+pub struct bindgen_vtable__bindgen_id_1 {
}
#[repr(C)]
-pub struct _vftable_Struct_C {
- pub do_thing: unsafe extern "C" fn(this: *mut ::std::os::raw::c_void,
- arg1: ::std::os::raw::c_char),
- pub do_thing1: unsafe extern "C" fn(this: *mut ::std::os::raw::c_void,
- arg1: ::std::os::raw::c_int),
-}
-impl ::std::clone::Clone for Struct_C {
- fn clone(&self) -> Self { *self }
+#[derive(Debug, Copy)]
+pub struct C {
+ pub vtable_: *const bindgen_vtable__bindgen_id_1,
}
#[test]
-fn bindgen_test_layout_Struct_C() {
- assert_eq!(::std::mem::size_of::<Struct_C>() , 8usize);
- assert_eq!(::std::mem::align_of::<Struct_C>() , 8usize);
+fn bindgen_test_layout_C() {
+ assert_eq!(::std::mem::size_of::<C>() , 8usize);
+ assert_eq!(::std::mem::align_of::<C>() , 8usize);
+}
+impl Clone for C {
+ fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/vtable_recursive_sig.rs b/tests/expectations/vtable_recursive_sig.rs
index 8f972e92..1044c4e4 100644
--- a/tests/expectations/vtable_recursive_sig.rs
+++ b/tests/expectations/vtable_recursive_sig.rs
@@ -6,31 +6,30 @@
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Base {
- pub _vftable: *const _vftable_Base,
+pub struct Derived {
+ pub _base: Base,
}
-#[repr(C)]
-pub struct _vftable_Base {
- pub AsDerived: unsafe extern "C" fn(this: *mut ::std::os::raw::c_void)
- -> *mut Derived,
+#[test]
+fn bindgen_test_layout_Derived() {
+ assert_eq!(::std::mem::size_of::<Derived>() , 8usize);
+ assert_eq!(::std::mem::align_of::<Derived>() , 8usize);
}
-impl ::std::clone::Clone for Base {
+impl Clone for Derived {
fn clone(&self) -> Self { *self }
}
-#[test]
-fn bindgen_test_layout_Base() {
- assert_eq!(::std::mem::size_of::<Base>() , 8usize);
- assert_eq!(::std::mem::align_of::<Base>() , 8usize);
+#[repr(C)]
+pub struct bindgen_vtable__bindgen_id_2 {
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Derived {
- pub _base: Base,
+pub struct Base {
+ pub vtable_: *const bindgen_vtable__bindgen_id_2,
}
-#[repr(C)]
-pub struct _vftable_Derived {
- pub _base: _vftable_Base,
+#[test]
+fn bindgen_test_layout_Base() {
+ assert_eq!(::std::mem::size_of::<Base>() , 8usize);
+ assert_eq!(::std::mem::align_of::<Base>() , 8usize);
}
-impl ::std::clone::Clone for Derived {
+impl Clone for Base {
fn clone(&self) -> Self { *self }
}
diff --git a/tests/expectations/weird_bitfields.rs b/tests/expectations/weird_bitfields.rs
index 6166a60f..56ee76a5 100644
--- a/tests/expectations/weird_bitfields.rs
+++ b/tests/expectations/weird_bitfields.rs
@@ -5,17 +5,17 @@
#[repr(u32)]
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum Enum_nsStyleSVGOpacitySource {
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum nsStyleSVGOpacitySource {
eStyleSVGOpacitySource_Normal = 0,
eStyleSVGOpacitySource_ContextFillOpacity = 1,
eStyleSVGOpacitySource_ContextStrokeOpacity = 2,
}
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct Struct_Weird {
+pub struct Weird {
pub mStrokeDasharrayLength: ::std::os::raw::c_uint,
- pub _bitfield_1: ::std::os::raw::c_uint,
+ pub _bitfield_1: u32,
pub mClipRule: ::std::os::raw::c_uchar,
pub mColorInterpolation: ::std::os::raw::c_uchar,
pub mColorInterpolationFilters: ::std::os::raw::c_uchar,
@@ -27,100 +27,102 @@ pub struct Struct_Weird {
pub mStrokeLinejoin: ::std::os::raw::c_uchar,
pub mTextAnchor: ::std::os::raw::c_uchar,
pub mTextRendering: ::std::os::raw::c_uchar,
- pub _bitfield_2: u32,
+ pub _bitfield_2: u16,
}
-impl Struct_Weird {
+#[test]
+fn bindgen_test_layout_Weird() {
+ assert_eq!(::std::mem::size_of::<Weird>() , 24usize);
+ assert_eq!(::std::mem::align_of::<Weird>() , 4usize);
+}
+impl Clone for Weird {
+ fn clone(&self) -> Self { *self }
+}
+impl Weird {
#[inline]
pub fn bitTest(&self) -> ::std::os::raw::c_uint {
- (self._bitfield_1 & (65535usize as ::std::os::raw::c_uint)) >> 0usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 & (65535usize as u32)) >>
+ 0u32) as u32)
+ }
}
#[inline]
- pub fn set_bitTest(&mut self, val: u16) {
- self._bitfield_1 &= !(65535usize as ::std::os::raw::c_uint);
+ pub fn set_bitTest(&mut self, val: ::std::os::raw::c_uint) {
+ self._bitfield_1 &= !(65535usize as u32);
self._bitfield_1 |=
- ((val as ::std::os::raw::c_uint) << 0usize) &
- (65535usize as ::std::os::raw::c_uint);
+ ((val as u32 as u32) << 0u32) & (65535usize as u32);
}
#[inline]
pub fn bitTest2(&self) -> ::std::os::raw::c_uint {
- (self._bitfield_1 & (2147418112usize as ::std::os::raw::c_uint)) >>
- 16usize
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_1 &
+ (2147418112usize as u32)) >> 16u32) as
+ u32)
+ }
}
#[inline]
- pub fn set_bitTest2(&mut self, val: u16) {
- self._bitfield_1 &= !(2147418112usize as ::std::os::raw::c_uint);
+ pub fn set_bitTest2(&mut self, val: ::std::os::raw::c_uint) {
+ self._bitfield_1 &= !(2147418112usize as u32);
self._bitfield_1 |=
- ((val as ::std::os::raw::c_uint) << 16usize) &
- (2147418112usize as ::std::os::raw::c_uint);
- }
- #[inline]
- pub fn new_bitfield_1(bitTest: u16, bitTest2: u16)
- -> ::std::os::raw::c_uint {
- 0 | ((bitTest as ::std::os::raw::c_uint) << 0u32) |
- ((bitTest2 as ::std::os::raw::c_uint) << 16u32)
+ ((val as u32 as u32) << 16u32) & (2147418112usize as u32);
}
#[inline]
- pub fn mFillOpacitySource(&self) -> u32 {
- (self._bitfield_2 & (7usize as u32)) >> 0usize
+ pub fn mFillOpacitySource(&self) -> nsStyleSVGOpacitySource {
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_2 & (7usize as u16)) >>
+ 0u32) as u32)
+ }
}
#[inline]
- pub fn set_mFillOpacitySource(&mut self, val: u8) {
- self._bitfield_2 &= !(7usize as u32);
- self._bitfield_2 |= ((val as u32) << 0usize) & (7usize as u32);
+ pub fn set_mFillOpacitySource(&mut self, val: nsStyleSVGOpacitySource) {
+ self._bitfield_2 &= !(7usize as u16);
+ self._bitfield_2 |= ((val as u32 as u16) << 0u32) & (7usize as u16);
}
#[inline]
- pub fn mStrokeOpacitySource(&self) -> u32 {
- (self._bitfield_2 & (56usize as u32)) >> 3usize
+ pub fn mStrokeOpacitySource(&self) -> nsStyleSVGOpacitySource {
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_2 & (56usize as u16)) >>
+ 3u32) as u32)
+ }
}
#[inline]
- pub fn set_mStrokeOpacitySource(&mut self, val: u8) {
- self._bitfield_2 &= !(56usize as u32);
- self._bitfield_2 |= ((val as u32) << 3usize) & (56usize as u32);
+ pub fn set_mStrokeOpacitySource(&mut self, val: nsStyleSVGOpacitySource) {
+ self._bitfield_2 &= !(56usize as u16);
+ self._bitfield_2 |= ((val as u32 as u16) << 3u32) & (56usize as u16);
}
#[inline]
- pub fn mStrokeDasharrayFromObject(&self) -> u32 {
- (self._bitfield_2 & (64usize as u32)) >> 6usize
+ pub fn mStrokeDasharrayFromObject(&self) -> bool {
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_2 & (64usize as u16)) >>
+ 6u32) as u8)
+ }
}
#[inline]
pub fn set_mStrokeDasharrayFromObject(&mut self, val: bool) {
- self._bitfield_2 &= !(64usize as u32);
- self._bitfield_2 |= ((val as u32) << 6usize) & (64usize as u32);
+ self._bitfield_2 &= !(64usize as u16);
+ self._bitfield_2 |= ((val as u8 as u16) << 6u32) & (64usize as u16);
}
#[inline]
- pub fn mStrokeDashoffsetFromObject(&self) -> u32 {
- (self._bitfield_2 & (128usize as u32)) >> 7usize
+ pub fn mStrokeDashoffsetFromObject(&self) -> bool {
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_2 & (128usize as u16)) >>
+ 7u32) as u8)
+ }
}
#[inline]
pub fn set_mStrokeDashoffsetFromObject(&mut self, val: bool) {
- self._bitfield_2 &= !(128usize as u32);
- self._bitfield_2 |= ((val as u32) << 7usize) & (128usize as u32);
+ self._bitfield_2 &= !(128usize as u16);
+ self._bitfield_2 |= ((val as u8 as u16) << 7u32) & (128usize as u16);
}
#[inline]
- pub fn mStrokeWidthFromObject(&self) -> u32 {
- (self._bitfield_2 & (256usize as u32)) >> 8usize
+ pub fn mStrokeWidthFromObject(&self) -> bool {
+ unsafe {
+ ::std::mem::transmute(((self._bitfield_2 & (256usize as u16)) >>
+ 8u32) as u8)
+ }
}
#[inline]
pub fn set_mStrokeWidthFromObject(&mut self, val: bool) {
- self._bitfield_2 &= !(256usize as u32);
- self._bitfield_2 |= ((val as u32) << 8usize) & (256usize as u32);
+ self._bitfield_2 &= !(256usize as u16);
+ self._bitfield_2 |= ((val as u8 as u16) << 8u32) & (256usize as u16);
}
- #[inline]
- pub fn new_bitfield_2(mFillOpacitySource: u8, mStrokeOpacitySource: u8,
- mStrokeDasharrayFromObject: bool,
- mStrokeDashoffsetFromObject: bool,
- mStrokeWidthFromObject: bool) -> u32 {
- 0 | ((mFillOpacitySource as u32) << 0u32) |
- ((mStrokeOpacitySource as u32) << 3u32) |
- ((mStrokeDasharrayFromObject as u32) << 6u32) |
- ((mStrokeDashoffsetFromObject as u32) << 7u32) |
- ((mStrokeWidthFromObject as u32) << 8u32)
- }
-}
-impl ::std::clone::Clone for Struct_Weird {
- fn clone(&self) -> Self { *self }
-}
-#[test]
-fn bindgen_test_layout_Struct_Weird() {
- assert_eq!(::std::mem::size_of::<Struct_Weird>() , 24usize);
- assert_eq!(::std::mem::align_of::<Struct_Weird>() , 4usize);
}
diff --git a/tests/expectations/what_is_going_on.rs b/tests/expectations/what_is_going_on.rs
new file mode 100644
index 00000000..b6a5c86a
--- /dev/null
+++ b/tests/expectations/what_is_going_on.rs
@@ -0,0 +1,29 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct UnknownUnits {
+ pub _address: u8,
+}
+#[test]
+fn bindgen_test_layout_UnknownUnits() {
+ assert_eq!(::std::mem::size_of::<UnknownUnits>() , 1usize);
+ assert_eq!(::std::mem::align_of::<UnknownUnits>() , 1usize);
+}
+impl Clone for UnknownUnits {
+ fn clone(&self) -> Self { *self }
+}
+pub type Float = f32;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct PointTyped<units, F> {
+ pub x: Float,
+ pub y: Float,
+ pub _phantom_0: ::std::marker::PhantomData<units>,
+ pub _phantom_1: ::std::marker::PhantomData<F>,
+}
+pub type IntPoint = PointTyped<UnknownUnits, f32>;
diff --git a/tests/expectations/whitelist_basic.rs b/tests/expectations/whitelist_basic.rs
new file mode 100644
index 00000000..0104f049
--- /dev/null
+++ b/tests/expectations/whitelist_basic.rs
@@ -0,0 +1,18 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct WhitelistMe<T> {
+ pub foo: ::std::os::raw::c_int,
+ pub bar: WhitelistMe_Inner<T>,
+ pub _phantom_0: ::std::marker::PhantomData<T>,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct WhitelistMe_Inner<T> {
+ pub bar: T,
+}
diff --git a/tests/headers/anon_enum.hpp b/tests/headers/anon_enum.hpp
new file mode 100644
index 00000000..c7405202
--- /dev/null
+++ b/tests/headers/anon_enum.hpp
@@ -0,0 +1,5 @@
+struct Test {
+ int foo;
+ float bar;
+ enum { T_NONE };
+};
diff --git a/tests/headers/anon_enum_whitelist.h b/tests/headers/anon_enum_whitelist.h
new file mode 100644
index 00000000..15cda6b1
--- /dev/null
+++ b/tests/headers/anon_enum_whitelist.h
@@ -0,0 +1,6 @@
+// bindgen-flags: --whitelist-var NODE_.*
+
+enum {
+ NODE_FLAG_FOO,
+ NODE_FLAG_BAR,
+};
diff --git a/tests/headers/anon_union.hpp b/tests/headers/anon_union.hpp
new file mode 100644
index 00000000..126f6a6e
--- /dev/null
+++ b/tests/headers/anon_union.hpp
@@ -0,0 +1,20 @@
+template<typename T>
+struct TErrorResult {
+ enum UnionState {
+ HasMessage,
+ HasException,
+ };
+ int mResult;
+ struct Message;
+ struct DOMExceptionInfo;
+ union {
+ Message* mMessage;
+ DOMExceptionInfo* mDOMExceptionInfo;
+ };
+
+ bool mMightHaveUnreported;
+ UnionState mUnionState;
+};
+
+struct ErrorResult : public TErrorResult<int> {
+};
diff --git a/tests/headers/arg_keyword.hpp b/tests/headers/arg_keyword.hpp
new file mode 100644
index 00000000..9f0af850
--- /dev/null
+++ b/tests/headers/arg_keyword.hpp
@@ -0,0 +1 @@
+void foo(const char* type);
diff --git a/tests/headers/const_ptr.hpp b/tests/headers/const_ptr.hpp
new file mode 100644
index 00000000..66744f8b
--- /dev/null
+++ b/tests/headers/const_ptr.hpp
@@ -0,0 +1,3 @@
+extern "C" {
+ void foo(const void* bar);
+}
diff --git a/tests/headers/const_resolved_ty.h b/tests/headers/const_resolved_ty.h
new file mode 100644
index 00000000..2521e61c
--- /dev/null
+++ b/tests/headers/const_resolved_ty.h
@@ -0,0 +1,3 @@
+typedef unsigned char uint8_t;
+
+void foo(const uint8_t* foo);
diff --git a/tests/headers/const_tparam.hpp b/tests/headers/const_tparam.hpp
new file mode 100644
index 00000000..a2db574c
--- /dev/null
+++ b/tests/headers/const_tparam.hpp
@@ -0,0 +1,4 @@
+template<typename T>
+class C {
+ const T* const foo;
+};
diff --git a/tests/headers/duplicated_constants_in_ns.hpp b/tests/headers/duplicated_constants_in_ns.hpp
index 42197a16..bb343641 100644
--- a/tests/headers/duplicated_constants_in_ns.hpp
+++ b/tests/headers/duplicated_constants_in_ns.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: --no-namespaced-constants
+// bindgen-flags: --enable-cxx-namespaces
namespace foo {
const int FOO = 4;
}
diff --git a/tests/headers/empty_template_param_name.hpp b/tests/headers/empty_template_param_name.hpp
new file mode 100644
index 00000000..b3360bc9
--- /dev/null
+++ b/tests/headers/empty_template_param_name.hpp
@@ -0,0 +1,4 @@
+template<typename...> using __void_t = void;
+
+template<typename _Iterator, typename = __void_t<>>
+ struct __iterator_traits { };
diff --git a/tests/headers/enum_alias.hpp b/tests/headers/enum_alias.hpp
new file mode 100644
index 00000000..658f8fde
--- /dev/null
+++ b/tests/headers/enum_alias.hpp
@@ -0,0 +1,7 @@
+// bindgen-flags: -- -std=c++11
+
+typedef unsigned char uint8_t;
+
+enum Bar : uint8_t {
+ VAL
+};
diff --git a/tests/headers/in_class_typedef.hpp b/tests/headers/in_class_typedef.hpp
new file mode 100644
index 00000000..dda7472d
--- /dev/null
+++ b/tests/headers/in_class_typedef.hpp
@@ -0,0 +1,10 @@
+
+template<typename T>
+class Foo {
+ typedef T elem_type;
+ typedef T* ptr_type;
+
+ typedef struct Bar {
+ int x, y;
+ } Bar;
+};
diff --git a/tests/headers/inherit_named.hpp b/tests/headers/inherit_named.hpp
new file mode 100644
index 00000000..9881d1b6
--- /dev/null
+++ b/tests/headers/inherit_named.hpp
@@ -0,0 +1,5 @@
+template<typename T>
+class Wohoo {};
+
+template<typename T>
+class Weeee : public T {};
diff --git a/tests/headers/inherit_typedef.hpp b/tests/headers/inherit_typedef.hpp
new file mode 100644
index 00000000..8d699e82
--- /dev/null
+++ b/tests/headers/inherit_typedef.hpp
@@ -0,0 +1,5 @@
+struct Foo {};
+
+typedef Foo TypedefedFoo;
+
+struct Bar: public TypedefedFoo {};
diff --git a/tests/headers/inner_const.hpp b/tests/headers/inner_const.hpp
new file mode 100644
index 00000000..25c2e603
--- /dev/null
+++ b/tests/headers/inner_const.hpp
@@ -0,0 +1,6 @@
+
+class Foo {
+ static int BOO;
+ static Foo whatever;
+ int bar;
+};
diff --git a/tests/headers/jsval_layout_opaque.hpp b/tests/headers/jsval_layout_opaque.hpp
index d432d8d3..85c5be63 100644
--- a/tests/headers/jsval_layout_opaque.hpp
+++ b/tests/headers/jsval_layout_opaque.hpp
@@ -1,7 +1,16 @@
-// bindgen-flags: --match jsval_layout_opaque.hpp --no-type-renaming --no-unstable-rust -- -std=c++11
+// bindgen-flags: --no-unstable-rust -- -std=c++11
+
+/**
+ * These typedefs are hacky, but keep our tests consistent across 64-bit
+ * platforms, otherwise the id's change and our CI is unhappy.
+ */
+typedef unsigned char uint8_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long long size_t;
+typedef unsigned long long uintptr_t;
-#include <stdint.h>
-#include <stddef.h>
#define JS_PUNBOX64
#define IS_LITTLE_ENDIAN
diff --git a/tests/headers/nested_vtable.hpp b/tests/headers/nested_vtable.hpp
new file mode 100644
index 00000000..87d6ce1f
--- /dev/null
+++ b/tests/headers/nested_vtable.hpp
@@ -0,0 +1,8 @@
+class nsISupports {
+public:
+ virtual nsISupports* QueryInterface();
+};
+
+class nsIRunnable : public nsISupports {};
+
+class Runnable : public nsIRunnable {};
diff --git a/tests/headers/opaque_typedef.hpp b/tests/headers/opaque_typedef.hpp
index 2d9a5781..25640738 100644
--- a/tests/headers/opaque_typedef.hpp
+++ b/tests/headers/opaque_typedef.hpp
@@ -14,4 +14,4 @@ class Wat3<3>;
/** <div rustbindgen opaque></div> */
typedef RandomTemplate<int> ShouldBeOpaque;
-typedef RandomTemplate<int> ShouldNotBeOpaque;
+typedef RandomTemplate<float> ShouldNotBeOpaque;
diff --git a/tests/headers/private.hpp b/tests/headers/private.hpp
index 070bdddc..c0f3ce7f 100644
--- a/tests/headers/private.hpp
+++ b/tests/headers/private.hpp
@@ -15,7 +15,7 @@ struct VeryPrivate {
/** <div rustbindgen private></div> */
struct ContradictPrivate {
- /** <div rustbindgen private=false></div> */
+ /** <div rustbindgen private="false"></div> */
int mNotPrivate;
int mIsPrivate;
};
diff --git a/tests/headers/redeclaration.hpp b/tests/headers/redeclaration.hpp
new file mode 100644
index 00000000..d536b158
--- /dev/null
+++ b/tests/headers/redeclaration.hpp
@@ -0,0 +1,7 @@
+extern "C" {
+ void foo();
+}
+
+extern "C" {
+ void foo();
+}
diff --git a/tests/headers/typeref.hpp b/tests/headers/typeref.hpp
new file mode 100644
index 00000000..b94c98ef
--- /dev/null
+++ b/tests/headers/typeref.hpp
@@ -0,0 +1,28 @@
+struct nsFoo;
+
+namespace mozilla {
+
+struct FragmentOrURL { bool mIsLocalRef; };
+struct Position { };
+
+} // namespace mozilla
+
+class Bar {
+ nsFoo* mFoo;
+};
+
+namespace mozilla {
+
+template<typename ReferenceBox>
+struct StyleShapeSource {
+ union {
+ Position* mPosition;
+ FragmentOrURL* mFragmentOrURL;
+ };
+};
+
+} // namespace mozilla
+
+struct nsFoo {
+ mozilla::StyleShapeSource<int> mBar;
+};
diff --git a/tests/headers/unknown_attr.h b/tests/headers/unknown_attr.h
new file mode 100644
index 00000000..f87e9f0b
--- /dev/null
+++ b/tests/headers/unknown_attr.h
@@ -0,0 +1,6 @@
+typedef struct {
+ long long __clang_max_align_nonce1
+ __attribute__((__aligned__(__alignof__(long long))));
+ long double __clang_max_align_nonce2
+ __attribute__((__aligned__(__alignof__(long double))));
+} max_align_t;
diff --git a/tests/headers/virtual_dtor.hpp b/tests/headers/virtual_dtor.hpp
new file mode 100644
index 00000000..c35dcab1
--- /dev/null
+++ b/tests/headers/virtual_dtor.hpp
@@ -0,0 +1,3 @@
+struct nsSlots {
+ virtual ~nsSlots();
+};
diff --git a/tests/headers/what_is_going_on.hpp b/tests/headers/what_is_going_on.hpp
new file mode 100644
index 00000000..078c1ad5
--- /dev/null
+++ b/tests/headers/what_is_going_on.hpp
@@ -0,0 +1,19 @@
+
+struct UnknownUnits {};
+typedef float Float;
+
+template<class units, class F = Float>
+struct PointTyped {
+ F x;
+ F y;
+
+ static PointTyped<units, F> FromUnknownPoint(const PointTyped<UnknownUnits, F>& aPoint) {
+ return PointTyped<units, F>(aPoint.x, aPoint.y);
+ }
+
+ PointTyped<UnknownUnits, F> ToUnknownPoint() const {
+ return PointTyped<UnknownUnits, F>(this->x, this->y);
+ }
+};
+
+typedef PointTyped<UnknownUnits> IntPoint;
diff --git a/tests/headers/whitelist_basic.hpp b/tests/headers/whitelist_basic.hpp
new file mode 100644
index 00000000..661528ba
--- /dev/null
+++ b/tests/headers/whitelist_basic.hpp
@@ -0,0 +1,15 @@
+// bindgen-flags: --whitelist-type WhitelistMe
+
+template<typename T>
+class WhitelistMe {
+ class Inner {
+ T bar;
+ };
+
+ int foo;
+ Inner bar;
+};
+
+struct DontWhitelistMe {
+ void* foo;
+};