From 8270a0ca766ea834032daeb67c7f32a1947ab3bd Mon Sep 17 00:00:00 2001 From: Jeff Waugh Date: Tue, 15 Nov 2016 14:37:20 +1100 Subject: Transition to libbindgen sub-crate - The root crate is the `bindgen` binary - Rust-ify the test suite, no more subprocesses! - Update Travis config to test both crates --- .gitignore | 4 - .travis.yml | 7 +- CONTRIBUTING.md | 48 +- Cargo.toml | 42 +- Makefile | 34 - build.rs | 19 - libbindgen/Cargo.toml | 54 + libbindgen/build.rs | 19 + libbindgen/src/chooser.rs | 14 + libbindgen/src/clang.rs | 1259 ++++++++++++ libbindgen/src/clangll.rs | 1439 +++++++++++++ libbindgen/src/codegen/helpers.rs | 135 ++ libbindgen/src/codegen/mod.rs | 2121 ++++++++++++++++++++ libbindgen/src/ir/annotations.rs | 157 ++ libbindgen/src/ir/comp.rs | 871 ++++++++ libbindgen/src/ir/context.rs | 1055 ++++++++++ libbindgen/src/ir/enum_ty.rs | 137 ++ libbindgen/src/ir/function.rs | 282 +++ libbindgen/src/ir/int.rs | 93 + libbindgen/src/ir/item.rs | 1172 +++++++++++ libbindgen/src/ir/item_kind.rs | 114 ++ libbindgen/src/ir/layout.rs | 34 + libbindgen/src/ir/mod.rs | 18 + libbindgen/src/ir/module.rs | 61 + libbindgen/src/ir/ty.rs | 869 ++++++++ libbindgen/src/ir/type_collector.rs | 22 + libbindgen/src/ir/var.rs | 246 +++ libbindgen/src/lib.rs | 611 ++++++ libbindgen/src/parse.rs | 106 + libbindgen/src/regex_set.rs | 66 + libbindgen/src/uses.rs | 102 + libbindgen/tests/expectations/Cargo.toml | 11 + libbindgen/tests/expectations/src/lib.rs | 0 libbindgen/tests/expectations/tests/accessors.rs | 204 ++ .../tests/expectations/tests/annotation_hide.rs | 35 + libbindgen/tests/expectations/tests/anon_enum.rs | 24 + .../expectations/tests/anon_enum_whitelist.rs | 11 + libbindgen/tests/expectations/tests/anon_union.rs | 77 + libbindgen/tests/expectations/tests/arg_keyword.rs | 10 + .../tests/expectations/tests/base-to-derived.rs | 19 + .../expectations/tests/bitfield-enum-basic.rs | 77 + libbindgen/tests/expectations/tests/blocks.rs | 9 + libbindgen/tests/expectations/tests/class.rs | 127 ++ .../tests/expectations/tests/class_nested.rs | 59 + .../tests/expectations/tests/class_no_members.rs | 45 + .../tests/expectations/tests/class_static.rs | 32 + .../tests/expectations/tests/class_static_const.rs | 22 + .../tests/expectations/tests/class_use_as.rs | 35 + .../tests/expectations/tests/class_with_dtor.rs | 22 + .../expectations/tests/class_with_inner_struct.rs | 195 ++ .../tests/expectations/tests/class_with_typedef.rs | 72 + libbindgen/tests/expectations/tests/complex.rs | 64 + .../tests/expectations/tests/complex_global.rs | 24 + .../tests/expectations/tests/const_enum_unnamed.rs | 28 + libbindgen/tests/expectations/tests/const_ptr.rs | 9 + .../tests/expectations/tests/const_resolved_ty.rs | 9 + .../tests/expectations/tests/const_tparam.rs | 12 + .../tests/expectations/tests/convert-floats.rs | 30 + libbindgen/tests/expectations/tests/crtp.rs | 43 + .../expectations/tests/decl_extern_int_twice.rs | 10 + .../tests/expectations/tests/decl_ptr_to_array.rs | 10 + .../tests/duplicated_constants_in_ns.rs | 17 + libbindgen/tests/expectations/tests/elaborated.rs | 11 + .../tests/empty_template_param_name.rs | 13 + libbindgen/tests/expectations/tests/enum.rs | 12 + libbindgen/tests/expectations/tests/enum_alias.rs | 9 + .../expectations/tests/enum_and_vtable_mangling.rs | 28 + libbindgen/tests/expectations/tests/enum_dupe.rs | 10 + .../tests/expectations/tests/enum_explicit_type.rs | 24 + .../tests/expectations/tests/enum_negative.rs | 9 + libbindgen/tests/expectations/tests/enum_packed.rs | 15 + libbindgen/tests/expectations/tests/extern.rs | 9 + libbindgen/tests/expectations/tests/float128.rs | 7 + .../tests/forward-inherit-struct-with-fields.rs | 17 + .../expectations/tests/forward-inherit-struct.rs | 18 + .../expectations/tests/forward_declared_struct.rs | 32 + libbindgen/tests/expectations/tests/func_proto.rs | 9 + libbindgen/tests/expectations/tests/func_ptr.rs | 15 + .../tests/expectations/tests/func_ptr_in_struct.rs | 25 + .../expectations/tests/func_with_array_arg.rs | 9 + .../expectations/tests/func_with_func_ptr_arg.rs | 9 + .../tests/expectations/tests/in_class_typedef.rs | 21 + .../tests/expectations/tests/inherit-namespaced.rs | 18 + .../tests/expectations/tests/inherit_named.rs | 17 + .../tests/expectations/tests/inherit_typedef.rs | 33 + libbindgen/tests/expectations/tests/inner_const.rs | 27 + .../expectations/tests/inner_template_self.rs | 25 + libbindgen/tests/expectations/tests/int128_t.rs | 7 + .../expectations/tests/jsval_layout_opaque.rs | 200 ++ libbindgen/tests/expectations/tests/keywords.rs | 202 ++ .../tests/expectations/tests/macro-expr-basic.rs | 15 + libbindgen/tests/expectations/tests/macro-redef.rs | 9 + .../tests/multiple-inherit-empty-correct-layout.rs | 45 + libbindgen/tests/expectations/tests/mutable.rs | 42 + libbindgen/tests/expectations/tests/namespace.rs | 85 + libbindgen/tests/expectations/tests/nested.rs | 59 + .../tests/expectations/tests/nested_vtable.rs | 48 + libbindgen/tests/expectations/tests/no-std.rs | 23 + libbindgen/tests/expectations/tests/no_copy.rs | 13 + .../tests/expectations/tests/nsStyleAutoArray.rs | 22 + .../tests/expectations/tests/only_bitfields.rs | 45 + .../tests/expectations/tests/opaque_in_struct.rs | 33 + .../tests/expectations/tests/opaque_pointer.rs | 45 + .../tests/expectations/tests/opaque_typedef.rs | 15 + .../tests/expectations/tests/overflowed_enum.rs | 16 + libbindgen/tests/expectations/tests/overloading.rs | 23 + libbindgen/tests/expectations/tests/private.rs | 52 + .../tests/expectations/tests/redeclaration.rs | 9 + .../tests/expectations/tests/ref_argument_array.rs | 23 + .../expectations/tests/replace_template_alias.rs | 15 + .../tests/expectations/tests/replaces_double.rs | 15 + .../tests/expectations/tests/size_t_template.rs | 19 + .../struct_containing_forward_declared_struct.rs | 32 + .../expectations/tests/struct_with_anon_struct.rs | 33 + .../tests/struct_with_anon_struct_array.rs | 48 + .../tests/struct_with_anon_struct_pointer.rs | 33 + .../expectations/tests/struct_with_anon_union.rs | 58 + .../tests/struct_with_anon_unnamed_struct.rs | 33 + .../tests/struct_with_anon_unnamed_union.rs | 58 + .../expectations/tests/struct_with_bitfields.rs | 122 ++ .../expectations/tests/struct_with_derive_debug.rs | 50 + .../expectations/tests/struct_with_nesting.rs | 90 + .../expectations/tests/struct_with_packing.rs | 20 + .../tests/expectations/tests/struct_with_struct.rs | 33 + .../tests/struct_with_typedef_template_arg.rs | 15 + libbindgen/tests/expectations/tests/template.rs | 170 ++ .../tests/expectations/tests/template_alias.rs | 12 + .../expectations/tests/template_alias_basic.rs | 7 + .../expectations/tests/template_alias_namespace.rs | 21 + .../tests/template_typedef_transitive_param.rs | 18 + .../tests/expectations/tests/template_typedefs.rs | 22 + .../tests/expectations/tests/type_alias_empty.rs | 7 + libbindgen/tests/expectations/tests/typeref.rs | 96 + libbindgen/tests/expectations/tests/union_dtor.rs | 42 + .../tests/expectations/tests/union_fields.rs | 47 + .../tests/expectations/tests/union_template.rs | 62 + .../expectations/tests/union_with_anon_struct.rs | 58 + .../tests/union_with_anon_struct_bitfield.rs | 86 + .../expectations/tests/union_with_anon_union.rs | 59 + .../tests/union_with_anon_unnamed_struct.rs | 61 + .../tests/union_with_anon_unnamed_union.rs | 60 + .../expectations/tests/union_with_big_member.rs | 75 + .../tests/expectations/tests/union_with_nesting.rs | 89 + .../tests/expectations/tests/unknown_attr.rs | 16 + libbindgen/tests/expectations/tests/use-core.rs | 24 + libbindgen/tests/expectations/tests/using.rs | 14 + libbindgen/tests/expectations/tests/vector.rs | 19 + .../tests/expectations/tests/virtual_dtor.rs | 19 + .../tests/expectations/tests/virtual_overloaded.rs | 22 + .../expectations/tests/vtable_recursive_sig.rs | 35 + .../tests/expectations/tests/weird_bitfields.rs | 128 ++ .../tests/expectations/tests/what_is_going_on.rs | 28 + .../tests/expectations/tests/whitelist_basic.rs | 18 + .../tests/expectations/tests/whitelist_vars.rs | 10 + libbindgen/tests/headers/accessors.hpp | 46 + libbindgen/tests/headers/annotation_hide.hpp | 16 + libbindgen/tests/headers/anon_enum.hpp | 5 + libbindgen/tests/headers/anon_enum_whitelist.h | 6 + libbindgen/tests/headers/anon_union.hpp | 20 + libbindgen/tests/headers/arg_keyword.hpp | 1 + libbindgen/tests/headers/base-to-derived.hpp | 19 + libbindgen/tests/headers/bitfield-enum-basic.h | 27 + libbindgen/tests/headers/blocks.h | 3 + libbindgen/tests/headers/class.hpp | 29 + libbindgen/tests/headers/class_nested.hpp | 24 + libbindgen/tests/headers/class_no_members.hpp | 16 + libbindgen/tests/headers/class_static.hpp | 7 + libbindgen/tests/headers/class_static_const.hpp | 8 + libbindgen/tests/headers/class_use_as.hpp | 15 + libbindgen/tests/headers/class_with_dtor.hpp | 13 + .../tests/headers/class_with_inner_struct.hpp | 43 + libbindgen/tests/headers/class_with_typedef.hpp | 22 + libbindgen/tests/headers/complex.h | 16 + libbindgen/tests/headers/complex_global.h | 3 + libbindgen/tests/headers/const_enum_unnamed.hpp | 9 + libbindgen/tests/headers/const_ptr.hpp | 3 + libbindgen/tests/headers/const_resolved_ty.h | 3 + libbindgen/tests/headers/const_tparam.hpp | 5 + libbindgen/tests/headers/convert-floats.h | 9 + libbindgen/tests/headers/crtp.hpp | 12 + libbindgen/tests/headers/decl_extern_int_twice.h | 2 + libbindgen/tests/headers/decl_ptr_to_array.h | 1 + .../tests/headers/duplicated_constants_in_ns.hpp | 7 + libbindgen/tests/headers/elaborated.hpp | 5 + .../tests/headers/empty_template_param_name.hpp | 4 + libbindgen/tests/headers/enum.h | 9 + libbindgen/tests/headers/enum_alias.hpp | 7 + .../tests/headers/enum_and_vtable_mangling.hpp | 11 + libbindgen/tests/headers/enum_dupe.h | 4 + libbindgen/tests/headers/enum_explicit_type.hpp | 28 + libbindgen/tests/headers/enum_negative.h | 4 + libbindgen/tests/headers/enum_packed.h | 14 + libbindgen/tests/headers/extern.hpp | 3 + libbindgen/tests/headers/float128.hpp | 13 + .../headers/forward-inherit-struct-with-fields.hpp | 8 + .../tests/headers/forward-inherit-struct.hpp | 5 + libbindgen/tests/headers/forward_declared_struct.h | 11 + libbindgen/tests/headers/func_proto.h | 1 + libbindgen/tests/headers/func_ptr.h | 1 + libbindgen/tests/headers/func_ptr_in_struct.h | 6 + libbindgen/tests/headers/func_with_array_arg.h | 1 + libbindgen/tests/headers/func_with_func_ptr_arg.h | 1 + libbindgen/tests/headers/in_class_typedef.hpp | 10 + libbindgen/tests/headers/inherit-namespaced.hpp | 4 + libbindgen/tests/headers/inherit_named.hpp | 5 + libbindgen/tests/headers/inherit_typedef.hpp | 5 + libbindgen/tests/headers/inner_const.hpp | 6 + libbindgen/tests/headers/inner_template_self.hpp | 10 + libbindgen/tests/headers/int128_t.h | 7 + libbindgen/tests/headers/jsval_layout_opaque.hpp | 424 ++++ libbindgen/tests/headers/keywords.h | 49 + libbindgen/tests/headers/macro-expr-basic.h | 14 + libbindgen/tests/headers/macro-redef.h | 5 + .../multiple-inherit-empty-correct-layout.hpp | 3 + libbindgen/tests/headers/mutable.hpp | 14 + libbindgen/tests/headers/namespace.hpp | 47 + libbindgen/tests/headers/nested.hpp | 15 + libbindgen/tests/headers/nested_vtable.hpp | 8 + libbindgen/tests/headers/no-std.h | 5 + libbindgen/tests/headers/no_copy.hpp | 6 + libbindgen/tests/headers/nsStyleAutoArray.hpp | 57 + libbindgen/tests/headers/only_bitfields.hpp | 5 + libbindgen/tests/headers/opaque_in_struct.hpp | 10 + libbindgen/tests/headers/opaque_pointer.hpp | 22 + libbindgen/tests/headers/opaque_typedef.hpp | 17 + libbindgen/tests/headers/overflowed_enum.hpp | 12 + libbindgen/tests/headers/overloading.hpp | 9 + libbindgen/tests/headers/private.hpp | 21 + libbindgen/tests/headers/redeclaration.hpp | 7 + libbindgen/tests/headers/ref_argument_array.hpp | 6 + .../tests/headers/replace_template_alias.hpp | 23 + libbindgen/tests/headers/replaces_double.hpp | 20 + libbindgen/tests/headers/size_t_template.hpp | 8 + .../struct_containing_forward_declared_struct.h | 7 + libbindgen/tests/headers/struct_with_anon_struct.h | 6 + .../tests/headers/struct_with_anon_struct_array.h | 10 + .../headers/struct_with_anon_struct_pointer.h | 6 + libbindgen/tests/headers/struct_with_anon_union.h | 6 + .../headers/struct_with_anon_unnamed_struct.h | 6 + .../tests/headers/struct_with_anon_unnamed_union.h | 6 + libbindgen/tests/headers/struct_with_bitfields.h | 13 + .../tests/headers/struct_with_derive_debug.h | 15 + libbindgen/tests/headers/struct_with_nesting.h | 17 + libbindgen/tests/headers/struct_with_packing.h | 4 + libbindgen/tests/headers/struct_with_struct.h | 6 + .../headers/struct_with_typedef_template_arg.hpp | 4 + libbindgen/tests/headers/template.hpp | 144 ++ libbindgen/tests/headers/template_alias.hpp | 13 + libbindgen/tests/headers/template_alias_basic.hpp | 4 + .../tests/headers/template_alias_namespace.hpp | 13 + .../headers/template_typedef_transitive_param.hpp | 7 + libbindgen/tests/headers/template_typedefs.hpp | 8 + libbindgen/tests/headers/type_alias_empty.hpp | 10 + libbindgen/tests/headers/typeref.hpp | 28 + libbindgen/tests/headers/union_dtor.hpp | 5 + libbindgen/tests/headers/union_fields.hpp | 5 + libbindgen/tests/headers/union_template.hpp | 19 + libbindgen/tests/headers/union_with_anon_struct.h | 6 + .../headers/union_with_anon_struct_bitfield.h | 8 + libbindgen/tests/headers/union_with_anon_union.h | 6 + .../tests/headers/union_with_anon_unnamed_struct.h | 9 + .../tests/headers/union_with_anon_unnamed_union.h | 7 + libbindgen/tests/headers/union_with_big_member.h | 14 + libbindgen/tests/headers/union_with_nesting.h | 14 + libbindgen/tests/headers/unknown_attr.h | 6 + libbindgen/tests/headers/use-core.h | 8 + libbindgen/tests/headers/using.hpp | 11 + libbindgen/tests/headers/vector.hpp | 3 + libbindgen/tests/headers/virtual_dtor.hpp | 3 + libbindgen/tests/headers/virtual_overloaded.hpp | 5 + libbindgen/tests/headers/vtable_recursive_sig.hpp | 11 + libbindgen/tests/headers/weird_bitfields.hpp | 35 + libbindgen/tests/headers/what_is_going_on.hpp | 19 + libbindgen/tests/headers/whitelist_basic.hpp | 16 + libbindgen/tests/headers/whitelist_vars.h | 4 + libbindgen/tests/tests.rs | 138 ++ libbindgen/tests/uses/.gitignore | 2 + src/bin/bindgen.rs | 87 - src/bin/options.rs | 269 --- src/chooser.rs | 14 - src/clang.rs | 1259 ------------ src/clangll.rs | 1439 ------------- src/codegen/helpers.rs | 135 -- src/codegen/mod.rs | 2121 -------------------- src/ir/annotations.rs | 157 -- src/ir/comp.rs | 871 -------- src/ir/context.rs | 1055 ---------- src/ir/enum_ty.rs | 137 -- src/ir/function.rs | 282 --- src/ir/int.rs | 93 - src/ir/item.rs | 1172 ----------- src/ir/item_kind.rs | 114 -- src/ir/layout.rs | 34 - src/ir/mod.rs | 18 - src/ir/module.rs | 61 - src/ir/ty.rs | 869 -------- src/ir/type_collector.rs | 22 - src/ir/var.rs | 246 --- src/lib.rs | 614 ------ src/main.rs | 84 + src/options.rs | 266 +++ src/parse.rs | 106 - src/regex_set.rs | 66 - src/uses.rs | 102 - tests/expectations/Cargo.toml | 11 - tests/expectations/src/lib.rs | 0 tests/expectations/tests/accessors.rs | 204 -- tests/expectations/tests/annotation_hide.rs | 35 - tests/expectations/tests/anon_enum.rs | 24 - tests/expectations/tests/anon_enum_whitelist.rs | 11 - tests/expectations/tests/anon_union.rs | 77 - tests/expectations/tests/arg_keyword.rs | 10 - tests/expectations/tests/base-to-derived.rs | 19 - tests/expectations/tests/bitfield-enum-basic.rs | 77 - tests/expectations/tests/blocks.rs | 9 - tests/expectations/tests/class.rs | 127 -- tests/expectations/tests/class_nested.rs | 59 - tests/expectations/tests/class_no_members.rs | 45 - tests/expectations/tests/class_static.rs | 32 - tests/expectations/tests/class_static_const.rs | 22 - tests/expectations/tests/class_use_as.rs | 35 - tests/expectations/tests/class_with_dtor.rs | 22 - .../expectations/tests/class_with_inner_struct.rs | 195 -- tests/expectations/tests/class_with_typedef.rs | 72 - tests/expectations/tests/complex.rs | 64 - tests/expectations/tests/complex_global.rs | 24 - tests/expectations/tests/const_enum_unnamed.rs | 28 - tests/expectations/tests/const_ptr.rs | 9 - tests/expectations/tests/const_resolved_ty.rs | 9 - tests/expectations/tests/const_tparam.rs | 12 - tests/expectations/tests/convert-floats.rs | 30 - tests/expectations/tests/crtp.rs | 43 - tests/expectations/tests/decl_extern_int_twice.rs | 10 - tests/expectations/tests/decl_ptr_to_array.rs | 10 - .../tests/duplicated_constants_in_ns.rs | 17 - tests/expectations/tests/elaborated.rs | 11 - .../tests/empty_template_param_name.rs | 13 - tests/expectations/tests/enum.rs | 12 - tests/expectations/tests/enum_alias.rs | 9 - .../expectations/tests/enum_and_vtable_mangling.rs | 28 - tests/expectations/tests/enum_dupe.rs | 10 - tests/expectations/tests/enum_explicit_type.rs | 24 - tests/expectations/tests/enum_negative.rs | 9 - tests/expectations/tests/enum_packed.rs | 15 - tests/expectations/tests/extern.rs | 9 - tests/expectations/tests/float128.rs | 7 - .../tests/forward-inherit-struct-with-fields.rs | 17 - tests/expectations/tests/forward-inherit-struct.rs | 18 - .../expectations/tests/forward_declared_struct.rs | 32 - tests/expectations/tests/func_proto.rs | 9 - tests/expectations/tests/func_ptr.rs | 15 - tests/expectations/tests/func_ptr_in_struct.rs | 25 - tests/expectations/tests/func_with_array_arg.rs | 9 - tests/expectations/tests/func_with_func_ptr_arg.rs | 9 - tests/expectations/tests/in_class_typedef.rs | 21 - tests/expectations/tests/inherit-namespaced.rs | 18 - tests/expectations/tests/inherit_named.rs | 17 - tests/expectations/tests/inherit_typedef.rs | 33 - tests/expectations/tests/inner_const.rs | 27 - tests/expectations/tests/inner_template_self.rs | 25 - tests/expectations/tests/int128_t.rs | 7 - tests/expectations/tests/jsval_layout_opaque.rs | 200 -- tests/expectations/tests/keywords.rs | 202 -- tests/expectations/tests/macro-expr-basic.rs | 15 - tests/expectations/tests/macro-redef.rs | 9 - .../tests/multiple-inherit-empty-correct-layout.rs | 45 - tests/expectations/tests/mutable.rs | 42 - tests/expectations/tests/namespace.rs | 85 - tests/expectations/tests/nested.rs | 59 - tests/expectations/tests/nested_vtable.rs | 48 - tests/expectations/tests/no-std.rs | 23 - tests/expectations/tests/no_copy.rs | 13 - tests/expectations/tests/nsStyleAutoArray.rs | 22 - tests/expectations/tests/only_bitfields.rs | 45 - tests/expectations/tests/opaque_in_struct.rs | 33 - tests/expectations/tests/opaque_pointer.rs | 45 - tests/expectations/tests/opaque_typedef.rs | 15 - tests/expectations/tests/overflowed_enum.rs | 16 - tests/expectations/tests/overloading.rs | 23 - tests/expectations/tests/private.rs | 52 - tests/expectations/tests/redeclaration.rs | 9 - tests/expectations/tests/ref_argument_array.rs | 23 - tests/expectations/tests/replace_template_alias.rs | 15 - tests/expectations/tests/replaces_double.rs | 15 - tests/expectations/tests/size_t_template.rs | 19 - .../struct_containing_forward_declared_struct.rs | 32 - .../expectations/tests/struct_with_anon_struct.rs | 33 - .../tests/struct_with_anon_struct_array.rs | 48 - .../tests/struct_with_anon_struct_pointer.rs | 33 - tests/expectations/tests/struct_with_anon_union.rs | 58 - .../tests/struct_with_anon_unnamed_struct.rs | 33 - .../tests/struct_with_anon_unnamed_union.rs | 58 - tests/expectations/tests/struct_with_bitfields.rs | 122 -- .../expectations/tests/struct_with_derive_debug.rs | 50 - tests/expectations/tests/struct_with_nesting.rs | 90 - tests/expectations/tests/struct_with_packing.rs | 20 - tests/expectations/tests/struct_with_struct.rs | 33 - .../tests/struct_with_typedef_template_arg.rs | 15 - tests/expectations/tests/template.rs | 170 -- tests/expectations/tests/template_alias.rs | 12 - tests/expectations/tests/template_alias_basic.rs | 7 - .../expectations/tests/template_alias_namespace.rs | 21 - .../tests/template_typedef_transitive_param.rs | 18 - tests/expectations/tests/template_typedefs.rs | 22 - tests/expectations/tests/type_alias_empty.rs | 7 - tests/expectations/tests/typeref.rs | 96 - tests/expectations/tests/union_dtor.rs | 42 - tests/expectations/tests/union_fields.rs | 47 - tests/expectations/tests/union_template.rs | 62 - tests/expectations/tests/union_with_anon_struct.rs | 58 - .../tests/union_with_anon_struct_bitfield.rs | 86 - tests/expectations/tests/union_with_anon_union.rs | 59 - .../tests/union_with_anon_unnamed_struct.rs | 61 - .../tests/union_with_anon_unnamed_union.rs | 60 - tests/expectations/tests/union_with_big_member.rs | 75 - tests/expectations/tests/union_with_nesting.rs | 89 - tests/expectations/tests/unknown_attr.rs | 16 - tests/expectations/tests/use-core.rs | 24 - tests/expectations/tests/using.rs | 14 - tests/expectations/tests/vector.rs | 19 - tests/expectations/tests/virtual_dtor.rs | 19 - tests/expectations/tests/virtual_overloaded.rs | 22 - tests/expectations/tests/vtable_recursive_sig.rs | 35 - tests/expectations/tests/weird_bitfields.rs | 128 -- tests/expectations/tests/what_is_going_on.rs | 28 - tests/expectations/tests/whitelist_basic.rs | 18 - tests/expectations/tests/whitelist_vars.rs | 10 - tests/headers/accessors.hpp | 46 - tests/headers/annotation_hide.hpp | 16 - tests/headers/anon_enum.hpp | 5 - tests/headers/anon_enum_whitelist.h | 6 - tests/headers/anon_union.hpp | 20 - tests/headers/arg_keyword.hpp | 1 - tests/headers/base-to-derived.hpp | 19 - tests/headers/bitfield-enum-basic.h | 27 - tests/headers/blocks.h | 3 - tests/headers/class.hpp | 29 - tests/headers/class_nested.hpp | 24 - tests/headers/class_no_members.hpp | 16 - tests/headers/class_static.hpp | 7 - tests/headers/class_static_const.hpp | 8 - tests/headers/class_use_as.hpp | 15 - tests/headers/class_with_dtor.hpp | 13 - tests/headers/class_with_inner_struct.hpp | 43 - tests/headers/class_with_typedef.hpp | 22 - tests/headers/complex.h | 16 - tests/headers/complex_global.h | 3 - tests/headers/const_enum_unnamed.hpp | 9 - tests/headers/const_ptr.hpp | 3 - tests/headers/const_resolved_ty.h | 3 - tests/headers/const_tparam.hpp | 5 - tests/headers/convert-floats.h | 9 - tests/headers/crtp.hpp | 12 - tests/headers/decl_extern_int_twice.h | 2 - tests/headers/decl_ptr_to_array.h | 1 - tests/headers/duplicated_constants_in_ns.hpp | 7 - tests/headers/elaborated.hpp | 5 - tests/headers/empty_template_param_name.hpp | 4 - tests/headers/enum.h | 9 - tests/headers/enum_alias.hpp | 7 - tests/headers/enum_and_vtable_mangling.hpp | 11 - tests/headers/enum_dupe.h | 4 - tests/headers/enum_explicit_type.hpp | 28 - tests/headers/enum_negative.h | 4 - tests/headers/enum_packed.h | 14 - tests/headers/extern.hpp | 3 - tests/headers/float128.hpp | 13 - .../headers/forward-inherit-struct-with-fields.hpp | 8 - tests/headers/forward-inherit-struct.hpp | 5 - tests/headers/forward_declared_struct.h | 11 - tests/headers/func_proto.h | 1 - tests/headers/func_ptr.h | 1 - tests/headers/func_ptr_in_struct.h | 6 - tests/headers/func_with_array_arg.h | 1 - tests/headers/func_with_func_ptr_arg.h | 1 - tests/headers/in_class_typedef.hpp | 10 - tests/headers/inherit-namespaced.hpp | 4 - tests/headers/inherit_named.hpp | 5 - tests/headers/inherit_typedef.hpp | 5 - tests/headers/inner_const.hpp | 6 - tests/headers/inner_template_self.hpp | 10 - tests/headers/int128_t.h | 7 - tests/headers/jsval_layout_opaque.hpp | 424 ---- tests/headers/keywords.h | 49 - tests/headers/macro-expr-basic.h | 14 - tests/headers/macro-redef.h | 5 - .../multiple-inherit-empty-correct-layout.hpp | 3 - tests/headers/mutable.hpp | 14 - tests/headers/namespace.hpp | 47 - tests/headers/nested.hpp | 15 - tests/headers/nested_vtable.hpp | 8 - tests/headers/no-std.h | 5 - tests/headers/no_copy.hpp | 6 - tests/headers/nsStyleAutoArray.hpp | 57 - tests/headers/only_bitfields.hpp | 5 - tests/headers/opaque_in_struct.hpp | 10 - tests/headers/opaque_pointer.hpp | 22 - tests/headers/opaque_typedef.hpp | 17 - tests/headers/overflowed_enum.hpp | 12 - tests/headers/overloading.hpp | 9 - tests/headers/private.hpp | 21 - tests/headers/redeclaration.hpp | 7 - tests/headers/ref_argument_array.hpp | 6 - tests/headers/replace_template_alias.hpp | 23 - tests/headers/replaces_double.hpp | 20 - tests/headers/size_t_template.hpp | 8 - .../struct_containing_forward_declared_struct.h | 7 - tests/headers/struct_with_anon_struct.h | 6 - tests/headers/struct_with_anon_struct_array.h | 10 - tests/headers/struct_with_anon_struct_pointer.h | 6 - tests/headers/struct_with_anon_union.h | 6 - tests/headers/struct_with_anon_unnamed_struct.h | 6 - tests/headers/struct_with_anon_unnamed_union.h | 6 - tests/headers/struct_with_bitfields.h | 13 - tests/headers/struct_with_derive_debug.h | 15 - tests/headers/struct_with_nesting.h | 17 - tests/headers/struct_with_packing.h | 4 - tests/headers/struct_with_struct.h | 6 - tests/headers/struct_with_typedef_template_arg.hpp | 4 - tests/headers/template.hpp | 144 -- tests/headers/template_alias.hpp | 13 - tests/headers/template_alias_basic.hpp | 4 - tests/headers/template_alias_namespace.hpp | 13 - .../headers/template_typedef_transitive_param.hpp | 7 - tests/headers/template_typedefs.hpp | 8 - tests/headers/type_alias_empty.hpp | 10 - tests/headers/typeref.hpp | 28 - tests/headers/union_dtor.hpp | 5 - tests/headers/union_fields.hpp | 5 - tests/headers/union_template.hpp | 19 - tests/headers/union_with_anon_struct.h | 6 - tests/headers/union_with_anon_struct_bitfield.h | 8 - tests/headers/union_with_anon_union.h | 6 - tests/headers/union_with_anon_unnamed_struct.h | 9 - tests/headers/union_with_anon_unnamed_union.h | 7 - tests/headers/union_with_big_member.h | 14 - tests/headers/union_with_nesting.h | 14 - tests/headers/unknown_attr.h | 6 - tests/headers/use-core.h | 8 - tests/headers/using.hpp | 11 - tests/headers/vector.hpp | 3 - tests/headers/virtual_dtor.hpp | 3 - tests/headers/virtual_overloaded.hpp | 5 - tests/headers/vtable_recursive_sig.hpp | 11 - tests/headers/weird_bitfields.hpp | 35 - tests/headers/what_is_going_on.hpp | 19 - tests/headers/whitelist_basic.hpp | 16 - tests/headers/whitelist_vars.h | 4 - tests/tests.rs | 171 -- tests/tools/run-bindgen.py | 175 -- tests/uses/.gitignore | 2 - 551 files changed, 18289 insertions(+), 18545 deletions(-) delete mode 100644 Makefile delete mode 100644 build.rs create mode 100644 libbindgen/Cargo.toml create mode 100644 libbindgen/build.rs create mode 100644 libbindgen/src/chooser.rs create mode 100644 libbindgen/src/clang.rs create mode 100644 libbindgen/src/clangll.rs create mode 100644 libbindgen/src/codegen/helpers.rs create mode 100644 libbindgen/src/codegen/mod.rs create mode 100644 libbindgen/src/ir/annotations.rs create mode 100644 libbindgen/src/ir/comp.rs create mode 100644 libbindgen/src/ir/context.rs create mode 100644 libbindgen/src/ir/enum_ty.rs create mode 100644 libbindgen/src/ir/function.rs create mode 100644 libbindgen/src/ir/int.rs create mode 100644 libbindgen/src/ir/item.rs create mode 100644 libbindgen/src/ir/item_kind.rs create mode 100644 libbindgen/src/ir/layout.rs create mode 100644 libbindgen/src/ir/mod.rs create mode 100644 libbindgen/src/ir/module.rs create mode 100644 libbindgen/src/ir/ty.rs create mode 100644 libbindgen/src/ir/type_collector.rs create mode 100644 libbindgen/src/ir/var.rs create mode 100644 libbindgen/src/lib.rs create mode 100644 libbindgen/src/parse.rs create mode 100644 libbindgen/src/regex_set.rs create mode 100644 libbindgen/src/uses.rs create mode 100644 libbindgen/tests/expectations/Cargo.toml create mode 100644 libbindgen/tests/expectations/src/lib.rs create mode 100644 libbindgen/tests/expectations/tests/accessors.rs create mode 100644 libbindgen/tests/expectations/tests/annotation_hide.rs create mode 100644 libbindgen/tests/expectations/tests/anon_enum.rs create mode 100644 libbindgen/tests/expectations/tests/anon_enum_whitelist.rs create mode 100644 libbindgen/tests/expectations/tests/anon_union.rs create mode 100644 libbindgen/tests/expectations/tests/arg_keyword.rs create mode 100644 libbindgen/tests/expectations/tests/base-to-derived.rs create mode 100644 libbindgen/tests/expectations/tests/bitfield-enum-basic.rs create mode 100644 libbindgen/tests/expectations/tests/blocks.rs create mode 100644 libbindgen/tests/expectations/tests/class.rs create mode 100644 libbindgen/tests/expectations/tests/class_nested.rs create mode 100644 libbindgen/tests/expectations/tests/class_no_members.rs create mode 100644 libbindgen/tests/expectations/tests/class_static.rs create mode 100644 libbindgen/tests/expectations/tests/class_static_const.rs create mode 100644 libbindgen/tests/expectations/tests/class_use_as.rs create mode 100644 libbindgen/tests/expectations/tests/class_with_dtor.rs create mode 100644 libbindgen/tests/expectations/tests/class_with_inner_struct.rs create mode 100644 libbindgen/tests/expectations/tests/class_with_typedef.rs create mode 100644 libbindgen/tests/expectations/tests/complex.rs create mode 100644 libbindgen/tests/expectations/tests/complex_global.rs create mode 100644 libbindgen/tests/expectations/tests/const_enum_unnamed.rs create mode 100644 libbindgen/tests/expectations/tests/const_ptr.rs create mode 100644 libbindgen/tests/expectations/tests/const_resolved_ty.rs create mode 100644 libbindgen/tests/expectations/tests/const_tparam.rs create mode 100644 libbindgen/tests/expectations/tests/convert-floats.rs create mode 100644 libbindgen/tests/expectations/tests/crtp.rs create mode 100644 libbindgen/tests/expectations/tests/decl_extern_int_twice.rs create mode 100644 libbindgen/tests/expectations/tests/decl_ptr_to_array.rs create mode 100644 libbindgen/tests/expectations/tests/duplicated_constants_in_ns.rs create mode 100644 libbindgen/tests/expectations/tests/elaborated.rs create mode 100644 libbindgen/tests/expectations/tests/empty_template_param_name.rs create mode 100644 libbindgen/tests/expectations/tests/enum.rs create mode 100644 libbindgen/tests/expectations/tests/enum_alias.rs create mode 100644 libbindgen/tests/expectations/tests/enum_and_vtable_mangling.rs create mode 100644 libbindgen/tests/expectations/tests/enum_dupe.rs create mode 100644 libbindgen/tests/expectations/tests/enum_explicit_type.rs create mode 100644 libbindgen/tests/expectations/tests/enum_negative.rs create mode 100644 libbindgen/tests/expectations/tests/enum_packed.rs create mode 100644 libbindgen/tests/expectations/tests/extern.rs create mode 100644 libbindgen/tests/expectations/tests/float128.rs create mode 100644 libbindgen/tests/expectations/tests/forward-inherit-struct-with-fields.rs create mode 100644 libbindgen/tests/expectations/tests/forward-inherit-struct.rs create mode 100644 libbindgen/tests/expectations/tests/forward_declared_struct.rs create mode 100644 libbindgen/tests/expectations/tests/func_proto.rs create mode 100644 libbindgen/tests/expectations/tests/func_ptr.rs create mode 100644 libbindgen/tests/expectations/tests/func_ptr_in_struct.rs create mode 100644 libbindgen/tests/expectations/tests/func_with_array_arg.rs create mode 100644 libbindgen/tests/expectations/tests/func_with_func_ptr_arg.rs create mode 100644 libbindgen/tests/expectations/tests/in_class_typedef.rs create mode 100644 libbindgen/tests/expectations/tests/inherit-namespaced.rs create mode 100644 libbindgen/tests/expectations/tests/inherit_named.rs create mode 100644 libbindgen/tests/expectations/tests/inherit_typedef.rs create mode 100644 libbindgen/tests/expectations/tests/inner_const.rs create mode 100644 libbindgen/tests/expectations/tests/inner_template_self.rs create mode 100644 libbindgen/tests/expectations/tests/int128_t.rs create mode 100644 libbindgen/tests/expectations/tests/jsval_layout_opaque.rs create mode 100644 libbindgen/tests/expectations/tests/keywords.rs create mode 100644 libbindgen/tests/expectations/tests/macro-expr-basic.rs create mode 100644 libbindgen/tests/expectations/tests/macro-redef.rs create mode 100644 libbindgen/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs create mode 100644 libbindgen/tests/expectations/tests/mutable.rs create mode 100644 libbindgen/tests/expectations/tests/namespace.rs create mode 100644 libbindgen/tests/expectations/tests/nested.rs create mode 100644 libbindgen/tests/expectations/tests/nested_vtable.rs create mode 100644 libbindgen/tests/expectations/tests/no-std.rs create mode 100644 libbindgen/tests/expectations/tests/no_copy.rs create mode 100644 libbindgen/tests/expectations/tests/nsStyleAutoArray.rs create mode 100644 libbindgen/tests/expectations/tests/only_bitfields.rs create mode 100644 libbindgen/tests/expectations/tests/opaque_in_struct.rs create mode 100644 libbindgen/tests/expectations/tests/opaque_pointer.rs create mode 100644 libbindgen/tests/expectations/tests/opaque_typedef.rs create mode 100644 libbindgen/tests/expectations/tests/overflowed_enum.rs create mode 100644 libbindgen/tests/expectations/tests/overloading.rs create mode 100644 libbindgen/tests/expectations/tests/private.rs create mode 100644 libbindgen/tests/expectations/tests/redeclaration.rs create mode 100644 libbindgen/tests/expectations/tests/ref_argument_array.rs create mode 100644 libbindgen/tests/expectations/tests/replace_template_alias.rs create mode 100644 libbindgen/tests/expectations/tests/replaces_double.rs create mode 100644 libbindgen/tests/expectations/tests/size_t_template.rs create mode 100644 libbindgen/tests/expectations/tests/struct_containing_forward_declared_struct.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_anon_struct.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_anon_struct_array.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_anon_struct_pointer.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_anon_union.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_anon_unnamed_struct.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_anon_unnamed_union.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_bitfields.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_derive_debug.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_nesting.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_packing.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_struct.rs create mode 100644 libbindgen/tests/expectations/tests/struct_with_typedef_template_arg.rs create mode 100644 libbindgen/tests/expectations/tests/template.rs create mode 100644 libbindgen/tests/expectations/tests/template_alias.rs create mode 100644 libbindgen/tests/expectations/tests/template_alias_basic.rs create mode 100644 libbindgen/tests/expectations/tests/template_alias_namespace.rs create mode 100644 libbindgen/tests/expectations/tests/template_typedef_transitive_param.rs create mode 100644 libbindgen/tests/expectations/tests/template_typedefs.rs create mode 100644 libbindgen/tests/expectations/tests/type_alias_empty.rs create mode 100644 libbindgen/tests/expectations/tests/typeref.rs create mode 100644 libbindgen/tests/expectations/tests/union_dtor.rs create mode 100644 libbindgen/tests/expectations/tests/union_fields.rs create mode 100644 libbindgen/tests/expectations/tests/union_template.rs create mode 100644 libbindgen/tests/expectations/tests/union_with_anon_struct.rs create mode 100644 libbindgen/tests/expectations/tests/union_with_anon_struct_bitfield.rs create mode 100644 libbindgen/tests/expectations/tests/union_with_anon_union.rs create mode 100644 libbindgen/tests/expectations/tests/union_with_anon_unnamed_struct.rs create mode 100644 libbindgen/tests/expectations/tests/union_with_anon_unnamed_union.rs create mode 100644 libbindgen/tests/expectations/tests/union_with_big_member.rs create mode 100644 libbindgen/tests/expectations/tests/union_with_nesting.rs create mode 100644 libbindgen/tests/expectations/tests/unknown_attr.rs create mode 100644 libbindgen/tests/expectations/tests/use-core.rs create mode 100644 libbindgen/tests/expectations/tests/using.rs create mode 100644 libbindgen/tests/expectations/tests/vector.rs create mode 100644 libbindgen/tests/expectations/tests/virtual_dtor.rs create mode 100644 libbindgen/tests/expectations/tests/virtual_overloaded.rs create mode 100644 libbindgen/tests/expectations/tests/vtable_recursive_sig.rs create mode 100644 libbindgen/tests/expectations/tests/weird_bitfields.rs create mode 100644 libbindgen/tests/expectations/tests/what_is_going_on.rs create mode 100644 libbindgen/tests/expectations/tests/whitelist_basic.rs create mode 100644 libbindgen/tests/expectations/tests/whitelist_vars.rs create mode 100644 libbindgen/tests/headers/accessors.hpp create mode 100644 libbindgen/tests/headers/annotation_hide.hpp create mode 100644 libbindgen/tests/headers/anon_enum.hpp create mode 100644 libbindgen/tests/headers/anon_enum_whitelist.h create mode 100644 libbindgen/tests/headers/anon_union.hpp create mode 100644 libbindgen/tests/headers/arg_keyword.hpp create mode 100644 libbindgen/tests/headers/base-to-derived.hpp create mode 100644 libbindgen/tests/headers/bitfield-enum-basic.h create mode 100644 libbindgen/tests/headers/blocks.h create mode 100644 libbindgen/tests/headers/class.hpp create mode 100644 libbindgen/tests/headers/class_nested.hpp create mode 100644 libbindgen/tests/headers/class_no_members.hpp create mode 100644 libbindgen/tests/headers/class_static.hpp create mode 100644 libbindgen/tests/headers/class_static_const.hpp create mode 100644 libbindgen/tests/headers/class_use_as.hpp create mode 100644 libbindgen/tests/headers/class_with_dtor.hpp create mode 100644 libbindgen/tests/headers/class_with_inner_struct.hpp create mode 100644 libbindgen/tests/headers/class_with_typedef.hpp create mode 100644 libbindgen/tests/headers/complex.h create mode 100644 libbindgen/tests/headers/complex_global.h create mode 100644 libbindgen/tests/headers/const_enum_unnamed.hpp create mode 100644 libbindgen/tests/headers/const_ptr.hpp create mode 100644 libbindgen/tests/headers/const_resolved_ty.h create mode 100644 libbindgen/tests/headers/const_tparam.hpp create mode 100644 libbindgen/tests/headers/convert-floats.h create mode 100644 libbindgen/tests/headers/crtp.hpp create mode 100644 libbindgen/tests/headers/decl_extern_int_twice.h create mode 100644 libbindgen/tests/headers/decl_ptr_to_array.h create mode 100644 libbindgen/tests/headers/duplicated_constants_in_ns.hpp create mode 100644 libbindgen/tests/headers/elaborated.hpp create mode 100644 libbindgen/tests/headers/empty_template_param_name.hpp create mode 100644 libbindgen/tests/headers/enum.h create mode 100644 libbindgen/tests/headers/enum_alias.hpp create mode 100644 libbindgen/tests/headers/enum_and_vtable_mangling.hpp create mode 100644 libbindgen/tests/headers/enum_dupe.h create mode 100644 libbindgen/tests/headers/enum_explicit_type.hpp create mode 100644 libbindgen/tests/headers/enum_negative.h create mode 100644 libbindgen/tests/headers/enum_packed.h create mode 100644 libbindgen/tests/headers/extern.hpp create mode 100644 libbindgen/tests/headers/float128.hpp create mode 100644 libbindgen/tests/headers/forward-inherit-struct-with-fields.hpp create mode 100644 libbindgen/tests/headers/forward-inherit-struct.hpp create mode 100644 libbindgen/tests/headers/forward_declared_struct.h create mode 100644 libbindgen/tests/headers/func_proto.h create mode 100644 libbindgen/tests/headers/func_ptr.h create mode 100644 libbindgen/tests/headers/func_ptr_in_struct.h create mode 100644 libbindgen/tests/headers/func_with_array_arg.h create mode 100644 libbindgen/tests/headers/func_with_func_ptr_arg.h create mode 100644 libbindgen/tests/headers/in_class_typedef.hpp create mode 100644 libbindgen/tests/headers/inherit-namespaced.hpp create mode 100644 libbindgen/tests/headers/inherit_named.hpp create mode 100644 libbindgen/tests/headers/inherit_typedef.hpp create mode 100644 libbindgen/tests/headers/inner_const.hpp create mode 100644 libbindgen/tests/headers/inner_template_self.hpp create mode 100644 libbindgen/tests/headers/int128_t.h create mode 100644 libbindgen/tests/headers/jsval_layout_opaque.hpp create mode 100644 libbindgen/tests/headers/keywords.h create mode 100644 libbindgen/tests/headers/macro-expr-basic.h create mode 100644 libbindgen/tests/headers/macro-redef.h create mode 100644 libbindgen/tests/headers/multiple-inherit-empty-correct-layout.hpp create mode 100644 libbindgen/tests/headers/mutable.hpp create mode 100644 libbindgen/tests/headers/namespace.hpp create mode 100644 libbindgen/tests/headers/nested.hpp create mode 100644 libbindgen/tests/headers/nested_vtable.hpp create mode 100644 libbindgen/tests/headers/no-std.h create mode 100644 libbindgen/tests/headers/no_copy.hpp create mode 100644 libbindgen/tests/headers/nsStyleAutoArray.hpp create mode 100644 libbindgen/tests/headers/only_bitfields.hpp create mode 100644 libbindgen/tests/headers/opaque_in_struct.hpp create mode 100644 libbindgen/tests/headers/opaque_pointer.hpp create mode 100644 libbindgen/tests/headers/opaque_typedef.hpp create mode 100644 libbindgen/tests/headers/overflowed_enum.hpp create mode 100644 libbindgen/tests/headers/overloading.hpp create mode 100644 libbindgen/tests/headers/private.hpp create mode 100644 libbindgen/tests/headers/redeclaration.hpp create mode 100644 libbindgen/tests/headers/ref_argument_array.hpp create mode 100644 libbindgen/tests/headers/replace_template_alias.hpp create mode 100644 libbindgen/tests/headers/replaces_double.hpp create mode 100644 libbindgen/tests/headers/size_t_template.hpp create mode 100644 libbindgen/tests/headers/struct_containing_forward_declared_struct.h create mode 100644 libbindgen/tests/headers/struct_with_anon_struct.h create mode 100644 libbindgen/tests/headers/struct_with_anon_struct_array.h create mode 100644 libbindgen/tests/headers/struct_with_anon_struct_pointer.h create mode 100644 libbindgen/tests/headers/struct_with_anon_union.h create mode 100644 libbindgen/tests/headers/struct_with_anon_unnamed_struct.h create mode 100644 libbindgen/tests/headers/struct_with_anon_unnamed_union.h create mode 100644 libbindgen/tests/headers/struct_with_bitfields.h create mode 100644 libbindgen/tests/headers/struct_with_derive_debug.h create mode 100644 libbindgen/tests/headers/struct_with_nesting.h create mode 100644 libbindgen/tests/headers/struct_with_packing.h create mode 100644 libbindgen/tests/headers/struct_with_struct.h create mode 100644 libbindgen/tests/headers/struct_with_typedef_template_arg.hpp create mode 100644 libbindgen/tests/headers/template.hpp create mode 100644 libbindgen/tests/headers/template_alias.hpp create mode 100644 libbindgen/tests/headers/template_alias_basic.hpp create mode 100644 libbindgen/tests/headers/template_alias_namespace.hpp create mode 100644 libbindgen/tests/headers/template_typedef_transitive_param.hpp create mode 100644 libbindgen/tests/headers/template_typedefs.hpp create mode 100644 libbindgen/tests/headers/type_alias_empty.hpp create mode 100644 libbindgen/tests/headers/typeref.hpp create mode 100644 libbindgen/tests/headers/union_dtor.hpp create mode 100644 libbindgen/tests/headers/union_fields.hpp create mode 100644 libbindgen/tests/headers/union_template.hpp create mode 100644 libbindgen/tests/headers/union_with_anon_struct.h create mode 100644 libbindgen/tests/headers/union_with_anon_struct_bitfield.h create mode 100644 libbindgen/tests/headers/union_with_anon_union.h create mode 100644 libbindgen/tests/headers/union_with_anon_unnamed_struct.h create mode 100644 libbindgen/tests/headers/union_with_anon_unnamed_union.h create mode 100644 libbindgen/tests/headers/union_with_big_member.h create mode 100644 libbindgen/tests/headers/union_with_nesting.h create mode 100644 libbindgen/tests/headers/unknown_attr.h create mode 100644 libbindgen/tests/headers/use-core.h create mode 100644 libbindgen/tests/headers/using.hpp create mode 100644 libbindgen/tests/headers/vector.hpp create mode 100644 libbindgen/tests/headers/virtual_dtor.hpp create mode 100644 libbindgen/tests/headers/virtual_overloaded.hpp create mode 100644 libbindgen/tests/headers/vtable_recursive_sig.hpp create mode 100644 libbindgen/tests/headers/weird_bitfields.hpp create mode 100644 libbindgen/tests/headers/what_is_going_on.hpp create mode 100644 libbindgen/tests/headers/whitelist_basic.hpp create mode 100644 libbindgen/tests/headers/whitelist_vars.h create mode 100644 libbindgen/tests/tests.rs create mode 100644 libbindgen/tests/uses/.gitignore delete mode 100755 src/bin/bindgen.rs delete mode 100644 src/bin/options.rs delete mode 100644 src/chooser.rs delete mode 100755 src/clang.rs delete mode 100644 src/clangll.rs delete mode 100644 src/codegen/helpers.rs delete mode 100755 src/codegen/mod.rs delete mode 100644 src/ir/annotations.rs delete mode 100644 src/ir/comp.rs delete mode 100644 src/ir/context.rs delete mode 100644 src/ir/enum_ty.rs delete mode 100644 src/ir/function.rs delete mode 100644 src/ir/int.rs delete mode 100644 src/ir/item.rs delete mode 100644 src/ir/item_kind.rs delete mode 100644 src/ir/layout.rs delete mode 100644 src/ir/mod.rs delete mode 100644 src/ir/module.rs delete mode 100644 src/ir/ty.rs delete mode 100644 src/ir/type_collector.rs delete mode 100644 src/ir/var.rs delete mode 100755 src/lib.rs create mode 100644 src/main.rs create mode 100644 src/options.rs delete mode 100644 src/parse.rs delete mode 100644 src/regex_set.rs delete mode 100644 src/uses.rs delete mode 100644 tests/expectations/Cargo.toml delete mode 100644 tests/expectations/src/lib.rs delete mode 100644 tests/expectations/tests/accessors.rs delete mode 100644 tests/expectations/tests/annotation_hide.rs delete mode 100644 tests/expectations/tests/anon_enum.rs delete mode 100644 tests/expectations/tests/anon_enum_whitelist.rs delete mode 100644 tests/expectations/tests/anon_union.rs delete mode 100644 tests/expectations/tests/arg_keyword.rs delete mode 100644 tests/expectations/tests/base-to-derived.rs delete mode 100644 tests/expectations/tests/bitfield-enum-basic.rs delete mode 100644 tests/expectations/tests/blocks.rs delete mode 100644 tests/expectations/tests/class.rs delete mode 100644 tests/expectations/tests/class_nested.rs delete mode 100644 tests/expectations/tests/class_no_members.rs delete mode 100644 tests/expectations/tests/class_static.rs delete mode 100644 tests/expectations/tests/class_static_const.rs delete mode 100644 tests/expectations/tests/class_use_as.rs delete mode 100644 tests/expectations/tests/class_with_dtor.rs delete mode 100644 tests/expectations/tests/class_with_inner_struct.rs delete mode 100644 tests/expectations/tests/class_with_typedef.rs delete mode 100644 tests/expectations/tests/complex.rs delete mode 100644 tests/expectations/tests/complex_global.rs delete mode 100644 tests/expectations/tests/const_enum_unnamed.rs delete mode 100644 tests/expectations/tests/const_ptr.rs delete mode 100644 tests/expectations/tests/const_resolved_ty.rs delete mode 100644 tests/expectations/tests/const_tparam.rs delete mode 100644 tests/expectations/tests/convert-floats.rs delete mode 100644 tests/expectations/tests/crtp.rs delete mode 100644 tests/expectations/tests/decl_extern_int_twice.rs delete mode 100644 tests/expectations/tests/decl_ptr_to_array.rs delete mode 100644 tests/expectations/tests/duplicated_constants_in_ns.rs delete mode 100644 tests/expectations/tests/elaborated.rs delete mode 100644 tests/expectations/tests/empty_template_param_name.rs delete mode 100644 tests/expectations/tests/enum.rs delete mode 100644 tests/expectations/tests/enum_alias.rs delete mode 100644 tests/expectations/tests/enum_and_vtable_mangling.rs delete mode 100644 tests/expectations/tests/enum_dupe.rs delete mode 100644 tests/expectations/tests/enum_explicit_type.rs delete mode 100644 tests/expectations/tests/enum_negative.rs delete mode 100644 tests/expectations/tests/enum_packed.rs delete mode 100644 tests/expectations/tests/extern.rs delete mode 100644 tests/expectations/tests/float128.rs delete mode 100644 tests/expectations/tests/forward-inherit-struct-with-fields.rs delete mode 100644 tests/expectations/tests/forward-inherit-struct.rs delete mode 100644 tests/expectations/tests/forward_declared_struct.rs delete mode 100644 tests/expectations/tests/func_proto.rs delete mode 100644 tests/expectations/tests/func_ptr.rs delete mode 100644 tests/expectations/tests/func_ptr_in_struct.rs delete mode 100644 tests/expectations/tests/func_with_array_arg.rs delete mode 100644 tests/expectations/tests/func_with_func_ptr_arg.rs delete mode 100644 tests/expectations/tests/in_class_typedef.rs delete mode 100644 tests/expectations/tests/inherit-namespaced.rs delete mode 100644 tests/expectations/tests/inherit_named.rs delete mode 100644 tests/expectations/tests/inherit_typedef.rs delete mode 100644 tests/expectations/tests/inner_const.rs delete mode 100644 tests/expectations/tests/inner_template_self.rs delete mode 100644 tests/expectations/tests/int128_t.rs delete mode 100644 tests/expectations/tests/jsval_layout_opaque.rs delete mode 100644 tests/expectations/tests/keywords.rs delete mode 100644 tests/expectations/tests/macro-expr-basic.rs delete mode 100644 tests/expectations/tests/macro-redef.rs delete mode 100644 tests/expectations/tests/multiple-inherit-empty-correct-layout.rs delete mode 100644 tests/expectations/tests/mutable.rs delete mode 100644 tests/expectations/tests/namespace.rs delete mode 100644 tests/expectations/tests/nested.rs delete mode 100644 tests/expectations/tests/nested_vtable.rs delete mode 100644 tests/expectations/tests/no-std.rs delete mode 100644 tests/expectations/tests/no_copy.rs delete mode 100644 tests/expectations/tests/nsStyleAutoArray.rs delete mode 100644 tests/expectations/tests/only_bitfields.rs delete mode 100644 tests/expectations/tests/opaque_in_struct.rs delete mode 100644 tests/expectations/tests/opaque_pointer.rs delete mode 100644 tests/expectations/tests/opaque_typedef.rs delete mode 100644 tests/expectations/tests/overflowed_enum.rs delete mode 100644 tests/expectations/tests/overloading.rs delete mode 100644 tests/expectations/tests/private.rs delete mode 100644 tests/expectations/tests/redeclaration.rs delete mode 100644 tests/expectations/tests/ref_argument_array.rs delete mode 100644 tests/expectations/tests/replace_template_alias.rs delete mode 100644 tests/expectations/tests/replaces_double.rs delete mode 100644 tests/expectations/tests/size_t_template.rs delete mode 100644 tests/expectations/tests/struct_containing_forward_declared_struct.rs delete mode 100644 tests/expectations/tests/struct_with_anon_struct.rs delete mode 100644 tests/expectations/tests/struct_with_anon_struct_array.rs delete mode 100644 tests/expectations/tests/struct_with_anon_struct_pointer.rs delete mode 100644 tests/expectations/tests/struct_with_anon_union.rs delete mode 100644 tests/expectations/tests/struct_with_anon_unnamed_struct.rs delete mode 100644 tests/expectations/tests/struct_with_anon_unnamed_union.rs delete mode 100644 tests/expectations/tests/struct_with_bitfields.rs delete mode 100644 tests/expectations/tests/struct_with_derive_debug.rs delete mode 100644 tests/expectations/tests/struct_with_nesting.rs delete mode 100644 tests/expectations/tests/struct_with_packing.rs delete mode 100644 tests/expectations/tests/struct_with_struct.rs delete mode 100644 tests/expectations/tests/struct_with_typedef_template_arg.rs delete mode 100644 tests/expectations/tests/template.rs delete mode 100644 tests/expectations/tests/template_alias.rs delete mode 100644 tests/expectations/tests/template_alias_basic.rs delete mode 100644 tests/expectations/tests/template_alias_namespace.rs delete mode 100644 tests/expectations/tests/template_typedef_transitive_param.rs delete mode 100644 tests/expectations/tests/template_typedefs.rs delete mode 100644 tests/expectations/tests/type_alias_empty.rs delete mode 100644 tests/expectations/tests/typeref.rs delete mode 100644 tests/expectations/tests/union_dtor.rs delete mode 100644 tests/expectations/tests/union_fields.rs delete mode 100644 tests/expectations/tests/union_template.rs delete mode 100644 tests/expectations/tests/union_with_anon_struct.rs delete mode 100644 tests/expectations/tests/union_with_anon_struct_bitfield.rs delete mode 100644 tests/expectations/tests/union_with_anon_union.rs delete mode 100644 tests/expectations/tests/union_with_anon_unnamed_struct.rs delete mode 100644 tests/expectations/tests/union_with_anon_unnamed_union.rs delete mode 100644 tests/expectations/tests/union_with_big_member.rs delete mode 100644 tests/expectations/tests/union_with_nesting.rs delete mode 100644 tests/expectations/tests/unknown_attr.rs delete mode 100644 tests/expectations/tests/use-core.rs delete mode 100644 tests/expectations/tests/using.rs delete mode 100644 tests/expectations/tests/vector.rs delete mode 100644 tests/expectations/tests/virtual_dtor.rs delete mode 100644 tests/expectations/tests/virtual_overloaded.rs delete mode 100644 tests/expectations/tests/vtable_recursive_sig.rs delete mode 100644 tests/expectations/tests/weird_bitfields.rs delete mode 100644 tests/expectations/tests/what_is_going_on.rs delete mode 100644 tests/expectations/tests/whitelist_basic.rs delete mode 100644 tests/expectations/tests/whitelist_vars.rs delete mode 100644 tests/headers/accessors.hpp delete mode 100644 tests/headers/annotation_hide.hpp delete mode 100644 tests/headers/anon_enum.hpp delete mode 100644 tests/headers/anon_enum_whitelist.h delete mode 100644 tests/headers/anon_union.hpp delete mode 100644 tests/headers/arg_keyword.hpp delete mode 100644 tests/headers/base-to-derived.hpp delete mode 100644 tests/headers/bitfield-enum-basic.h delete mode 100644 tests/headers/blocks.h delete mode 100644 tests/headers/class.hpp delete mode 100644 tests/headers/class_nested.hpp delete mode 100644 tests/headers/class_no_members.hpp delete mode 100644 tests/headers/class_static.hpp delete mode 100644 tests/headers/class_static_const.hpp delete mode 100644 tests/headers/class_use_as.hpp delete mode 100644 tests/headers/class_with_dtor.hpp delete mode 100644 tests/headers/class_with_inner_struct.hpp delete mode 100644 tests/headers/class_with_typedef.hpp delete mode 100644 tests/headers/complex.h delete mode 100644 tests/headers/complex_global.h delete mode 100644 tests/headers/const_enum_unnamed.hpp delete mode 100644 tests/headers/const_ptr.hpp delete mode 100644 tests/headers/const_resolved_ty.h delete mode 100644 tests/headers/const_tparam.hpp delete mode 100644 tests/headers/convert-floats.h delete mode 100644 tests/headers/crtp.hpp delete mode 100644 tests/headers/decl_extern_int_twice.h delete mode 100644 tests/headers/decl_ptr_to_array.h delete mode 100644 tests/headers/duplicated_constants_in_ns.hpp delete mode 100644 tests/headers/elaborated.hpp delete mode 100644 tests/headers/empty_template_param_name.hpp delete mode 100644 tests/headers/enum.h delete mode 100644 tests/headers/enum_alias.hpp delete mode 100644 tests/headers/enum_and_vtable_mangling.hpp delete mode 100644 tests/headers/enum_dupe.h delete mode 100644 tests/headers/enum_explicit_type.hpp delete mode 100644 tests/headers/enum_negative.h delete mode 100644 tests/headers/enum_packed.h delete mode 100644 tests/headers/extern.hpp delete mode 100644 tests/headers/float128.hpp delete mode 100644 tests/headers/forward-inherit-struct-with-fields.hpp delete mode 100644 tests/headers/forward-inherit-struct.hpp delete mode 100644 tests/headers/forward_declared_struct.h delete mode 100644 tests/headers/func_proto.h delete mode 100644 tests/headers/func_ptr.h delete mode 100644 tests/headers/func_ptr_in_struct.h delete mode 100644 tests/headers/func_with_array_arg.h delete mode 100644 tests/headers/func_with_func_ptr_arg.h delete mode 100644 tests/headers/in_class_typedef.hpp delete mode 100644 tests/headers/inherit-namespaced.hpp delete mode 100644 tests/headers/inherit_named.hpp delete mode 100644 tests/headers/inherit_typedef.hpp delete mode 100644 tests/headers/inner_const.hpp delete mode 100644 tests/headers/inner_template_self.hpp delete mode 100644 tests/headers/int128_t.h delete mode 100644 tests/headers/jsval_layout_opaque.hpp delete mode 100644 tests/headers/keywords.h delete mode 100644 tests/headers/macro-expr-basic.h delete mode 100644 tests/headers/macro-redef.h delete mode 100644 tests/headers/multiple-inherit-empty-correct-layout.hpp delete mode 100644 tests/headers/mutable.hpp delete mode 100644 tests/headers/namespace.hpp delete mode 100644 tests/headers/nested.hpp delete mode 100644 tests/headers/nested_vtable.hpp delete mode 100644 tests/headers/no-std.h delete mode 100644 tests/headers/no_copy.hpp delete mode 100644 tests/headers/nsStyleAutoArray.hpp delete mode 100644 tests/headers/only_bitfields.hpp delete mode 100644 tests/headers/opaque_in_struct.hpp delete mode 100644 tests/headers/opaque_pointer.hpp delete mode 100644 tests/headers/opaque_typedef.hpp delete mode 100644 tests/headers/overflowed_enum.hpp delete mode 100644 tests/headers/overloading.hpp delete mode 100644 tests/headers/private.hpp delete mode 100644 tests/headers/redeclaration.hpp delete mode 100644 tests/headers/ref_argument_array.hpp delete mode 100644 tests/headers/replace_template_alias.hpp delete mode 100644 tests/headers/replaces_double.hpp delete mode 100644 tests/headers/size_t_template.hpp delete mode 100644 tests/headers/struct_containing_forward_declared_struct.h delete mode 100644 tests/headers/struct_with_anon_struct.h delete mode 100644 tests/headers/struct_with_anon_struct_array.h delete mode 100644 tests/headers/struct_with_anon_struct_pointer.h delete mode 100644 tests/headers/struct_with_anon_union.h delete mode 100644 tests/headers/struct_with_anon_unnamed_struct.h delete mode 100644 tests/headers/struct_with_anon_unnamed_union.h delete mode 100644 tests/headers/struct_with_bitfields.h delete mode 100644 tests/headers/struct_with_derive_debug.h delete mode 100644 tests/headers/struct_with_nesting.h delete mode 100644 tests/headers/struct_with_packing.h delete mode 100644 tests/headers/struct_with_struct.h delete mode 100644 tests/headers/struct_with_typedef_template_arg.hpp delete mode 100644 tests/headers/template.hpp delete mode 100644 tests/headers/template_alias.hpp delete mode 100644 tests/headers/template_alias_basic.hpp delete mode 100644 tests/headers/template_alias_namespace.hpp delete mode 100644 tests/headers/template_typedef_transitive_param.hpp delete mode 100644 tests/headers/template_typedefs.hpp delete mode 100644 tests/headers/type_alias_empty.hpp delete mode 100644 tests/headers/typeref.hpp delete mode 100644 tests/headers/union_dtor.hpp delete mode 100644 tests/headers/union_fields.hpp delete mode 100644 tests/headers/union_template.hpp delete mode 100644 tests/headers/union_with_anon_struct.h delete mode 100644 tests/headers/union_with_anon_struct_bitfield.h delete mode 100644 tests/headers/union_with_anon_union.h delete mode 100644 tests/headers/union_with_anon_unnamed_struct.h delete mode 100644 tests/headers/union_with_anon_unnamed_union.h delete mode 100644 tests/headers/union_with_big_member.h delete mode 100644 tests/headers/union_with_nesting.h delete mode 100644 tests/headers/unknown_attr.h delete mode 100644 tests/headers/use-core.h delete mode 100644 tests/headers/using.hpp delete mode 100644 tests/headers/vector.hpp delete mode 100644 tests/headers/virtual_dtor.hpp delete mode 100644 tests/headers/virtual_overloaded.hpp delete mode 100644 tests/headers/vtable_recursive_sig.hpp delete mode 100644 tests/headers/weird_bitfields.hpp delete mode 100644 tests/headers/what_is_going_on.hpp delete mode 100644 tests/headers/whitelist_basic.hpp delete mode 100644 tests/headers/whitelist_vars.h delete mode 100644 tests/tests.rs delete mode 100755 tests/tools/run-bindgen.py delete mode 100644 tests/uses/.gitignore diff --git a/.gitignore b/.gitignore index f54aca98..049fbc4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,5 @@ -bindgen -libbindgen* - # Cargo target/ Cargo.lock *~ #*# - diff --git a/.travis.yml b/.travis.yml index 467c42dc..48f0b4b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,16 +24,19 @@ cache: before_install: . ./ci/before_install.sh +before_script: cd libbindgen + script: - - cargo build --verbose --features "$BINDGEN_FEATURES" - cargo test --features "$BINDGEN_FEATURES" - - cargo build --release --verbose --features "$BINDGEN_FEATURES" - cargo test --release --features "$BINDGEN_FEATURES" - git add -A - git diff @ - git diff-index --quiet HEAD - cargo test -p tests_expectations - cargo build --features "$BINDGEN_FEATURES _docs" + - cd .. + - cargo test --features "$BINDGEN_FEATURES" + - cargo test --release --features "$BINDGEN_FEATURES" notifications: webhooks: http://build.servo.org:54856/travis diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ce95e21c..bab631d6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,20 +42,22 @@ that you aren't forgetting to document types and functions. CI will catch it if you forget, but the turn around will be a lot slower ;) ``` -$ cargo build --features "llvm_stable _docs" +$ cd libbindgen && cargo build --features "llvm_stable _docs" ``` ## Testing +Code for binding generation and testing thereof is in the `libbindgen` crate. +The following sections assume you are working in that subdirectory. + ### Overview -Input C/C++ test headers reside in the `tests/headers` directory. The expected -output rust bindings live in `tests/expectations/tests`; for example, -`tests/headers/my_header.h`'s expected generated rust bindings would be +Input C/C++ test headers reside in the `tests/headers` directory. Expected +output Rust bindings live in `tests/expectations/tests`. For example, +`tests/headers/my_header.h`'s expected generated Rust bindings would be `tests/expectations/tests/my_header.rs`. -The `tests/tools/run-bindgen.py` script runs `bindgen` on the test headers and -compares the results to the expectations. +Run `cargo test` to compare generated Rust bindings to the expectations. ### Running All Tests @@ -63,25 +65,11 @@ compares the results to the expectations. $ cargo test [--features llvm_stable] ``` -This spawns a `tests/tools/run-bindgen.py` subprocess for each test header. - -### Running a Single, Specific Test - -``` -$ ./tests/tools/run-bindgen.py ./target/debug/bindgen ./tests/headers/some_header.h -``` - -To learn more about the options available with `run-bindgen.py`: - -``` -$ ./tests/tools/run-bindgen.py --help -``` - ### Authoring New Tests To add a new test header to the suite, simply put it in the `tests/headers` -directory. Next, run the `run-bindgen.py` script with the new test header, which -will generate the initial expected output rust bindings. +directory. Next, run `bindgen` to generate the initial expected output Rust +bindings. Put those in `tests/expectations/tests`. If your new test requires certain flags to be passed to `bindgen`, you can specify them at the top of the test header, with a comment like this: @@ -90,14 +78,7 @@ specify them at the top of the test header, with a comment like this: // bindgen-flags: --enable-cxx-namespaces -- -std=c++14 ``` -If your new test requires `bindgen` to be built with certain features, you can -specify the required features at the top of the test header in a similar manner: - -```c -// bingden-features: llvm_stable -``` - -Then verify the new rust bindings compile and its tests pass: +Then verify the new Rust bindings compile and pass some basic tests: ``` $ cargo test -p tests_expectations @@ -130,14 +111,13 @@ To help debug what `bindgen` is doing, you can define the environment variable `RUST_LOG=bindgen` to get a bunch of debugging log spew. ``` -$ RUST_LOG=bindgen ./target/debug/bindgen [flags...] ~/path/to/some/header.h +$ RUST_LOG=libbindgen ./target/debug/bindgen [flags...] ~/path/to/some/header.h ``` -This logging can also be used when debugging failing tests under -`run-bindgen.py`: +This logging can also be used when debugging failing tests: ``` -$ RUST_LOG=bindgen ./tests/tools/run-bindgen.py ./target/debug/bindgen tests/headers/whatever.h +$ RUST_LOG=libbindgen cd libbindgen && cargo test ``` ## Using `creduce` to Minimize Test Cases diff --git a/Cargo.toml b/Cargo.toml index 92090226..e5a14a6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,6 @@ authors = [ "Emilio Cobos Álvarez ", "The Servo project developers", ] -build = "build.rs" description = "A binding generator for Rust" homepage = "https://github.com/servo/rust-bindgen" keywords = ["bindings", "ffi", "code-generation"] @@ -14,50 +13,13 @@ readme = "README.md" repository = "https://github.com/servo/rust-bindgen" version = "0.17.0" -[[bin]] -doc = false -name = "bindgen" - -[build-dependencies] -quasi_codegen = "0.20" - [dependencies] -cfg-if = "0.1.0" clang-sys = "0.8.0" clap = "2" -lazy_static = "0.1.*" -libc = "0.2" +libbindgen = { path = "libbindgen" } log = "0.3" env_logger = "0.3" rustc-serialize = "0.3.19" -syntex_syntax = "0.44" -regex = "0.1" -cexpr = "0.2" - -[dependencies.aster] -features = ["with-syntex"] -version = "0.28" - -[dependencies.clippy] -optional = true -version = "*" - -[dependencies.quasi] -features = ["with-syntex"] -version = "0.20" [features] -llvm_stable = [] -static = [] -# This feature only exists for CI -- don't use it! -_docs = [] - -[lib] -name = "bindgen" -path = "src/lib.rs" - -[dev-dependencies.tests_expectations] -path = "tests/expectations" - -[[test]] -name = "tests" +llvm_stable = ["libbindgen/llvm_stable"] diff --git a/Makefile b/Makefile deleted file mode 100644 index 90281f7b..00000000 --- a/Makefile +++ /dev/null @@ -1,34 +0,0 @@ - -TEST_HEADERS := $(wildcard tests/headers/*.h) $(wildcard tests/headers/*.hpp) - -TEST_TARGETS := $(TEST_HEADERS:.h=.rs) -TEST_TARGETS := $(TEST_TARGETS:.hpp=.rs) -TEST_TARGETS := $(patsubst tests/headers/%, tests/expectations/tests/%, $(TEST_TARGETS)) - -BINDGEN := ./target/debug/bindgen - -.PHONY: $(BINDGEN) -$(BINDGEN): - [ -f $@ ] || cargo build --features llvm_stable - -.PHONY: test -test: - cargo test --features llvm_stable - - -.PHONY: regen-tests -regen-tests: $(BINDGEN) clean-tests $(TEST_TARGETS) - @echo > /dev/null - -.PHONY: clean-tests -clean-tests: - $(RM) $(TEST_TARGETS) - -# TODO: Add options to add flags and whatnot -tests/expectations/tests/%.rs: tests/headers/%.h - @mkdir -p $(dir $@) - ./tests/tools/run-bindgen.py $(BINDGEN) $< $@ - -tests/expectations/tests/%.rs: tests/headers/%.hpp - @mkdir -p $(dir $@) - ./tests/tools/run-bindgen.py $(BINDGEN) $< $@ diff --git a/build.rs b/build.rs deleted file mode 100644 index b9cf3e60..00000000 --- a/build.rs +++ /dev/null @@ -1,19 +0,0 @@ -mod codegen { - extern crate quasi_codegen; - use std::path::Path; - use std::env; - - pub fn main() { - let out_dir = env::var_os("OUT_DIR").unwrap(); - 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/codegen/mod.rs"); - println!("cargo:rerun-if-changed=src/codegen/helpers.rs"); - } -} - -fn main() { - codegen::main(); -} diff --git a/libbindgen/Cargo.toml b/libbindgen/Cargo.toml new file mode 100644 index 00000000..664ece6e --- /dev/null +++ b/libbindgen/Cargo.toml @@ -0,0 +1,54 @@ +[package] +authors = [ + "Jyun-Yan You ", + "Emilio Cobos Álvarez ", + "The Servo project developers", +] +build = "build.rs" +description = "A binding generator for Rust" +homepage = "https://github.com/servo/rust-bindgen" +keywords = ["bindings", "ffi", "code-generation"] +license = "BSD-3-Clause" +name = "libbindgen" +readme = "README.md" +repository = "https://github.com/servo/rust-bindgen" +version = "0.17.0" + +[dev-dependencies] +diff = "0.1" +clap = "2" +shlex = "0.1" +tests_expectations = { path = "tests/expectations" } + +[build-dependencies] +quasi_codegen = "0.20" + +[dependencies] +cfg-if = "0.1.0" +clang-sys = "0.8.0" +lazy_static = "0.1.*" +libc = "0.2" +log = "0.3" +env_logger = "0.3" +rustc-serialize = "0.3.19" +syntex_syntax = "0.44" +regex = "0.1" +cexpr = "0.2" + +[dependencies.aster] +features = ["with-syntex"] +version = "0.28" + +[dependencies.clippy] +optional = true +version = "*" + +[dependencies.quasi] +features = ["with-syntex"] +version = "0.20" + +[features] +llvm_stable = [] +static = [] +# This feature only exists for CI -- don't use it! +_docs = [] diff --git a/libbindgen/build.rs b/libbindgen/build.rs new file mode 100644 index 00000000..b9cf3e60 --- /dev/null +++ b/libbindgen/build.rs @@ -0,0 +1,19 @@ +mod codegen { + extern crate quasi_codegen; + use std::path::Path; + use std::env; + + pub fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + 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/codegen/mod.rs"); + println!("cargo:rerun-if-changed=src/codegen/helpers.rs"); + } +} + +fn main() { + codegen::main(); +} diff --git a/libbindgen/src/chooser.rs b/libbindgen/src/chooser.rs new file mode 100644 index 00000000..10a77dc9 --- /dev/null +++ b/libbindgen/src/chooser.rs @@ -0,0 +1,14 @@ +//! A public API for more fine-grained customization of bindgen behavior. + +pub use ir::int::IntKind; +use std::fmt; + +/// A trait to allow configuring different kinds of types in different +/// situations. +pub trait TypeChooser: fmt::Debug { + /// The integer kind an integer macro should have, given a name and the + /// value of that macro, or `None` if you want the default to be chosen. + fn int_macro(&self, _name: &str, _value: i64) -> Option { + None + } +} diff --git a/libbindgen/src/clang.rs b/libbindgen/src/clang.rs new file mode 100644 index 00000000..7da755ea --- /dev/null +++ b/libbindgen/src/clang.rs @@ -0,0 +1,1259 @@ +//! A higher level Clang API built on top of the generated bindings in the +//! `clangll` module. + +#![allow(non_upper_case_globals, dead_code)] + + +use cexpr; +use clangll::*; +use std::{mem, ptr, slice}; +use std::ffi::{CStr, CString}; +use std::fmt; +use std::hash::Hash; +use std::hash::Hasher; +use std::os::raw::{c_char, c_int, c_uint, c_ulong}; + +/// A cursor into the Clang AST, pointing to an AST node. +/// +/// We call the AST node pointed to by the cursor the cursor's "referent". +#[derive(Copy, Clone)] +pub struct Cursor { + x: CXCursor, +} + +impl fmt::Debug for Cursor { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, + "Cursor({} kind: {}, loc: {}, usr: {:?})", + self.spelling(), + kind_to_str(self.kind()), + self.location(), + self.usr()) + } +} + +impl Cursor { + /// Get the Unified Symbol Resolution for this cursor's referent, if + /// available. + /// + /// The USR can be used to compare entities across translation units. + pub fn usr(&self) -> Option { + let s: String = unsafe { clang_getCursorUSR(self.x) }.into(); + if s.is_empty() { None } else { Some(s) } + } + + /// Is this cursor's referent a declaration? + pub fn is_declaration(&self) -> bool { + unsafe { clang_isDeclaration(self.kind()) != 0 } + } + + /// Get the null cursor, which has no referent. + pub fn null() -> Self { + Cursor { + x: unsafe { clang_getNullCursor() }, + } + } + + /// Get this cursor's referent's spelling. + pub fn spelling(&self) -> String { + unsafe { clang_getCursorSpelling(self.x).into() } + } + + /// Get this cursor's referent's display name. + /// + /// This is not necessarily a valid identifier. It includes extra + /// information, such as parameters for a function, etc. + pub fn display_name(&self) -> String { + unsafe { clang_getCursorDisplayName(self.x).into() } + } + + /// Get the mangled name of this cursor's referent. + pub fn mangling(&self) -> String { + unsafe { clang_Cursor_getMangling(self.x).into() } + } + + /// Get the `Cursor` for this cursor's referent's lexical parent. + /// + /// The lexical parent is the parent of the definition. The semantic parent + /// is the parent of the declaration. Generally, the lexical parent doesn't + /// have any effect on semantics, while the semantic parent does. + /// + /// In the following snippet, the `Foo` class would be the semantic parent + /// of the out-of-line `method` definition, while the lexical parent is the + /// translation unit. + /// + /// ```c++ + /// class Foo { + /// void method(); + /// }; + /// + /// void Foo::method() { /* ... */ } + /// ``` + pub fn lexical_parent(&self) -> Cursor { + unsafe { + Cursor { + x: clang_getCursorLexicalParent(self.x), + } + } + } + + /// Get the referent's semantic parent, if one is available. + /// + /// See documentation for `lexical_parent` for details on semantic vs + /// lexical parents. + pub fn fallible_semantic_parent(&self) -> Option { + let sp = unsafe { + Cursor { + x: clang_getCursorSemanticParent(self.x), + } + }; + if sp == *self || !sp.is_valid() { + return None; + } + Some(sp) + } + + /// Get the referent's semantic parent. + /// + /// See documentation for `lexical_parent` for details on semantic vs + /// lexical parents. + pub fn semantic_parent(&self) -> Cursor { + self.fallible_semantic_parent().unwrap() + } + + /// Return the number of template arguments used by this cursor's referent, + /// if the referent is either a template specialization or + /// declaration. Returns -1 otherwise. + /// + /// NOTE: This may not return `Some` for some non-fully specialized + /// templates, see #193 and #194. + pub fn num_template_args(&self) -> Option { + let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; + + if n >= 0 { + Some(n as u32) + } else { + debug_assert_eq!(n, -1); + None + } + } + + /// Get a cursor pointing to this referent's containing translation unit. + /// + /// 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 + /// disposes 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 + } + } + + /// Is the referent a top level construct? + pub fn is_toplevel(&self) -> bool { + let mut semantic_parent = self.fallible_semantic_parent(); + + while semantic_parent.is_some() && + (semantic_parent.unwrap().kind() == CXCursor_Namespace || + semantic_parent.unwrap().kind() == CXCursor_NamespaceAlias || + semantic_parent.unwrap().kind() == CXCursor_NamespaceRef) { + semantic_parent = semantic_parent.unwrap() + .fallible_semantic_parent(); + } + + let tu = self.translation_unit(); + // Yes, this can happen with, e.g., macro definitions. + semantic_parent == tu.fallible_semantic_parent() + } + + /// Get the kind of referent this cursor is pointing to. + pub fn kind(&self) -> Enum_CXCursorKind { + unsafe { clang_getCursorKind(self.x) } + } + + /// Is the referent an anonymous record definition? + pub fn is_anonymous(&self) -> bool { + unsafe { clang_Cursor_isAnonymous(self.x) != 0 } + } + + /// Is the referent a template specialization? + pub fn is_template(&self) -> bool { + self.specialized().is_some() + } + + /// Is the referent a fully specialized template specialization without any + /// remaining free template arguments? + pub fn is_fully_specialized_template(&self) -> bool { + self.is_template() && self.num_template_args().unwrap_or(0) > 0 + } + + /// Is the referent a template specialization that still has remaining free + /// template arguments? + pub fn is_in_non_fully_specialized_template(&self) -> bool { + if self.is_toplevel() { + return false; + } + let parent = self.semantic_parent(); + (parent.is_template() && !parent.is_fully_specialized_template()) || + parent.is_in_non_fully_specialized_template() + } + + /// Is this cursor pointing a valid referent? + pub fn is_valid(&self) -> bool { + unsafe { clang_isInvalid(self.kind()) == 0 } + } + + /// Get the source location for the referent. + pub fn location(&self) -> SourceLocation { + unsafe { + SourceLocation { + x: clang_getCursorLocation(self.x), + } + } + } + + /// Get the source location range for the referent. + pub fn extent(&self) -> CXSourceRange { + unsafe { clang_getCursorExtent(self.x) } + } + + /// Get the raw declaration comment for this referent, if one exists. + pub fn raw_comment(&self) -> Option { + let s: String = + unsafe { clang_Cursor_getRawCommentText(self.x).into() }; + if s.is_empty() { None } else { Some(s) } + } + + /// Get the referent's parsed comment. + pub fn comment(&self) -> Comment { + unsafe { + Comment { + x: clang_Cursor_getParsedComment(self.x), + } + } + } + + /// Get the referent's type. + pub fn cur_type(&self) -> Type { + unsafe { + Type { + x: clang_getCursorType(self.x), + } + } + } + + /// Given that this cursor's referent is a reference to another type, or is + /// a declaration, get the cursor pointing to the referenced type or type of + /// the declared thing. + pub fn definition(&self) -> Option { + unsafe { + let ret = Cursor { + x: clang_getCursorDefinition(self.x), + }; + + if ret.is_valid() { Some(ret) } else { None } + } + } + + /// Given that this cursor's referent is reference type, get the cursor + /// pointing to the referenced type. + pub fn referenced(&self) -> Option { + unsafe { + let ret = Cursor { + x: clang_getCursorReferenced(self.x), + }; + + if ret.is_valid() { Some(ret) } else { None } + } + } + + /// Get the canonical cursor for this referent. + /// + /// Many types can be declared multiple times before finally being properly + /// defined. This method allows us to get the canonical cursor for the + /// referent type. + pub fn canonical(&self) -> Cursor { + unsafe { + Cursor { + x: clang_getCanonicalCursor(self.x), + } + } + } + + /// Given that this cursor points to a template specialization, get a cursor + /// pointing to the template definition that is being specialized. + pub fn specialized(&self) -> Option { + unsafe { + let ret = Cursor { + x: clang_getSpecializedCursorTemplate(self.x), + }; + if ret.is_valid() { Some(ret) } else { None } + } + } + + /// Assuming that this cursor's referent is a template declaration, get the + /// kind of cursor that would be generated for its specializations. + pub fn template_kind(&self) -> Enum_CXCursorKind { + unsafe { clang_getTemplateCursorKind(self.x) } + } + + /// Traverse this cursor's referent and its children. + /// + /// Call the given function on each AST node traversed. + pub fn visit(&self, mut visitor: Visitor) + where Visitor: FnMut(Cursor) -> Enum_CXChildVisitResult, + { + unsafe { + clang_visitChildren(self.x, + Some(visit_children::), + mem::transmute(&mut visitor)); + } + } + + /// Returns whether the given location contains a cursor with the given + /// kind in the first level of nesting underneath (doesn't look + /// recursively). + pub fn contains_cursor(&self, kind: Enum_CXCursorKind) -> bool { + let mut found = false; + + self.visit(|c| { + if c.kind() == kind { + found = true; + CXChildVisit_Break + } else { + CXChildVisit_Continue + } + }); + + found + } + + /// Is the referent an inlined function? + #[cfg(not(feature="llvm_stable"))] + pub fn is_inlined_function(&self) -> bool { + unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 } + } + + // TODO: Remove this when LLVM 3.9 is released. + // + // This is currently used for CI purposes. + + /// Is the referent an inlined function? + #[cfg(feature="llvm_stable")] + pub fn is_inlined_function(&self) -> bool { + false + } + + /// Get the width of this cursor's referent bit field, or `None` if the + /// referent is not a bit field. + pub fn bit_width(&self) -> Option { + unsafe { + let w = clang_getFieldDeclBitWidth(self.x); + if w == -1 { None } else { Some(w as u32) } + } + } + + /// Get the integer representation type used to hold this cursor's referent + /// enum type. + pub fn enum_type(&self) -> Type { + unsafe { + Type { + x: clang_getEnumDeclIntegerType(self.x), + } + } + } + + /// Get the signed constant value for this cursor's enum variant referent. + /// + /// Returns None if the cursor's referent is not an enum variant. + pub fn enum_val_signed(&self) -> Option { + unsafe { + if self.kind() == CXCursor_EnumConstantDecl { + Some(clang_getEnumConstantDeclValue(self.x) as i64) + } else { + None + } + } + } + + /// Get the unsigned constant value for this cursor's enum variant referent. + /// + /// Returns None if the cursor's referent is not an enum variant. + pub fn enum_val_unsigned(&self) -> Option { + unsafe { + if self.kind() == CXCursor_EnumConstantDecl { + Some(clang_getEnumConstantDeclUnsignedValue(self.x) as u64) + } else { + None + } + } + } + + /// Given that this cursor's referent is a `typedef`, get the `Type` that is + /// being aliased. + pub fn typedef_type(&self) -> Type { + unsafe { + Type { + x: clang_getTypedefDeclUnderlyingType(self.x), + } + } + } + + /// Get the linkage kind for this cursor's referent. + /// + /// This only applies to functions and variables. + pub fn linkage(&self) -> Enum_CXLinkageKind { + unsafe { clang_getCursorLinkage(self.x) } + } + + /// Get the visibility of this cursor's referent. + pub fn visibility(&self) -> Enum_CXVisibilityKind { + unsafe { clang_getCursorVisibility(self.x) } + } + + /// Given that this cursor's referent is a function, return cursors to its + /// parameters. + pub fn args(&self) -> Vec { + unsafe { + let num = self.num_args().expect("expected value, got none") as u32; + let mut args = vec![]; + for i in 0..num { + args.push(Cursor { + x: clang_Cursor_getArgument(self.x, i as c_uint), + }); + } + args + } + } + + /// Given that this cursor's referent is a function/method call or + /// declaration, return the number of arguments it takes. + /// + /// Returns -1 if the cursor's referent is not a function/method call or + /// declaration. + pub fn num_args(&self) -> Result { + unsafe { + let w = clang_Cursor_getNumArguments(self.x); + if w == -1 { Err(()) } else { Ok(w as u32) } + } + } + + /// Get the access specifier for this cursor's referent. + pub fn access_specifier(&self) -> Enum_CX_CXXAccessSpecifier { + unsafe { clang_getCXXAccessSpecifier(self.x) } + } + + /// Is this cursor's referent a field declaration that is marked as + /// `mutable`? + pub fn is_mutable_field(&self) -> bool { + unsafe { clang_CXXField_isMutable(self.x) != 0 } + } + + /// Is this cursor's referent a member function that is declared `static`? + pub fn method_is_static(&self) -> bool { + unsafe { clang_CXXMethod_isStatic(self.x) != 0 } + } + + /// Is this cursor's referent a member function that is declared `const`? + pub fn method_is_const(&self) -> bool { + unsafe { clang_CXXMethod_isConst(self.x) != 0 } + } + + /// Is this cursor's referent a member function that is declared `const`? + pub fn method_is_virtual(&self) -> bool { + unsafe { clang_CXXMethod_isVirtual(self.x) != 0 } + } + + /// Is this cursor's referent a struct or class with virtual members? + pub fn is_virtual_base(&self) -> bool { + unsafe { clang_isVirtualBase(self.x) != 0 } + } +} + +extern "C" fn visit_children(cur: CXCursor, + _parent: CXCursor, + data: CXClientData) + -> Enum_CXChildVisitResult + where Visitor: FnMut(Cursor) -> Enum_CXChildVisitResult, +{ + let func: &mut Visitor = unsafe { mem::transmute(data) }; + let child = Cursor { + x: cur, + }; + + (*func)(child) +} + +impl PartialEq for Cursor { + fn eq(&self, other: &Cursor) -> bool { + unsafe { clang_equalCursors(self.x, other.x) == 1 } + } +} + +impl Eq for Cursor {} + +impl Hash for Cursor { + fn hash(&self, state: &mut H) { + unsafe { clang_hashCursor(self.x) }.hash(state) + } +} + +/// The type of a node in clang's AST. +#[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()) + } +} + +/// An error about the layout of a struct, class, or type. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum LayoutError { + /// Asked for the layout of an invalid type. + Invalid, + /// Asked for the layout of an incomplete type. + Incomplete, + /// Asked for the layout of a dependent type. + Dependent, + /// Asked for the layout of a type that does not have constant size. + NotConstantSize, + /// Asked for the layout of a field in a type that does not have such a + /// field. + InvalidFieldName, + /// An unknown layout error. + Unknown, +} + +impl ::std::convert::From for LayoutError { + fn from(val: i32) -> Self { + use self::LayoutError::*; + match val { + CXTypeLayoutError_Invalid => Invalid, + CXTypeLayoutError_Incomplete => Incomplete, + CXTypeLayoutError_Dependent => Dependent, + CXTypeLayoutError_NotConstantSize => NotConstantSize, + CXTypeLayoutError_InvalidFieldName => InvalidFieldName, + _ => Unknown, + } + } +} + +impl Type { + /// Get this type's kind. + pub fn kind(&self) -> Enum_CXTypeKind { + self.x.kind + } + + /// Get a cursor pointing to this type's declaration. + pub fn declaration(&self) -> Cursor { + unsafe { + Cursor { + x: clang_getTypeDeclaration(self.x), + } + } + } + + /// Get a raw display name for this type. + pub fn spelling(&self) -> String { + unsafe { clang_getTypeSpelling(self.x).into() } + } + + /// Is this type const qualified? + pub fn is_const(&self) -> bool { + unsafe { clang_isConstQualifiedType(self.x) != 0 } + } + + /// What is the size of this type? Paper over invalid types by returning `0` + /// for them. + pub fn size(&self) -> usize { + unsafe { + let val = clang_Type_getSizeOf(self.x); + if val < 0 { 0 } else { val as usize } + } + } + + /// What is the size of this type? + pub fn fallible_size(&self) -> Result { + let val = unsafe { clang_Type_getSizeOf(self.x) }; + if val < 0 { + Err(LayoutError::from(val as i32)) + } else { + Ok(val as usize) + } + } + + /// What is the alignment of this type? Paper over invalid types by + /// returning `0`. + pub fn align(&self) -> usize { + unsafe { + let val = clang_Type_getAlignOf(self.x); + if val < 0 { 0 } else { val as usize } + } + } + + /// What is the alignment of this type? + pub fn fallible_align(&self) -> Result { + unsafe { + let val = clang_Type_getAlignOf(self.x); + if val < 0 { + Err(LayoutError::from(val as i32)) + } else { + Ok(val as usize) + } + } + } + + /// Get the layout for this type, or an error describing why it does not + /// have a valid layout. + 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)) + } + + /// If this type is a class template specialization, return its + /// template arguments. Otherwise, return None. + pub fn template_args(&self) -> Option { + let n = unsafe { clang_Type_getNumTemplateArguments(self.x) }; + if n >= 0 { + Some(TypeTemplateArgIterator { + x: self.x, + length: n as u32, + index: 0, + }) + } else { + debug_assert_eq!(n, -1); + None + } + } + + /// Given that this type is a pointer type, return the type that it points + /// to. + pub fn pointee_type(&self) -> Option { + match self.kind() { + CXType_Pointer | + CXType_RValueReference | + CXType_LValueReference | + CXType_MemberPointer => { + let ret = Type { + x: unsafe { clang_getPointeeType(self.x) }, + }; + debug_assert!(ret.is_valid()); + Some(ret) + } + _ => None, + } + } + + /// Given that this type is an array, vector, or complex type, return the + /// type of its elements. + pub fn elem_type(&self) -> Option { + let current_type = Type { + x: unsafe { clang_getElementType(self.x) }, + }; + if current_type.is_valid() { + Some(current_type) + } else { + None + } + } + + /// Given that this type is an array or vector type, return its number of + /// elements. + pub fn num_elements(&self) -> Option { + let num_elements_returned = unsafe { clang_getNumElements(self.x) }; + if num_elements_returned != -1 { + Some(num_elements_returned as usize) + } else { + None + } + } + + /// Get the canonical version of this type. This sees through `typdef`s and + /// aliases to get the underlying, canonical type. + pub fn canonical_type(&self) -> Type { + unsafe { + Type { + x: clang_getCanonicalType(self.x), + } + } + } + + /// Is this type a variadic function type? + pub fn is_variadic(&self) -> bool { + unsafe { clang_isFunctionTypeVariadic(self.x) != 0 } + } + + /// Given that this type is a function type, get the type of its return + /// value. + pub fn ret_type(&self) -> Option { + let rt = Type { + x: unsafe { clang_getResultType(self.x) }, + }; + if rt.is_valid() { Some(rt) } else { None } + } + + /// Given that this type is a function type, get its calling convention. If + /// this is not a function type, `CXCallingConv_Invalid` is returned. + pub fn call_conv(&self) -> Enum_CXCallingConv { + unsafe { clang_getFunctionTypeCallingConv(self.x) } + } + + /// For elaborated types (types which use `class`, `struct`, or `union` to + /// disambiguate types from local bindings), get the underlying type. + #[cfg(not(feature="llvm_stable"))] + pub fn named(&self) -> Type { + unsafe { + Type { + x: clang_Type_getNamedType(self.x), + } + } + } + + /// Is this a valid type? + pub fn is_valid(&self) -> bool { + self.kind() != CXType_Invalid + } + + /// Is this a valid and exposed type? + pub fn is_valid_and_exposed(&self) -> bool { + self.is_valid() && self.kind() != CXType_Unexposed + } +} + +/// An iterator for a type's template arguments. +pub struct TypeTemplateArgIterator { + x: CXType, + length: u32, + index: u32, +} + +impl Iterator for TypeTemplateArgIterator { + type Item = Type; + fn next(&mut self) -> Option { + if self.index < self.length { + let idx = self.index as c_int; + self.index += 1; + Some(Type { + x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) }, + }) + } else { + None + } + } +} + +impl ExactSizeIterator for TypeTemplateArgIterator { + fn len(&self) -> usize { + assert!(self.index <= self.length); + (self.length - self.index) as usize + } +} + +/// A `SourceLocation` is a file, line, column, and byte offset location for +/// some source text. +pub struct SourceLocation { + x: CXSourceLocation, +} + +impl SourceLocation { + /// Get the (file, line, column, byte offset) tuple for this source + /// location. + pub fn location(&self) -> (File, usize, usize, usize) { + unsafe { + let mut file = ptr::null_mut(); + let mut line = 0; + let mut col = 0; + let mut off = 0; + clang_getSpellingLocation(self.x, + &mut file, + &mut line, + &mut col, + &mut off); + (File { + x: file, + }, + line as usize, + col as usize, + off as usize) + } + } +} + +impl fmt::Display for SourceLocation { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let (file, line, col, _) = self.location(); + if let Some(name) = file.name() { + write!(f, "{}:{}:{}", name, line, col) + } else { + "builtin definitions".fmt(f) + } + } +} + +/// A comment in the source text. +/// +/// Comments are sort of parsed by Clang, and have a tree structure. +pub struct Comment { + x: CXComment, +} + +impl Comment { + /// What kind of comment is this? + pub fn kind(&self) -> Enum_CXCommentKind { + unsafe { clang_Comment_getKind(self.x) } + } + + /// Get this comment's children comment + pub fn get_children(&self) -> CommentChildrenIterator { + CommentChildrenIterator { + parent: self.x, + length: unsafe { clang_Comment_getNumChildren(self.x) }, + index: 0, + } + } + + /// Given that this comment is the start or end of an HTML tag, get its tag + /// name. + pub fn get_tag_name(&self) -> String { + unsafe { clang_HTMLTagComment_getTagName(self.x).into() } + } + + /// Given that this comment is an HTML start tag, get its attributes. + pub fn get_tag_attrs(&self) -> CommentAttributesIterator { + CommentAttributesIterator { + x: self.x, + length: unsafe { clang_HTMLStartTag_getNumAttrs(self.x) }, + index: 0, + } + } +} + +/// An iterator for a comment's children +pub struct CommentChildrenIterator { + parent: CXComment, + length: c_uint, + index: c_uint, +} + +impl Iterator for CommentChildrenIterator { + type Item = Comment; + fn next(&mut self) -> Option { + if self.index < self.length { + let idx = self.index; + self.index += 1; + Some(Comment { + x: unsafe { clang_Comment_getChild(self.parent, idx) }, + }) + } else { + None + } + } +} + +/// An HTML start tag comment attribute +pub struct CommentAttribute { + /// HTML start tag attribute name + pub name: String, + /// HTML start tag attribute value + pub value: String, +} + +/// An iterator for a comment's attributes +pub struct CommentAttributesIterator { + x: CXComment, + length: c_uint, + index: c_uint, +} + +impl Iterator for CommentAttributesIterator { + type Item = CommentAttribute; + fn next(&mut self) -> Option { + if self.index < self.length { + let idx = self.index; + self.index += 1; + Some(CommentAttribute { + name: unsafe { + clang_HTMLStartTag_getAttrName(self.x, idx).into() + }, + value: unsafe { + clang_HTMLStartTag_getAttrValue(self.x, idx).into() + }, + }) + } else { + None + } + } +} + +/// A source file. +pub struct File { + x: CXFile, +} + +impl File { + /// Get the name of this source file. + pub fn name(&self) -> Option { + if self.x.is_null() { + return None; + } + unsafe { Some(clang_getFileName(self.x).into()) } + } +} + +impl Into for CXString { + fn into(self) -> String { + if self.data.is_null() { + return "".to_owned(); + } + unsafe { + let c_str = CStr::from_ptr(clang_getCString(self) as *const _); + c_str.to_string_lossy().into_owned() + } + } +} + +/// An `Index` is an environment for a set of translation units that will +/// typically end up linked together in one final binary. +pub struct Index { + x: CXIndex, +} + +impl Index { + /// Construct a new `Index`. + /// + /// The `pch` parameter controls whether declarations in pre-compiled + /// headers are included when enumerating a translation unit's "locals". + /// + /// The `diag` parameter controls whether debugging diagnostics are enabled. + pub fn new(pch: bool, diag: bool) -> Index { + unsafe { + Index { + x: clang_createIndex(pch as c_int, diag as c_int), + } + } + } +} + +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); + } + } +} + +/// A token emitted by clang's lexer. +#[derive(Debug)] +pub struct Token { + /// The kind of token this is. + pub kind: CXTokenKind, + /// A display name for this token. + pub spelling: String, +} + +/// A translation unit (or "compilation unit"). +pub struct TranslationUnit { + x: CXTranslationUnit, +} + +impl fmt::Debug for TranslationUnit { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "TranslationUnit {{ }}") + } +} + +impl TranslationUnit { + /// Parse a source file into a translation unit. + pub fn parse(ix: &Index, + file: &str, + cmd_args: &[String], + unsaved: &[UnsavedFile], + opts: ::libc::c_uint) + -> Option { + let fname = CString::new(file).unwrap(); + let _c_args: Vec = + cmd_args.iter().map(|s| CString::new(s.clone()).unwrap()).collect(); + let c_args: Vec<*const c_char> = + _c_args.iter().map(|s| s.as_ptr()).collect(); + let mut c_unsaved: Vec = + unsaved.iter().map(|f| f.x).collect(); + let tu = unsafe { + clang_parseTranslationUnit(ix.x, + fname.as_ptr(), + c_args.as_ptr(), + c_args.len() as c_int, + c_unsaved.as_mut_ptr(), + c_unsaved.len() as c_uint, + opts) + }; + if tu.is_null() { + None + } else { + Some(TranslationUnit { + x: tu, + }) + } + } + + /// Reparse this translation unit, maybe because the file changed on disk or + /// something like that. + pub fn reparse(&self, unsaved: &[UnsavedFile], opts: usize) -> bool { + let mut c_unsaved: Vec = + unsaved.iter().map(|f| f.x).collect(); + + unsafe { + clang_reparseTranslationUnit(self.x, + c_unsaved.len() as c_uint, + c_unsaved.as_mut_ptr(), + opts as c_uint) == 0 + } + } + + /// Get the Clang diagnostic information associated with this translation + /// unit. + pub fn diags(&self) -> Vec { + unsafe { + let num = clang_getNumDiagnostics(self.x) as usize; + let mut diags = vec![]; + for i in 0..num { + diags.push(Diagnostic { + x: clang_getDiagnostic(self.x, i as c_uint), + }); + } + diags + } + } + + /// Get a cursor pointing to the root of this translation unit's AST. + pub fn cursor(&self) -> Cursor { + unsafe { + Cursor { + x: clang_getTranslationUnitCursor(self.x), + } + } + } + + /// Is this the null translation unit? + pub fn is_null(&self) -> bool { + self.x.is_null() + } + + /// Invoke Clang's lexer on this translation unit and get the stream of + /// tokens that come out. + pub fn tokens(&self, cursor: &Cursor) -> Option> { + let range = cursor.extent(); + let mut tokens = vec![]; + unsafe { + let mut token_ptr = ptr::null_mut(); + let mut num_tokens: c_uint = 0; + clang_tokenize(self.x, range, &mut token_ptr, &mut num_tokens); + if token_ptr.is_null() { + return None; + } + + let token_array = slice::from_raw_parts(token_ptr, + num_tokens as usize); + for &token in token_array.iter() { + let kind = clang_getTokenKind(token); + let spelling = clang_getTokenSpelling(self.x, token).into(); + + tokens.push(Token { + kind: kind, + spelling: spelling, + }); + } + clang_disposeTokens(self.x, token_ptr, num_tokens); + } + Some(tokens) + } + + /// Convert a set of tokens from clang into `cexpr` tokens, for further + /// processing. + pub fn cexpr_tokens(&self, + cursor: &Cursor) + -> Option> { + use cexpr::token; + + let mut tokens = match self.tokens(cursor) { + Some(tokens) => tokens, + None => return None, + }; + + // FIXME(emilio): LLVM 3.9 at least always include an extra token for no + // good reason (except if we're at EOF). So we do this kind of hack, + // where we skip known-to-cause problems trailing punctuation and + // trailing keywords. + // + // This is sort of unfortunate, though :(. + // + // I'll try to get it fixed in LLVM if I have the time to submit a + // patch. + let mut trim_last_token = false; + if let Some(token) = tokens.last() { + // The starting of the next macro. + trim_last_token |= token.spelling == "#" && + token.kind == CXToken_Punctuation; + + // A following keyword of any kind, like a following declaration. + trim_last_token |= token.kind == CXToken_Keyword; + } + + if trim_last_token { + tokens.pop().unwrap(); + } + + Some(tokens.into_iter() + .filter_map(|token| { + let kind = match token.kind { + CXToken_Punctuation => token::Kind::Punctuation, + CXToken_Literal => token::Kind::Literal, + CXToken_Identifier => token::Kind::Identifier, + CXToken_Keyword => token::Kind::Keyword, + // NB: cexpr is not too happy about comments inside + // expressions, so we strip them down here. + CXToken_Comment => return None, + _ => panic!("Found unexpected token kind: {}", token.kind), + }; + + Some(token::Token { + kind: kind, + raw: token.spelling.into_bytes().into_boxed_slice(), + }) + }) + .collect::>()) + } +} + +impl Drop for TranslationUnit { + fn drop(&mut self) { + unsafe { + clang_disposeTranslationUnit(self.x); + } + } +} + + +/// A diagnostic message generated while parsing a translation unit. +pub struct Diagnostic { + x: CXDiagnostic, +} + +impl Diagnostic { + /// Get the default diagnostic display option bit flags. + pub fn default_opts() -> usize { + unsafe { clang_defaultDiagnosticDisplayOptions() as usize } + } + + /// Format this diagnostic message as a string, using the given option bit + /// flags. + pub fn format(&self, opts: usize) -> String { + unsafe { clang_formatDiagnostic(self.x, opts as c_uint).into() } + } + + /// What is the severity of this diagnostic message? + pub fn severity(&self) -> Enum_CXDiagnosticSeverity { + unsafe { clang_getDiagnosticSeverity(self.x) } + } +} + +impl Drop for Diagnostic { + /// Destroy this diagnostic message. + fn drop(&mut self) { + unsafe { + clang_disposeDiagnostic(self.x); + } + } +} + +/// A file which has not been saved to disk. +pub struct UnsavedFile { + x: Struct_CXUnsavedFile, + name: CString, + contents: CString, +} + +impl UnsavedFile { + /// Construct a new unsaved file with the given `name` and `contents`. + pub fn new(name: &str, contents: &str) -> UnsavedFile { + let name = CString::new(name).unwrap(); + let contents = CString::new(contents).unwrap(); + let x = Struct_CXUnsavedFile { + Filename: name.as_ptr(), + Contents: contents.as_ptr(), + Length: contents.as_bytes().len() as c_ulong, + }; + UnsavedFile { + x: x, + name: name, + contents: contents, + } + } +} + +/// Convert a cursor kind into a static string. +pub fn kind_to_str(x: Enum_CXCursorKind) -> String { + unsafe { clang_getCursorKindSpelling(x) }.into() +} + +/// Convert a type kind to a static string. +pub fn type_to_str(x: Enum_CXTypeKind) -> String { + unsafe { clang_getTypeKindSpelling(x).into() } +} + +/// Dump the Clang AST to stdout for debugging purposes. +pub fn ast_dump(c: &Cursor, depth: isize) -> Enum_CXVisitorResult { + fn print_indent(depth: isize, s: &str) { + let mut i = 0; + while i < depth { + print!("\t"); + i += 1; + } + println!("{}", s); + } + let ct = c.cur_type().kind(); + print_indent(depth, + &format!("({} {} {}", + kind_to_str(c.kind()), + c.spelling(), + type_to_str(ct))); + c.visit(|s| ast_dump(&s, depth + 1)); + print_indent(depth, ")"); + CXChildVisit_Continue +} + +/// Try to extract the clang version to a string +pub fn extract_clang_version() -> String { + unsafe { clang_getClangVersion().into() } +} diff --git a/libbindgen/src/clangll.rs b/libbindgen/src/clangll.rs new file mode 100644 index 00000000..b9743117 --- /dev/null +++ b/libbindgen/src/clangll.rs @@ -0,0 +1,1439 @@ +/* automatically generated by rust-bindgen */ + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#![allow(unused_attributes)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![cfg_attr(rustfmt, rustfmt_skip)] + +use ::std::os::raw::{ c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void}; + +pub type ptrdiff_t = c_long; +pub type size_t = c_ulong; +pub type wchar_t = c_int; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXString { + pub data: *const c_void, + pub private_flags: c_uint, +} +pub type CXIndex = *mut c_void; +pub enum Struct_CXTranslationUnitImpl { } +pub type CXTranslationUnit = *mut Struct_CXTranslationUnitImpl; +pub type CXClientData = *mut c_void; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Struct_CXUnsavedFile { + pub Filename: *const c_char, + pub Contents: *const c_char, + pub Length: c_ulong, +} +pub type Enum_CXAvailabilityKind = c_uint; +pub const CXAvailability_Available: c_uint = 0; +pub const CXAvailability_Deprecated: c_uint = 1; +pub const CXAvailability_NotAvailable: c_uint = 2; +pub const CXAvailability_NotAccessible: c_uint = 3; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Struct_CXVersion { + pub Major: c_int, + pub Minor: c_int, + pub Subminor: c_int, +} +pub type CXVersion = Struct_CXVersion; +pub type CXGlobalOptFlags = c_uint; +pub const CXGlobalOpt_None: c_uint = 0; +pub const CXGlobalOpt_ThreadBackgroundPriorityForIndexing: c_uint = + 1; +pub const CXGlobalOpt_ThreadBackgroundPriorityForEditing: c_uint = 2; +pub const CXGlobalOpt_ThreadBackgroundPriorityForAll: c_uint = 3; +pub type CXFile = *mut c_void; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXFileUniqueID { + pub data: [c_ulonglong; 3], +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXSourceLocation { + pub ptr_data: [*const c_void; 2], + pub int_data: c_uint, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXSourceRange { + pub ptr_data: [*const c_void; 2], + pub begin_int_data: c_uint, + pub end_int_data: c_uint, +} +pub type Enum_CXDiagnosticSeverity = c_uint; +pub const CXDiagnostic_Ignored: c_uint = 0; +pub const CXDiagnostic_Note: c_uint = 1; +pub const CXDiagnostic_Warning: c_uint = 2; +pub const CXDiagnostic_Error: c_uint = 3; +pub const CXDiagnostic_Fatal: c_uint = 4; +pub type CXDiagnostic = *mut c_void; +pub type CXDiagnosticSet = *mut c_void; +pub type Enum_CXLoadDiag_Error = c_uint; +pub const CXLoadDiag_None: c_uint = 0; +pub const CXLoadDiag_Unknown: c_uint = 1; +pub const CXLoadDiag_CannotLoad: c_uint = 2; +pub const CXLoadDiag_InvalidFile: c_uint = 3; +pub type Enum_CXDiagnosticDisplayOptions = c_uint; +pub const CXDiagnostic_DisplaySourceLocation: c_uint = 1; +pub const CXDiagnostic_DisplayColumn: c_uint = 2; +pub const CXDiagnostic_DisplaySourceRanges: c_uint = 4; +pub const CXDiagnostic_DisplayOption: c_uint = 8; +pub const CXDiagnostic_DisplayCategoryId: c_uint = 16; +pub const CXDiagnostic_DisplayCategoryName: c_uint = 32; +pub type Enum_CXTranslationUnit_Flags = c_uint; +pub const CXTranslationUnit_None: c_uint = 0; +pub const CXTranslationUnit_DetailedPreprocessingRecord: c_uint = 1; +pub const CXTranslationUnit_Incomplete: c_uint = 2; +pub const CXTranslationUnit_PrecompiledPreamble: c_uint = 4; +pub const CXTranslationUnit_CacheCompletionResults: c_uint = 8; +pub const CXTranslationUnit_ForSerialization: c_uint = 16; +pub const CXTranslationUnit_CXXChainedPCH: c_uint = 32; +pub const CXTranslationUnit_SkipFunctionBodies: c_uint = 64; +pub const CXTranslationUnit_IncludeBriefCommentsInCodeCompletion: + c_uint = + 128; +pub type Enum_CXSaveTranslationUnit_Flags = c_uint; +pub const CXSaveTranslationUnit_None: c_uint = 0; +pub type Enum_CXSaveError = c_uint; +pub const CXSaveError_None: c_uint = 0; +pub const CXSaveError_Unknown: c_uint = 1; +pub const CXSaveError_TranslationErrors: c_uint = 2; +pub const CXSaveError_InvalidTU: c_uint = 3; +pub type Enum_CXReparse_Flags = c_uint; +pub const CXReparse_None: c_uint = 0; +pub type Enum_CXTUResourceUsageKind = c_uint; +pub const CXTUResourceUsage_AST: c_uint = 1; +pub const CXTUResourceUsage_Identifiers: c_uint = 2; +pub const CXTUResourceUsage_Selectors: c_uint = 3; +pub const CXTUResourceUsage_GlobalCompletionResults: c_uint = 4; +pub const CXTUResourceUsage_SourceManagerContentCache: c_uint = 5; +pub const CXTUResourceUsage_AST_SideTables: c_uint = 6; +pub const CXTUResourceUsage_SourceManager_Membuffer_Malloc: c_uint = + 7; +pub const CXTUResourceUsage_SourceManager_Membuffer_MMap: c_uint = 8; +pub const CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc: + c_uint = + 9; +pub const CXTUResourceUsage_ExternalASTSource_Membuffer_MMap: c_uint + = + 10; +pub const CXTUResourceUsage_Preprocessor: c_uint = 11; +pub const CXTUResourceUsage_PreprocessingRecord: c_uint = 12; +pub const CXTUResourceUsage_SourceManager_DataStructures: c_uint = + 13; +pub const CXTUResourceUsage_Preprocessor_HeaderSearch: c_uint = 14; +pub const CXTUResourceUsage_MEMORY_IN_BYTES_BEGIN: c_uint = 1; +pub const CXTUResourceUsage_MEMORY_IN_BYTES_END: c_uint = 14; +pub const CXTUResourceUsage_First: c_uint = 1; +pub const CXTUResourceUsage_Last: c_uint = 14; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Struct_CXTUResourceUsageEntry { + pub kind: Enum_CXTUResourceUsageKind, + pub amount: c_ulong, +} +pub type CXTUResourceUsageEntry = Struct_CXTUResourceUsageEntry; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Struct_CXTUResourceUsage { + pub data: *mut c_void, + pub numEntries: c_uint, + pub entries: *mut CXTUResourceUsageEntry, +} +pub type CXTUResourceUsage = Struct_CXTUResourceUsage; +pub type Enum_CXCursorKind = c_uint; +pub const CXCursor_UnexposedDecl: c_uint = 1; +pub const CXCursor_StructDecl: c_uint = 2; +pub const CXCursor_UnionDecl: c_uint = 3; +pub const CXCursor_ClassDecl: c_uint = 4; +pub const CXCursor_EnumDecl: c_uint = 5; +pub const CXCursor_FieldDecl: c_uint = 6; +pub const CXCursor_EnumConstantDecl: c_uint = 7; +pub const CXCursor_FunctionDecl: c_uint = 8; +pub const CXCursor_VarDecl: c_uint = 9; +pub const CXCursor_ParmDecl: c_uint = 10; +pub const CXCursor_ObjCInterfaceDecl: c_uint = 11; +pub const CXCursor_ObjCCategoryDecl: c_uint = 12; +pub const CXCursor_ObjCProtocolDecl: c_uint = 13; +pub const CXCursor_ObjCPropertyDecl: c_uint = 14; +pub const CXCursor_ObjCIvarDecl: c_uint = 15; +pub const CXCursor_ObjCInstanceMethodDecl: c_uint = 16; +pub const CXCursor_ObjCClassMethodDecl: c_uint = 17; +pub const CXCursor_ObjCImplementationDecl: c_uint = 18; +pub const CXCursor_ObjCCategoryImplDecl: c_uint = 19; +pub const CXCursor_TypedefDecl: c_uint = 20; +pub const CXCursor_CXXMethod: c_uint = 21; +pub const CXCursor_Namespace: c_uint = 22; +pub const CXCursor_LinkageSpec: c_uint = 23; +pub const CXCursor_Constructor: c_uint = 24; +pub const CXCursor_Destructor: c_uint = 25; +pub const CXCursor_ConversionFunction: c_uint = 26; +pub const CXCursor_TemplateTypeParameter: c_uint = 27; +pub const CXCursor_NonTypeTemplateParameter: c_uint = 28; +pub const CXCursor_TemplateTemplateParameter: c_uint = 29; +pub const CXCursor_FunctionTemplate: c_uint = 30; +pub const CXCursor_ClassTemplate: c_uint = 31; +pub const CXCursor_ClassTemplatePartialSpecialization: c_uint = 32; +pub const CXCursor_NamespaceAlias: c_uint = 33; +pub const CXCursor_UsingDirective: c_uint = 34; +pub const CXCursor_UsingDeclaration: c_uint = 35; +pub const CXCursor_TypeAliasDecl: c_uint = 36; +pub const CXCursor_ObjCSynthesizeDecl: c_uint = 37; +pub const CXCursor_ObjCDynamicDecl: c_uint = 38; +pub const CXCursor_CXXAccessSpecifier: c_uint = 39; +pub const CXCursor_FirstDecl: c_uint = 1; +pub const CXCursor_LastDecl: c_uint = 39; +pub const CXCursor_FirstRef: c_uint = 40; +pub const CXCursor_ObjCSuperClassRef: c_uint = 40; +pub const CXCursor_ObjCProtocolRef: c_uint = 41; +pub const CXCursor_ObjCClassRef: c_uint = 42; +pub const CXCursor_TypeRef: c_uint = 43; +pub const CXCursor_CXXBaseSpecifier: c_uint = 44; +pub const CXCursor_TemplateRef: c_uint = 45; +pub const CXCursor_NamespaceRef: c_uint = 46; +pub const CXCursor_MemberRef: c_uint = 47; +pub const CXCursor_LabelRef: c_uint = 48; +pub const CXCursor_OverloadedDeclRef: c_uint = 49; +pub const CXCursor_VariableRef: c_uint = 50; +pub const CXCursor_LastRef: c_uint = 50; +pub const CXCursor_FirstInvalid: c_uint = 70; +pub const CXCursor_InvalidFile: c_uint = 70; +pub const CXCursor_NoDeclFound: c_uint = 71; +pub const CXCursor_NotImplemented: c_uint = 72; +pub const CXCursor_InvalidCode: c_uint = 73; +pub const CXCursor_LastInvalid: c_uint = 73; +pub const CXCursor_FirstExpr: c_uint = 100; +pub const CXCursor_UnexposedExpr: c_uint = 100; +pub const CXCursor_DeclRefExpr: c_uint = 101; +pub const CXCursor_MemberRefExpr: c_uint = 102; +pub const CXCursor_CallExpr: c_uint = 103; +pub const CXCursor_ObjCMessageExpr: c_uint = 104; +pub const CXCursor_BlockExpr: c_uint = 105; +pub const CXCursor_IntegerLiteral: c_uint = 106; +pub const CXCursor_FloatingLiteral: c_uint = 107; +pub const CXCursor_ImaginaryLiteral: c_uint = 108; +pub const CXCursor_StringLiteral: c_uint = 109; +pub const CXCursor_CharacterLiteral: c_uint = 110; +pub const CXCursor_ParenExpr: c_uint = 111; +pub const CXCursor_UnaryOperator: c_uint = 112; +pub const CXCursor_ArraySubscriptExpr: c_uint = 113; +pub const CXCursor_BinaryOperator: c_uint = 114; +pub const CXCursor_CompoundAssignOperator: c_uint = 115; +pub const CXCursor_ConditionalOperator: c_uint = 116; +pub const CXCursor_CStyleCastExpr: c_uint = 117; +pub const CXCursor_CompoundLiteralExpr: c_uint = 118; +pub const CXCursor_InitListExpr: c_uint = 119; +pub const CXCursor_AddrLabelExpr: c_uint = 120; +pub const CXCursor_StmtExpr: c_uint = 121; +pub const CXCursor_GenericSelectionExpr: c_uint = 122; +pub const CXCursor_GNUNullExpr: c_uint = 123; +pub const CXCursor_CXXStaticCastExpr: c_uint = 124; +pub const CXCursor_CXXDynamicCastExpr: c_uint = 125; +pub const CXCursor_CXXReinterpretCastExpr: c_uint = 126; +pub const CXCursor_CXXConstCastExpr: c_uint = 127; +pub const CXCursor_CXXFunctionalCastExpr: c_uint = 128; +pub const CXCursor_CXXTypeidExpr: c_uint = 129; +pub const CXCursor_CXXBoolLiteralExpr: c_uint = 130; +pub const CXCursor_CXXNullPtrLiteralExpr: c_uint = 131; +pub const CXCursor_CXXThisExpr: c_uint = 132; +pub const CXCursor_CXXThrowExpr: c_uint = 133; +pub const CXCursor_CXXNewExpr: c_uint = 134; +pub const CXCursor_CXXDeleteExpr: c_uint = 135; +pub const CXCursor_UnaryExpr: c_uint = 136; +pub const CXCursor_ObjCStringLiteral: c_uint = 137; +pub const CXCursor_ObjCEncodeExpr: c_uint = 138; +pub const CXCursor_ObjCSelectorExpr: c_uint = 139; +pub const CXCursor_ObjCProtocolExpr: c_uint = 140; +pub const CXCursor_ObjCBridgedCastExpr: c_uint = 141; +pub const CXCursor_PackExpansionExpr: c_uint = 142; +pub const CXCursor_SizeOfPackExpr: c_uint = 143; +pub const CXCursor_LambdaExpr: c_uint = 144; +pub const CXCursor_ObjCBoolLiteralExpr: c_uint = 145; +pub const CXCursor_ObjCSelfExpr: c_uint = 146; +pub const CXCursor_LastExpr: c_uint = 146; +pub const CXCursor_FirstStmt: c_uint = 200; +pub const CXCursor_UnexposedStmt: c_uint = 200; +pub const CXCursor_LabelStmt: c_uint = 201; +pub const CXCursor_CompoundStmt: c_uint = 202; +pub const CXCursor_CaseStmt: c_uint = 203; +pub const CXCursor_DefaultStmt: c_uint = 204; +pub const CXCursor_IfStmt: c_uint = 205; +pub const CXCursor_SwitchStmt: c_uint = 206; +pub const CXCursor_WhileStmt: c_uint = 207; +pub const CXCursor_DoStmt: c_uint = 208; +pub const CXCursor_ForStmt: c_uint = 209; +pub const CXCursor_GotoStmt: c_uint = 210; +pub const CXCursor_IndirectGotoStmt: c_uint = 211; +pub const CXCursor_ContinueStmt: c_uint = 212; +pub const CXCursor_BreakStmt: c_uint = 213; +pub const CXCursor_ReturnStmt: c_uint = 214; +pub const CXCursor_GCCAsmStmt: c_uint = 215; +pub const CXCursor_AsmStmt: c_uint = 215; +pub const CXCursor_ObjCAtTryStmt: c_uint = 216; +pub const CXCursor_ObjCAtCatchStmt: c_uint = 217; +pub const CXCursor_ObjCAtFinallyStmt: c_uint = 218; +pub const CXCursor_ObjCAtThrowStmt: c_uint = 219; +pub const CXCursor_ObjCAtSynchronizedStmt: c_uint = 220; +pub const CXCursor_ObjCAutoreleasePoolStmt: c_uint = 221; +pub const CXCursor_ObjCForCollectionStmt: c_uint = 222; +pub const CXCursor_CXXCatchStmt: c_uint = 223; +pub const CXCursor_CXXTryStmt: c_uint = 224; +pub const CXCursor_CXXForRangeStmt: c_uint = 225; +pub const CXCursor_SEHTryStmt: c_uint = 226; +pub const CXCursor_SEHExceptStmt: c_uint = 227; +pub const CXCursor_SEHFinallyStmt: c_uint = 228; +pub const CXCursor_MSAsmStmt: c_uint = 229; +pub const CXCursor_NullStmt: c_uint = 230; +pub const CXCursor_DeclStmt: c_uint = 231; +pub const CXCursor_OMPParallelDirective: c_uint = 232; +pub const CXCursor_LastStmt: c_uint = 232; +pub const CXCursor_TranslationUnit: c_uint = 300; +pub const CXCursor_FirstAttr: c_uint = 400; +pub const CXCursor_UnexposedAttr: c_uint = 400; +pub const CXCursor_IBActionAttr: c_uint = 401; +pub const CXCursor_IBOutletAttr: c_uint = 402; +pub const CXCursor_IBOutletCollectionAttr: c_uint = 403; +pub const CXCursor_CXXFinalAttr: c_uint = 404; +pub const CXCursor_CXXOverrideAttr: c_uint = 405; +pub const CXCursor_AnnotateAttr: c_uint = 406; +pub const CXCursor_AsmLabelAttr: c_uint = 407; +pub const CXCursor_PackedAttr: c_uint = 408; +pub const CXCursor_LastAttr: c_uint = 408; +pub const CXCursor_PreprocessingDirective: c_uint = 500; +pub const CXCursor_MacroDefinition: c_uint = 501; +pub const CXCursor_MacroExpansion: c_uint = 502; +pub const CXCursor_MacroInstantiation: c_uint = 502; +pub const CXCursor_InclusionDirective: c_uint = 503; +pub const CXCursor_FirstPreprocessing: c_uint = 500; +pub const CXCursor_LastPreprocessing: c_uint = 503; +pub const CXCursor_ModuleImportDecl: c_uint = 600; +pub const CXCursor_TypeAliasTemplateDecl: c_uint = 601; +pub const CXCursor_StaticAssert: c_uint = 602; +pub const CXCursor_FirstExtraDecl: c_uint = 600; +pub const CXCursor_LastExtraDecl: c_uint = 602; +pub const CXCursor_OverloadCandidate: c_uint = 700; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXCursor { + pub kind: Enum_CXCursorKind, + pub xdata: c_int, + pub data: [*const c_void; 3], +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXComment { + pub ASTNode: *const c_void, + pub TranslationUnit: CXTranslationUnit, +} +pub type Enum_CXLinkageKind = ::libc::c_uint; +pub const CXLinkage_Invalid: ::libc::c_uint = 0; +pub const CXLinkage_NoLinkage: ::libc::c_uint = 1; +pub const CXLinkage_Internal: ::libc::c_uint = 2; +pub const CXLinkage_UniqueExternal: ::libc::c_uint = 3; +pub const CXLinkage_External: ::libc::c_uint = 4; +pub type Enum_CXVisibilityKind = ::libc::c_uint; +pub const CXVisibility_Invalid: ::libc::c_uint = 0; +pub const CXVisibility_Hidden: ::libc::c_uint = 1; +pub const CXVisibility_Protected: ::libc::c_uint = 2; +pub const CXVisibility_Default: ::libc::c_uint = 3; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Struct_CXPlatformAvailability { + pub Platform: CXString, + pub Introduced: CXVersion, + pub Deprecated: CXVersion, + pub Obsoleted: CXVersion, + pub Unavailable: c_int, + pub Message: CXString, +} +pub type CXPlatformAvailability = Struct_CXPlatformAvailability; +pub type Enum_CXLanguageKind = c_uint; +pub const CXLanguage_Invalid: c_uint = 0; +pub const CXLanguage_C: c_uint = 1; +pub const CXLanguage_ObjC: c_uint = 2; +pub const CXLanguage_CPlusPlus: c_uint = 3; +pub enum Struct_CXCursorSetImpl { } +pub type CXCursorSet = *mut Struct_CXCursorSetImpl; +pub type Enum_CXTypeKind = c_uint; +pub const CXType_Invalid: c_uint = 0; +pub const CXType_Unexposed: c_uint = 1; +pub const CXType_Void: c_uint = 2; +pub const CXType_Bool: c_uint = 3; +pub const CXType_Char_U: c_uint = 4; +pub const CXType_UChar: c_uint = 5; +pub const CXType_Char16: c_uint = 6; +pub const CXType_Char32: c_uint = 7; +pub const CXType_UShort: c_uint = 8; +pub const CXType_UInt: c_uint = 9; +pub const CXType_ULong: c_uint = 10; +pub const CXType_ULongLong: c_uint = 11; +pub const CXType_UInt128: c_uint = 12; +pub const CXType_Char_S: c_uint = 13; +pub const CXType_SChar: c_uint = 14; +pub const CXType_WChar: c_uint = 15; +pub const CXType_Short: c_uint = 16; +pub const CXType_Int: c_uint = 17; +pub const CXType_Long: c_uint = 18; +pub const CXType_LongLong: c_uint = 19; +pub const CXType_Int128: c_uint = 20; +pub const CXType_Float: c_uint = 21; +pub const CXType_Double: c_uint = 22; +pub const CXType_LongDouble: c_uint = 23; +pub const CXType_NullPtr: c_uint = 24; +pub const CXType_Overload: c_uint = 25; +pub const CXType_Dependent: c_uint = 26; +pub const CXType_ObjCId: c_uint = 27; +pub const CXType_ObjCClass: c_uint = 28; +pub const CXType_ObjCSel: c_uint = 29; +pub const CXType_Float128: c_uint = 30; +pub const CXType_FirstBuiltin: c_uint = 2; +pub const CXType_LastBuiltin: c_uint = 29; +pub const CXType_Complex: c_uint = 100; +pub const CXType_Pointer: c_uint = 101; +pub const CXType_BlockPointer: c_uint = 102; +pub const CXType_LValueReference: c_uint = 103; +pub const CXType_RValueReference: c_uint = 104; +pub const CXType_Record: c_uint = 105; +pub const CXType_Enum: c_uint = 106; +pub const CXType_Typedef: c_uint = 107; +pub const CXType_ObjCInterface: c_uint = 108; +pub const CXType_ObjCObjectPointer: c_uint = 109; +pub const CXType_FunctionNoProto: c_uint = 110; +pub const CXType_FunctionProto: c_uint = 111; +pub const CXType_ConstantArray: c_uint = 112; +pub const CXType_Vector: c_uint = 113; +pub const CXType_IncompleteArray: c_uint = 114; +pub const CXType_VariableArray: c_uint = 115; +pub const CXType_DependentSizedArray: c_uint = 116; +pub const CXType_MemberPointer: c_uint = 117; +#[cfg(not(feature="llvm_stable"))] +pub const CXType_Auto: c_uint = 118; +#[cfg(not(feature="llvm_stable"))] +pub const CXType_Elaborated: c_uint = 119; +pub type Enum_CXCallingConv = c_uint; +pub const CXCallingConv_Default: c_uint = 0; +pub const CXCallingConv_C: c_uint = 1; +pub const CXCallingConv_X86StdCall: c_uint = 2; +pub const CXCallingConv_X86FastCall: c_uint = 3; +pub const CXCallingConv_X86ThisCall: c_uint = 4; +pub const CXCallingConv_X86Pascal: c_uint = 5; +pub const CXCallingConv_AAPCS: c_uint = 6; +pub const CXCallingConv_AAPCS_VFP: c_uint = 7; +pub const CXCallingConv_PnaclCall: c_uint = 8; +pub const CXCallingConv_IntelOclBicc: c_uint = 9; +pub const CXCallingConv_X86_64Win64: c_uint = 10; +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, Hash)] +pub struct CXType { + pub kind: Enum_CXTypeKind, + pub data: [*mut c_void; 2], +} +pub type Enum_CXTypeLayoutError = c_int; +pub const CXTypeLayoutError_Invalid: c_int = -1; +pub const CXTypeLayoutError_Incomplete: c_int = -2; +pub const CXTypeLayoutError_Dependent: c_int = -3; +pub const CXTypeLayoutError_NotConstantSize: c_int = -4; +pub const CXTypeLayoutError_InvalidFieldName: c_int = -5; +pub type Enum_CXRefQualifierKind = c_uint; +pub const CXRefQualifier_None: c_uint = 0; +pub const CXRefQualifier_LValue: c_uint = 1; +pub const CXRefQualifier_RValue: c_uint = 2; +pub type Enum_CX_CXXAccessSpecifier = c_uint; +pub const CX_CXXInvalidAccessSpecifier: c_uint = 0; +pub const CX_CXXPublic: c_uint = 1; +pub const CX_CXXProtected: c_uint = 2; +pub const CX_CXXPrivate: c_uint = 3; +pub type Enum_CXChildVisitResult = c_uint; +pub const CXChildVisit_Break: c_uint = 0; +pub const CXChildVisit_Continue: c_uint = 1; +pub const CXChildVisit_Recurse: c_uint = 2; +pub type CXCursorVisitor = + ::std::option::Option Enum_CXChildVisitResult>; +pub type CXObjCPropertyAttrKind = c_uint; +pub const CXObjCPropertyAttr_noattr: c_uint = 0; +pub const CXObjCPropertyAttr_readonly: c_uint = 1; +pub const CXObjCPropertyAttr_getter: c_uint = 2; +pub const CXObjCPropertyAttr_assign: c_uint = 4; +pub const CXObjCPropertyAttr_readwrite: c_uint = 8; +pub const CXObjCPropertyAttr_retain: c_uint = 16; +pub const CXObjCPropertyAttr_copy: c_uint = 32; +pub const CXObjCPropertyAttr_nonatomic: c_uint = 64; +pub const CXObjCPropertyAttr_setter: c_uint = 128; +pub const CXObjCPropertyAttr_atomic: c_uint = 256; +pub const CXObjCPropertyAttr_weak: c_uint = 512; +pub const CXObjCPropertyAttr_strong: c_uint = 1024; +pub const CXObjCPropertyAttr_unsafe_unretained: c_uint = 2048; +pub type CXObjCDeclQualifierKind = c_uint; +pub const CXObjCDeclQualifier_None: c_uint = 0; +pub const CXObjCDeclQualifier_In: c_uint = 1; +pub const CXObjCDeclQualifier_Inout: c_uint = 2; +pub const CXObjCDeclQualifier_Out: c_uint = 4; +pub const CXObjCDeclQualifier_Bycopy: c_uint = 8; +pub const CXObjCDeclQualifier_Byref: c_uint = 16; +pub const CXObjCDeclQualifier_Oneway: c_uint = 32; +pub type CXModule = *mut c_void; +pub type Enum_CXCommentKind = c_uint; +pub const CXComment_Null: c_uint = 0; +pub const CXComment_Text: c_uint = 1; +pub const CXComment_InlineCommand: c_uint = 2; +pub const CXComment_HTMLStartTag: c_uint = 3; +pub const CXComment_HTMLEndTag: c_uint = 4; +pub const CXComment_Paragraph: c_uint = 5; +pub const CXComment_BlockCommand: c_uint = 6; +pub const CXComment_ParamCommand: c_uint = 7; +pub const CXComment_TParamCommand: c_uint = 8; +pub const CXComment_VerbatimBlockCommand: c_uint = 9; +pub const CXComment_VerbatimBlockLine: c_uint = 10; +pub const CXComment_VerbatimLine: c_uint = 11; +pub const CXComment_FullComment: c_uint = 12; +pub type Enum_CXCommentInlineCommandRenderKind = c_uint; +pub const CXCommentInlineCommandRenderKind_Normal: c_uint = 0; +pub const CXCommentInlineCommandRenderKind_Bold: c_uint = 1; +pub const CXCommentInlineCommandRenderKind_Monospaced: c_uint = 2; +pub const CXCommentInlineCommandRenderKind_Emphasized: c_uint = 3; +pub type Enum_CXCommentParamPassDirection = c_uint; +pub const CXCommentParamPassDirection_In: c_uint = 0; +pub const CXCommentParamPassDirection_Out: c_uint = 1; +pub const CXCommentParamPassDirection_InOut: c_uint = 2; +pub type Enum_CXNameRefFlags = c_uint; +pub const CXNameRange_WantQualifier: c_uint = 1; +pub const CXNameRange_WantTemplateArgs: c_uint = 2; +pub const CXNameRange_WantSinglePiece: c_uint = 4; +pub type Enum_CXTokenKind = c_uint; +pub const CXToken_Punctuation: c_uint = 0; +pub const CXToken_Keyword: c_uint = 1; +pub const CXToken_Identifier: c_uint = 2; +pub const CXToken_Literal: c_uint = 3; +pub const CXToken_Comment: c_uint = 4; +pub type CXTokenKind = Enum_CXTokenKind; +pub type Enum_CXTemplateArgumentKind = c_uint; +pub const CXTemplateArgumentKind_Null: c_uint = 0; +pub const CXTemplateArgumentKind_Type: c_uint = 1; +pub const CXTemplateArgumentKind_Declaration: c_uint = 2; +pub const CXTemplateArgumentKind_NullPtr: c_uint = 3; +pub const CXTemplateArgumentKind_Integral: c_uint = 4; +pub const CXTemplateArgumentKind_Template: c_uint = 5; +pub const CXTemplateArgumentKind_TemplateExpansion: c_uint = 6; +pub const CXTemplateArgumentKind_Expression: c_uint = 7; +pub const CXTemplateArgumentKind_Pack: c_uint = 8; +pub const CXTemplateArgumentKind_Invalid: c_uint = 9; +pub type CXTemplateArgumentKind = Enum_CXTemplateArgumentKind; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXToken { + pub int_data: [c_uint; 4], + pub ptr_data: *mut c_void, +} +pub type CXCompletionString = *mut c_void; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXCompletionResult { + pub CursorKind: Enum_CXCursorKind, + pub CompletionString: CXCompletionString, +} +pub type Enum_CXCompletionChunkKind = c_uint; +pub const CXCompletionChunk_Optional: c_uint = 0; +pub const CXCompletionChunk_TypedText: c_uint = 1; +pub const CXCompletionChunk_Text: c_uint = 2; +pub const CXCompletionChunk_Placeholder: c_uint = 3; +pub const CXCompletionChunk_Informative: c_uint = 4; +pub const CXCompletionChunk_CurrentParameter: c_uint = 5; +pub const CXCompletionChunk_LeftParen: c_uint = 6; +pub const CXCompletionChunk_RightParen: c_uint = 7; +pub const CXCompletionChunk_LeftBracket: c_uint = 8; +pub const CXCompletionChunk_RightBracket: c_uint = 9; +pub const CXCompletionChunk_LeftBrace: c_uint = 10; +pub const CXCompletionChunk_RightBrace: c_uint = 11; +pub const CXCompletionChunk_LeftAngle: c_uint = 12; +pub const CXCompletionChunk_RightAngle: c_uint = 13; +pub const CXCompletionChunk_Comma: c_uint = 14; +pub const CXCompletionChunk_ResultType: c_uint = 15; +pub const CXCompletionChunk_Colon: c_uint = 16; +pub const CXCompletionChunk_SemiColon: c_uint = 17; +pub const CXCompletionChunk_Equal: c_uint = 18; +pub const CXCompletionChunk_HorizontalSpace: c_uint = 19; +pub const CXCompletionChunk_VerticalSpace: c_uint = 20; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXCodeCompleteResults { + pub Results: *mut CXCompletionResult, + pub NumResults: c_uint, +} +pub type Enum_CXCodeComplete_Flags = c_uint; +pub const CXCodeComplete_IncludeMacros: c_uint = 1; +pub const CXCodeComplete_IncludeCodePatterns: c_uint = 2; +pub const CXCodeComplete_IncludeBriefComments: c_uint = 4; +pub type Enum_CXCompletionContext = c_uint; +pub const CXCompletionContext_Unexposed: c_uint = 0; +pub const CXCompletionContext_AnyType: c_uint = 1; +pub const CXCompletionContext_AnyValue: c_uint = 2; +pub const CXCompletionContext_ObjCObjectValue: c_uint = 4; +pub const CXCompletionContext_ObjCSelectorValue: c_uint = 8; +pub const CXCompletionContext_CXXClassTypeValue: c_uint = 16; +pub const CXCompletionContext_DotMemberAccess: c_uint = 32; +pub const CXCompletionContext_ArrowMemberAccess: c_uint = 64; +pub const CXCompletionContext_ObjCPropertyAccess: c_uint = 128; +pub const CXCompletionContext_EnumTag: c_uint = 256; +pub const CXCompletionContext_UnionTag: c_uint = 512; +pub const CXCompletionContext_StructTag: c_uint = 1024; +pub const CXCompletionContext_ClassTag: c_uint = 2048; +pub const CXCompletionContext_Namespace: c_uint = 4096; +pub const CXCompletionContext_NestedNameSpecifier: c_uint = 8192; +pub const CXCompletionContext_ObjCInterface: c_uint = 16384; +pub const CXCompletionContext_ObjCProtocol: c_uint = 32768; +pub const CXCompletionContext_ObjCCategory: c_uint = 65536; +pub const CXCompletionContext_ObjCInstanceMessage: c_uint = 131072; +pub const CXCompletionContext_ObjCClassMessage: c_uint = 262144; +pub const CXCompletionContext_ObjCSelectorName: c_uint = 524288; +pub const CXCompletionContext_MacroName: c_uint = 1048576; +pub const CXCompletionContext_NaturalLanguage: c_uint = 2097152; +pub const CXCompletionContext_Unknown: c_uint = 4194303; +pub type CXInclusionVisitor = + ::std::option::Option; +pub type CXRemapping = *mut c_void; +pub type Enum_CXVisitorResult = c_uint; +pub const CXVisit_Break: c_uint = 0; +pub const CXVisit_Continue: c_uint = 1; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXCursorAndRangeVisitor { + pub context: *mut c_void, + pub visit: ::std::option::Option Enum_CXVisitorResult>, +} +pub type CXResult = c_uint; +pub const CXResult_Success: c_uint = 0; +pub const CXResult_Invalid: c_uint = 1; +pub const CXResult_VisitBreak: c_uint = 2; +pub type CXIdxClientFile = *mut c_void; +pub type CXIdxClientEntity = *mut c_void; +pub type CXIdxClientContainer = *mut c_void; +pub type CXIdxClientASTFile = *mut c_void; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxLoc { + pub ptr_data: [*mut c_void; 2], + pub int_data: c_uint, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxIncludedFileInfo { + pub hashLoc: CXIdxLoc, + pub filename: *const c_char, + pub file: CXFile, + pub isImport: c_int, + pub isAngled: c_int, + pub isModuleImport: c_int, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxImportedASTFileInfo { + pub file: CXFile, + pub module: CXModule, + pub loc: CXIdxLoc, + pub isImplicit: c_int, +} +pub type CXIdxEntityKind = c_uint; +pub const CXIdxEntity_Unexposed: c_uint = 0; +pub const CXIdxEntity_Typedef: c_uint = 1; +pub const CXIdxEntity_Function: c_uint = 2; +pub const CXIdxEntity_Variable: c_uint = 3; +pub const CXIdxEntity_Field: c_uint = 4; +pub const CXIdxEntity_EnumConstant: c_uint = 5; +pub const CXIdxEntity_ObjCClass: c_uint = 6; +pub const CXIdxEntity_ObjCProtocol: c_uint = 7; +pub const CXIdxEntity_ObjCCategory: c_uint = 8; +pub const CXIdxEntity_ObjCInstanceMethod: c_uint = 9; +pub const CXIdxEntity_ObjCClassMethod: c_uint = 10; +pub const CXIdxEntity_ObjCProperty: c_uint = 11; +pub const CXIdxEntity_ObjCIvar: c_uint = 12; +pub const CXIdxEntity_Enum: c_uint = 13; +pub const CXIdxEntity_Struct: c_uint = 14; +pub const CXIdxEntity_Union: c_uint = 15; +pub const CXIdxEntity_CXXClass: c_uint = 16; +pub const CXIdxEntity_CXXNamespace: c_uint = 17; +pub const CXIdxEntity_CXXNamespaceAlias: c_uint = 18; +pub const CXIdxEntity_CXXStaticVariable: c_uint = 19; +pub const CXIdxEntity_CXXStaticMethod: c_uint = 20; +pub const CXIdxEntity_CXXInstanceMethod: c_uint = 21; +pub const CXIdxEntity_CXXConstructor: c_uint = 22; +pub const CXIdxEntity_CXXDestructor: c_uint = 23; +pub const CXIdxEntity_CXXConversionFunction: c_uint = 24; +pub const CXIdxEntity_CXXTypeAlias: c_uint = 25; +pub const CXIdxEntity_CXXInterface: c_uint = 26; +pub type CXIdxEntityLanguage = c_uint; +pub const CXIdxEntityLang_None: c_uint = 0; +pub const CXIdxEntityLang_C: c_uint = 1; +pub const CXIdxEntityLang_ObjC: c_uint = 2; +pub const CXIdxEntityLang_CXX: c_uint = 3; +pub type CXIdxEntityCXXTemplateKind = c_uint; +pub const CXIdxEntity_NonTemplate: c_uint = 0; +pub const CXIdxEntity_Template: c_uint = 1; +pub const CXIdxEntity_TemplatePartialSpecialization: c_uint = 2; +pub const CXIdxEntity_TemplateSpecialization: c_uint = 3; +pub type CXIdxAttrKind = c_uint; +pub const CXIdxAttr_Unexposed: c_uint = 0; +pub const CXIdxAttr_IBAction: c_uint = 1; +pub const CXIdxAttr_IBOutlet: c_uint = 2; +pub const CXIdxAttr_IBOutletCollection: c_uint = 3; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxAttrInfo { + pub kind: CXIdxAttrKind, + pub cursor: CXCursor, + pub loc: CXIdxLoc, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxEntityInfo { + pub kind: CXIdxEntityKind, + pub templateKind: CXIdxEntityCXXTemplateKind, + pub lang: CXIdxEntityLanguage, + pub name: *const c_char, + pub USR: *const c_char, + pub cursor: CXCursor, + pub attributes: *const *const CXIdxAttrInfo, + pub numAttributes: c_uint, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxContainerInfo { + pub cursor: CXCursor, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxIBOutletCollectionAttrInfo { + pub attrInfo: *const CXIdxAttrInfo, + pub objcClass: *const CXIdxEntityInfo, + pub classCursor: CXCursor, + pub classLoc: CXIdxLoc, +} +pub type CXIdxDeclInfoFlags = c_uint; +pub const CXIdxDeclFlag_Skipped: c_uint = 1; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxDeclInfo { + pub entityInfo: *const CXIdxEntityInfo, + pub cursor: CXCursor, + pub loc: CXIdxLoc, + pub semanticContainer: *const CXIdxContainerInfo, + pub lexicalContainer: *const CXIdxContainerInfo, + pub isRedeclaration: c_int, + pub isDefinition: c_int, + pub isContainer: c_int, + pub declAsContainer: *const CXIdxContainerInfo, + pub isImplicit: c_int, + pub attributes: *const *const CXIdxAttrInfo, + pub numAttributes: c_uint, + pub flags: c_uint, +} +pub type CXIdxObjCContainerKind = c_uint; +pub const CXIdxObjCContainer_ForwardRef: c_uint = 0; +pub const CXIdxObjCContainer_Interface: c_uint = 1; +pub const CXIdxObjCContainer_Implementation: c_uint = 2; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxObjCContainerDeclInfo { + pub declInfo: *const CXIdxDeclInfo, + pub kind: CXIdxObjCContainerKind, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxBaseClassInfo { + pub base: *const CXIdxEntityInfo, + pub cursor: CXCursor, + pub loc: CXIdxLoc, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxObjCProtocolRefInfo { + pub protocol: *const CXIdxEntityInfo, + pub cursor: CXCursor, + pub loc: CXIdxLoc, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxObjCProtocolRefListInfo { + pub protocols: *const *const CXIdxObjCProtocolRefInfo, + pub numProtocols: c_uint, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxObjCInterfaceDeclInfo { + pub containerInfo: *const CXIdxObjCContainerDeclInfo, + pub superInfo: *const CXIdxBaseClassInfo, + pub protocols: *const CXIdxObjCProtocolRefListInfo, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxObjCCategoryDeclInfo { + pub containerInfo: *const CXIdxObjCContainerDeclInfo, + pub objcClass: *const CXIdxEntityInfo, + pub classCursor: CXCursor, + pub classLoc: CXIdxLoc, + pub protocols: *const CXIdxObjCProtocolRefListInfo, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxObjCPropertyDeclInfo { + pub declInfo: *const CXIdxDeclInfo, + pub getter: *const CXIdxEntityInfo, + pub setter: *const CXIdxEntityInfo, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxCXXClassDeclInfo { + pub declInfo: *const CXIdxDeclInfo, + pub bases: *const *const CXIdxBaseClassInfo, + pub numBases: c_uint, +} +pub type CXIdxEntityRefKind = c_uint; +pub const CXIdxEntityRef_Direct: c_uint = 1; +pub const CXIdxEntityRef_Implicit: c_uint = 2; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CXIdxEntityRefInfo { + pub kind: CXIdxEntityRefKind, + pub cursor: CXCursor, + pub loc: CXIdxLoc, + pub referencedEntity: *const CXIdxEntityInfo, + pub parentEntity: *const CXIdxEntityInfo, + pub container: *const CXIdxContainerInfo, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct IndexerCallbacks { + pub abortQuery: ::std::option::Option c_int>, + pub diagnostic: ::std::option::Option, + pub enteredMainFile: ::std::option::Option CXIdxClientFile>, + pub ppIncludedFile: ::std::option::Option CXIdxClientFile>, + pub importedASTFile: ::std::option::Option CXIdxClientASTFile>, + pub startedTranslationUnit: ::std::option::Option + CXIdxClientContainer>, + pub indexDeclaration: ::std::option::Option, + pub indexEntityReference: ::std::option::Option, +} +pub type CXIndexAction = *mut c_void; +pub type CXIndexOptFlags = c_uint; +pub const CXIndexOpt_None: c_uint = 0; +pub const CXIndexOpt_SuppressRedundantRefs: c_uint = 1; +pub const CXIndexOpt_IndexFunctionLocalSymbols: c_uint = 2; +pub const CXIndexOpt_IndexImplicitTemplateInstantiations: c_uint = 4; +pub const CXIndexOpt_SuppressWarnings: c_uint = 8; +pub const CXIndexOpt_SkipParsedBodiesInSession: c_uint = 16; +extern "C" { + pub fn clang_getCString(string: CXString) -> *const c_char; + pub fn clang_disposeString(string: CXString); + pub fn clang_createIndex(excludeDeclarationsFromPCH: c_int, + displayDiagnostics: c_int) -> CXIndex; + pub fn clang_disposeIndex(index: CXIndex); + pub fn clang_CXIndex_setGlobalOptions(arg1: CXIndex, + options: c_uint); + pub fn clang_CXIndex_getGlobalOptions(arg1: CXIndex) -> c_uint; + pub fn clang_getFileName(SFile: CXFile) -> CXString; + pub fn clang_getFileTime(SFile: CXFile) -> ::libc::time_t; + pub fn clang_getFileUniqueID(file: CXFile, outID: *mut CXFileUniqueID) -> + c_int; + pub fn clang_isFileMultipleIncludeGuarded(tu: CXTranslationUnit, + file: CXFile) -> c_uint; + pub fn clang_getFile(tu: CXTranslationUnit, + file_name: *const c_char) -> CXFile; + pub fn clang_getNullLocation() -> CXSourceLocation; + pub fn clang_equalLocations(loc1: CXSourceLocation, + loc2: CXSourceLocation) -> c_uint; + pub fn clang_getLocation(tu: CXTranslationUnit, file: CXFile, + line: c_uint, column: c_uint) -> + CXSourceLocation; + pub fn clang_getLocationForOffset(tu: CXTranslationUnit, file: CXFile, + offset: c_uint) -> + CXSourceLocation; + pub fn clang_Location_isInSystemHeader(location: CXSourceLocation) -> + c_int; + pub fn clang_Location_isFromMainFile(location: CXSourceLocation) -> + c_int; + pub fn clang_getNullRange() -> CXSourceRange; + pub fn clang_getRange(begin: CXSourceLocation, end: CXSourceLocation) -> + CXSourceRange; + pub fn clang_equalRanges(range1: CXSourceRange, range2: CXSourceRange) -> + c_uint; + pub fn clang_Range_isNull(range: CXSourceRange) -> c_int; + pub fn clang_getExpansionLocation(location: CXSourceLocation, + file: *mut CXFile, + line: *mut c_uint, + column: *mut c_uint, + offset: *mut c_uint); + pub fn clang_getPresumedLocation(location: CXSourceLocation, + filename: *mut CXString, + line: *mut c_uint, + column: *mut c_uint); + pub fn clang_getInstantiationLocation(location: CXSourceLocation, + file: *mut CXFile, + line: *mut c_uint, + column: *mut c_uint, + offset: *mut c_uint); + pub fn clang_getSpellingLocation(location: CXSourceLocation, + file: *mut CXFile, + line: *mut c_uint, + column: *mut c_uint, + offset: *mut c_uint); + pub fn clang_getFileLocation(location: CXSourceLocation, + file: *mut CXFile, line: *mut c_uint, + column: *mut c_uint, + offset: *mut c_uint); + pub fn clang_getRangeStart(range: CXSourceRange) -> CXSourceLocation; + pub fn clang_getRangeEnd(range: CXSourceRange) -> CXSourceLocation; + pub fn clang_getNumDiagnosticsInSet(Diags: CXDiagnosticSet) -> + c_uint; + pub fn clang_getDiagnosticInSet(Diags: CXDiagnosticSet, + Index: c_uint) -> CXDiagnostic; + pub fn clang_loadDiagnostics(file: *const c_char, + error: *mut Enum_CXLoadDiag_Error, + errorString: *mut CXString) -> + CXDiagnosticSet; + pub fn clang_disposeDiagnosticSet(Diags: CXDiagnosticSet); + pub fn clang_getChildDiagnostics(D: CXDiagnostic) -> CXDiagnosticSet; + pub fn clang_getNumDiagnostics(Unit: CXTranslationUnit) -> c_uint; + pub fn clang_getDiagnostic(Unit: CXTranslationUnit, Index: c_uint) + -> CXDiagnostic; + pub fn clang_getDiagnosticSetFromTU(Unit: CXTranslationUnit) -> + CXDiagnosticSet; + pub fn clang_disposeDiagnostic(Diagnostic: CXDiagnostic); + pub fn clang_formatDiagnostic(Diagnostic: CXDiagnostic, + Options: c_uint) -> CXString; + pub fn clang_defaultDiagnosticDisplayOptions() -> c_uint; + pub fn clang_getDiagnosticSeverity(arg1: CXDiagnostic) -> + Enum_CXDiagnosticSeverity; + pub fn clang_getDiagnosticLocation(arg1: CXDiagnostic) -> + CXSourceLocation; + pub fn clang_getDiagnosticSpelling(arg1: CXDiagnostic) -> CXString; + pub fn clang_getDiagnosticOption(Diag: CXDiagnostic, + Disable: *mut CXString) -> CXString; + pub fn clang_getDiagnosticCategory(arg1: CXDiagnostic) -> c_uint; + pub fn clang_getDiagnosticCategoryName(Category: c_uint) -> + CXString; + pub fn clang_getDiagnosticCategoryText(arg1: CXDiagnostic) -> CXString; + pub fn clang_getDiagnosticNumRanges(arg1: CXDiagnostic) -> c_uint; + pub fn clang_getDiagnosticRange(Diagnostic: CXDiagnostic, + Range: c_uint) -> CXSourceRange; + pub fn clang_getDiagnosticNumFixIts(Diagnostic: CXDiagnostic) -> + c_uint; + pub fn clang_getDiagnosticFixIt(Diagnostic: CXDiagnostic, + FixIt: c_uint, + ReplacementRange: *mut CXSourceRange) -> + CXString; + pub fn clang_getTranslationUnitSpelling(CTUnit: CXTranslationUnit) -> + CXString; + pub fn clang_createTranslationUnitFromSourceFile(CIdx: CXIndex, + source_filename: + *const c_char, + num_clang_command_line_args: + c_int, + clang_command_line_args: + *const *const c_char, + num_unsaved_files: + c_uint, + unsaved_files: + *mut Struct_CXUnsavedFile) + -> CXTranslationUnit; + pub fn clang_createTranslationUnit(arg1: CXIndex, + ast_filename: *const c_char) -> + CXTranslationUnit; + pub fn clang_defaultEditingTranslationUnitOptions() -> c_uint; + pub fn clang_parseTranslationUnit(CIdx: CXIndex, + source_filename: *const c_char, + command_line_args: + *const *const c_char, + num_command_line_args: c_int, + unsaved_files: + *mut Struct_CXUnsavedFile, + num_unsaved_files: c_uint, + options: c_uint) -> + CXTranslationUnit; + pub fn clang_defaultSaveOptions(TU: CXTranslationUnit) -> c_uint; + pub fn clang_saveTranslationUnit(TU: CXTranslationUnit, + FileName: *const c_char, + options: c_uint) -> + c_int; + pub fn clang_disposeTranslationUnit(arg1: CXTranslationUnit); + pub fn clang_defaultReparseOptions(TU: CXTranslationUnit) -> + c_uint; + pub fn clang_reparseTranslationUnit(TU: CXTranslationUnit, + num_unsaved_files: c_uint, + unsaved_files: + *mut Struct_CXUnsavedFile, + options: c_uint) -> + c_int; + pub fn clang_getTUResourceUsageName(kind: Enum_CXTUResourceUsageKind) -> + *const c_char; + pub fn clang_getCXTUResourceUsage(TU: CXTranslationUnit) -> + CXTUResourceUsage; + pub fn clang_disposeCXTUResourceUsage(usage: CXTUResourceUsage); + pub fn clang_getNullCursor() -> CXCursor; + pub fn clang_getTranslationUnitCursor(arg1: CXTranslationUnit) -> + CXCursor; + pub fn clang_equalCursors(arg1: CXCursor, arg2: CXCursor) -> + c_uint; + pub fn clang_Cursor_isNull(cursor: CXCursor) -> c_int; + pub fn clang_hashCursor(arg1: CXCursor) -> c_uint; + pub fn clang_getCursorKind(arg1: CXCursor) -> Enum_CXCursorKind; + pub fn clang_isDeclaration(arg1: Enum_CXCursorKind) -> c_uint; + pub fn clang_isReference(arg1: Enum_CXCursorKind) -> c_uint; + pub fn clang_isExpression(arg1: Enum_CXCursorKind) -> c_uint; + pub fn clang_isStatement(arg1: Enum_CXCursorKind) -> c_uint; + pub fn clang_isAttribute(arg1: Enum_CXCursorKind) -> c_uint; + pub fn clang_isInvalid(arg1: Enum_CXCursorKind) -> c_uint; + pub fn clang_isTranslationUnit(arg1: Enum_CXCursorKind) -> c_uint; + pub fn clang_isPreprocessing(arg1: Enum_CXCursorKind) -> c_uint; + pub fn clang_isUnexposed(arg1: Enum_CXCursorKind) -> c_uint; + pub fn clang_getCursorLinkage(cursor: CXCursor) -> Enum_CXLinkageKind; + pub fn clang_getCursorVisibility(cursor: CXCursor) -> Enum_CXVisibilityKind; + pub fn clang_getCursorAvailability(cursor: CXCursor) -> + Enum_CXAvailabilityKind; + pub fn clang_getCursorPlatformAvailability(cursor: CXCursor, + always_deprecated: + *mut c_int, + deprecated_message: + *mut CXString, + always_unavailable: + *mut c_int, + unavailable_message: + *mut CXString, + availability: + *mut CXPlatformAvailability, + availability_size: + c_int) -> + c_int; + pub fn clang_disposeCXPlatformAvailability(availability: + *mut CXPlatformAvailability); + pub fn clang_getCursorLanguage(cursor: CXCursor) -> Enum_CXLanguageKind; + pub fn clang_Cursor_getTranslationUnit(arg1: CXCursor) -> + CXTranslationUnit; + pub fn clang_createCXCursorSet() -> CXCursorSet; + pub fn clang_disposeCXCursorSet(cset: CXCursorSet); + pub fn clang_CXCursorSet_contains(cset: CXCursorSet, cursor: CXCursor) -> + c_uint; + pub fn clang_CXCursorSet_insert(cset: CXCursorSet, cursor: CXCursor) -> + c_uint; + pub fn clang_getCursorSemanticParent(cursor: CXCursor) -> CXCursor; + pub fn clang_getCursorLexicalParent(cursor: CXCursor) -> CXCursor; + pub fn clang_getOverriddenCursors(cursor: CXCursor, + overridden: *mut *mut CXCursor, + num_overridden: *mut c_uint); + pub fn clang_disposeOverriddenCursors(overridden: *mut CXCursor); + pub fn clang_getIncludedFile(cursor: CXCursor) -> CXFile; + pub fn clang_getCursor(arg1: CXTranslationUnit, arg2: CXSourceLocation) -> + CXCursor; + pub fn clang_getCursorLocation(arg1: CXCursor) -> CXSourceLocation; + pub fn clang_getCursorExtent(arg1: CXCursor) -> CXSourceRange; + pub fn clang_getCursorType(C: CXCursor) -> CXType; + pub fn clang_getTypeSpelling(CT: CXType) -> CXString; + pub fn clang_getTypedefDeclUnderlyingType(C: CXCursor) -> CXType; + pub fn clang_getEnumDeclIntegerType(C: CXCursor) -> CXType; + pub fn clang_getEnumConstantDeclValue(C: CXCursor) -> c_longlong; + pub fn clang_getEnumConstantDeclUnsignedValue(C: CXCursor) -> + c_ulonglong; + pub fn clang_getFieldDeclBitWidth(C: CXCursor) -> c_int; + 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) -> + c_longlong; + pub fn clang_Cursor_getTemplateArgumentUnsignedValue(C: CXCursor, i: c_uint) -> + c_ulonglong; + pub fn clang_equalTypes(A: CXType, B: CXType) -> c_uint; + pub fn clang_getCanonicalType(T: CXType) -> CXType; + pub fn clang_isConstQualifiedType(T: CXType) -> c_uint; + pub fn clang_isVolatileQualifiedType(T: CXType) -> c_uint; + pub fn clang_isRestrictQualifiedType(T: CXType) -> c_uint; + pub fn clang_getPointeeType(T: CXType) -> CXType; + pub fn clang_getTypeDeclaration(T: CXType) -> CXCursor; + pub fn clang_getDeclObjCTypeEncoding(C: CXCursor) -> CXString; + pub fn clang_getTypeKindSpelling(K: Enum_CXTypeKind) -> CXString; + pub fn clang_getFunctionTypeCallingConv(T: CXType) -> Enum_CXCallingConv; + pub fn clang_getResultType(T: CXType) -> CXType; + pub fn clang_getNumArgTypes(T: CXType) -> c_int; + pub fn clang_getArgType(T: CXType, i: c_uint) -> CXType; + pub fn clang_isFunctionTypeVariadic(T: CXType) -> c_uint; + pub fn clang_getCursorResultType(C: CXCursor) -> CXType; + pub fn clang_isPODType(T: CXType) -> c_uint; + pub fn clang_getElementType(T: CXType) -> CXType; + pub fn clang_getNumElements(T: CXType) -> c_longlong; + pub fn clang_getArrayElementType(T: CXType) -> CXType; + pub fn clang_getArraySize(T: CXType) -> c_longlong; + pub fn clang_Type_getAlignOf(T: CXType) -> c_longlong; + pub fn clang_Type_getClassType(T: CXType) -> CXType; + pub fn clang_Type_getSizeOf(T: CXType) -> c_longlong; + pub fn clang_Type_getOffsetOf(T: CXType, S: *const c_char) -> + c_longlong; + pub fn clang_Type_getCXXRefQualifier(T: CXType) -> + Enum_CXRefQualifierKind; + pub fn clang_Type_getNumTemplateArguments(T: CXType) -> c_int; + pub fn clang_Type_getTemplateArgumentAsType(T: CXType, i: c_int) -> + CXType; + #[cfg(not(feature="llvm_stable"))] + pub fn clang_Type_getNamedType(CT: CXType) -> CXType; + pub fn clang_Cursor_isBitField(C: CXCursor) -> c_uint; + #[cfg(not(feature="llvm_stable"))] + pub fn clang_Cursor_isFunctionInlined(C: CXCursor) -> c_uint; + pub fn clang_isVirtualBase(arg1: CXCursor) -> c_uint; + pub fn clang_getCXXAccessSpecifier(arg1: CXCursor) -> + Enum_CX_CXXAccessSpecifier; + pub fn clang_getNumOverloadedDecls(cursor: CXCursor) -> c_uint; + pub fn clang_getOverloadedDecl(cursor: CXCursor, index: c_uint) -> + CXCursor; + pub fn clang_getIBOutletCollectionType(arg1: CXCursor) -> CXType; + pub fn clang_visitChildren(parent: CXCursor, visitor: CXCursorVisitor, + client_data: CXClientData) -> c_uint; + pub fn clang_getCursorUSR(arg1: CXCursor) -> CXString; + pub fn clang_constructUSR_ObjCClass(class_name: *const c_char) -> + CXString; + pub fn clang_constructUSR_ObjCCategory(class_name: *const c_char, + category_name: + *const c_char) -> + CXString; + pub fn clang_constructUSR_ObjCProtocol(protocol_name: + *const c_char) -> + CXString; + pub fn clang_constructUSR_ObjCIvar(name: *const c_char, + classUSR: CXString) -> CXString; + pub fn clang_constructUSR_ObjCMethod(name: *const c_char, + isInstanceMethod: c_uint, + classUSR: CXString) -> CXString; + pub fn clang_constructUSR_ObjCProperty(property: *const c_char, + classUSR: CXString) -> CXString; + pub fn clang_getCursorSpelling(arg1: CXCursor) -> CXString; + pub fn clang_Cursor_getSpellingNameRange(arg1: CXCursor, + 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; + pub fn clang_isCursorDefinition(arg1: CXCursor) -> c_uint; + pub fn clang_getCanonicalCursor(arg1: CXCursor) -> CXCursor; + pub fn clang_Cursor_getObjCSelectorIndex(arg1: CXCursor) -> c_int; + pub fn clang_Cursor_isDynamicCall(C: CXCursor) -> c_int; + pub fn clang_Cursor_getReceiverType(C: CXCursor) -> CXType; + pub fn clang_Cursor_getObjCPropertyAttributes(C: CXCursor, + reserved: c_uint) -> + c_uint; + pub fn clang_Cursor_getObjCDeclQualifiers(C: CXCursor) -> c_uint; + pub fn clang_Cursor_isObjCOptional(C: CXCursor) -> c_uint; + pub fn clang_Cursor_isVariadic(C: CXCursor) -> c_uint; + pub fn clang_Cursor_getCommentRange(C: CXCursor) -> CXSourceRange; + pub fn clang_Cursor_getRawCommentText(C: CXCursor) -> CXString; + pub fn clang_Cursor_getBriefCommentText(C: CXCursor) -> CXString; + 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; + pub fn clang_Module_getFullName(Module: CXModule) -> CXString; + pub fn clang_Module_getNumTopLevelHeaders(arg1: CXTranslationUnit, + Module: CXModule) -> + c_uint; + pub fn clang_Module_getTopLevelHeader(arg1: CXTranslationUnit, + Module: CXModule, + Index: c_uint) -> CXFile; + pub fn clang_Comment_getKind(Comment: CXComment) -> Enum_CXCommentKind; + pub fn clang_Comment_getNumChildren(Comment: CXComment) -> c_uint; + pub fn clang_Comment_getChild(Comment: CXComment, + ChildIdx: c_uint) -> CXComment; + pub fn clang_Comment_isWhitespace(Comment: CXComment) -> c_uint; + pub fn clang_InlineContentComment_hasTrailingNewline(Comment: CXComment) + -> c_uint; + pub fn clang_TextComment_getText(Comment: CXComment) -> CXString; + pub fn clang_InlineCommandComment_getCommandName(Comment: CXComment) -> + CXString; + pub fn clang_InlineCommandComment_getRenderKind(Comment: CXComment) -> + Enum_CXCommentInlineCommandRenderKind; + pub fn clang_InlineCommandComment_getNumArgs(Comment: CXComment) -> + c_uint; + pub fn clang_InlineCommandComment_getArgText(Comment: CXComment, + ArgIdx: c_uint) -> + CXString; + pub fn clang_HTMLTagComment_getTagName(Comment: CXComment) -> CXString; + pub fn clang_HTMLStartTagComment_isSelfClosing(Comment: CXComment) -> + c_uint; + pub fn clang_HTMLStartTag_getNumAttrs(Comment: CXComment) -> + c_uint; + pub fn clang_HTMLStartTag_getAttrName(Comment: CXComment, + AttrIdx: c_uint) -> + CXString; + pub fn clang_HTMLStartTag_getAttrValue(Comment: CXComment, + AttrIdx: c_uint) -> + CXString; + pub fn clang_BlockCommandComment_getCommandName(Comment: CXComment) -> + CXString; + pub fn clang_BlockCommandComment_getNumArgs(Comment: CXComment) -> + c_uint; + pub fn clang_BlockCommandComment_getArgText(Comment: CXComment, + ArgIdx: c_uint) -> + CXString; + pub fn clang_BlockCommandComment_getParagraph(Comment: CXComment) -> + CXComment; + pub fn clang_ParamCommandComment_getParamName(Comment: CXComment) -> + CXString; + pub fn clang_ParamCommandComment_isParamIndexValid(Comment: CXComment) -> + c_uint; + pub fn clang_ParamCommandComment_getParamIndex(Comment: CXComment) -> + c_uint; + pub fn clang_ParamCommandComment_isDirectionExplicit(Comment: CXComment) + -> c_uint; + pub fn clang_ParamCommandComment_getDirection(Comment: CXComment) -> + Enum_CXCommentParamPassDirection; + pub fn clang_TParamCommandComment_getParamName(Comment: CXComment) -> + CXString; + pub fn clang_TParamCommandComment_isParamPositionValid(Comment: CXComment) + -> c_uint; + pub fn clang_TParamCommandComment_getDepth(Comment: CXComment) -> + c_uint; + pub fn clang_TParamCommandComment_getIndex(Comment: CXComment, + Depth: c_uint) -> + c_uint; + pub fn clang_VerbatimBlockLineComment_getText(Comment: CXComment) -> + CXString; + pub fn clang_VerbatimLineComment_getText(Comment: CXComment) -> CXString; + pub fn clang_HTMLTagComment_getAsString(Comment: CXComment) -> CXString; + 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; + pub fn clang_getTemplateCursorKind(C: CXCursor) -> Enum_CXCursorKind; + pub fn clang_getSpecializedCursorTemplate(C: CXCursor) -> CXCursor; + pub fn clang_getCursorReferenceNameRange(C: CXCursor, + NameFlags: c_uint, + PieceIndex: c_uint) -> + CXSourceRange; + pub fn clang_getTokenKind(arg1: CXToken) -> CXTokenKind; + pub fn clang_getTokenSpelling(arg1: CXTranslationUnit, arg2: CXToken) -> + CXString; + pub fn clang_getTokenLocation(arg1: CXTranslationUnit, arg2: CXToken) -> + CXSourceLocation; + pub fn clang_getTokenExtent(arg1: CXTranslationUnit, arg2: CXToken) -> + CXSourceRange; + pub fn clang_tokenize(TU: CXTranslationUnit, Range: CXSourceRange, + Tokens: *mut *mut CXToken, + NumTokens: *mut c_uint); + pub fn clang_annotateTokens(TU: CXTranslationUnit, Tokens: *mut CXToken, + NumTokens: c_uint, + Cursors: *mut CXCursor); + pub fn clang_disposeTokens(TU: CXTranslationUnit, Tokens: *mut CXToken, + NumTokens: c_uint); + pub fn clang_getCursorKindSpelling(Kind: Enum_CXCursorKind) -> CXString; + pub fn clang_getDefinitionSpellingAndExtent(arg1: CXCursor, + startBuf: + *mut *const c_char, + endBuf: + *mut *const c_char, + startLine: + *mut c_uint, + startColumn: + *mut c_uint, + endLine: *mut c_uint, + endColumn: + *mut c_uint); + pub fn clang_enableStackTraces(); + pub fn clang_executeOnThread(_fn: + ::std::option::Option, + user_data: *mut c_void, + stack_size: c_uint); + pub fn clang_getCompletionChunkKind(completion_string: CXCompletionString, + chunk_number: c_uint) -> + Enum_CXCompletionChunkKind; + pub fn clang_getCompletionChunkText(completion_string: CXCompletionString, + chunk_number: c_uint) -> + CXString; + pub fn clang_getCompletionChunkCompletionString(completion_string: + CXCompletionString, + chunk_number: + c_uint) -> + CXCompletionString; + pub fn clang_getNumCompletionChunks(completion_string: CXCompletionString) + -> c_uint; + pub fn clang_getCompletionPriority(completion_string: CXCompletionString) + -> c_uint; + pub fn clang_getCompletionAvailability(completion_string: + CXCompletionString) -> + Enum_CXAvailabilityKind; + pub fn clang_getCompletionNumAnnotations(completion_string: + CXCompletionString) -> + c_uint; + pub fn clang_getCompletionAnnotation(completion_string: + CXCompletionString, + annotation_number: c_uint) -> + CXString; + pub fn clang_getCompletionParent(completion_string: CXCompletionString, + kind: *mut Enum_CXCursorKind) -> + CXString; + pub fn clang_getCompletionBriefComment(completion_string: + CXCompletionString) -> + CXString; + pub fn clang_getCursorCompletionString(cursor: CXCursor) -> + CXCompletionString; + pub fn clang_defaultCodeCompleteOptions() -> c_uint; + pub fn clang_codeCompleteAt(TU: CXTranslationUnit, + complete_filename: *const c_char, + complete_line: c_uint, + complete_column: c_uint, + unsaved_files: *mut Struct_CXUnsavedFile, + num_unsaved_files: c_uint, + options: c_uint) -> + *mut CXCodeCompleteResults; + pub fn clang_sortCodeCompletionResults(Results: *mut CXCompletionResult, + NumResults: c_uint); + pub fn clang_disposeCodeCompleteResults(Results: + *mut CXCodeCompleteResults); + pub fn clang_codeCompleteGetNumDiagnostics(Results: + *mut CXCodeCompleteResults) + -> c_uint; + pub fn clang_codeCompleteGetDiagnostic(Results: + *mut CXCodeCompleteResults, + Index: c_uint) -> + CXDiagnostic; + pub fn clang_codeCompleteGetContexts(Results: *mut CXCodeCompleteResults) + -> c_ulonglong; + pub fn clang_codeCompleteGetContainerKind(Results: + *mut CXCodeCompleteResults, + IsIncomplete: + *mut c_uint) -> + Enum_CXCursorKind; + pub fn clang_codeCompleteGetContainerUSR(Results: + *mut CXCodeCompleteResults) + -> CXString; + pub fn clang_codeCompleteGetObjCSelector(Results: + *mut CXCodeCompleteResults) + -> CXString; + pub fn clang_getClangVersion() -> CXString; + pub fn clang_toggleCrashRecovery(isEnabled: c_uint); + pub fn clang_getInclusions(tu: CXTranslationUnit, + visitor: CXInclusionVisitor, + client_data: CXClientData); + pub fn clang_getRemappings(path: *const c_char) -> CXRemapping; + pub fn clang_getRemappingsFromFileList(filePaths: + *mut *const c_char, + numFiles: c_uint) -> + CXRemapping; + pub fn clang_remap_getNumFiles(arg1: CXRemapping) -> c_uint; + pub fn clang_remap_getFilenames(arg1: CXRemapping, index: c_uint, + original: *mut CXString, + transformed: *mut CXString); + pub fn clang_remap_dispose(arg1: CXRemapping); + pub fn clang_findReferencesInFile(cursor: CXCursor, file: CXFile, + visitor: CXCursorAndRangeVisitor) -> + CXResult; + pub fn clang_findIncludesInFile(TU: CXTranslationUnit, file: CXFile, + visitor: CXCursorAndRangeVisitor) -> + CXResult; + pub fn clang_index_isEntityObjCContainerKind(arg1: CXIdxEntityKind) -> + c_int; + pub fn clang_index_getObjCContainerDeclInfo(arg1: *const CXIdxDeclInfo) -> + *const CXIdxObjCContainerDeclInfo; + pub fn clang_index_getObjCInterfaceDeclInfo(arg1: *const CXIdxDeclInfo) -> + *const CXIdxObjCInterfaceDeclInfo; + pub fn clang_index_getObjCCategoryDeclInfo(arg1: *const CXIdxDeclInfo) -> + *const CXIdxObjCCategoryDeclInfo; + pub fn clang_index_getObjCProtocolRefListInfo(arg1: *const CXIdxDeclInfo) + -> *const CXIdxObjCProtocolRefListInfo; + pub fn clang_index_getObjCPropertyDeclInfo(arg1: *const CXIdxDeclInfo) -> + *const CXIdxObjCPropertyDeclInfo; + pub fn clang_index_getIBOutletCollectionAttrInfo(arg1: + *const CXIdxAttrInfo) + -> *const CXIdxIBOutletCollectionAttrInfo; + pub fn clang_index_getCXXClassDeclInfo(arg1: *const CXIdxDeclInfo) -> + *const CXIdxCXXClassDeclInfo; + pub fn clang_index_getClientContainer(arg1: *const CXIdxContainerInfo) -> + CXIdxClientContainer; + pub fn clang_index_setClientContainer(arg1: *const CXIdxContainerInfo, + arg2: CXIdxClientContainer); + pub fn clang_index_getClientEntity(arg1: *const CXIdxEntityInfo) -> + CXIdxClientEntity; + pub fn clang_index_setClientEntity(arg1: *const CXIdxEntityInfo, + arg2: CXIdxClientEntity); + pub fn clang_IndexAction_create(CIdx: CXIndex) -> CXIndexAction; + pub fn clang_IndexAction_dispose(arg1: CXIndexAction); + pub fn clang_indexSourceFile(arg1: CXIndexAction, + client_data: CXClientData, + index_callbacks: *mut IndexerCallbacks, + index_callbacks_size: c_uint, + index_options: c_uint, + source_filename: *const c_char, + command_line_args: + *const *const c_char, + num_command_line_args: c_int, + unsaved_files: *mut Struct_CXUnsavedFile, + num_unsaved_files: c_uint, + out_TU: *mut CXTranslationUnit, + TU_options: c_uint) -> c_int; + pub fn clang_indexTranslationUnit(arg1: CXIndexAction, + client_data: CXClientData, + index_callbacks: *mut IndexerCallbacks, + index_callbacks_size: c_uint, + index_options: c_uint, + arg2: CXTranslationUnit) -> + c_int; + pub fn clang_indexLoc_getFileLocation(loc: CXIdxLoc, + indexFile: *mut CXIdxClientFile, + file: *mut CXFile, + line: *mut c_uint, + column: *mut c_uint, + offset: *mut c_uint); + pub fn clang_indexLoc_getCXSourceLocation(loc: CXIdxLoc) -> + CXSourceLocation; +} diff --git a/libbindgen/src/codegen/helpers.rs b/libbindgen/src/codegen/helpers.rs new file mode 100644 index 00000000..6e5a6f0e --- /dev/null +++ b/libbindgen/src/codegen/helpers.rs @@ -0,0 +1,135 @@ +//! Helpers for code generation that don't need macro expansion. + +use aster; +use ir::layout::Layout; +use syntax::ast; +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 { + 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 { + aster::ty::TyBuilder::new().array(data_len).build(inner_ty) + } + } +} + +pub mod ast_ty { + use aster; + use ir::context::BindgenContext; + use ir::ty::FloatKind; + use syntax::ast; + use syntax::ptr::P; + + pub fn raw_type(ctx: &BindgenContext, name: &str) -> P { + let ident = ctx.rust_ident_raw(&name); + match ctx.options().ctypes_prefix { + Some(ref prefix) => { + let prefix = ctx.rust_ident_raw(prefix); + quote_ty!(ctx.ext_cx(), $prefix::$ident) + } + None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident), + } + } + + pub fn float_kind_rust_type(ctx: &BindgenContext, + fk: FloatKind) + -> P { + macro_rules! raw { + ($ty: ident) => { + raw_type(ctx, stringify!($ty)) + } + } + // TODO: we probably should just take the type layout into + // account? + // + // Also, maybe this one shouldn't be the default? + // + // FIXME: `c_longdouble` doesn't seem to be defined in some + // systems, so we use `c_double` directly. + match (fk, ctx.options().convert_floats) { + (FloatKind::Float, true) => aster::ty::TyBuilder::new().f32(), + (FloatKind::Double, true) | + (FloatKind::LongDouble, true) => aster::ty::TyBuilder::new().f64(), + (FloatKind::Float, false) => raw!(c_float), + (FloatKind::Double, false) | + (FloatKind::LongDouble, false) => raw!(c_double), + (FloatKind::Float128, _) => { + aster::ty::TyBuilder::new().array(16).u8() + } + } + } + + pub fn int_expr(val: i64) -> P { + use std::i64; + let expr = aster::AstBuilder::new().expr(); + + // This is not representable as an i64 if it's negative, so we + // special-case it. + // + // Fix in aster incoming. + if val == i64::MIN { + expr.neg().uint(1u64 << 63) + } else { + expr.int(val) + } + } +} diff --git a/libbindgen/src/codegen/mod.rs b/libbindgen/src/codegen/mod.rs new file mode 100644 index 00000000..8e04fd7c --- /dev/null +++ b/libbindgen/src/codegen/mod.rs @@ -0,0 +1,2121 @@ +mod helpers; + + +use aster; + +use ir::annotations::FieldAccessorKind; +use ir::comp::{CompInfo, CompKind, Field, Method}; +use ir::context::{BindgenContext, ItemId}; +use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; +use ir::function::{Function, FunctionSig}; +use ir::int::IntKind; +use ir::item::{Item, ItemCanonicalName, ItemCanonicalPath}; +use ir::item_kind::ItemKind; +use ir::layout::Layout; +use ir::module::Module; +use ir::ty::{Type, TypeKind}; +use ir::type_collector::ItemSet; +use ir::var::Var; +use self::helpers::{BlobTyBuilder, attributes}; + +use std::borrow::Cow; +use std::collections::HashSet; +use std::collections::hash_map::{Entry, HashMap}; +use std::fmt::Write; +use std::mem; +use std::ops; +use syntax::abi::Abi; +use syntax::ast; +use syntax::codemap::{Span, respan}; +use syntax::ptr::P; + +fn root_import(ctx: &BindgenContext) -> P { + 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>, + saw_union: bool, + items_seen: HashSet, + /// The set of generated function/var names, needed because in C/C++ is + /// legal to do something like: + /// + /// ```c++ + /// extern "C" { + /// void foo(); + /// extern int bar; + /// } + /// + /// extern "C" { + /// void foo(); + /// extern int bar; + /// } + /// ``` + /// + /// Being these two different declarations. + functions_seen: HashSet, + vars_seen: HashSet, + + /// Used for making bindings to overloaded functions. Maps from a canonical + /// function name to the number of overloads we have already codegen'd for + /// that name. This lets us give each overload a unique suffix. + overload_counters: HashMap, +} + +impl CodegenResult { + fn new() -> Self { + CodegenResult { + items: vec![], + saw_union: false, + items_seen: Default::default(), + functions_seen: Default::default(), + vars_seen: Default::default(), + overload_counters: 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()); + } + + /// Get the overload number for the given function name. Increments the + /// counter internally so the next time we ask for the overload for this + /// name, we get the incremented value, and so on. + fn overload_number(&mut self, name: &str) -> u32 { + let mut counter = + self.overload_counters.entry(name.into()).or_insert(0); + let number = *counter; + *counter += 1; + number + } + + fn seen_var(&self, name: &str) -> bool { + self.vars_seen.contains(name) + } + + fn saw_var(&mut self, name: &str) { + self.vars_seen.insert(name.into()); + } + + fn inner(&mut self, cb: F) -> Vec> + 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>; + + 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(mut self, items: I) -> Self + where I: IntoIterator, + { + self.inner.items.extend(items.into_iter()); + self + } + + fn build(self, ctx: &BindgenContext) -> P { + 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; +} + +impl ToPtr for P { + 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 canonical_name = item.canonical_name(ctx); + + if result.seen_var(&canonical_name) { + return; + } + result.saw_var(&canonical_name); + + let ty = self.ty().to_rust_ty(ctx); + + if let Some(val) = self.val() { + let const_item = aster::AstBuilder::new() + .item() + .pub_() + .const_(canonical_name) + .expr() + .build(helpers::ast_ty::int_expr(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 canonical_name != self.name() { + attrs.push(attributes::link_name(self.name())); + } + + let item = ast::ForeignItem { + ident: ctx.rust_ident_raw(&canonical_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::Complex(..) | + TypeKind::Array(..) | + TypeKind::Pointer(..) | + TypeKind::BlockPointer | + 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::TemplateAlias(inner, _) => { + // NB: The inner Alias will pick the correct + // applicable_template_args. + let inner_item = ctx.resolve_item(inner); + inner_item.expect_type().codegen(ctx, result, inner_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 \ + parameter: {:?}", 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.canonical_name(ctx)) + } +} + +impl<'a> ItemToRustTy for Vtable<'a> { + fn to_rust_ty(&self, ctx: &BindgenContext) -> P { + 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, + methods: &mut Vec) { + 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; + let prefix = ctx.trait_prefix(); + // 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 { + ::$prefix::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 is_union = self.kind() == CompKind::Union; + let mut derives = vec![]; + let ty = item.expect_type(); + if ty.can_derive_debug(ctx) { + derives.push("Debug"); + } + + if item.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 = if is_union && ctx.options().unstable_rust { + aster::AstBuilder::new() + .item() + .pub_() + .with_attrs(attributes) + .union_(&canonical_name) + } else { + 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_id) in applicable_template_args.iter().enumerate() { + let template_arg_ty = ctx.resolve_type(*ty_id); + if base_ty.signature_contains_named_type(ctx, template_arg_ty) { + template_args_used[i] = true; + } + } + + let inner = base.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); + } + 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 = 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_id) in applicable_template_args.iter().enumerate() { + let template_arg = ctx.resolve_type(*ty_id); + if field_ty.signature_contains_named_type(ctx, template_arg) { + template_args_used[i] = true; + } + } + + let ty = field.ty().to_rust_ty(ctx); + + // NB: In unstable rust we use proper `union` types. + let ty = if is_union && !ctx.options().unstable_rust { + 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 && !ctx.options().unstable_rust { + 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 prefix = ctx.trait_prefix(); + let phantom = quote_ty!(ctx.ext_cx(), + ::$prefix::marker::PhantomData<$ident>); + let field = + StructFieldBuilder::named(format!("_phantom_{}", i)) + .pub_() + .build_ty(phantom); + fields.push(field) + } + } + + + let mut generics = aster::AstBuilder::new().generics(); + 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 = format!("bindgen_test_layout_{}", canonical_name); + let fn_name = ctx.rust_ident_raw(&fn_name); + let ident = ctx.rust_ident_raw(&canonical_name); + let prefix = ctx.trait_prefix(); + let size_of_expr = quote_expr!(ctx.ext_cx(), + ::$prefix::mem::size_of::<$ident>()); + let align_of_expr = quote_expr!(ctx.ext_cx(), + ::$prefix::mem::align_of::<$ident>()); + let size = layout.size; + let align = layout.align; + let item = quote_item!(ctx.ext_cx(), + #[test] + fn $fn_name() { + assert_eq!($size_of_expr, $size); + 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, + method_names: &mut HashMap, + result: &mut CodegenResult, + parent: &Item); +} + +impl MethodCodegen for Method { + fn codegen_method(&self, + ctx: &BindgenContext, + methods: &mut Vec, + method_names: &mut HashMap, + 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::>(); + + 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); + } +} + +/// A helper type to construct enums, either bitfield ones or rust-style ones. +enum EnumBuilder<'a> { + Rust(aster::item::ItemEnumBuilder), + Bitfield { + canonical_name: &'a str, + aster: P, + }, +} + +impl<'a> EnumBuilder<'a> { + /// Create a new enum given an item builder, a canonical name, a name for + /// the representation, and whether it should be represented as a rust enum. + fn new(aster: aster::item::ItemBuilder, + name: &'a str, + repr_name: &str, + is_rust: bool) + -> Self { + if is_rust { + EnumBuilder::Rust(aster.enum_(name)) + } else { + EnumBuilder::Bitfield { + canonical_name: name, + aster: aster.tuple_struct(name) + .field() + .pub_() + .ty() + .id(repr_name) + .build(), + } + } + } + + /// Add a variant to this enum. + fn with_variant(self, + ctx: &BindgenContext, + variant: &EnumVariant, + mangling_prefix: Option<&String>, + rust_ty: P, + result: &mut CodegenResult) + -> Self { + let variant_name = ctx.rust_mangle(variant.name()); + let expr = aster::AstBuilder::new().expr(); + let expr = match variant.val() { + EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v), + EnumVariantValue::Unsigned(v) => expr.uint(v), + }; + + match self { + EnumBuilder::Rust(b) => { + EnumBuilder::Rust(b.with_variant_(ast::Variant_ { + name: ctx.rust_ident(&*variant_name), + attrs: vec![], + data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), + disr_expr: Some(expr), + })) + } + EnumBuilder::Bitfield { canonical_name, .. } => { + let constant_name = match mangling_prefix { + Some(prefix) => { + Cow::Owned(format!("{}_{}", prefix, variant_name)) + } + None => variant_name, + }; + + let constant = aster::AstBuilder::new() + .item() + .pub_() + .const_(&*constant_name) + .expr() + .call() + .id(canonical_name) + .arg() + .build(expr) + .build() + .build(rust_ty); + result.push(constant); + self + } + } + } + + fn build(self, + ctx: &BindgenContext, + rust_ty: P, + result: &mut CodegenResult) + -> P { + match self { + EnumBuilder::Rust(b) => b.build(), + EnumBuilder::Bitfield { canonical_name, aster } => { + let rust_ty_name = ctx.rust_ident_raw(canonical_name); + let prefix = ctx.trait_prefix(); + + let impl_ = quote_item!(ctx.ext_cx(), + impl ::$prefix::ops::BitOr<$rust_ty> for $rust_ty { + type Output = Self; + + #[inline] + fn bitor(self, other: Self) -> Self { + $rust_ty_name(self.0 | other.0) + } + } + ) + .unwrap(); + + result.push(impl_); + aster + } + } + } +} + +impl CodeGenerator for Enum { + type Extra = Item; + + fn codegen(&self, + ctx: &BindgenContext, + result: &mut CodegenResult, + item: &Item) { + let name = item.canonical_name(ctx); + let enum_ty = item.expect_type(); + let layout = enum_ty.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_(); + + let is_bitfield = { + ctx.options().bitfield_enums.matches(&name) || + (enum_ty.name().is_none() && + self.variants() + .iter() + .any(|v| ctx.options().bitfield_enums.matches(&v.name()))) + }; + + let is_rust_enum = !is_bitfield; + + // FIXME: Rust forbids repr with empty enums. Remove this condition when + // this is allowed. + if is_rust_enum { + if !self.variants().is_empty() { + builder = builder.with_attr(attributes::repr(repr_name)); + } + } else { + builder = builder.with_attr(attributes::repr("C")); + } + + 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); + + 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, + 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); + } + + let mut builder = + EnumBuilder::new(builder, &name, repr_name, is_rust_enum); + + // A map where we keep a value -> variant relation. + let mut seen_values = HashMap::<_, String>::new(); + let enum_rust_ty = item.to_rust_ty(ctx); + let is_toplevel = item.is_toplevel(ctx); + + // Used to mangle the constants we generate in the unnamed-enum case. + let parent_canonical_name = if is_toplevel { + None + } else { + Some(item.parent_id().canonical_name(ctx)) + }; + + let constant_mangling_prefix = if enum_ty.name().is_none() { + parent_canonical_name.as_ref().map(|n| &*n) + } else { + Some(&name) + }; + + for variant in self.variants().iter() { + match seen_values.entry(variant.val()) { + Entry::Occupied(ref entry) => { + if is_rust_enum { + 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); + } else { + builder = builder.with_variant(ctx, + variant, + constant_mangling_prefix, + enum_rust_ty.clone(), + result); + } + } + Entry::Vacant(entry) => { + builder = builder.with_variant(ctx, + variant, + constant_mangling_prefix, + enum_rust_ty.clone(), + result); + + let variant_name = ctx.rust_mangle(variant.name()); + + // If it's an unnamed enum, we also generate a constant so + // it can be properly accessed. + if is_rust_enum && enum_ty.name().is_none() { + // NB: if we want to do this for other kind of nested + // enums we can probably mangle the name. + let mangled_name = if is_toplevel { + variant_name.clone() + } else { + let parent_name = parent_canonical_name.as_ref() + .unwrap(); + + Cow::Owned( + format!("{}_{}", parent_name, variant_name)) + }; + + add_constant(enum_ty, + &name, + &mangled_name, + &variant_name, + enum_rust_ty.clone(), + result); + } + + entry.insert(variant_name.into_owned()); + } + } + } + + let enum_ = builder.build(ctx, enum_rust_ty, result); + result.push(enum_); + } +} + +trait ToRustTy { + type Extra; + + fn to_rust_ty(&self, + ctx: &BindgenContext, + extra: &Self::Extra) + -> P; +} + +trait ItemToRustTy { + fn to_rust_ty(&self, ctx: &BindgenContext) -> P; +} + +// Convenience implementation. +impl ItemToRustTy for ItemId { + fn to_rust_ty(&self, ctx: &BindgenContext) -> P { + ctx.resolve_item(*self).to_rust_ty(ctx) + } +} + +impl ItemToRustTy for Item { + fn to_rust_ty(&self, ctx: &BindgenContext) -> P { + self.kind().expect_type().to_rust_ty(ctx, self) + } +} + +impl ToRustTy for Type { + type Extra = Item; + + fn to_rust_ty(&self, ctx: &BindgenContext, item: &Item) -> P { + use self::helpers::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 => raw!(c_void).to_ptr(true, ctx.span()), + 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::I8 => aster::ty::TyBuilder::new().i8(), + IntKind::U8 => aster::ty::TyBuilder::new().u8(), + IntKind::I16 => aster::ty::TyBuilder::new().i16(), + IntKind::U16 => aster::ty::TyBuilder::new().u16(), + IntKind::I32 => aster::ty::TyBuilder::new().i32(), + IntKind::U32 => aster::ty::TyBuilder::new().u32(), + IntKind::I64 => aster::ty::TyBuilder::new().i64(), + IntKind::U64 => aster::ty::TyBuilder::new().u64(), + IntKind::Custom { name, .. } => { + let ident = ctx.rust_ident_raw(name); + quote_ty!(ctx.ext_cx(), $ident) + } + // FIXME: This doesn't generate the proper alignment, but we + // can't do better right now. We should be able to use + // i128/u128 when they're available. + IntKind::U128 | IntKind::I128 => { + aster::ty::TyBuilder::new().array(2).u64() + } + } + } + TypeKind::Float(fk) => float_kind_rust_type(ctx, fk), + TypeKind::Complex(fk) => { + let float_path = float_kind_rust_type(ctx, fk); + + ctx.generated_bindegen_complex(); + quote_ty!(ctx.ext_cx(), __BindgenComplex<$float_path>) + } + TypeKind::Function(ref fs) => { + let ty = fs.to_rust_ty(ctx, item); + let prefix = ctx.trait_prefix(); + quote_ty!(ctx.ext_cx(), ::$prefix::option::Option<$ty>) + } + TypeKind::Array(item, len) => { + let inner = item.to_rust_ty(ctx); + aster::ty::TyBuilder::new().array(len).build(inner) + } + TypeKind::Enum(..) => { + let path = item.canonical_path(ctx); + aster::AstBuilder::new().ty().path().ids(path).build() + } + TypeKind::TemplateAlias(inner, ref template_args) | + 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 { + let template_args = template_args.iter() + .map(|arg| arg.to_rust_ty(ctx)) + .collect(); + + path.segments.last_mut().unwrap().parameters = + ast::PathParameters::AngleBracketed( + ast::AngleBracketedParameterData { + lifetimes: vec![], + types: P::from_vec(template_args), + 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 \ + type template params or opaque, expect \ + dragons!"); + aster::AstBuilder::new().ty().unit() + } + }; + } + + utils::build_templated_path(item, ctx, false) + } + TypeKind::BlockPointer => { + let void = raw!(c_void); + void.to_ptr(/* is_const = */ + false, + ctx.span()) + } + TypeKind::Pointer(inner) | + TypeKind::Reference(inner) => { + let inner = ctx.resolve_item(inner); + let inner_ty = inner.expect_type(); + let ty = inner.to_rust_ty(ctx); + + // Avoid the first function pointer level, since it's already + // represented in Rust. + if inner_ty.canonical_type(ctx).is_function() { + ty + } else { + let is_const = self.is_const() || + inner.expect_type().is_const(); + ty.to_ptr(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 { + // 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[1]: + // + // 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. + // + // [1]: http://c0x.coding-guidelines.com/6.7.5.3.html + 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::>(); + + 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 mut canonical_name = item.canonical_name(ctx); + let mangled_name = self.mangled_name(); + + { + let seen_symbol_name = mangled_name.unwrap_or(&canonical_name); + + // TODO: Maybe warn here if there's a type/argument mismatch, or + // something? + if result.seen_function(seen_symbol_name) { + return; + } + result.saw_function(seen_symbol_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) = 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()); + + // Handle overloaded functions by giving each overload its own unique + // suffix. + let times_seen = result.overload_number(&canonical_name); + if times_seen > 0 { + write!(&mut canonical_name, "{}", times_seen).unwrap(); + } + + 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); + } +} + +// Return true if any of the ancestors of `id` are in the whitelisted items set, +// false otherwise. +fn ancestor_is_whitelisted(ctx: &BindgenContext, + whitelisted_items: &ItemSet, + id: ItemId) + -> bool { + let item = ctx.resolve_item(id); + let mut last = id; + let mut current = item.parent_id(); + + while last != current { + if whitelisted_items.contains(¤t) { + return true; + } + last = current; + current = ctx.resolve_item(current).parent_id(); + } + + false +} + +pub fn codegen(context: &mut BindgenContext) -> Vec> { + context.gen(|context| { + let mut result = CodegenResult::new(); + + debug!("codegen: {:?}", context.options()); + + let whitelisted_items: ItemSet = context.whitelisted_items().collect(); + + for &id in whitelisted_items.iter() { + let item = context.resolve_item(id); + + // Non-toplevel items' parents are responsible one for generating + // their children. However, if we find an orphaned reference to a + // non-toplevel item whose parent is not in our whitelisted set, we + // need to take responsibility for generating it. + if item.is_toplevel(context) || + !ancestor_is_whitelisted(context, &whitelisted_items, id) { + item.codegen(context, &mut result, &()); + } + } + + let saw_union = result.saw_union; + let mut result = result.items; + if saw_union && !context.options().unstable_rust { + utils::prepend_union_types(context, &mut result); + } + if context.need_bindegen_complex_type() { + utils::prepend_complex_type(context, &mut result); + } + result + }) +} + +mod utils { + use aster; + use ir::context::{BindgenContext, ItemId}; + use ir::item::{Item, ItemCanonicalPath}; + use ir::ty::TypeKind; + use std::mem; + use super::ItemToRustTy; + use syntax::ast; + use syntax::ptr::P; + + pub fn prepend_union_types(ctx: &BindgenContext, + result: &mut Vec>) { + let prefix = ctx.trait_prefix(); + + // TODO(emilio): The fmt::Debug impl could be way nicer with + // std::intrinsics::type_name, but... + let union_field_decl = quote_item!(ctx.ext_cx(), + #[repr(C)] + pub struct __BindgenUnionField( + ::$prefix::marker::PhantomData); + ) + .unwrap(); + + let union_field_impl = quote_item!(&ctx.ext_cx(), + impl __BindgenUnionField { + #[inline] + pub fn new() -> Self { + __BindgenUnionField(::$prefix::marker::PhantomData) + } + + #[inline] + pub unsafe fn as_ref(&self) -> &T { + ::$prefix::mem::transmute(self) + } + + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + ::$prefix::mem::transmute(self) + } + } + ) + .unwrap(); + + let union_field_default_impl = quote_item!(&ctx.ext_cx(), + impl ::$prefix::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { + Self::new() + } + } + ) + .unwrap(); + + let union_field_clone_impl = quote_item!(&ctx.ext_cx(), + impl ::$prefix::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { + Self::new() + } + } + ) + .unwrap(); + + let union_field_copy_impl = quote_item!(&ctx.ext_cx(), + impl ::$prefix::marker::Copy for __BindgenUnionField {} + ) + .unwrap(); + + let union_field_debug_impl = quote_item!(ctx.ext_cx(), + impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) + -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } + } + ) + .unwrap(); + + let items = vec![ + union_field_decl, union_field_impl, + union_field_default_impl, + union_field_clone_impl, + union_field_copy_impl, + union_field_debug_impl, + ]; + + let old_items = mem::replace(result, items); + result.extend(old_items.into_iter()); + } + + pub fn prepend_complex_type(ctx: &BindgenContext, + result: &mut Vec>) { + let complex_type = quote_item!(ctx.ext_cx(), + #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] + #[repr(C)] + pub struct __BindgenComplex { + pub re: T, + pub im: T + } + ) + .unwrap(); + + let items = vec![complex_type]; + 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 { + 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::>() + } else { + item.applicable_template_args(ctx) + .iter() + .map(|arg| arg.to_rust_ty(ctx)) + .collect::>() + }; + + // 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 { + 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> { + // 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 { + 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/libbindgen/src/ir/annotations.rs b/libbindgen/src/ir/annotations.rs new file mode 100644 index 00000000..58308d6d --- /dev/null +++ b/libbindgen/src/ir/annotations.rs @@ -0,0 +1,157 @@ +//! Types and functions related to bindgen annotation comments. +//! +//! Users can add annotations in doc comments to types that they would like to +//! replace other types with, mark as opaque, etc. This module deals with all of +//! that stuff. + +use clang; + +/// What kind of accessor should we provide for a field? +#[derive(Copy, PartialEq, Clone, Debug)] +pub enum FieldAccessorKind { + /// No accessor. + None, + /// Plain accessor. + Regular, + /// Unsafe accessor. + Unsafe, + /// Immutable accessor. + 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, + /// 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, + /// 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, +} + +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 { + /// Construct new annotations for the given cursor and its bindgen comments + /// (if any). + pub fn new(cursor: &clang::Cursor) -> Option { + let mut anno = Annotations::default(); + let mut matched_one = false; + anno.parse(&cursor.comment(), &mut matched_one); + + if matched_one { Some(anno) } else { None } + } + + /// Should this type be hidden? + pub fn hide(&self) -> bool { + self.hide + } + + /// Should this type be opaque? + pub fn opaque(&self) -> bool { + self.opaque + } + + /// For a given type, indicates the type it should replace. + /// + /// For example, in the following code: + /// + /// ```cpp + /// + /// /**
*/ + /// struct Foo { int x; }; + /// + /// struct Bar { char foo; }; + /// ``` + /// + /// the generated code would look something like: + /// + /// ``` + /// /**
*/ + /// struct Bar { + /// x: ::std::os::raw::c_int, + /// }; + /// ``` + /// + /// 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) + } + + /// Should we avoid implementing the `Copy` trait? + pub fn disallow_copy(&self) -> bool { + self.disallow_copy + } + + /// Should the fields be private? + pub fn private_fields(&self) -> Option { + self.private_fields + } + + /// What kind of accessors should we provide for this type's fields? + pub fn accessor_kind(&self) -> Option { + 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_tag_attrs() + .next() + .map_or(false, |attr| attr.name == "rustbindgen") { + *matched = true; + for attr in comment.get_tag_attrs() { + match attr.name.as_str() { + "opaque" => self.opaque = true, + "hide" => self.hide = true, + "nocopy" => self.disallow_copy = true, + "replaces" => self.use_instead_of = Some(attr.value), + "private" => { + self.private_fields = Some(attr.value != "false") + } + "accessor" => { + self.accessor_kind = Some(parse_accessor(&attr.value)) + } + _ => {} + } + } + } + + for child in comment.get_children() { + self.parse(&child, matched); + } + } +} diff --git a/libbindgen/src/ir/comp.rs b/libbindgen/src/ir/comp.rs new file mode 100644 index 00000000..d19d1209 --- /dev/null +++ b/libbindgen/src/ir/comp.rs @@ -0,0 +1,871 @@ +//! Compound types (unions and structs) in our intermediate representation. + +use clang; +use parse::{ClangItemParser, ParseError}; +use std::cell::Cell; +use std::cmp; +use super::annotations::Annotations; +use super::context::{BindgenContext, ItemId}; +use super::item::Item; +use super::layout::Layout; +use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type}; +use super::type_collector::{ItemSet, TypeCollector}; + +/// The kind of compound type. +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum CompKind { + /// A struct. + Struct, + /// A union. + Union, +} + +/// The kind of C++ method. +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum MethodKind { + /// A static method. + Static, + /// A normal method. + Normal, + /// A virtual method. + 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 { + /// Construct a new `Method`. + fn new(kind: MethodKind, signature: ItemId, is_const: bool) -> Self { + Method { + kind: kind, + signature: signature, + is_const: is_const, + } + } + + /// What kind of method is this? + pub fn kind(&self) -> MethodKind { + self.kind + } + + /// Is this a virtual method? + pub fn is_virtual(&self) -> bool { + self.kind == MethodKind::Virtual + } + + /// Is this a static method? + pub fn is_static(&self) -> bool { + self.kind == MethodKind::Static + } + + /// Get the `ItemId` for the `Function` signature for this method. + pub fn signature(&self) -> ItemId { + self.signature + } + + /// Is this a const qualified method? + 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, + /// The inner type. + ty: ItemId, + /// The doc comment on the field if any. + comment: Option, + /// 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, + /// If the C++ field is marked as `mutable` + mutable: bool, +} + +impl Field { + /// Construct a new `Field`. + pub fn new(name: Option, + ty: ItemId, + comment: Option, + annotations: Option, + bitfield: Option, + mutable: bool) + -> Field { + Field { + name: name, + ty: ty, + comment: comment, + annotations: annotations.unwrap_or_default(), + bitfield: bitfield, + mutable: mutable, + } + } + + /// Get the name of this field. + pub fn name(&self) -> Option<&str> { + self.name.as_ref().map(|n| &**n) + } + + /// Get the type of this field. + pub fn ty(&self) -> ItemId { + self.ty + } + + /// Get the comment for this field. + pub fn comment(&self) -> Option<&str> { + self.comment.as_ref().map(|c| &**c) + } + + /// If this is a bitfield, how many bits does it need? + pub fn bitfield(&self) -> Option { + self.bitfield + } + + /// Is this field marked as `mutable`? + pub fn is_mutable(&self) -> bool { + self.mutable + } + + /// Get the annotations for this field. + pub fn annotations(&self) -> &Annotations { + &self.annotations + } +} + +/// A compound type. +/// +/// Either a struct or union, a compound type is built up from the combination +/// of fields which also are associated with their own (potentially compound) +/// type. +#[derive(Debug)] +pub struct CompInfo { + /// Whether this is a struct or a union. + kind: CompKind, + + /// The members of this struct or union. + fields: Vec, + + /// 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, + + /// The method declarations inside this class, if in C++ mode. + methods: Vec, + + /// Vector of classes this one inherits from. + base_members: Vec, + + /// The parent reference template if any. + ref_template: Option, + + /// 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, + + /// Set of static constants declared inside this class. + inner_vars: Vec, + + /// 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, + + /// Used to detect if we've run in a has_destructor cycle while cycling + /// around the template arguments. + detect_has_destructor_cycle: Cell, +} + +impl CompInfo { + /// Construct a new compound type. + 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), + } + } + + /// Can we derive the `Debug` trait for this compound type? + pub fn can_derive_debug(&self, + ctx: &BindgenContext, + layout: Option) + -> 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 { + if ctx.options().unstable_rust { + return false; + } + + 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.base_members + .iter() + .all(|ty| ctx.resolve_type(*ty).can_derive_debug(ctx)) && + self.template_args + .iter() + .all(|ty| ctx.resolve_type(*ty).can_derive_debug(ctx)) && + self.fields + .iter() + .all(|f| ctx.resolve_type(f.ty).can_derive_debug(ctx)) && + self.ref_template.map_or(true, |template| { + ctx.resolve_type(template).can_derive_debug(ctx) + }) + }; + + self.detect_derive_debug_cycle.set(false); + + can_derive_debug + } + + /// Is this compound type unsized? + pub fn is_unsized(&self, ctx: &BindgenContext) -> bool { + !self.has_vtable(ctx) && self.fields.is_empty() && + self.base_members.iter().all(|base| { + ctx.resolve_type(*base).canonical_type(ctx).is_unsized(ctx) + }) && + self.ref_template + .map_or(true, |template| ctx.resolve_type(template).is_unsized(ctx)) + } + + /// Does this compound type have a destructor? + pub fn has_destructor(&self, ctx: &BindgenContext) -> 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| { + ctx.resolve_type(*t).has_destructor(ctx) + }) || + self.template_args + .iter() + .any(|t| ctx.resolve_type(*t).has_destructor(ctx)) || + self.base_members + .iter() + .any(|t| ctx.resolve_type(*t).has_destructor(ctx)) || + self.fields.iter().any(|field| { + ctx.resolve_type(field.ty) + .has_destructor(ctx) + }) + } + }; + + self.detect_has_destructor_cycle.set(false); + + has_destructor + } + + /// Can we derive the `Copy` trait for this type? + pub fn can_derive_copy(&self, ctx: &BindgenContext, item: &Item) -> 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(ctx) { + return false; + } + + if self.kind == CompKind::Union { + if !ctx.options().unstable_rust { + return true; + } + + // https://github.com/rust-lang/rust/issues/36640 + if !self.template_args.is_empty() || self.ref_template.is_some() || + !item.applicable_template_args(ctx).is_empty() { + return false; + } + } + + // With template args, use a safe subset of the types, + // since copyability depends on the types itself. + self.ref_template + .as_ref() + .map_or(true, |t| ctx.resolve_item(*t).can_derive_copy(ctx)) && + self.base_members + .iter() + .all(|t| ctx.resolve_item(*t).can_derive_copy(ctx)) && + self.fields.iter().all(|field| { + ctx.resolve_item(field.ty) + .can_derive_copy(ctx) + }) + } + + /// Is this type a template specialization? + pub fn is_template_specialization(&self) -> bool { + self.ref_template.is_some() + } + + /// Get the template declaration this specialization is specializing. + pub fn specialized_template(&self) -> Option { + self.ref_template + } + + /// Compute 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, ctx: &BindgenContext) -> Option { + 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 = ctx.resolve_type(field.ty) + .layout(ctx); + + 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)) + } + + /// Get this type's set of fields. + pub fn fields(&self) -> &[Field] { + &self.fields + } + + /// Get this type's set of free template arguments. Empty if this is not a + /// template. + pub fn template_args(&self) -> &[ItemId] { + &self.template_args + } + + /// Does this type have any template parameters that aren't types + /// (e.g. int)? + pub fn has_non_type_template_params(&self) -> bool { + self.has_non_type_template_params + } + + /// Does this type have a virtual table? + pub fn has_vtable(&self, ctx: &BindgenContext) -> bool { + self.has_vtable || + self.base_members().iter().any(|base| { + ctx.resolve_type(*base) + .has_vtable(ctx) + }) || + self.ref_template.map_or(false, |template| { + ctx.resolve_type(template).has_vtable(ctx) + }) + } + + /// Get this type's set of methods. + pub fn methods(&self) -> &[Method] { + &self.methods + } + + /// What kind of compound type is this? + pub fn kind(&self) -> CompKind { + self.kind + } + + /// The set of types that this one inherits from. + pub fn base_members(&self) -> &[ItemId] { + &self.base_members + } + + /// Construct a new compound type from a Clang type. + pub fn from_ty(potential_id: ItemId, + ty: &clang::Type, + location: Option, + ctx: &mut BindgenContext) + -> Result { + 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.template_args() { + // In forward declarations and not specializations, + // etc, they are in + // the ast, we'll meet them in + // CXCursor_TemplateTypeParameter + None => vec![], + Some(arg_types) => { + let num_arg_types = arg_types.len(); + + let args = arg_types.filter(|t| t.kind() != CXType_Invalid) + .map(|t| Item::from_ty_or_ref(t, None, None, ctx)) + .collect::>(); + + if args.len() != num_arg_types { + ci.has_non_type_template_params = true; + warn!("warning: Template parameter is not a type"); + } + + args + } + }; + + ci.ref_template = cursor.specialized() + .and_then(|c| Item::parse(c, None, ctx).ok()); + + let mut maybe_anonymous_struct_field = None; + cursor.visit(|cur| { + if cur.kind() != CXCursor_FieldDecl { + if let Some((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 { + let ty = cur.cur_type(); + maybe_anonymous_struct_field = Some((inner, ty)); + } + } + 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(), Some(cur), 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 + }; + + let method = + Method::new(method_kind, method_signature, is_const); + + ci.methods.push(method); + } + 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 comp 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 { + use clangll::*; + Ok(match cursor.kind() { + CXCursor_UnionDecl => CompKind::Union, + CXCursor_ClassDecl | + CXCursor_StructDecl => CompKind::Struct, + CXCursor_CXXBaseSpecifier | + 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); + } + }) + } + + /// Do any of the types that participate in this type's "signature" use the + /// named type `ty`? + /// + /// See also documentation for `ir::Item::signature_contains_named_type`. + pub fn signature_contains_named_type(&self, + ctx: &BindgenContext, + ty: &Type) + -> bool { + // We don't generate these, so rather don't make the codegen step to + // think we got it covered. + if self.has_non_type_template_params() { + return false; + } + self.template_args.iter().any(|arg| { + ctx.resolve_type(*arg) + .signature_contains_named_type(ctx, ty) + }) + } + + /// Get the set of types that were declared within this compound type + /// (e.g. nested class definitions). + pub fn inner_types(&self) -> &[ItemId] { + &self.inner_types + } + + /// Get the set of static variables declared within this compound type. + pub fn inner_vars(&self) -> &[ItemId] { + &self.inner_vars + } + + /// Have we found a field with an opaque type that could potentially mess up + /// the layout of this compound type? + pub fn found_unknown_attr(&self) -> bool { + self.found_unknown_attr + } + + /// Is this compound type packed? + 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, ctx: &BindgenContext) -> bool { + self.has_vtable(ctx) && + !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. + ctx.resolve_type(*base) + .canonical_type(ctx) + .as_comp() + .map_or(false, |ci| ci.has_vtable(ctx)) + }) + } +} + +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() { + types.insert(template); + } + + let applicable_template_args = item.applicable_template_args(context); + for arg in applicable_template_args { + types.insert(arg); + } + + for &base in self.base_members() { + types.insert(base); + } + + for field in self.fields() { + types.insert(field.ty()); + } + + for &ty in self.inner_types() { + types.insert(ty); + } + + // FIXME(emilio): Methods, VTable? + } +} diff --git a/libbindgen/src/ir/context.rs b/libbindgen/src/ir/context.rs new file mode 100644 index 00000000..85721978 --- /dev/null +++ b/libbindgen/src/ir/context.rs @@ -0,0 +1,1055 @@ +//! Common context that is passed around during parsing and codegen. + +use BindgenOptions; +use cexpr; +use clang::{self, Cursor}; +use parse::ClangItemParser; +use std::borrow::Cow; +use std::cell::Cell; +use std::collections::{HashMap, hash_map}; +use std::collections::btree_map::{self, BTreeMap}; +use std::fmt; +use super::int::IntKind; +use super::item::{Item, ItemCanonicalName}; +use super::item_kind::ItemKind; +use super::module::Module; +use super::ty::{FloatKind, Type, TypeKind}; +use super::type_collector::{ItemSet, TypeCollector}; +use syntax::ast::Ident; +use syntax::codemap::{DUMMY_SP, Span}; +use syntax::ext::base::ExtCtxt; + +/// 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 ItemId { + /// Get a numeric representation of this id. + pub fn as_usize(&self) -> usize { + self.0 + } +} + +/// A key used to index a resolved type, so we only process it once. +/// +/// This is almost always a USR string (an unique identifier generated by +/// clang), but it can also be the canonical declaration if the type is unnamed, +/// in which case clang may generate the same USR for multiple nested unnamed +/// types. +#[derive(Eq, PartialEq, Hash, Debug)] +enum TypeKey { + USR(String), + Declaration(Cursor), +} + +// 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, + + /// The next item id to use during this bindings regeneration. + next_item_id: ItemId, + + /// Clang USR to type map. This is needed to be able to associate types with + /// item ids during parsing. + types: HashMap, + + /// A cursor to module map. Similar reason than above. + modules: HashMap, + + /// 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, as well to allow macro + /// expression parsing. + parsed_macros: HashMap, cexpr::expr::EvalResult>, + + /// The active replacements collected from replaces="xxx" annotations. + replacements: HashMap, + + 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, + + /// Whether a bindgen complex was generated + generated_bindegen_complex: Cell, +} + +impl<'ctx> BindgenContext<'ctx> { + /// Construct the context for the given `options`. + pub fn new(options: BindgenOptions) -> Self { + use clangll; + + let index = clang::Index::new(false, true); + + let parse_options = + clangll::CXTranslationUnit_DetailedPreprocessingRecord; + let translation_unit = + clang::TranslationUnit::parse(&index, + "", + &options.clang_args, + &[], + parse_options) + .expect("TranslationUnit::parse"); + + let root_module = Self::build_root_module(ItemId(0)); + let mut me = BindgenContext { + items: Default::default(), + types: Default::default(), + modules: Default::default(), + next_item_id: ItemId(1), + 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, + generated_bindegen_complex: Cell::new(false), + }; + + me.add_item(root_module, None, None); + + me + } + + /// Define a new item. + /// + /// This inserts it into the internal items set, and its type into the + /// internal types set. + pub fn add_item(&mut self, + item: Item, + declaration: Option, + location: Option) { + 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 is_unnamed = is_type && item.expect_type().name().is_none(); + let old_item = self.items.insert(id, item); + assert!(old_item.is_none(), "Inserted type twice?"); + + // Unnamed items can have an USR, but they can't be referenced from + // other sites explicitly and the USR can match if the unnamed items are + // nested, so don't bother tracking them. + if is_type && declaration.is_some() { + let mut declaration = declaration.unwrap(); + if !declaration.is_valid() { + if let Some(location) = location { + if location.kind() == CXCursor_ClassTemplate || + location.kind() == + CXCursor_ClassTemplatePartialSpecialization { + declaration = location; + } + } + } + declaration = declaration.canonical(); + if !declaration.is_valid() { + // 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()); + return; + } + + let key = if is_unnamed { + TypeKey::Declaration(declaration) + } else if let Some(usr) = declaration.usr() { + TypeKey::USR(usr) + } else { + error!("Valid declaration with no USR: {:?}, {:?}", + declaration, + location); + return; + }; + + let old = self.types.insert(key, id); + debug_assert_eq!(old, None); + } + } + + // TODO: Move all this syntax crap to other part of the code. + + /// Given that we are in the codegen phase, get the syntex context. + pub fn ext_cx(&self) -> &ExtCtxt<'ctx> { + &self.gen_ctx.expect("Not in gen phase").0 + } + + /// Given that we are in the codegen phase, get the current syntex span. + 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)) + } + + /// Returns a mangled name as a rust identifier. + pub fn rust_ident_raw(&self, name: &str) -> Ident { + self.ext_cx().ident_of(name) + } + + /// Iterate over all items that have been defined. + pub fn items<'a>(&'a self) -> btree_map::Iter<'a, ItemId, Item> { + self.items.iter() + } + + /// Have we collected all unresolved type references yet? + pub fn collected_typerefs(&self) -> bool { + self.collected_typerefs + } + + /// Gather all the unresolved type references. + fn collect_typerefs + (&mut self) + -> Vec<(ItemId, clang::Type, Option, Option)> { + 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, parent_id) => { + typerefs.push((*id, ty.clone(), loc, parent_id)); + } + _ => {} + }; + } + typerefs + } + + /// Collect all of our unresolved type references and resolve them. + fn resolve_typerefs(&mut self) { + let typerefs = self.collect_typerefs(); + + for (id, ty, loc, parent_id) in typerefs { + let _resolved = { + let resolved = Item::from_ty(&ty, loc, parent_id, 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?"); + } + } + + /// Iterate over all items and replace any item that has been named in a + /// `replaces="SomeType"` annotation with the replacement type. + fn process_replacements(&mut self) { + if self.replacements.is_empty() { + debug!("No replacements to process"); + 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() { + // Calls to `canonical_name` are expensive, so eagerly filter out + // items that cannot be replaced. + let ty = match item.kind().as_type() { + Some(ty) => ty, + None => continue, + }; + + match *ty.kind() { + TypeKind::Comp(ref ci) if !ci.is_template_specialization() => {} + TypeKind::TemplateAlias(_, _) | + TypeKind::Alias(_, _) => {} + _ => continue, + } + + let name = item.real_canonical_name(self, + self.options() + .enable_cxx_namespaces, + true); + let replacement = self.replacements.get(&name); + + if let Some(replacement) = replacement { + 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 { + debug!("Replacing {:?} with {:?}", id, replacement); + + let mut item = self.items.get_mut(&id).unwrap(); + *item.kind_mut().as_type_mut().unwrap().kind_mut() = + TypeKind::ResolvedTypeRef(replacement); + } + } + + /// Enter the code generation phase, invoke the given callback `cb`, and + /// leave the code generation phase. + pub fn gen(&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::DummyResolver; + 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) }); + + if !self.collected_typerefs() { + 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!("add_builtin_item: 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(id: ItemId) -> Item { + let module = Module::new(Some("root".into())); + Item::new(id, None, None, id, ItemKind::Module(module)) + } + + /// Get the root module. + pub fn root_module(&self) -> ItemId { + self.root_module + } + + /// Resolve the given `ItemId` as a type. + /// + /// Panics if there is no item for the given `ItemId` or if the resolved + /// item is not a `Type`. + pub fn resolve_type(&self, type_id: ItemId) -> &Type { + self.items.get(&type_id).unwrap().kind().expect_type() + } + + /// Resolve the given `ItemId` as a type, or `None` if there is no item with + /// the given id. + /// + /// Panics if the id resolves to an item that is not a type. + pub fn safe_resolve_type(&self, type_id: ItemId) -> Option<&Type> { + self.items.get(&type_id).map(|t| t.kind().expect_type()) + } + + /// Resolve the given `ItemId` into an `Item`, or `None` if no such item + /// exists. + pub fn resolve_item_fallible(&self, item_id: ItemId) -> Option<&Item> { + self.items.get(&item_id) + } + + /// Resolve the given `ItemId` into an `Item`. + /// + /// Panics if the given id does not resolve to any item. + 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), + } + } + + /// Get the current module. + 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: + /// + /// ```c++ + /// template + /// class Incomplete { + /// T p; + /// }; + /// + /// template + /// class Foo { + /// Incomplete bar; + /// }; + /// ``` + fn build_template_wrapper(&mut self, + with_id: ItemId, + wrapping: ItemId, + parent_id: ItemId, + ty: &clang::Type, + location: clang::Cursor, + declaration: clang::Cursor) + -> ItemId { + use clangll::*; + let mut args = vec![]; + location.visit(|c| { + if c.kind() == CXCursor_TypeRef { + // The `with_id` id will potentially end up unused if we give up + // on this type (for example, its a tricky partial template + // specialization), so if we pass `with_id` as the parent, it is + // potentially a dangling reference. Instead, use the canonical + // template declaration as the parent. It is already parsed and + // has a known-resolvable `ItemId`. + let new_ty = Item::from_ty_or_ref(c.cur_type(), + Some(c), + Some(wrapping), + self); + args.push(new_ty); + } + CXChildVisit_Continue + }); + + let item = { + let wrapping_type = self.resolve_type(wrapping); + if let TypeKind::Comp(ref ci) = *wrapping_type.kind() { + let old_args = ci.template_args(); + + // 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, + // which sucks. The same happens for specialized type alias + // template declarations, where we have that ugly hack up there. + // + // This flaw was already on the old parser, but I now think it + // has no clear solution (apart from patching libclang to + // somehow expose them, of course). + // + // For an easy example in which there's no way at all of getting + // the `int` type, except manually parsing the spelling: + // + // template + // class Incomplete { + // T d; + // U p; + // }; + // + // template + // class Foo { + // Incomplete 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; + } + } else { + assert_eq!(declaration.kind(), + ::clangll::CXCursor_TypeAliasTemplateDecl, + "Expected wrappable type"); + } + + 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(with_id, None, None, parent_id, ItemKind::Type(ty)) + }; + + // Bypass all the validations in add_item explicitly. + debug!("build_template_wrapper: inserting item: {:?}", item); + debug_assert!(with_id == item.id()); + self.items.insert(with_id, item); + with_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, + with_id: ItemId, + parent_id: Option, + ty: &clang::Type, + location: Option) + -> Option { + use clangll::{CXCursor_ClassTemplate, + CXCursor_ClassTemplatePartialSpecialization, + CXCursor_TypeAliasTemplateDecl, + CXCursor_TypeRef}; + 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() { + let id = self.types + .get(&TypeKey::Declaration(canonical_declaration)) + .map(|id| *id) + .or_else(|| { + canonical_declaration.usr() + .and_then(|usr| self.types.get(&TypeKey::USR(usr))) + .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 || + declaration.kind() == CXCursor_TypeAliasTemplateDecl) && + *ty != canonical_declaration.cur_type() && + location.is_some() && + parent_id.is_some() { + // For specialized type aliases, there's no way to get the + // template parameters as of this writing (for a struct + // specialization we wouldn't be in this branch anyway). + // + // Explicitly return `None` if there aren't any + // unspecialized parameters (contains any `TypeRef`) so we + // resolve the canonical type if there is one and it's + // exposed. + // + // This is _tricky_, I know :( + if declaration.kind() == CXCursor_TypeAliasTemplateDecl && + !location.unwrap().contains_cursor(CXCursor_TypeRef) && + ty.canonical_type().is_valid_and_exposed() { + return None; + } + + return Some(self.build_template_wrapper(with_id, + id, + parent_id.unwrap(), + ty, + location.unwrap(), + declaration)); + } + + return Some(self.build_ty_wrapper(with_id, 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, + with_id: ItemId, + wrapped_id: ItemId, + parent_id: Option, + ty: &clang::Type) + -> ItemId { + 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(with_id, + None, + None, + parent_id.unwrap_or(self.current_module), + ItemKind::Type(ty)); + self.add_builtin_item(item); + with_id + } + + /// Returns the next item id to be used for an item. + pub fn next_item_id(&mut self) -> ItemId { + let ret = self.next_item_id; + self.next_item_id = ItemId(self.next_item_id.0 + 1); + ret + } + + fn build_builtin_ty(&mut self, + ty: &clang::Type, + _declaration: Cursor) + -> Option { + 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_Int128 => TypeKind::Int(IntKind::I128), + CXType_UInt128 => TypeKind::Int(IntKind::U128), + CXType_Float => TypeKind::Float(FloatKind::Float), + CXType_Double => TypeKind::Float(FloatKind::Double), + CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble), + CXType_Float128 => TypeKind::Float(FloatKind::Float128), + CXType_Complex => { + let float_type = ty.elem_type() + .expect("Not able to resolve complex type?"); + let float_kind = match float_type.kind() { + CXType_Float => FloatKind::Float, + CXType_Double => FloatKind::Double, + CXType_LongDouble => FloatKind::LongDouble, + _ => panic!("Non floating-type complex?"), + }; + TypeKind::Complex(float_kind) + } + _ => 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 = self.next_item_id(); + let item = + Item::new(id, None, None, self.root_module, ItemKind::Type(ty)); + self.add_builtin_item(item); + Some(id) + } + + /// Get the current Clang translation unit that is being processed. + pub fn translation_unit(&self) -> &clang::TranslationUnit { + &self.translation_unit + } + + /// Have we parsed the macro named `macro_name` already? + pub fn parsed_macro(&self, macro_name: &[u8]) -> bool { + self.parsed_macros.contains_key(macro_name) + } + + /// Get the currently parsed macros. + pub fn parsed_macros(&self) -> &HashMap, cexpr::expr::EvalResult> { + debug_assert!(!self.in_codegen_phase()); + &self.parsed_macros + } + + /// Mark the macro named `macro_name` as parsed. + pub fn note_parsed_macro(&mut self, + id: Vec, + value: cexpr::expr::EvalResult) { + self.parsed_macros.insert(id, value); + } + + /// Are we in the codegen phase? + pub fn in_codegen_phase(&self) -> bool { + self.gen_ctx.is_some() + } + + /// Mark the type with the given `name` as replaced by the type with id + /// `potential_ty`. + /// + /// Replacement types are declared using the `replaces="xxx"` annotation, + /// and implies that the original type is hidden. + pub fn replace(&mut self, name: &str, potential_ty: ItemId) { + match self.replacements.entry(name.into()) { + hash_map::Entry::Vacant(entry) => { + debug!("Defining replacement for {} as {:?}", + name, + potential_ty); + entry.insert(potential_ty); + } + hash_map::Entry::Occupied(occupied) => { + warn!("Replacement for {} already defined as {:?}; \ + ignoring duplicate replacement definition as {:?}}}", + name, + occupied.get(), + potential_ty); + } + } + } + + /// Is the item with the given `name` hidden? Or is the item with the given + /// `name` and `id` replaced by another type, and effectively hidden? + pub fn hidden_by_name(&self, name: &str, id: ItemId) -> bool { + debug_assert!(self.in_codegen_phase(), + "You're not supposed to call this yet"); + self.options.hidden_types.contains(name) || + self.is_replaced_type(name, id) + } + + /// Has the item with the given `name` and `id` been replaced by another + /// type? + pub fn is_replaced_type(&self, name: &str, id: ItemId) -> bool { + match self.replacements.get(name) { + Some(replaced_by) if *replaced_by != id => true, + _ => false, + } + } + + /// Is the type with the given `name` marked as opaque? + 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) + } + + /// Get the options used to configure this bindgen context. + 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(); + if let Some(id) = self.modules.get(&cursor) { + return *id; + } + + let module_id = self.next_item_id(); + 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 + } + + /// Start traversing the module with the given `module_id`, invoke the + /// callback `cb`, and then return to traversing the original module. + pub fn with_module(&mut self, module_id: ItemId, cb: F) + where F: FnOnce(&mut Self, &mut Vec), + { + 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; + } + + /// Iterate over all (explicitly or transitively) whitelisted items. + /// + /// If no items are explicitly whitelisted, then all items are considered + /// whitelisted. + pub fn whitelisted_items<'me>(&'me self) + -> WhitelistedItemsIter<'me, 'ctx> { + assert!(self.in_codegen_phase()); + assert!(self.current_module == self.root_module); + + let roots = self.items() + .filter(|&(_, item)| { + // If nothing is explicitly whitelisted, then everything is fair + // game. + if self.options().whitelisted_types.is_empty() && + self.options().whitelisted_functions.is_empty() && + self.options().whitelisted_vars.is_empty() { + return true; + } + + let name = item.canonical_name(self); + match *item.kind() { + ItemKind::Module(..) => false, + ItemKind::Function(_) => { + self.options().whitelisted_functions.matches(&name) + } + ItemKind::Var(_) => { + self.options().whitelisted_vars.matches(&name) + } + ItemKind::Type(ref ty) => { + if self.options().whitelisted_types.matches(&name) { + return true; + } + + // 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() && + enum_.variants().iter().any(|variant| { + self.options() + .whitelisted_vars + .matches(&variant.name()) + }) { + return true; + } + } + + false + } + } + }) + .map(|(&id, _)| id); + + let seen: ItemSet = roots.collect(); + + // The .rev() preserves the expected ordering traversal, resulting in + // more stable-ish bindgen-generated names for anonymous types (like + // unions). + let to_iterate = seen.iter().cloned().rev().collect(); + + WhitelistedItemsIter { + ctx: self, + seen: seen, + to_iterate: to_iterate, + } + } + + /// Convenient method for getting the prefix to use for most traits in + /// codegen depending on the `use_core` option. + pub fn trait_prefix(&self) -> Ident { + if self.options().use_core { + self.rust_ident_raw("core") + } else { + self.rust_ident_raw("std") + } + } + + /// Call if a binden complex is generated + pub fn generated_bindegen_complex(&self) { + self.generated_bindegen_complex.set(true) + } + + /// Whether we need to generate the binden complex type + pub fn need_bindegen_complex_type(&self) -> bool { + self.generated_bindegen_complex.get() + } +} + +/// An iterator over whitelisted items. +/// +/// See `BindgenContext::whitelisted_items` for more information. +pub struct WhitelistedItemsIter<'ctx, 'gen> + where 'gen: 'ctx, +{ + ctx: &'ctx BindgenContext<'gen>, + + // The set of whitelisted items we have seen. If you think of traversing + // whitelisted items like GC tracing, this is the mark bits, and contains + // both black and gray items. + seen: ItemSet, + + // The set of whitelisted items that we have seen but have yet to iterate + // over and collect transitive references from. To return to the GC analogy, + // this is the mark stack, containing the set of gray items which we have + // not finished tracing yet. + to_iterate: Vec, +} + +impl<'ctx, 'gen> Iterator for WhitelistedItemsIter<'ctx, 'gen> + where 'gen: 'ctx, +{ + type Item = ItemId; + + fn next(&mut self) -> Option { + let id = match self.to_iterate.pop() { + None => return None, + Some(id) => id, + }; + + debug_assert!(self.seen.contains(&id)); + debug_assert!(self.ctx.items.contains_key(&id)); + + let mut sub_types = ItemSet::new(); + id.collect_types(self.ctx, &mut sub_types, &()); + + for id in sub_types { + if self.seen.insert(id) { + self.to_iterate.push(id); + } + } + + Some(id) + } +} diff --git a/libbindgen/src/ir/enum_ty.rs b/libbindgen/src/ir/enum_ty.rs new file mode 100644 index 00000000..6085833d --- /dev/null +++ b/libbindgen/src/ir/enum_ty.rs @@ -0,0 +1,137 @@ +//! Intermediate representation for C/C++ enumerations. + +use clang; +use parse::{ClangItemParser, ParseError}; +use super::context::{BindgenContext, ItemId}; +use super::item::Item; +use super::ty::TypeKind; + +/// A C/C++ enumeration. +#[derive(Debug)] +pub struct Enum { + /// The representation used for this enum; it should be an `IntKind` type or + /// an alias to one. + /// + /// 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, + + /// The different variants, with explicit values. + variants: Vec, +} + +impl Enum { + /// Construct a new `Enum` with the given representation and variants. + pub fn new(repr: Option, variants: Vec) -> Self { + Enum { + repr: repr, + variants: variants, + } + } + + /// Get this enumeration's representation. + pub fn repr(&self) -> Option { + self.repr + } + + /// Get this enumeration's variants. + pub fn variants(&self) -> &[EnumVariant] { + &self.variants + } + + /// Construct an enumeration from the given Clang type. + pub fn from_ty(ty: &clang::Type, + ctx: &mut BindgenContext) + -> Result { + 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 value = if is_signed { + cursor.enum_val_signed().map(EnumVariantValue::Signed) + } else { + cursor.enum_val_unsigned().map(EnumVariantValue::Unsigned) + }; + if let Some(val) = value { + let name = cursor.spelling(); + let comment = cursor.raw_comment(); + 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, + + /// The integer value of the variant. + val: EnumVariantValue, +} + +/// A constant value assigned to an enumeration variant. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum EnumVariantValue { + /// A signed constant. + Signed(i64), + + /// An unsigned constant. + Unsigned(u64), +} + +impl EnumVariant { + /// Construct a new enumeration variant from the given parts. + pub fn new(name: String, + comment: Option, + val: EnumVariantValue) + -> Self { + EnumVariant { + name: name, + comment: comment, + val: val, + } + } + + /// Get this variant's name. + pub fn name(&self) -> &str { + &self.name + } + + /// Get this variant's value. + pub fn val(&self) -> EnumVariantValue { + self.val + } +} diff --git a/libbindgen/src/ir/function.rs b/libbindgen/src/ir/function.rs new file mode 100644 index 00000000..eacb6c0e --- /dev/null +++ b/libbindgen/src/ir/function.rs @@ -0,0 +1,282 @@ +//! Intermediate representation for C/C++ functions and methods. + +use clang; +use clangll::Enum_CXCallingConv; +use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; +use super::context::{BindgenContext, ItemId}; +use super::item::Item; +use super::ty::TypeKind; +use super::type_collector::{ItemSet, TypeCollector}; +use syntax::abi; + +/// 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 { + /// The name of this function. + name: String, + + /// The mangled name, that is, the symbol. + mangled_name: Option, + + /// The id pointing to the current function signature. + signature: ItemId, + + /// The doc comment on the function, if any. + comment: Option, +} + +impl Function { + /// Construct a new function. + pub fn new(name: String, + mangled_name: Option, + sig: ItemId, + comment: Option) + -> Self { + Function { + name: name, + mangled_name: mangled_name, + signature: sig, + comment: comment, + } + } + + /// Get this function's name. + pub fn name(&self) -> &str { + &self.name + } + + /// Get this function's name. + pub fn mangled_name(&self) -> Option<&str> { + self.mangled_name.as_ref().map(|n| &**n) + } + + /// Get this function's signature. + 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, 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), + } +} + +/// Get the mangled name for the cursor's referent. +pub fn cursor_mangling(cursor: &clang::Cursor) -> Option { + // We early return here because libclang may crash in some case + // if we pass in a variable inside a partial specialized template. + // See servo/rust-bindgen#67. + if cursor.is_in_non_fully_specialized_template() { + return None; + } + + let mut mangling = cursor.mangling(); + if mangling.is_empty() { + return None; + } + + // Try to undo backend linkage munging (prepended _, generally) + if cfg!(target_os = "macos") { + mangling.remove(0); + } + + Some(mangling) +} + +impl FunctionSig { + /// Construct a new function signature. + pub fn new(return_type: ItemId, + arguments: Vec<(Option, ItemId)>, + is_variadic: bool, + abi: abi::Abi) + -> Self { + FunctionSig { + return_type: return_type, + argument_types: arguments, + is_variadic: is_variadic, + abi: abi, + } + } + + /// Construct a new function signature from the given Clang type. + pub fn from_ty(ty: &clang::Type, + cursor: &clang::Cursor, + ctx: &mut BindgenContext) + -> Result { + 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 ty_ret_type = try!(ty.ret_type().ok_or(ParseError::Continue)); + 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)) + } + + /// Get this function signature's return type. + pub fn return_type(&self) -> ItemId { + self.return_type + } + + /// Get this function signature's argument (name, type) pairs. + pub fn argument_types(&self) -> &[(Option, ItemId)] { + &self.argument_types + } + + /// Get this function signature's ABI. + pub fn abi(&self) -> abi::Abi { + self.abi + } + + /// Is this function signature variadic? + 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, 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))) + } +} + +impl TypeCollector for FunctionSig { + type Extra = Item; + + fn collect_types(&self, + _context: &BindgenContext, + types: &mut ItemSet, + _item: &Item) { + types.insert(self.return_type()); + + for &(_, ty) in self.argument_types() { + types.insert(ty); + } + } +} diff --git a/libbindgen/src/ir/int.rs b/libbindgen/src/ir/int.rs new file mode 100644 index 00000000..2d85db83 --- /dev/null +++ b/libbindgen/src/ir/int.rs @@ -0,0 +1,93 @@ +//! Intermediate representation for integral types. + +/// Which integral type are we dealing with? +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum IntKind { + /// A `bool`. + Bool, + + /// A `char`. + Char, + + /// An `unsigned char`. + UChar, + + /// A `short`. + Short, + + /// An `unsigned short`. + UShort, + + /// An `int`. + Int, + + /// An `unsigned int`. + UInt, + + /// A `long`. + Long, + + /// An `unsigned long`. + ULong, + + /// A `long long`. + LongLong, + + /// An `unsigned long long`. + ULongLong, + + /// A 8-bit signed integer. + I8, + + /// A 8-bit unsigned integer. + U8, + + /// A 16-bit signed integer. + I16, + + /// Either a `char16_t` or a `wchar_t`. + U16, + + /// A 32-bit signed integer. + I32, + + /// A 32-bit unsigned integer. + U32, + + /// A 64-bit signed integer. + I64, + + /// A 64-bit unsigned integer. + U64, + + /// An `int128_t` + I128, + + /// A `uint128_t`. + U128, + + /// A custom integer type, used to allow custom macro types depending on + /// range. + Custom { + /// The name of the type, which would be used without modification. + name: &'static str, + /// Whether the type is signed or not. + is_signed: bool, + }, +} + +impl IntKind { + /// Is this integral type signed? + pub fn is_signed(&self) -> bool { + use self::IntKind::*; + match *self { + Bool | UChar | UShort | UInt | ULong | ULongLong | U8 | U16 | + U32 | U64 | U128 => false, + + Char | Short | Int | Long | LongLong | I8 | I16 | I32 | I64 | + I128 => true, + + Custom { is_signed, .. } => is_signed, + } + } +} diff --git a/libbindgen/src/ir/item.rs b/libbindgen/src/ir/item.rs new file mode 100644 index 00000000..1f05f92f --- /dev/null +++ b/libbindgen/src/ir/item.rs @@ -0,0 +1,1172 @@ +//! Bindgen's core intermediate representation type. + +use clang; +use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; +use regex::Regex; +use std::cell::{Cell, RefCell}; +use super::annotations::Annotations; +use super::context::{BindgenContext, ItemId}; +use super::function::Function; +use super::item_kind::ItemKind; +use super::module::Module; +use super::ty::{Type, TypeKind}; +use super::type_collector::{ItemSet, TypeCollector}; + +/// 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 { + /// Get the canonical name for this item. + 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: +/// +/// ```c++ +/// namespace foo { +/// const BAR = 3; +/// } +/// ``` +/// +/// For bar, the canonical path is `vec!["foo", "BAR"]`, while the canonical +/// name is just `"BAR"`. +pub trait ItemCanonicalPath { + /// Get the canonical path for this item. + fn canonical_path(&self, ctx: &BindgenContext) -> Vec; +} + +/// A trait for iterating over an item and its parents and up its ancestor chain +/// up to (but not including) the implicit root module. +pub trait ItemAncestors { + /// Get an iterable over this item's ancestors. + fn ancestors<'a, 'b>(&self, + ctx: &'a BindgenContext<'b>) + -> ItemAncestorsIter<'a, 'b>; +} + +/// An iterator over an item and its ancestors. +pub struct ItemAncestorsIter<'a, 'b> + where 'b: 'a, +{ + item: ItemId, + ctx: &'a BindgenContext<'b>, +} + +impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> + where 'b: 'a, +{ + type Item = ItemId; + + fn next(&mut self) -> Option { + let item = self.ctx.resolve_item(self.item); + if item.parent_id() == self.item { + None + } else { + self.item = item.parent_id(); + Some(item.id()) + } + } +} + +// 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 { + debug_assert!(ctx.in_codegen_phase(), + "You're not supposed to call this yet"); + ctx.resolve_item(*self).canonical_path(ctx) + } +} + +impl ItemAncestors for ItemId { + fn ancestors<'a, 'b>(&self, + ctx: &'a BindgenContext<'b>) + -> ItemAncestorsIter<'a, 'b> { + ItemAncestorsIter { + item: *self, + ctx: ctx, + } + } +} + +impl ItemAncestors for Item { + fn ancestors<'a, 'b>(&self, + ctx: &'a BindgenContext<'b>) + -> ItemAncestorsIter<'a, 'b> { + self.id().ancestors(ctx) + } +} + +impl TypeCollector for ItemId { + type Extra = (); + + fn collect_types(&self, + ctx: &BindgenContext, + types: &mut ItemSet, + extra: &()) { + ctx.resolve_item(*self).collect_types(ctx, types, extra); + } +} + +impl TypeCollector for Item { + type Extra = (); + + fn collect_types(&self, + ctx: &BindgenContext, + types: &mut ItemSet, + _extra: &()) { + if self.is_hidden(ctx) || types.contains(&self.id()) { + return; + } + + match *self.kind() { + ItemKind::Type(ref ty) => { + if !self.is_opaque(ctx) { + ty.collect_types(ctx, types, self); + } + } + _ => {} // FIXME. + } + } +} + +/// An item is the base of the bindgen representation, it can be either a +/// module, a type, a function, or a variable (see `ItemKind` for more +/// information). +/// +/// Items refer to each other by `ItemId`. Every item has its parent's +/// id. Depending on the kind of item this is, it may also refer to other items, +/// such as a compound type item referring to other types. Collectively, these +/// references form a graph. +/// +/// The entry-point to this graph is the "root module": a meta-item used to hold +/// all top-level items. +/// +/// An item may have a comment, and annotations (see the `annotations` module). +/// +/// Note that even though we parse all the types of annotations in comments, not +/// all of them apply to every item. Those rules are described in the +/// `annotations` module. +#[derive(Debug)] +pub struct Item { + /// This item's id. + id: ItemId, + + /// The item's local id, unique only amongst its siblings. Only used for + /// anonymous items. + /// + /// Lazily initialized in local_id(). + /// + /// Note that only structs, unions, and enums get a local type id. In any + /// case this is an implementation detail. + local_id: Cell>, + + /// The next local id to use for a child.. + next_child_local_id: Cell, + + /// A cached copy of the canonical name, as returned by `canonical_name`. + /// + /// This is a fairly used operation during codegen so this makes bindgen + /// considerably faster in those cases. + canonical_name_cache: RefCell>, + + /// A doc comment over the item, if any. + comment: Option, + /// 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 { + /// Construct a new `Item`. + pub fn new(id: ItemId, + comment: Option, + annotations: Option, + parent_id: ItemId, + kind: ItemKind) + -> Self { + debug_assert!(id != parent_id || kind.is_module()); + Item { + id: id, + local_id: Cell::new(None), + next_child_local_id: Cell::new(1), + canonical_name_cache: RefCell::new(None), + parent_id: parent_id, + comment: comment, + annotations: annotations.unwrap_or_default(), + kind: kind, + } + } + + /// Get this `Item`'s identifier. + pub fn id(&self) -> ItemId { + self.id + } + + /// Get this `Item`'s parent's identifier. + /// + /// For the root module, the parent's ID is its own ID. + pub fn parent_id(&self) -> ItemId { + self.parent_id + } + + /// Get this `Item`'s comment, if it has any. + pub fn comment(&self) -> Option<&str> { + self.comment.as_ref().map(|c| &**c) + } + + /// What kind of item is this? + pub fn kind(&self) -> &ItemKind { + &self.kind + } + + /// Get a mutable reference to this item's kind. + pub fn kind_mut(&mut self) -> &mut ItemKind { + &mut self.kind + } + + /// Get an identifier that differentiates this item from its siblings. + /// + /// This should stay relatively stable in the face of code motion outside or + /// below this item's lexical scope, meaning that this can be useful for + /// generating relatively stable identifiers within a scope. + pub fn local_id(&self, ctx: &BindgenContext) -> usize { + if self.local_id.get().is_none() { + let parent = ctx.resolve_item(self.parent_id); + let local_id = parent.next_child_local_id.get(); + parent.next_child_local_id.set(local_id + 1); + self.local_id.set(Some(local_id)); + } + self.local_id.get().unwrap() + } + + /// Returns whether this item is a top-level item, from the point of view of + /// bindgen. + /// + /// This point of view changes depending on whether namespaces are enabled + /// or not. That way, in the following example: + /// + /// ```c++ + /// namespace foo { + /// static int var; + /// } + /// ``` + /// + /// `var` would be a toplevel item if namespaces are disabled, but won't if + /// they aren't. + /// + /// This function is used to determine when the codegen phase should call + /// `codegen` on an item, since any item that is not top-level will be + /// generated by its parent. + 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(); + } + } + + /// Get a reference to this item's underlying `Type`. Panic if this is some + /// other kind of item. + pub fn expect_type(&self) -> &Type { + self.kind().expect_type() + } + + /// Get a reference to this item's underlying `Type`, or `None` if this is + /// some other kind of item. + pub fn as_type(&self) -> Option<&Type> { + self.kind().as_type() + } + + /// Get a reference to this item's underlying `Function`. Panic if this is + /// some other kind of item. + pub fn expect_function(&self) -> &Function { + self.kind().expect_function() + } + + /// Checks whether an item contains in its "type signature" some named type. + /// + /// This function is used to avoid unused template parameter errors in Rust + /// when generating typedef declarations, and also to know whether we need + /// to generate a `PhantomData` member for a template parameter. + /// + /// For example, in code like the following: + /// + /// ```c++ + /// template + /// struct Foo { + /// T bar; + /// + /// struct Baz { + /// U bas; + /// }; + /// }; + /// ``` + /// + /// Both `Foo` and `Baz` contain both `T` and `U` template parameters in + /// their signature: + /// + /// * `Foo` + /// * `Bar` + /// + /// But the Rust structure for `Foo` would look like: + /// + /// ```rust + /// struct Foo { + /// bar: T, + /// _phantom0: ::std::marker::PhantomData, + /// } + /// ``` + /// + /// because none of its member fields contained the `U` type in the + /// signature. Similarly, `Bar` would contain a `PhantomData` type, for + /// the same reason. + /// + /// Note that this is somewhat similar to `applicable_template_args`, but + /// this also takes into account other kind of types, like arrays, + /// (`[T; 40]`), pointers: `*mut T`, etc... + /// + /// Normally we could do this check just in the `Type` kind, but we also + /// need to check the `applicable_template_args` more generally, since we + /// could need a type transitively from our parent, see the test added in + /// commit 2a3f93074dd2898669dbbce6e97e5cc4405d7cb1. + /// + /// It's kind of unfortunate (in the sense that it's a sort of complex + /// process), but I think it should get all the cases. + fn signature_contains_named_type(&self, + ctx: &BindgenContext, + ty: &Type) + -> bool { + debug_assert!(ty.is_named()); + self.expect_type().signature_contains_named_type(ctx, ty) || + self.applicable_template_args(ctx).iter().any(|template| { + ctx.resolve_type(*template).signature_contains_named_type(ctx, ty) + }) + } + + /// Returns the template arguments that apply to a struct. This is a concept + /// needed because of type declarations inside templates, for example: + /// + /// ```c++ + /// template + /// class Foo { + /// typedef T element_type; + /// typedef int Bar; + /// + /// template + /// class Baz { + /// }; + /// }; + /// ``` + /// + /// In this case, the applicable template arguments for the different types + /// would be: + /// + /// * `Foo`: [`T`] + /// * `Foo::element_type`: [`T`] + /// * `Foo::Bar`: [`T`] + /// * `Foo::Baz`: [`T`, `U`] + /// + /// You might notice that we can't generate something like: + /// + /// ```rust,ignore + /// type Foo_Bar = ::std::os::raw::c_int; + /// ``` + /// + /// since that would be invalid Rust. Still, conceptually, `Bar` *could* use + /// the template parameter type `T`, and that's exactly what this method + /// represents. The unused template parameters get stripped in the + /// `signature_contains_named_type` check. + pub fn applicable_template_args(&self, + ctx: &BindgenContext) + -> Vec { + 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::ResolvedTypeRef(inner) => { + ctx.resolve_item(inner).applicable_template_args(ctx) + } + TypeKind::Alias(_, inner) => { + let parent_args = ctx.resolve_item(self.parent_id()) + .applicable_template_args(ctx); + let inner = ctx.resolve_item(inner); + + // Avoid unused type parameters, sigh. + parent_args.iter() + .cloned() + .filter(|arg| { + let arg = ctx.resolve_type(*arg); + arg.is_named() && + inner.signature_contains_named_type(ctx, arg) + }) + .collect() + } + // XXX Is this completely correct? Partial template specialization + // is hard anyways, sigh... + TypeKind::TemplateAlias(_, ref args) | + TypeKind::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, + } + } + + /// Get this item's annotations. + pub fn annotations(&self) -> &Annotations { + &self.annotations + } + + /// Whether this item should be hidden. + /// + /// This may be due to either annotations or 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, true), self.id) + } + + /// Is this item opaque? + 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, true)) + } + + /// Is this a reference to another type? + pub fn is_type_ref(&self) -> bool { + self.as_type().map_or(false, |ty| ty.is_type_ref()) + } + + /// Get the canonical name without taking into account the replaces + /// annotation. + /// + /// This is the base logic used to implement hiding and replacing via + /// annotations, and also to implement proper name mangling. + /// + /// The idea is that each generated type in the same "level" (read: module + /// or namespace) has a unique canonical name. + /// + /// This name should be derived from the immutable state contained in the + /// type and the parent chain, since it should be consistent. + pub fn real_canonical_name(&self, + ctx: &BindgenContext, + count_namespaces: bool, + for_name_checking: 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(); + } + // We call codegen on the inner type, but we do not want + // this alias's name to appear in the canonical name just + // because it is in the inner type's parent chain, so we use + // an empty base name. + // + // Note that this would be incorrect if this type could be + // referenced from, let's say, a member variable, but in + // that case the referenced type is the inner alias, so + // we're good there. If we wouldn't, a more complex solution + // would be needed. + TypeKind::TemplateAlias(inner, _) => { + if for_name_checking { + return ctx.resolve_item(inner) + .real_canonical_name(ctx, + count_namespaces, + false); + } + Some("") + } + // Else use the proper name, or fallback to a name with an + // id. + _ => { + ty.name() + } + }.map(ToOwned::to_owned) + } + 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()); + } + } + } + Some(base) + } + ItemKind::Var(ref var) => Some(var.name().to_owned()), + ItemKind::Module(ref module) => { + module.name().map(ToOwned::to_owned) + } + }; + + 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) { + let base_name = self.make_exposed_name(None, base_name, ctx); + return ctx.rust_mangle(&base_name).into_owned(); + } + + // TODO: allow modification of the mangling functions, maybe even per + // item type? + let parent_name = parent.canonical_name(ctx); + self.make_exposed_name(Some(parent_name), base_name, ctx) + } + + fn exposed_id(&self, ctx: &BindgenContext) -> String { + // Only use local ids for enums, classes, structs and union types. All + // other items use their global id. + let ty_kind = self.kind().as_type().map(|t| t.kind()); + if let Some(ty_kind) = ty_kind { + match *ty_kind { + TypeKind::Comp(..) | + TypeKind::Enum(..) => return self.local_id(ctx).to_string(), + _ => {} + } + } + + // Note that this `id_` prefix prevents (really unlikely) collisions + // between the global id and the local id of an item with the same + // parent. + format!("id_{}", self.id().as_usize()) + } + + fn make_exposed_name(&self, + parent_name: Option, + base_name: Option, + ctx: &BindgenContext) + -> String { + lazy_static! { + static ref RE_ENDS_WITH_BINDGEN_TY: Regex = + Regex::new(r"_bindgen_ty(_\d+)+$").unwrap(); + + static ref RE_ENDS_WITH_BINDGEN_MOD: Regex = + Regex::new(r"_bindgen_mod(_\d+)+$").unwrap(); + } + + let (re, kind) = match *self.kind() { + ItemKind::Module(..) => (&*RE_ENDS_WITH_BINDGEN_MOD, "mod"), + _ => (&*RE_ENDS_WITH_BINDGEN_TY, "ty"), + }; + + let parent_name = + parent_name.and_then(|n| if n.is_empty() { None } else { Some(n) }); + match (parent_name, base_name) { + (Some(parent), Some(base)) => format!("{}_{}", parent, base), + (Some(parent), None) => { + if re.is_match(parent.as_str()) { + format!("{}_{}", parent, self.exposed_id(ctx)) + } else { + format!("{}__bindgen_{}_{}", + parent, + kind, + self.exposed_id(ctx)) + } + } + (None, Some(base)) => base, + (None, None) => { + format!("_bindgen_{}_{}", kind, self.exposed_id(ctx)) + } + } + } + + /// Get a mutable reference to this item's `Module`, or `None` if this is + /// not a `Module` item. + pub fn as_module_mut(&mut self) -> Option<&mut Module> { + match self.kind { + ItemKind::Module(ref mut module) => Some(module), + _ => None, + } + } + + /// Can we derive an implementation of the `Copy` trait for this type? + pub fn can_derive_copy(&self, ctx: &BindgenContext) -> bool { + self.expect_type().can_derive_copy(ctx, self) + } + + /// Can we derive an implementation of the `Copy` trait for an array of this + /// type? + /// + /// See `Type::can_derive_copy_in_array` for details. + pub fn can_derive_copy_in_array(&self, ctx: &BindgenContext) -> bool { + self.expect_type().can_derive_copy_in_array(ctx, self) + } +} + +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 = ctx.next_item_id(); + 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, + ctx: &mut BindgenContext) + -> Result { + use ir::function::Function; + use ir::module::Module; + use ir::var::Var; + use clangll::*; + + if !cursor.is_valid() { + return Err(ParseError::Continue); + } + + let comment = cursor.raw_comment(); + let annotations = Annotations::new(&cursor); + + let current_module = ctx.current_module(); + let relevant_parent_id = parent_id.unwrap_or(current_module); + + macro_rules! try_parse { + ($what:ident) => { + match $what::parse(cursor, ctx) { + Ok(ParseResult::New(item, declaration)) => { + let id = ctx.next_item_id(); + + ctx.add_item(Item::new(id, comment, annotations, + relevant_parent_id, + 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 applicable_cursor = cursor.definition().unwrap_or(cursor); + match Self::from_ty(&applicable_cursor.cur_type(), + Some(applicable_cursor), + parent_id, + ctx) { + 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() == CXCursor_UnexposedDecl { + Err(ParseError::Recurse) + } else { + // We whitelist cursors here known to be unhandled, to prevent being + // too noisy about this. + match cursor.kind() { + CXCursor_MacroDefinition | + CXCursor_MacroExpansion | + CXCursor_UsingDeclaration | + CXCursor_StaticAssert | + CXCursor_InclusionDirective => { + debug!("Unhandled cursor kind {:?}: {:?}", + cursor.kind(), + cursor); + } + _ => { + error!("Unhandled cursor kind {:?}: {:?}", + cursor.kind(), + cursor); + } + } + + Err(ParseError::Continue) + } + } + + fn from_ty_or_ref(ty: clang::Type, + location: Option, + parent_id: Option, + ctx: &mut BindgenContext) + -> ItemId { + let id = ctx.next_item_id(); + Self::from_ty_or_ref_with_id(id, + ty, + location, + parent_id, + ctx) + } + + /// Parse a C++ type. If we find a reference to a type that has not been + /// defined yet, use `UnresolvedTypeRef` as a placeholder. + /// + /// This logic is needed to avoid parsing items with the incorrect parent + /// and it's sort of complex to explain, so I'll just point to + /// `tests/headers/typeref.hpp` to see the kind of constructs that forced + /// this. + /// + /// Typerefs are resolved once parsing is completely done, see + /// `BindgenContext::resolve_typerefs`. + fn from_ty_or_ref_with_id(potential_id: ItemId, + ty: clang::Type, + location: Option, + parent_id: Option, + ctx: &mut BindgenContext) + -> ItemId { + debug!("from_ty_or_ref_with_id: {:?} {:?}, {:?}, {:?}", + potential_id, + ty, + location, + parent_id); + + if ctx.collected_typerefs() { + debug!("refs already collected, resolving directly"); + return Self::from_ty_with_id(potential_id, + &ty, + location, + parent_id, + ctx) + .expect("Unable to resolve type"); + } + + if let Some(ty) = ctx.builtin_or_resolved_ty(potential_id, + 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, parent_id); + let current_module = ctx.current_module(); + ctx.add_item(Item::new(potential_id, + None, + None, + parent_id.unwrap_or(current_module), + ItemKind::Type(Type::new(None, + None, + kind, + is_const))), + Some(clang::Cursor::null()), + None); + potential_id + } + + + fn from_ty(ty: &clang::Type, + location: Option, + parent_id: Option, + ctx: &mut BindgenContext) + -> Result { + let id = ctx.next_item_id(); + Self::from_ty_with_id(id, ty, location, parent_id, ctx) + } + + /// This is one of the trickiest methods you'll find (probably along with + /// some of the ones that handle templates in `BindgenContext`). + /// + /// This method parses a type, given the potential id of that type (if + /// parsing it was correct), an optional location we're scanning, which is + /// critical some times to obtain information, an optional parent item id, + /// that will, if it's `None`, become the current module id, and the + /// context. + fn from_ty_with_id(id: ItemId, + ty: &clang::Type, + location: Option, + parent_id: Option, + ctx: &mut BindgenContext) + -> Result { + use clangll::*; + + let decl = { + let decl = ty.declaration(); + decl.definition().unwrap_or(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 annotations) = annotations { + if let Some(ref replaced) = annotations.use_instead_of() { + ctx.replace(replaced, id); + } + } + + if let Some(ty) = + ctx.builtin_or_resolved_ty(id, 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)) = ctx.currently_parsed_types + .iter() + .find(|&&(d, _)| d == declaration_to_look_for) { + debug!("Avoiding recursion parsing type: {:?}", ty); + return Ok(item_id); + } + } + + let current_module = ctx.current_module(); + if valid_decl { + ctx.currently_parsed_types.push((declaration_to_look_for, id)); + } + + let result = Type::from_clang_ty(id, ty, location, parent_id, ctx); + let relevant_parent_id = parent_id.unwrap_or(current_module); + let ret = match result { + Ok(ParseResult::AlreadyResolved(ty)) => Ok(ty), + Ok(ParseResult::New(item, declaration)) => { + ctx.add_item(Item::new(id, + comment, + annotations, + relevant_parent_id, + 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, _) = + ctx.currently_parsed_types.pop().unwrap(); + assert_eq!(popped_decl, declaration_to_look_for); + } + + location.visit(|cur| { + use clangll::*; + result = Item::from_ty_with_id(id, + ty, + Some(cur), + parent_id, + ctx); + match result { + Ok(..) => CXChildVisit_Break, + Err(ParseError::Recurse) => CXChildVisit_Recurse, + Err(ParseError::Continue) => CXChildVisit_Continue, + } + }); + + if valid_decl { + ctx.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 { + warn!("Unknown type, assuming named template type: id = {:?}; spelling = {}", + id, + ty.spelling()); + Ok(Self::named_type_with_id(id, + ty.spelling(), + None, + relevant_parent_id, + ctx)) + } else { + result + } + } + }; + + if valid_decl { + let (popped_decl, _) = ctx.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. 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(id: ItemId, + name: S, + default: Option, + parent_id: ItemId, + ctx: &mut BindgenContext) + -> ItemId + where S: Into, + { + // see tests/headers/const_tparam.hpp + // and tests/headers/variadic_tname.hpp + let name = name.into().replace("const ", "").replace(".", ""); + + ctx.add_item(Item::new(id, + None, + None, + parent_id, + ItemKind::Type(Type::named(name, default))), + None, + None); + + id + } + + fn named_type(name: S, + default: Option, + parent_id: ItemId, + ctx: &mut BindgenContext) + -> ItemId + where S: Into, + { + let id = ctx.next_item_id(); + Self::named_type_with_id(id, name, default, parent_id, ctx) + } +} + +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(); + } + if self.canonical_name_cache.borrow().is_none() { + *self.canonical_name_cache.borrow_mut() = + Some(self.real_canonical_name(ctx, + ctx.options() + .enable_cxx_namespaces, + false)); + } + return self.canonical_name_cache.borrow().as_ref().unwrap().clone(); + } +} + +impl ItemCanonicalPath for Item { + fn canonical_path(&self, ctx: &BindgenContext) -> Vec { + 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); + if parent_path.last() + .map_or(false, |parent_name| parent_name.is_empty()) { + // This only happens (or should only happen) when we're an alias, + // and our parent is a templated alias, in which case the last + // component of the path will be empty. + let is_alias = match *self.expect_type().kind() { + TypeKind::Alias(..) => true, + _ => false, + }; + debug_assert!(is_alias, "How can this ever happen?"); + parent_path.pop().unwrap(); + } + parent_path.push(self.real_canonical_name(ctx, true, false)); + + parent_path + } +} diff --git a/libbindgen/src/ir/item_kind.rs b/libbindgen/src/ir/item_kind.rs new file mode 100644 index 00000000..d9e4690c --- /dev/null +++ b/libbindgen/src/ir/item_kind.rs @@ -0,0 +1,114 @@ +//! Different variants of an `Item` in our intermediate representation. + +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 { + /// Get a reference to this `ItemKind`'s underying `Module`, or `None` if it + /// is some other kind. + pub fn as_module(&self) -> Option<&Module> { + match *self { + ItemKind::Module(ref module) => Some(module), + _ => None, + } + } + + /// Is this a module? + pub fn is_module(&self) -> bool { + self.as_module().is_some() + } + + /// Get a reference to this `ItemKind`'s underying `Module`, or panic if it + /// is some other kind. + pub fn expect_module(&self) -> &Module { + self.as_module().expect("Not a module") + } + + /// Get a reference to this `ItemKind`'s underying `Function`, or `None` if + /// it is some other kind. + pub fn as_function(&self) -> Option<&Function> { + match *self { + ItemKind::Function(ref func) => Some(func), + _ => None, + } + } + + /// Is this a function? + pub fn is_function(&self) -> bool { + self.as_function().is_some() + } + + /// Get a reference to this `ItemKind`'s underying `Function`, or panic if + /// it is some other kind. + pub fn expect_function(&self) -> &Function { + self.as_function().expect("Not a function") + } + + /// Get a reference to this `ItemKind`'s underying `Type`, or `None` if + /// it is some other kind. + pub fn as_type(&self) -> Option<&Type> { + match *self { + ItemKind::Type(ref ty) => Some(ty), + _ => None, + } + } + + /// Get a mutable reference to this `ItemKind`'s underying `Type`, or `None` + /// if it is some other kind. + pub fn as_type_mut(&mut self) -> Option<&mut Type> { + match *self { + ItemKind::Type(ref mut ty) => Some(ty), + _ => None, + } + } + + /// Is this a type? + pub fn is_type(&self) -> bool { + self.as_type().is_some() + } + + /// Get a reference to this `ItemKind`'s underying `Type`, or panic if it is + /// some other kind. + pub fn expect_type(&self) -> &Type { + self.as_type().expect("Not a type") + } + + /// Get a reference to this `ItemKind`'s underying `Var`, or `None` if it is + /// some other kind. + pub fn as_var(&self) -> Option<&Var> { + match *self { + ItemKind::Var(ref v) => Some(v), + _ => None, + } + } + + /// Is this a variable? + pub fn is_var(&self) -> bool { + self.as_var().is_some() + } + + /// Get a reference to this `ItemKind`'s underying `Var`, or panic if it is + /// some other kind. + pub fn expect_var(&self) -> &Var { + self.as_var().expect("Not a var") + } +} diff --git a/libbindgen/src/ir/layout.rs b/libbindgen/src/ir/layout.rs new file mode 100644 index 00000000..3ac4a5f4 --- /dev/null +++ b/libbindgen/src/ir/layout.rs @@ -0,0 +1,34 @@ +//! Intermediate representation for the physical layout of some type. + +/// A type that represents the struct layout of a type. +#[derive(Debug, Clone, Copy)] +pub struct Layout { + /// The size (in bytes) of this layout. + pub size: usize, + /// The alignment (in bytes) of this layout. + pub align: usize, + /// Whether this layout's members are packed or not. + pub packed: bool, +} + +impl Layout { + /// Construct a new `Layout` with the given `size` and `align`. It is not + /// packed. + pub fn new(size: usize, align: usize) -> Self { + Layout { + size: size, + align: align, + packed: false, + } + } + + /// Is this a zero-sized layout? + pub fn is_zero(&self) -> bool { + self.size == 0 && self.align == 0 + } + + /// Construct a zero-sized layout. + pub fn zero() -> Self { + Self::new(0, 0) + } +} diff --git a/libbindgen/src/ir/mod.rs b/libbindgen/src/ir/mod.rs new file mode 100644 index 00000000..3c658a4a --- /dev/null +++ b/libbindgen/src/ir/mod.rs @@ -0,0 +1,18 @@ +//! The ir module defines bindgen's intermediate representation. +//! +//! Parsing C/C++ generates the IR, while code generation outputs Rust code from +//! the IR. + +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 type_collector; +pub mod var; diff --git a/libbindgen/src/ir/module.rs b/libbindgen/src/ir/module.rs new file mode 100644 index 00000000..c5d8cfa7 --- /dev/null +++ b/libbindgen/src/ir/module.rs @@ -0,0 +1,61 @@ +//! Intermediate representation for modules (AKA C++ namespaces). + +use clang; +use parse::{ClangSubItemParser, ParseError, ParseResult}; +use parse_one; +use super::context::{BindgenContext, ItemId}; + +/// 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, + /// The children of this module, just here for convenience. + children_ids: Vec, +} + +impl Module { + /// Construct a new `Module`. + pub fn new(name: Option) -> Self { + Module { + name: name, + children_ids: vec![], + } + } + + /// Get this module's name. + pub fn name(&self) -> Option<&str> { + self.name.as_ref().map(|n| &**n) + } + + /// Get a mutable reference to this module's children. + pub fn children_mut(&mut self) -> &mut Vec { + &mut self.children_ids + } + + /// Get this module's children. + pub fn children(&self) -> &[ItemId] { + &self.children_ids + } +} + +impl ClangSubItemParser for Module { + fn parse(cursor: clang::Cursor, + ctx: &mut BindgenContext) + -> Result, 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/libbindgen/src/ir/ty.rs b/libbindgen/src/ir/ty.rs new file mode 100644 index 00000000..34af2db5 --- /dev/null +++ b/libbindgen/src/ir/ty.rs @@ -0,0 +1,869 @@ +//! Everything related to types in our intermediate representation. + +use clang::{self, Cursor}; +use parse::{ClangItemParser, ParseError, ParseResult}; +use super::comp::CompInfo; +use super::context::{BindgenContext, ItemId}; +use super::enum_ty::Enum; +use super::function::FunctionSig; +use super::int::IntKind; +use super::item::Item; +use super::layout::Layout; +use super::type_collector::{ItemSet, TypeCollector}; + +/// The base representation of a type in bindgen. +/// +/// A type has an optional name, which if present cannot be empty, a `layout` +/// (size, alignment and packedness) if known, a `Kind`, which determines which +/// kind of type it is, and whether the type is const. +#[derive(Debug)] +pub struct Type { + /// The name of the type, or None if it was an unnamed struct or union. + name: Option, + /// The layout of the type, if known. + layout: Option, + /// The inner kind of the type + kind: TypeKind, + /// Whether this type is const-qualified. + is_const: bool, +} + +/// The maximum number of items in an array for which Rust implements common +/// traits, and so if we have a type containing an array with more than this +/// many items, we won't be able to derive common traits on that type. +/// +/// We need type-level integers yesterday :'( +pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32; + +impl Type { + /// Get the underlying `CompInfo` for this type, or `None` if this is some + /// other kind of type. + pub fn as_comp(&self) -> Option<&CompInfo> { + match self.kind { + TypeKind::Comp(ref ci) => Some(ci), + _ => None, + } + } + + /// Construct a new `Type`. + pub fn new(name: Option, + layout: Option, + kind: TypeKind, + is_const: bool) + -> Self { + Type { + name: name, + layout: layout, + kind: kind, + is_const: is_const, + } + } + + /// Which kind of type is this? + pub fn kind(&self) -> &TypeKind { + &self.kind + } + + /// Get a mutable reference to this type's kind. + pub fn kind_mut(&mut self) -> &mut TypeKind { + &mut self.kind + } + + /// Get this type's name. + pub fn name(&self) -> Option<&str> { + self.name.as_ref().map(|name| &**name) + } + + /// Is this a compound type? + pub fn is_comp(&self) -> bool { + match self.kind { + TypeKind::Comp(..) => true, + _ => false, + } + } + + /// Is this a named type? + pub fn is_named(&self) -> bool { + match self.kind { + TypeKind::Named(..) => true, + _ => false, + } + } + + /// Is this a function type? + pub fn is_function(&self) -> bool { + match self.kind { + TypeKind::Function(..) => true, + _ => false, + } + } + + /// Is this either a builtin or named type? + pub fn is_builtin_or_named(&self) -> bool { + match self.kind { + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Function(..) | + TypeKind::Array(..) | + TypeKind::Reference(..) | + TypeKind::Pointer(..) | + TypeKind::BlockPointer | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Named(..) => true, + _ => false, + } + } + + /// Creates a new named type, with name `name`. + pub fn named(name: String, default: Option) -> 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) + } + + /// Is this an integer type? + pub fn is_integer(&self) -> bool { + match self.kind { + TypeKind::Int(..) => true, + _ => false, + } + } + + /// Is this a `const` qualified type? + pub fn is_const(&self) -> bool { + self.is_const + } + + /// Is this a reference to another type? + pub fn is_type_ref(&self) -> bool { + match self.kind { + TypeKind::ResolvedTypeRef(_) | + TypeKind::UnresolvedTypeRef(_, _, _) => true, + _ => false, + } + } + + /// What is the layout of this type? + pub fn layout(&self, ctx: &BindgenContext) -> Option { + use std::mem; + + self.layout.or_else(|| { + match self.kind { + TypeKind::Comp(ref ci) => ci.layout(ctx), + // FIXME(emilio): This is a hack for anonymous union templates. + // Use the actual pointer size! + TypeKind::Pointer(..) | + TypeKind::BlockPointer => { + Some(Layout::new(mem::size_of::<*mut ()>(), + mem::align_of::<*mut ()>())) + } + TypeKind::ResolvedTypeRef(inner) => { + ctx.resolve_type(inner).layout(ctx) + } + _ => None, + } + }) + } + + /// Wether we can derive rust's `Debug` annotation in Rust. This should + /// ideally be a no-op that just returns `true`, but instead needs to be a + /// recursive method that checks whether all the proper members can derive + /// debug or not, because of the limit rust has on 32 items as max in the + /// array. + pub fn can_derive_debug(&self, ctx: &BindgenContext) -> bool { + match self.kind { + TypeKind::Array(t, len) => { + len <= RUST_DERIVE_IN_ARRAY_LIMIT && + ctx.resolve_type(t).can_derive_debug(ctx) + } + TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(_, t) => ctx.resolve_type(t).can_derive_debug(ctx), + TypeKind::Comp(ref info) => { + info.can_derive_debug(ctx, self.layout(ctx)) + } + _ => 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.: + /// + /// ```rust + /// #[derive(Copy, Clone)] + /// struct A { + /// member: T, + /// } + /// ``` + /// + /// is fine, while: + /// + /// ```rust,ignore + /// #[derive(Copy, Clone)] + /// struct A { + /// member: [T; 1], + /// } + /// ``` + /// + /// is an error. + /// + /// That's the whole point of the existence of `can_derive_copy_in_array`. + pub fn can_derive_copy_in_array(&self, + ctx: &BindgenContext, + item: &Item) + -> bool { + match self.kind { + TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(_, t) | + TypeKind::Array(t, _) => { + ctx.resolve_item(t) + .can_derive_copy_in_array(ctx) + } + TypeKind::Named(..) => false, + _ => self.can_derive_copy(ctx, item), + } + } + + /// Wether we'd be able to derive the `Copy` trait in Rust or not. Same + /// rationale than `can_derive_debug`. + pub fn can_derive_copy(&self, ctx: &BindgenContext, item: &Item) -> bool { + match self.kind { + TypeKind::Array(t, len) => { + len <= RUST_DERIVE_IN_ARRAY_LIMIT && + ctx.resolve_item(t).can_derive_copy_in_array(ctx) + } + TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | + TypeKind::TemplateRef(t, _) | + TypeKind::Alias(_, t) => ctx.resolve_item(t).can_derive_copy(ctx), + TypeKind::Comp(ref info) => info.can_derive_copy(ctx, item), + _ => true, + } + } + + /// Whether this type has a vtable. + pub fn has_vtable(&self, ctx: &BindgenContext) -> bool { + // FIXME: Can we do something about template parameters? Huh... + match self.kind { + TypeKind::TemplateRef(t, _) | + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(_, t) | + TypeKind::ResolvedTypeRef(t) => ctx.resolve_type(t).has_vtable(ctx), + TypeKind::Comp(ref info) => info.has_vtable(ctx), + _ => false, + } + + } + + /// Returns whether this type has a destructor. + pub fn has_destructor(&self, ctx: &BindgenContext) -> bool { + match self.kind { + TypeKind::TemplateRef(t, _) | + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(_, t) | + TypeKind::ResolvedTypeRef(t) => { + ctx.resolve_type(t).has_destructor(ctx) + } + TypeKind::Comp(ref info) => info.has_destructor(ctx), + _ => false, + } + } + + /// See the comment in `Item::signature_contains_named_type`. + pub fn signature_contains_named_type(&self, + ctx: &BindgenContext, + 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) | + TypeKind::Alias(_, t) => { + ctx.resolve_type(t) + .signature_contains_named_type(ctx, ty) + } + TypeKind::Function(ref sig) => { + sig.argument_types().iter().any(|&(_, arg)| { + ctx.resolve_type(arg) + .signature_contains_named_type(ctx, ty) + }) || + ctx.resolve_type(sig.return_type()) + .signature_contains_named_type(ctx, ty) + } + TypeKind::TemplateAlias(_, ref template_args) | + TypeKind::TemplateRef(_, ref template_args) => { + template_args.iter().any(|arg| { + ctx.resolve_type(*arg) + .signature_contains_named_type(ctx, ty) + }) + } + TypeKind::Comp(ref ci) => ci.signature_contains_named_type(ctx, ty), + _ => false, + } + } + + /// See safe_canonical_type. + pub fn canonical_type<'tr>(&'tr self, + ctx: &'tr BindgenContext) + -> &'tr Type { + self.safe_canonical_type(ctx) + .expect("Should have been resolved after parsing!") + } + + /// Returns the canonical type of this type, that is, the "inner type". + /// + /// For example, for a `typedef`, the canonical type would be the + /// `typedef`ed type, for a template specialization, would be the template + /// its specializing, and so on. Return None if the type is unresolved. + pub fn safe_canonical_type<'tr>(&'tr self, + ctx: &'tr BindgenContext) + -> Option<&'tr Type> { + match self.kind { + TypeKind::Named(..) | + TypeKind::Array(..) | + TypeKind::Comp(..) | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) | + TypeKind::Function(..) | + TypeKind::Enum(..) | + TypeKind::Reference(..) | + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::BlockPointer | + TypeKind::Pointer(..) => Some(self), + + TypeKind::ResolvedTypeRef(inner) | + TypeKind::Alias(_, inner) | + TypeKind::TemplateAlias(inner, _) | + TypeKind::TemplateRef(inner, _) => { + ctx.resolve_type(inner).safe_canonical_type(ctx) + } + + TypeKind::UnresolvedTypeRef(..) => None, + } + } +} + +/// The kind of float this type represents. +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum FloatKind { + /// A `float`. + Float, + /// A `double`. + Double, + /// A `long double`. + LongDouble, + /// A `__float128`. + Float128, +} + +/// The different kinds of types that we can parse. +#[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 complex floating point type. + Complex(FloatKind), + + /// A type alias, with a name, that points to another type. + Alias(String, ItemId), + + /// A templated alias, pointing to an inner `Alias` type, with template + /// parameters. + TemplateAlias(ItemId, Vec), + + /// 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 pointer to an Apple block. + BlockPointer, + + /// 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), + + /// 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, + /* parent_id */ + Option), + + /// An indirection to another type. + /// + /// These are generated after we resolve a forward declaration, or when we + /// replace one type with another. + ResolvedTypeRef(ItemId), + + /// A named type, that is, a template parameter, with an optional default + /// type. + Named(String, Option), +} + +impl Type { + /// Whether this type is unsized, that is, has no members. This is used to + /// derive whether we should generate a dummy `_address` field for structs, + /// to comply to the C and C++ layouts, that specify that every type needs + /// to be addressable. + pub fn is_unsized(&self, ctx: &BindgenContext) -> bool { + debug_assert!(ctx.in_codegen_phase(), "Not yet"); + + match self.kind { + TypeKind::Void => true, + TypeKind::Comp(ref ci) => ci.is_unsized(ctx), + TypeKind::Array(inner, size) => { + size == 0 || ctx.resolve_type(inner).is_unsized(ctx) + } + TypeKind::ResolvedTypeRef(inner) | + TypeKind::Alias(_, inner) | + TypeKind::TemplateAlias(inner, _) | + TypeKind::TemplateRef(inner, _) => { + ctx.resolve_type(inner).is_unsized(ctx) + } + TypeKind::Named(..) | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) | + TypeKind::Function(..) | + TypeKind::Enum(..) | + TypeKind::Reference(..) | + TypeKind::NullPtr | + TypeKind::BlockPointer | + TypeKind::Pointer(..) => false, + + TypeKind::UnresolvedTypeRef(..) => { + unreachable!("Should have been resolved after parsing!"); + } + } + } + + /// This is another of the nasty methods. This one is the one that takes + /// care of the core logic of converting a clang type to a `Type`. + /// + /// It's sort of nasty and full of special-casing, but hopefully the + /// comments in every special case justify why they're there. + pub fn from_clang_ty(potential_id: ItemId, + ty: &clang::Type, + location: Option, + parent_id: Option, + ctx: &mut BindgenContext) + -> Result, ParseError> { + use clangll::*; + { + let already_resolved = + ctx.builtin_or_resolved_ty(potential_id, + parent_id, + ty, + location); + if let Some(ty) = already_resolved { + 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().is_some() { + 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.template_args().map_or(false, |x| x.len() > 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_CXXBaseSpecifier | + CXCursor_ClassTemplate => { + if location.kind() == CXCursor_CXXBaseSpecifier { + // In the case we're parsing a base specifier + // inside an unexposed or invalid type, it means + // that we're parsing one of two things: + // + // * A template parameter. + // * A complex class that isn't exposed. + // + // This means, unfortunately, that there's no + // good way to differentiate between them. + // + // Probably we could try to look at the + // declaration and complicate more this logic, + // but we'll keep it simple... if it's a valid + // C++ identifier, we'll consider it as a + // template parameter. + // + // This is because: + // + // * We expect every other base that is a + // proper identifier (that is, a simple + // struct/union declaration), to be exposed, + // so this path can't be reached in that + // case. + // + // * Quite conveniently, complex base + // specifiers preserve their full names (that + // is: Foo instead of Foo). We can take + // advantage of this. + // + // If we find some edge case where this doesn't + // work (which I guess is unlikely, see the + // different test cases[1][2][3][4]), we'd need + // to find more creative ways of differentiating + // these two cases. + // + // [1]: inherit_named.hpp + // [2]: forward-inherit-struct-with-fields.hpp + // [3]: forward-inherit-struct.hpp + // [4]: inherit-namespaced.hpp + if location.spelling() + .chars() + .all(|c| c.is_alphanumeric() || c == '_') { + return Err(ParseError::Recurse); + } + } else { + name = location.spelling(); + } + let complex = CompInfo::from_ty(potential_id, + ty, + Some(location), + ctx) + .expect("C'mon"); + TypeKind::Comp(complex) + } + CXCursor_TypeAliasTemplateDecl => { + debug!("TypeAliasTemplateDecl"); + + // We need to manually unwind this one. + let mut inner = Err(ParseError::Continue); + let mut args = vec![]; + + location.visit(|cur| { + match cur.kind() { + CXCursor_TypeAliasDecl => { + debug_assert!(cur.cur_type().kind() == + CXType_Typedef); + inner = + Item::from_ty(&cur.cur_type(), + Some(cur), + Some(potential_id), + ctx); + } + CXCursor_TemplateTypeParameter => { + // See the comment in src/ir/comp.rs + // about the same situation. + 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); + args.push(param); + } + _ => {} + } + CXChildVisit_Continue + }); + + if inner.is_err() { + error!("Failed to parse templated alias {:?}", + location); + return Err(ParseError::Continue); + } + + // NB: `args` may be empty here (if for example the + // template parameters are constants). + // + // We can't reject it here then because inner points + // to `potential_id` now, so either we remove + // `inner` and return an error, or carry on. + // + // In this case, we just carry on, since it seems + // easier if than removing every possible reference + // to `item` from `ctx`, and it doesn't give any + // problems that we didn't have anyway. + TypeKind::TemplateAlias(inner.unwrap(), args) + } + CXCursor_TemplateRef => { + let referenced = location.referenced().expect("expected value, got none"); + let referenced_ty = referenced.cur_type(); + let referenced_declaration = + Some(referenced_ty.declaration()); + + return Self::from_clang_ty(potential_id, + &referenced_ty, + referenced_declaration, + parent_id, + ctx); + } + CXCursor_TypeRef => { + let referenced = location.referenced().expect("expected value, got none"); + let referenced_ty = referenced.cur_type(); + let referenced_declaration = + Some(referenced_ty.declaration()); + + let item = + Item::from_ty_or_ref_with_id( + potential_id, + referenced_ty, + referenced_declaration, + parent_id, + ctx); + return Ok(ParseResult::AlreadyResolved(item)); + } + _ => { + if ty.kind() == CXType_Unexposed { + warn!("Unexposed type {:?}, recursing inside, \ + loc: {:?}", + ty, + location); + return Err(ParseError::Recurse); + } + + // If the type name is empty we're probably + // over-recursing to find a template parameter name + // or something like that, so just don't be too + // noisy with it since it causes confusion, see for + // example the discussion in: + // + // https://github.com/jamesmunns/teensy3-rs/issues/9 + if !ty.spelling().is_empty() { + error!("invalid type {:?}", ty); + } else { + warn!("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); + } + + if !ty.spelling().is_empty() { + error!("invalid type {:?}", ty); + } else { + warn!("invalid type {:?}", ty); + } + 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().unwrap(), + location, + parent_id, + ctx); + TypeKind::Pointer(inner) + } + CXType_BlockPointer => TypeKind::BlockPointer, + // 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().unwrap(), + location, + parent_id, + ctx); + TypeKind::Reference(inner) + } + // XXX DependentSizedArray is wrong + CXType_VariableArray | + CXType_DependentSizedArray | + CXType_IncompleteArray => { + let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(), + 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) + } + // FIXME: We stub vectors as arrays since in 99% of the cases the + // layout is going to be correct, and there's no way we can generate + // vector types properly in Rust for now. + // + // That being said, that should be fixed eventually. + CXType_Vector | + CXType_ConstantArray => { + let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(), + location, + parent_id, + ctx) + .expect("Not able to resolve array element?"); + TypeKind::Array(inner, ty.num_elements().unwrap()) + } + #[cfg(not(feature="llvm_stable"))] + CXType_Elaborated => { + return Self::from_clang_ty(potential_id, + &ty.named(), + location, + parent_id, + ctx); + } + _ => { + error!("unsupported type: kind = {:?}; ty = {:?}; at {:?}", + ty.kind(), + 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()))) + } +} + +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::TemplateAlias(inner, _) | + TypeKind::Alias(_, inner) | + TypeKind::Named(_, Some(inner)) | + TypeKind::ResolvedTypeRef(inner) => { + types.insert(inner); + } + + TypeKind::TemplateRef(inner, ref template_args) => { + types.insert(inner); + for &item in template_args { + types.insert(item); + } + } + 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!("::collect_types: Ignoring: {:?}", other); + } + } + } +} diff --git a/libbindgen/src/ir/type_collector.rs b/libbindgen/src/ir/type_collector.rs new file mode 100644 index 00000000..0f10152d --- /dev/null +++ b/libbindgen/src/ir/type_collector.rs @@ -0,0 +1,22 @@ +//! Collecting type items. + +use std::collections::BTreeSet; +use super::context::{BindgenContext, ItemId}; + +/// A set of items. +pub type ItemSet = BTreeSet; + +/// Collect all the type items referenced by this item. +pub trait TypeCollector { + /// If a particular type needs extra information beyond what it has in + /// `self` and `context` to find its referenced type items, its + /// implementation can define this associated type, forcing callers to pass + /// the needed information through. + type Extra; + + /// Add each type item referenced by `self` into the `types` set. + fn collect_types(&self, + context: &BindgenContext, + types: &mut ItemSet, + extra: &Self::Extra); +} diff --git a/libbindgen/src/ir/var.rs b/libbindgen/src/ir/var.rs new file mode 100644 index 00000000..d0c4d9ca --- /dev/null +++ b/libbindgen/src/ir/var.rs @@ -0,0 +1,246 @@ +//! Intermediate representation of variables. + +use cexpr; +use clang; +use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; +use std::num::Wrapping; +use super::context::{BindgenContext, ItemId}; +use super::function::cursor_mangling; +use super::int::IntKind; +use super::item::Item; +use super::ty::TypeKind; + +/// A `Var` is our intermediate representation of a variable. +#[derive(Debug)] +pub struct Var { + /// The name of the variable. + name: String, + /// The mangled name of the variable. + mangled_name: Option, + /// The type of the variable. + ty: ItemId, + /// TODO: support non-integer constants? + /// The integer value of the variable. + val: Option, + /// Whether this variable is const. + is_const: bool, +} + +impl Var { + /// Construct a new `Var`. + pub fn new(name: String, + mangled: Option, + ty: ItemId, + val: Option, + is_const: bool) + -> Var { + assert!(!name.is_empty()); + Var { + name: name, + mangled_name: mangled, + ty: ty, + val: val, + is_const: is_const, + } + } + + /// Is this variable `const` qualified? + pub fn is_const(&self) -> bool { + self.is_const + } + + /// The value of this constant variable, if any. + pub fn val(&self) -> Option { + self.val + } + + /// Get this variable's type. + pub fn ty(&self) -> ItemId { + self.ty + } + + /// Get this variable's name. + pub fn name(&self) -> &str { + &self.name + } + + /// Get this variable's mangled 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, + ctx: &mut BindgenContext) + -> Result, ParseError> { + use clangll::*; + use cexpr::expr::EvalResult; + match cursor.kind() { + CXCursor_MacroDefinition => { + let value = parse_macro(ctx, &cursor, ctx.translation_unit()); + + let (id, value) = match value { + Some(v) => v, + None => return Err(ParseError::Continue), + }; + + assert!(!id.is_empty(), "Empty macro name?"); + + let previously_defined = ctx.parsed_macro(&id); + + // NB: It's important to "note" the macro even if the result is + // not an integer, otherwise we might loose other kind of + // derived macros. + ctx.note_parsed_macro(id.clone(), value.clone()); + + if previously_defined { + let name = String::from_utf8(id).unwrap(); + warn!("Duplicated macro definition: {}", name); + return Err(ParseError::Continue); + } + + // NOTE: Unwrapping, here and above, is safe, because the + // identifier of a token comes straight from clang, and we + // enforce utf8 there, so we should have already panicked at + // this point. + let name = String::from_utf8(id).unwrap(); + let (int_kind, val) = match value { + // TODO(emilio): Handle the non-invalid ones! + EvalResult::Float(..) | + EvalResult::Char(..) | + EvalResult::Str(..) | + EvalResult::Invalid => return Err(ParseError::Continue), + + EvalResult::Int(Wrapping(value)) => { + let kind = ctx.options() + .type_chooser + .as_ref() + .and_then(|c| c.int_macro(&name, value)) + .unwrap_or_else(|| { + if value < 0 { + if value < i32::min_value() as i64 { + IntKind::LongLong + } else { + IntKind::Int + } + } else if value > u32::max_value() as i64 { + IntKind::ULongLong + } else { + IntKind::UInt + } + }); + + (kind, value) + } + }; + + let ty = Item::builtin_type(TypeKind::Int(int_kind), true, ctx); + + Ok(ParseResult::New(Var::new(name, None, ty, Some(val), 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, ctx) + .expect("Unable to resolve constant type?"); + + // 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. + let value = ctx.safe_resolve_type(ty) + .and_then(|t| t.safe_canonical_type(ctx)) + .and_then(|t| if t.is_integer() { Some(t) } else { None }) + .and_then(|_| { + get_integer_literal_from_cursor(&cursor, + ctx.translation_unit()) + }); + + 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) + } + } + } +} + +/// Try and parse a macro using all the macros parsed until now. +fn parse_macro(ctx: &BindgenContext, + cursor: &clang::Cursor, + unit: &clang::TranslationUnit) + -> Option<(Vec, cexpr::expr::EvalResult)> { + use cexpr::{expr, nom}; + + let cexpr_tokens = match unit.cexpr_tokens(cursor) { + None => return None, + Some(tokens) => tokens, + }; + + let parser = expr::IdentifierParser::new(ctx.parsed_macros()); + let result = parser.macro_definition(&cexpr_tokens); + + match result { + nom::IResult::Done(_, (id, val)) => Some((id.into(), val)), + _ => None, + } +} + +fn parse_int_literal_tokens(cursor: &clang::Cursor, + unit: &clang::TranslationUnit) + -> Option { + use cexpr::{expr, nom}; + use cexpr::expr::EvalResult; + + let cexpr_tokens = match unit.cexpr_tokens(cursor) { + None => return None, + Some(tokens) => tokens, + }; + + // TODO(emilio): We can try to parse other kinds of literals. + match expr::expr(&cexpr_tokens) { + nom::IResult::Done(_, EvalResult::Int(Wrapping(val))) => Some(val), + _ => None, + } +} + +fn get_integer_literal_from_cursor(cursor: &clang::Cursor, + unit: &clang::TranslationUnit) + -> Option { + use clangll::*; + let mut value = None; + cursor.visit(|c| { + match c.kind() { + CXCursor_IntegerLiteral | + CXCursor_UnaryOperator => { + value = parse_int_literal_tokens(&c, unit); + } + CXCursor_UnexposedExpr => { + value = get_integer_literal_from_cursor(&c, unit); + } + _ => (), + } + if value.is_some() { + CXChildVisit_Break + } else { + CXChildVisit_Continue + } + }); + value +} diff --git a/libbindgen/src/lib.rs b/libbindgen/src/lib.rs new file mode 100644 index 00000000..d0ca7b03 --- /dev/null +++ b/libbindgen/src/lib.rs @@ -0,0 +1,611 @@ +//! Generate Rust bindings for C and C++ libraries. +//! +//! Provide a C/C++ header file, receive Rust FFI code to call into C/C++ +//! functions and use types defined in the header. +//! +//! See the [Builder](./struct.Builder.html) struct for usage. + +#![cfg_attr(feature = "clippy", feature(plugin))] +#![cfg_attr(feature = "clippy", plugin(clippy))] + +#![deny(missing_docs)] +#![deny(warnings)] + +// We internally use the deprecated BindgenOptions all over the place. Once we +// remove its `pub` declaration, we can un-deprecate it and remove this pragma. +#![allow(deprecated)] + +// To avoid rather annoying warnings when matching with CXCursor_xxx as a +// constant. +#![allow(non_upper_case_globals)] + +#[macro_use] +extern crate cfg_if; +extern crate cexpr; +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; +#[macro_use] +extern crate lazy_static; + +// A macro to declare an internal module for which we *must* provide +// documentation for. If we are building with the "_docs" feature, then the +// module is declared public, and our `#![deny(missing_docs)]` pragma applies to +// it. This feature is used in CI, so we won't let anything slip by +// undocumented. Normal builds, however, will leave the module private, so that +// we don't expose internals to library consumers. +macro_rules! doc_mod { + ($m:ident, $doc_mod_name:ident) => { + cfg_if! { + if #[cfg(feature = "_docs")] { + pub mod $doc_mod_name { + //! Autogenerated documentation module. + pub use super::$m::*; + } + } else { + } + } + }; +} + +mod clangll; +mod clang; +mod ir; +mod parse; +mod regex_set; +mod uses; + +pub mod chooser; + +#[cfg(rustfmt)] +mod codegen; + +doc_mod!(clang, clang_docs); +doc_mod!(ir, ir_docs); +doc_mod!(parse, parse_docs); +doc_mod!(regex_set, regex_set_docs); +doc_mod!(uses, uses_docs); + +mod codegen { + include!(concat!(env!("OUT_DIR"), "/codegen.rs")); +} + +use ir::context::{BindgenContext, ItemId}; +use ir::item::Item; +use parse::{ClangItemParser, ParseError}; +use regex_set::RegexSet; + +use std::borrow::Borrow; +use std::collections::HashSet; +use std::fs::OpenOptions; +use std::io::{self, Write}; +use std::path::Path; + +use syntax::ast; +use syntax::codemap::{DUMMY_SP, Span}; +use syntax::print::pp::eof; +use syntax::print::pprust; +use syntax::ptr::P; + +/// Configure and generate Rust bindings for a C/C++ header. +/// +/// This is the main entry point to the library. +/// +/// ```ignore +/// use bindgen::builder; +/// +/// // Configure and generate bindings. +/// let bindings = try!(builder().header("path/to/input/header") +/// .whitelisted_type("SomeCoolClass") +/// .whitelisted_function("do_some_cool_thing") +/// .generate()); +/// +/// // Write the generated bindings to an output file. +/// try!(bindings.write_to_file("path/to/output.rs")); +/// ``` +#[derive(Debug,Default)] +pub struct Builder { + options: BindgenOptions, +} + +/// Construct a new [`Builder`](./struct.Builder.html). +pub fn builder() -> Builder { + Default::default() +} + +impl Builder { + /// Set the input C/C++ header. + pub fn header>(mut self, header: T) -> Builder { + let header = header.into(); + self.options.input_header = Some(header.clone()); + self.clang_arg(header) + } + + /// Generate a C/C++ file that includes the header and has dummy uses of + /// every type defined in the header. + pub fn dummy_uses>(mut self, dummy_uses: T) -> Builder { + self.options.dummy_uses = Some(dummy_uses.into()); + self + } + + /// Hide the given type from the generated bindings. + pub fn hide_type>(mut self, arg: T) -> Builder { + self.options.hidden_types.insert(arg.into()); + self + } + + /// Treat the given type as opaque in the generated bindings. + pub fn opaque_type>(mut self, arg: T) -> Builder { + self.options.opaque_types.insert(arg.into()); + self + } + + /// Whitelist the given type so that it (and all types that it transitively + /// refers to) appears in the generated bindings. + pub fn whitelisted_type>(mut self, arg: T) -> Builder { + self.options.whitelisted_types.insert(&arg); + self + } + + /// Whitelist the given function so that it (and all types that it + /// transitively refers to) appears in the generated bindings. + pub fn whitelisted_function>(mut self, arg: T) -> Builder { + self.options.whitelisted_functions.insert(&arg); + self + } + + /// Whitelist the given variable so that it (and all types that it + /// transitively refers to) appears in the generated bindings. + pub fn whitelisted_var>(mut self, arg: T) -> Builder { + self.options.whitelisted_vars.insert(&arg); + self + } + + /// Mark the given enum (or set of enums, if using a pattern) as being + /// bitfield-like. + /// + /// This makes bindgen generate a type that isn't a rust `enum`. + pub fn bitfield_enum>(mut self, arg: T) -> Builder { + self.options.bitfield_enums.insert(&arg); + self + } + + /// Add a string to prepend to the generated bindings. The string is passed + /// through without any modification. + pub fn raw_line>(mut self, arg: T) -> Builder { + self.options.raw_lines.push(arg.into()); + self + } + + /// Add an argument to be passed straight through to clang. + pub fn clang_arg>(mut self, arg: T) -> Builder { + self.options.clang_args.push(arg.into()); + self + } + + /// Make the generated bindings link the given shared library. + pub fn link>(mut self, library: T) -> Builder { + self.options.links.push((library.into(), LinkType::Default)); + self + } + + /// Make the generated bindings link the given static library. + pub fn link_static>(mut self, library: T) -> Builder { + self.options.links.push((library.into(), LinkType::Static)); + self + } + + /// Make the generated bindings link the given framework. + pub fn link_framework>(mut self, library: T) -> Builder { + self.options.links.push((library.into(), LinkType::Framework)); + self + } + + /// Emit bindings for builtin definitions (for example `__builtin_va_list`) + /// in the generated Rust. + pub fn emit_builtins(mut self) -> Builder { + self.options.builtins = true; + self + } + + /// Avoid converting floats to f32/f64 by default. + pub fn no_convert_floats(mut self) -> Self { + self.options.convert_floats = false; + self + } + + /// Emit Clang AST. + pub fn emit_clang_ast(mut self) -> Builder { + self.options.emit_ast = true; + self + } + + /// Enable C++ namespaces. + pub fn enable_cxx_namespaces(mut self) -> Builder { + self.options.enable_cxx_namespaces = true; + self + } + + /// Ignore functions. + pub fn ignore_functions(mut self) -> Builder { + self.options.ignore_functions = true; + self + } + + /// Ignore methods. + pub fn ignore_methods(mut self) -> Builder { + self.options.ignore_methods = true; + self + } + + /// Avoid generating any unstable Rust in the generated bindings. + pub fn no_unstable_rust(mut self) -> Builder { + self.options.unstable_rust = false; + self + } + + /// Use core instead of libstd in the generated bindings. + pub fn use_core(mut self) -> Builder { + self.options.use_core = true; + self + } + + /// Use the given prefix for the raw types instead of `::std::os::raw`. + pub fn ctypes_prefix>(mut self, prefix: T) -> Builder { + self.options.ctypes_prefix = Some(prefix.into()); + self + } + + /// Allows configuring types in different situations, see the `TypeChooser` + /// documentation. + pub fn type_chooser(mut self, cb: Box) -> Self { + self.options.type_chooser = Some(cb); + self + } + + /// Generate the Rust bindings using the options built up thus far. + pub fn generate<'ctx>(self) -> Result, ()> { + Bindings::generate(self.options, None) + } +} + +/// Configuration options for generated bindings. +/// +/// Deprecated: use a `Builder` instead. +#[derive(Debug)] +#[deprecated] +pub struct BindgenOptions { + /// The set of types that have been blacklisted and should not appear + /// anywhere in the generated code. + pub hidden_types: HashSet, + + /// The set of types that should be treated as opaque structures in the + /// generated code. + pub opaque_types: HashSet, + + /// The set of types that we should have bindings for in the generated + /// code. + /// + /// This includes all types transitively reachable from any type in this + /// set. One might think of whitelisted types/vars/functions as GC roots, + /// and the generated Rust code as including everything that gets marked. + pub whitelisted_types: RegexSet, + + /// Whitelisted functions. See docs for `whitelisted_types` for more. + pub whitelisted_functions: RegexSet, + + /// Whitelisted variables. See docs for `whitelisted_types` for more. + pub whitelisted_vars: RegexSet, + + /// The enum patterns to mark an enum as bitfield. + pub bitfield_enums: RegexSet, + + /// Whether we should generate builtins or not. + pub builtins: bool, + + /// The set of libraries we should link in the generated Rust code. + pub links: Vec<(String, LinkType)>, + + /// True if we should dump the Clang AST for debugging purposes. + pub emit_ast: bool, + + /// True if we should ignore functions and only generate bindings for + /// structures, types, and methods. + pub ignore_functions: bool, + + /// True if we should avoid generating bindings for methods, and instead + /// just generate code for structures and types. + pub ignore_methods: bool, + + /// True if we should emulate C++ namespaces with Rust modules in the + /// generated bindings. + pub enable_cxx_namespaces: bool, + + /// True if we shold derive Debug trait implementations for C/C++ structures + /// and types. + pub derive_debug: bool, + + /// True if we can use unstable Rust code in the bindings, false if we + /// cannot. + pub unstable_rust: bool, + + /// True if we should avoid using libstd to use libcore instead. + pub use_core: bool, + + /// An optional prefix for the "raw" types, like `c_int`, `c_void`... + pub ctypes_prefix: Option, + + /// True if we should generate constant names that are **directly** under + /// namespaces. + pub namespaced_constants: bool, + + /// True if we should use MSVC name mangling rules. + pub msvc_mangling: bool, + + /// Whether we should convert float types to f32/f64 types. + pub convert_floats: bool, + + /// The set of raw lines to prepend to the generated Rust code. + pub raw_lines: Vec, + + /// The set of arguments to pass straight through to Clang. + pub clang_args: Vec, + + /// The input header file. + pub input_header: Option, + + /// Generate a dummy C/C++ file that includes the header and has dummy uses + /// of all types defined therein. See the `uses` module for more. + pub dummy_uses: Option, + + /// A user-provided type chooser to allow customizing different kinds of + /// situations. + pub type_chooser: Option>, +} + +impl Default for BindgenOptions { + fn default() -> BindgenOptions { + BindgenOptions { + hidden_types: Default::default(), + opaque_types: Default::default(), + whitelisted_types: Default::default(), + whitelisted_functions: Default::default(), + whitelisted_vars: Default::default(), + bitfield_enums: Default::default(), + builtins: false, + links: vec![], + emit_ast: false, + ignore_functions: false, + ignore_methods: false, + derive_debug: true, + enable_cxx_namespaces: false, + unstable_rust: true, + use_core: false, + ctypes_prefix: None, + namespaced_constants: true, + msvc_mangling: false, + convert_floats: true, + raw_lines: vec![], + clang_args: vec![], + input_header: None, + dummy_uses: None, + type_chooser: None, + } + } +} + +/// The linking type to use with a given library. +/// +/// TODO: #104: This is ignored at the moment, but shouldn't be. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub enum LinkType { + /// Use shared library linking. This is the default. + Default, + /// Use static linking. + Static, + /// The library is an OSX framework. + Framework, +} + +/// Generated Rust bindings. +#[derive(Debug)] +pub struct Bindings<'ctx> { + context: BindgenContext<'ctx>, + module: ast::Mod, +} + +impl<'ctx> Bindings<'ctx> { + /// Generate bindings for the given options. + /// + /// Deprecated - use a `Builder` instead + #[deprecated] + pub fn generate(options: BindgenOptions, + span: Option) + -> Result, ()> { + let span = span.unwrap_or(DUMMY_SP); + + let mut context = BindgenContext::new(options); + parse(&mut context); + + let module = ast::Mod { + inner: span, + items: codegen::codegen(&mut context), + }; + + Ok(Bindings { + context: context, + module: module, + }) + } + + /// Convert these bindings into a Rust AST. + pub fn into_ast(self) -> Vec> { + self.module.items + } + + /// Convert these bindings into source text (with raw lines prepended). + pub fn to_string(&self) -> String { + let mut mod_str = vec![]; + { + let ref_writer = Box::new(mod_str.by_ref()) as Box; + self.write(ref_writer).expect("Could not write bindings to string"); + } + String::from_utf8(mod_str).unwrap() + } + + /// Write these bindings as source text to a file. + pub fn write_to_file>(&self, path: P) -> io::Result<()> { + let file = try!(OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(path)); + self.write(Box::new(file)) + } + + /// Write these bindings as source text to the given `Write`able. + // https://github.com/Manishearth/rust-clippy/issues/740 + #[cfg_attr(feature = "clippy", allow(needless_lifetimes))] + pub fn write<'a>(&self, mut writer: Box) -> io::Result<()> { + try!(writer.write("/* automatically generated by rust-bindgen */\n\n" + .as_bytes())); + + for line in self.context.options().raw_lines.iter() { + try!(writer.write(line.as_bytes())); + try!(writer.write("\n".as_bytes())); + } + if !self.context.options().raw_lines.is_empty() { + try!(writer.write("\n".as_bytes())); + } + + let mut ps = pprust::rust_printer(writer); + try!(ps.print_mod(&self.module, &[])); + try!(ps.print_remaining_comments()); + try!(eof(&mut ps.s)); + ps.s.out.flush() + } + + /// Generate and write dummy uses of all the types we parsed, if we've been + /// requested to do so in the options. + /// + /// See the `uses` module for more information. + pub fn write_dummy_uses(&mut self) -> io::Result<()> { + let file = + if let Some(ref dummy_path) = self.context.options().dummy_uses { + Some(try!(OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(dummy_path))) + } else { + None + }; + + if let Some(file) = file { + try!(uses::generate_dummy_uses(&mut self.context, file)); + } + + 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, + } +} + +/// Parse one `Item` from the Clang cursor. +pub fn parse_one(ctx: &mut BindgenContext, + cursor: clang::Cursor, + parent: Option, + children: &mut Vec) + -> 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 +} + +/// Parse the Clang AST into our `Item` internal representation. +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?"); +} + +/// Extracted Clang version data +#[derive(Debug)] +pub struct ClangVersion { + /// Major and minor semvar, if parsing was successful + pub parsed: Option<(u32, u32)>, + /// full version string + pub full: String, +} + +/// Get the major and the minor semvar numbers of Clang's version +pub fn clang_version() -> ClangVersion { + let raw_v: String = clang::extract_clang_version(); + let split_v: Option> = raw_v.split_whitespace() + .nth(2) + .map(|v| v.split('.').collect()); + match split_v { + Some(v) => { + if v.len() >= 2 { + let maybe_major = v[0].parse::(); + let maybe_minor = v[1].parse::(); + match (maybe_major, maybe_minor) { + (Ok(major), Ok(minor)) => { + return ClangVersion { + parsed: Some((major, minor)), + full: raw_v.clone(), + } + } + _ => {} + } + } + } + None => {} + }; + ClangVersion { + parsed: None, + full: raw_v.clone(), + } +} diff --git a/libbindgen/src/parse.rs b/libbindgen/src/parse.rs new file mode 100644 index 00000000..28e65759 --- /dev/null +++ b/libbindgen/src/parse.rs @@ -0,0 +1,106 @@ +//! Common traits and types related to parsing our IR from Clang cursors. + +use clang; +use ir::context::{BindgenContext, ItemId}; +use ir::ty::TypeKind; + +/// Not so much an error in the traditional sense, but a control flow message +/// when walking over Clang's AST with a cursor. +#[derive(Debug)] +pub enum ParseError { + /// Recurse down the current AST node's children. + Recurse, + /// Continue on to the next sibling AST node, or back up to the parent's + /// siblings if we've exhausted all of this node's siblings (and so on). + Continue, +} + +/// The result of parsing a Clang AST node. +#[derive(Debug)] +pub enum ParseResult { + /// We've already resolved this item before, here is the extant `ItemId` for + /// it. + AlreadyResolved(ItemId), + + /// This is a newly parsed item. If the cursor is `Some`, it points to the + /// AST node where the new `T` was declared. + New(T, Option), +} + +/// An intermediate representation "sub-item" (i.e. one of the types contained +/// inside an `ItemKind` variant) that can be parsed from a Clang cursor. +pub trait ClangSubItemParser: Sized { + /// Attempt to parse this type from the given cursor. + /// + /// The fact that is a reference guarantees it's held by the context, and + /// allow returning already existing types. + fn parse(cursor: clang::Cursor, + context: &mut BindgenContext) + -> Result, ParseError>; +} + +/// An intermediate representation item that can be parsed from a Clang cursor. +pub trait ClangItemParser: Sized { + /// Parse this item from the given Clang cursor. + fn parse(cursor: clang::Cursor, + parent: Option, + context: &mut BindgenContext) + -> Result; + + /// Parse this item from the given Clang type. + fn from_ty(ty: &clang::Type, + location: Option, + parent: Option, + ctx: &mut BindgenContext) + -> Result; + + /// Identical to `from_ty`, but use the given `id` as the `ItemId` for the + /// newly parsed item. + fn from_ty_with_id(id: ItemId, + ty: &clang::Type, + location: Option, + parent: Option, + ctx: &mut BindgenContext) + -> Result; + + /// Parse this item from the given Clang type, or if we haven't resolved all + /// the other items this one depends on, an unresolved reference. + fn from_ty_or_ref(ty: clang::Type, + location: Option, + parent_id: Option, + context: &mut BindgenContext) + -> ItemId; + + /// Identical to `from_ty_or_ref`, but use the given `potential_id` as the + /// `ItemId` for the newly parsed item. + fn from_ty_or_ref_with_id(potential_id: ItemId, + ty: clang::Type, + location: Option, + parent_id: Option, + context: &mut BindgenContext) + -> ItemId; + + /// Create a named template type. + fn named_type(name: S, + default: Option, + parent: ItemId, + context: &mut BindgenContext) + -> ItemId + where S: Into; + + /// Identical to `named_type`, but use `id` as the resulting item's + /// `ItemId`. + fn named_type_with_id(id: ItemId, + name: S, + default: Option, + parent: ItemId, + context: &mut BindgenContext) + -> ItemId + where S: Into; + + /// Create a builtin type. + fn builtin_type(kind: TypeKind, + is_const: bool, + context: &mut BindgenContext) + -> ItemId; +} diff --git a/libbindgen/src/regex_set.rs b/libbindgen/src/regex_set.rs new file mode 100644 index 00000000..93130590 --- /dev/null +++ b/libbindgen/src/regex_set.rs @@ -0,0 +1,66 @@ +//! A type that represents the union of a set of regular expressions. + +use regex::Regex; +use std::borrow::Borrow; + +// Yeah, I'm aware this is sorta crappy, should be cheaper to compile a regex +// ORing all the patterns, I guess... + +/// A dynamic set of regular expressions. +#[derive(Debug)] +pub struct RegexSet { + items: Vec, +} + +impl RegexSet { + /// Is this set empty? + pub fn is_empty(&self) -> bool { + self.items.is_empty() + } + + /// Extend this set with every regex in the iterator. + pub fn extend(&mut self, iter: I) + where I: IntoIterator, + { + for s in iter.into_iter() { + self.insert(&s) + } + } + + /// Insert a new regex into this set. + pub fn insert(&mut self, string: &S) + where S: Borrow, + { + let s = string.borrow(); + match Regex::new(&format!("^{}$", s)) { + Ok(r) => { + self.items.push(r); + } + Err(err) => { + error!("Invalid pattern provided: {}, {:?}", s, err); + } + } + } + + /// Does the given `string` match any of the regexes in this set? + pub fn matches(&self, string: &S) -> bool + where S: Borrow, + { + 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/libbindgen/src/uses.rs b/libbindgen/src/uses.rs new file mode 100644 index 00000000..47f72da6 --- /dev/null +++ b/libbindgen/src/uses.rs @@ -0,0 +1,102 @@ +//! Take in our IR and output a C/C++ file with dummy uses of each IR type. +//! +//! Say that we had this C++ header, `header.hpp`: +//! +//! ```c++ +//! class Point { +//! int x; +//! int y; +//! } +//! +//! enum Bar { +//! THIS, +//! THAT, +//! OTHER +//! } +//! ``` +//! +//! If we generated dummy uses for this header, we would get a `.cpp` file like +//! this: +//! +//! ```c++ +//! #include "header.hpp" +//! +//! void dummy(Point*) {} +//! void dummy(Bar*) {} +//! ``` +//! +//! This is useful because we can compile this `.cpp` file into an object file, +//! and then compare its debugging information to the debugging information +//! generated for our Rust bindings. These two sets of debugging information had +//! better agree on the C/C++ types' physical layout, or else our bindings are +//! incorrect! +//! +//! "But you still haven't explained why we have to generate the dummy uses" you +//! complain. Well if the types are never used, then they are elided when the +//! C/C++ compiler generates debugging information. + +use ir::context::BindgenContext; +use ir::item::{Item, ItemAncestors, ItemCanonicalName}; +use std::io; + +// Like `canonical_path`, except we always take namespaces into account, ignore +// the generated names of anonymous items, and return a `String`. +// +// TODO: Would it be easier to try and demangle the USR? +fn namespaced_name(ctx: &BindgenContext, item: &Item) -> String { + let mut names: Vec<_> = item.ancestors(ctx) + .map(|id| ctx.resolve_item(id).canonical_name(ctx)) + .filter(|name| !name.starts_with("_bindgen_")) + .collect(); + names.reverse(); + names.join("::") +} + +/// Generate the dummy uses for all the items in the given context, and write +/// the dummy uses to `dest`. +pub fn generate_dummy_uses(ctx: &mut BindgenContext, + mut dest: W) + -> io::Result<()> + where W: io::Write, +{ + ctx.gen(|ctx| { + let input_header = ctx.options() + .input_header + .as_ref() + .expect("Should not generate dummy uses without an input header"); + + try!(writeln!(dest, "/* automatically generated by rust-bindgen */")); + try!(writeln!(dest, "")); + try!(writeln!(dest, "#include \"{}\"", input_header)); + try!(writeln!(dest, "")); + + let type_items = ctx.whitelisted_items() + .map(|id| ctx.resolve_item(id)) + .filter(|item| { + // We only want type items. + if let Some(ty) = item.kind().as_type() { + // However, we don't want anonymous types, as we can't + // generate dummy uses for them. + ty.name().is_some() && + // Nor do we want builtin types or named template type + // arguments. Again, we can't generate dummy uses for + // these. + !ty.is_builtin_or_named() && + // And finally, we won't be creating any dummy + // specializations, so ignore template declarations and + // partial specializations. + item.applicable_template_args(ctx).is_empty() + } else { + false + } + }) + .map(|item| namespaced_name(ctx, item)) + .enumerate(); + + for (idx, name) in type_items { + try!(writeln!(dest, "void dummy{}({}*) {{ }}", idx, name)); + } + + Ok(()) + }) +} diff --git a/libbindgen/tests/expectations/Cargo.toml b/libbindgen/tests/expectations/Cargo.toml new file mode 100644 index 00000000..53f1b14f --- /dev/null +++ b/libbindgen/tests/expectations/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "tests_expectations" +description = "bindgen results when ran on ../headers/*" +version = "0.1.0" +authors = [ + "Jyun-Yan You ", + "Emilio Cobos Álvarez ", + "The Servo project developers", +] + +[dependencies] diff --git a/libbindgen/tests/expectations/src/lib.rs b/libbindgen/tests/expectations/src/lib.rs new file mode 100644 index 00000000..e69de29b diff --git a/libbindgen/tests/expectations/tests/accessors.rs b/libbindgen/tests/expectations/tests/accessors.rs new file mode 100644 index 00000000..b721980c --- /dev/null +++ b/libbindgen/tests/expectations/tests/accessors.rs @@ -0,0 +1,204 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct SomeAccessors { + pub mNoAccessor: ::std::os::raw::c_int, + /**
*/ + pub mBothAccessors: ::std::os::raw::c_int, + /**
*/ + pub mUnsafeAccessors: ::std::os::raw::c_int, + /**
*/ + pub mImmutableAccessor: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_SomeAccessors() { + assert_eq!(::std::mem::size_of::() , 16usize); + assert_eq!(::std::mem::align_of::() , 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 + } + #[inline] + 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 + } + #[inline] + pub fn get_mImmutableAccessor(&self) -> &::std::os::raw::c_int { + &self.mImmutableAccessor + } +} +/**
*/ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct AllAccessors { + pub mBothAccessors: ::std::os::raw::c_int, + pub mAlsoBothAccessors: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_AllAccessors() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 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 + } + #[inline] + 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 + } +} +/**
*/ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct AllUnsafeAccessors { + pub mBothAccessors: ::std::os::raw::c_int, + pub mAlsoBothAccessors: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_AllUnsafeAccessors() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 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 + } + #[inline] + 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 + } +} +/**
*/ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct ContradictAccessors { + pub mBothAccessors: ::std::os::raw::c_int, + /**
*/ + pub mNoAccessors: ::std::os::raw::c_int, + /**
*/ + pub mUnsafeAccessors: ::std::os::raw::c_int, + /**
*/ + pub mImmutableAccessor: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_ContradictAccessors() { + assert_eq!(::std::mem::size_of::() , 16usize); + assert_eq!(::std::mem::align_of::() , 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 + } + #[inline] + 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 + } + #[inline] + pub fn get_mImmutableAccessor(&self) -> &::std::os::raw::c_int { + &self.mImmutableAccessor + } +} +/**
*/ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Replaced { + pub mAccessor: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_Replaced() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 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 + } +} +/**
*/ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Wrapper { + pub mReplaced: Replaced, +} +#[test] +fn bindgen_test_layout_Wrapper() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for Wrapper { + fn clone(&self) -> Self { *self } +} +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/libbindgen/tests/expectations/tests/annotation_hide.rs b/libbindgen/tests/expectations/tests/annotation_hide.rs new file mode 100644 index 00000000..dcaf7997 --- /dev/null +++ b/libbindgen/tests/expectations/tests/annotation_hide.rs @@ -0,0 +1,35 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +/** + *
+ */ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct D { + pub _bindgen_opaque_blob: u32, +} +#[test] +fn bindgen_test_layout_D() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for D { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct NotAnnotated { + pub f: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_NotAnnotated() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for NotAnnotated { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/anon_enum.rs b/libbindgen/tests/expectations/tests/anon_enum.rs new file mode 100644 index 00000000..075830e6 --- /dev/null +++ b/libbindgen/tests/expectations/tests/anon_enum.rs @@ -0,0 +1,24 @@ +/* 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, +} +pub const Test_T_NONE: Test__bindgen_ty_1 = Test__bindgen_ty_1::T_NONE; +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Test__bindgen_ty_1 { T_NONE = 0, } +#[test] +fn bindgen_test_layout_Test() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for Test { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/anon_enum_whitelist.rs b/libbindgen/tests/expectations/tests/anon_enum_whitelist.rs new file mode 100644 index 00000000..b32396a0 --- /dev/null +++ b/libbindgen/tests/expectations/tests/anon_enum_whitelist.rs @@ -0,0 +1,11 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const NODE_FLAG_FOO: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_FOO; +pub const NODE_FLAG_BAR: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_BAR; +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum _bindgen_ty_1 { NODE_FLAG_FOO = 0, NODE_FLAG_BAR = 1, } diff --git a/libbindgen/tests/expectations/tests/anon_union.rs b/libbindgen/tests/expectations/tests/anon_union.rs new file mode 100644 index 00000000..8af416c3 --- /dev/null +++ b/libbindgen/tests/expectations/tests/anon_union.rs @@ -0,0 +1,77 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TErrorResult { + pub mResult: ::std::os::raw::c_int, + pub __bindgen_anon_1: TErrorResult__bindgen_ty_1, + pub mMightHaveUnreported: bool, + pub mUnionState: TErrorResult_UnionState, + pub _phantom_0: ::std::marker::PhantomData, +} +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 { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TErrorResult_DOMExceptionInfo { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TErrorResult__bindgen_ty_1 { + pub mMessage: __BindgenUnionField<*mut TErrorResult_Message>, + pub mDOMExceptionInfo: __BindgenUnionField<*mut TErrorResult_DOMExceptionInfo>, + pub bindgen_union_field: u64, + pub _phantom_0: ::std::marker::PhantomData, +} +#[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::() , 24usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for ErrorResult { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/arg_keyword.rs b/libbindgen/tests/expectations/tests/arg_keyword.rs new file mode 100644 index 00000000..cb1cc432 --- /dev/null +++ b/libbindgen/tests/expectations/tests/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/libbindgen/tests/expectations/tests/base-to-derived.rs b/libbindgen/tests/expectations/tests/base-to-derived.rs new file mode 100644 index 00000000..c2af2c43 --- /dev/null +++ b/libbindgen/tests/expectations/tests/base-to-derived.rs @@ -0,0 +1,19 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct false_type { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_false_type() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for false_type { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/bitfield-enum-basic.rs b/libbindgen/tests/expectations/tests/bitfield-enum-basic.rs new file mode 100644 index 00000000..03e07de6 --- /dev/null +++ b/libbindgen/tests/expectations/tests/bitfield-enum-basic.rs @@ -0,0 +1,77 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const Foo_Bar: Foo = Foo(2); +pub const Foo_Baz: Foo = Foo(4); +pub const Foo_Duplicated: Foo = Foo(4); +pub const Foo_Negative: Foo = Foo(-3); +impl ::std::ops::BitOr for Foo { + type + Output + = + Self; + #[inline] + fn bitor(self, other: Self) -> Self { Foo(self.0 | other.0) } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Foo(pub i32); +pub const Buz_Bar: Buz = Buz(2); +pub const Buz_Baz: Buz = Buz(4); +pub const Buz_Duplicated: Buz = Buz(4); +pub const Buz_Negative: Buz = Buz(-3); +impl ::std::ops::BitOr for Buz { + type + Output + = + Self; + #[inline] + fn bitor(self, other: Self) -> Self { Buz(self.0 | other.0) } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Buz(pub i8); +pub const NS_FOO: _bindgen_ty_1 = _bindgen_ty_1(1); +pub const NS_BAR: _bindgen_ty_1 = _bindgen_ty_1(2); +impl ::std::ops::BitOr<_bindgen_ty_1> for _bindgen_ty_1 { + type + Output + = + Self; + #[inline] + fn bitor(self, other: Self) -> Self { _bindgen_ty_1(self.0 | other.0) } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct _bindgen_ty_1(pub u32); +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Dummy { + pub _address: u8, +} +pub const Dummy_DUMMY_FOO: Dummy__bindgen_ty_1 = Dummy__bindgen_ty_1(1); +pub const Dummy_DUMMY_BAR: Dummy__bindgen_ty_1 = Dummy__bindgen_ty_1(2); +impl ::std::ops::BitOr for Dummy__bindgen_ty_1 { + type + Output + = + Self; + #[inline] + fn bitor(self, other: Self) -> Self { + Dummy__bindgen_ty_1(self.0 | other.0) + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Dummy__bindgen_ty_1(pub u32); +#[test] +fn bindgen_test_layout_Dummy() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for Dummy { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/blocks.rs b/libbindgen/tests/expectations/tests/blocks.rs new file mode 100644 index 00000000..528ea518 --- /dev/null +++ b/libbindgen/tests/expectations/tests/blocks.rs @@ -0,0 +1,9 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +extern "C" { + pub fn atexit_b(arg1: *mut ::std::os::raw::c_void); +} diff --git a/libbindgen/tests/expectations/tests/class.rs b/libbindgen/tests/expectations/tests/class.rs new file mode 100644 index 00000000..579c24a4 --- /dev/null +++ b/libbindgen/tests/expectations/tests/class.rs @@ -0,0 +1,127 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +pub struct C { + pub a: ::std::os::raw::c_int, + pub big_array: [::std::os::raw::c_char; 33usize], +} +#[test] +fn bindgen_test_layout_C() { + assert_eq!(::std::mem::size_of::() , 40usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +#[repr(C)] +#[derive(Debug)] +pub struct WithDtor { + pub b: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_WithDtor() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Union { + pub d: __BindgenUnionField, + pub i: __BindgenUnionField<::std::os::raw::c_int>, + pub bindgen_union_field: u32, +} +#[test] +fn bindgen_test_layout_Union() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for Union { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct WithUnion { + pub data: Union, +} +#[test] +fn bindgen_test_layout_WithUnion() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for WithUnion { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct RealAbstractionWithTonsOfMethods { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_RealAbstractionWithTonsOfMethods() { + assert_eq!(::std::mem::size_of::() , + 1usize); + assert_eq!(::std::mem::align_of::() , + 1usize); +} +extern "C" { + #[link_name = "_ZNK32RealAbstractionWithTonsOfMethods3barEv"] + pub fn RealAbstractionWithTonsOfMethods_bar(this: + *const RealAbstractionWithTonsOfMethods); +} +extern "C" { + #[link_name = "_ZN32RealAbstractionWithTonsOfMethods3barEv"] + pub fn RealAbstractionWithTonsOfMethods_bar1(this: + *mut RealAbstractionWithTonsOfMethods); +} +extern "C" { + #[link_name = "_ZN32RealAbstractionWithTonsOfMethods3barEi"] + pub fn RealAbstractionWithTonsOfMethods_bar2(this: + *mut RealAbstractionWithTonsOfMethods, + foo: ::std::os::raw::c_int); +} +extern "C" { + #[link_name = "_ZN32RealAbstractionWithTonsOfMethods3staEv"] + pub fn RealAbstractionWithTonsOfMethods_sta(); +} +impl Clone for RealAbstractionWithTonsOfMethods { + fn clone(&self) -> Self { *self } +} +impl RealAbstractionWithTonsOfMethods { + #[inline] + pub unsafe fn bar(&self) { RealAbstractionWithTonsOfMethods_bar(&*self) } + #[inline] + pub unsafe fn bar1(&mut self) { + RealAbstractionWithTonsOfMethods_bar1(&mut *self) + } + #[inline] + pub unsafe fn bar2(&mut self, foo: ::std::os::raw::c_int) { + RealAbstractionWithTonsOfMethods_bar2(&mut *self, foo) + } + #[inline] + pub unsafe fn sta() { RealAbstractionWithTonsOfMethods_sta() } +} diff --git a/libbindgen/tests/expectations/tests/class_nested.rs b/libbindgen/tests/expectations/tests/class_nested.rs new file mode 100644 index 00000000..593e156d --- /dev/null +++ b/libbindgen/tests/expectations/tests/class_nested.rs @@ -0,0 +1,59 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct A { + pub member_a: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct A_B { + pub member_b: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_A_B() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for A_B { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_A() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for A { + fn clone(&self) -> Self { *self } +} +extern "C" { + #[link_name = "var"] + pub static mut var: A_B; +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct D { + pub member: A_B, +} +#[test] +fn bindgen_test_layout_D() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for D { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Templated { + pub member: T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Templated_Templated_inner { + pub member_ptr: *mut T, +} diff --git a/libbindgen/tests/expectations/tests/class_no_members.rs b/libbindgen/tests/expectations/tests/class_no_members.rs new file mode 100644 index 00000000..017f7c22 --- /dev/null +++ b/libbindgen/tests/expectations/tests/class_no_members.rs @@ -0,0 +1,45 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct whatever { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_whatever() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for whatever { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct whatever_child { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_whatever_child() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for whatever_child { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct whatever_child_with_member { + pub m_member: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_whatever_child_with_member() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for whatever_child_with_member { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/class_static.rs b/libbindgen/tests/expectations/tests/class_static.rs new file mode 100644 index 00000000..8108be2d --- /dev/null +++ b/libbindgen/tests/expectations/tests/class_static.rs @@ -0,0 +1,32 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct MyClass { + pub _address: u8, +} +extern "C" { + #[link_name = "_ZN7MyClass7exampleE"] + pub static mut MyClass_example: *const ::std::os::raw::c_int; +} +extern "C" { + #[link_name = "_ZN7MyClass26example_check_no_collisionE"] + 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::() , 1usize); + assert_eq!(::std::mem::align_of::() , 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/libbindgen/tests/expectations/tests/class_static_const.rs b/libbindgen/tests/expectations/tests/class_static_const.rs new file mode 100644 index 00000000..eed6590c --- /dev/null +++ b/libbindgen/tests/expectations/tests/class_static_const.rs @@ -0,0 +1,22 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct A { + pub _address: u8, +} +pub const A_a: ::std::os::raw::c_int = 0; +pub const A_b: i32 = 63; +pub const A_c: u32 = 255; +#[test] +fn bindgen_test_layout_A() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for A { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/class_use_as.rs b/libbindgen/tests/expectations/tests/class_use_as.rs new file mode 100644 index 00000000..c3843b31 --- /dev/null +++ b/libbindgen/tests/expectations/tests/class_use_as.rs @@ -0,0 +1,35 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +/** + *
+ */ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct whatever { + pub replacement: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_whatever() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for whatever { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct container { + pub c: whatever, +} +#[test] +fn bindgen_test_layout_container() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for container { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/class_with_dtor.rs b/libbindgen/tests/expectations/tests/class_with_dtor.rs new file mode 100644 index 00000000..8ed1ddf9 --- /dev/null +++ b/libbindgen/tests/expectations/tests/class_with_dtor.rs @@ -0,0 +1,22 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug)] +pub struct HandleWithDtor { + pub ptr: *mut T, +} +pub type HandleValue = HandleWithDtor<::std::os::raw::c_int>; +#[repr(C)] +#[derive(Debug)] +pub struct WithoutDtor { + pub shouldBeWithDtor: HandleValue, +} +#[test] +fn bindgen_test_layout_WithoutDtor() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} diff --git a/libbindgen/tests/expectations/tests/class_with_inner_struct.rs b/libbindgen/tests/expectations/tests/class_with_inner_struct.rs new file mode 100644 index 00000000..ab51396d --- /dev/null +++ b/libbindgen/tests/expectations/tests/class_with_inner_struct.rs @@ -0,0 +1,195 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct A { + pub c: ::std::os::raw::c_uint, + pub named_union: A__bindgen_ty_1, + pub __bindgen_anon_1: A__bindgen_ty_2, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct A_Segment { + pub begin: ::std::os::raw::c_int, + pub end: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_A_Segment() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for A_Segment { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct A__bindgen_ty_1 { + pub f: __BindgenUnionField<::std::os::raw::c_int>, + pub bindgen_union_field: u32, +} +#[test] +fn bindgen_test_layout_A__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for A__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct A__bindgen_ty_2 { + pub d: __BindgenUnionField<::std::os::raw::c_int>, + pub bindgen_union_field: u32, +} +#[test] +fn bindgen_test_layout_A__bindgen_ty_2() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for A__bindgen_ty_2 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_A() { + assert_eq!(::std::mem::size_of::
() , 12usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for A { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct B { + pub d: ::std::os::raw::c_uint, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct B_Segment { + pub begin: ::std::os::raw::c_int, + pub end: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_B_Segment() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for B_Segment { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_B() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for B { + fn clone(&self) -> Self { *self } +} +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum StepSyntax { + Keyword = 0, + FunctionalWithoutKeyword = 1, + FunctionalWithStartKeyword = 2, + FunctionalWithEndKeyword = 3, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C { + pub d: ::std::os::raw::c_uint, + pub __bindgen_anon_1: C__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C__bindgen_ty_1 { + pub mFunc: __BindgenUnionField, + pub __bindgen_anon_1: __BindgenUnionField, + pub bindgen_union_field: [u32; 4usize], +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C__bindgen_ty_1_1 { + pub mX1: f32, + pub mY1: f32, + pub mX2: f32, + pub mY2: f32, +} +#[test] +fn bindgen_test_layout_C__bindgen_ty_1_1() { + assert_eq!(::std::mem::size_of::() , 16usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for C__bindgen_ty_1_1 { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C__bindgen_ty_1_2 { + pub mStepSyntax: StepSyntax, + pub mSteps: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_C__bindgen_ty_1_2() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for C__bindgen_ty_1_2 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_C__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 16usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for C__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C_Segment { + pub begin: ::std::os::raw::c_int, + pub end: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_C_Segment() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for C_Segment { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_C() { + assert_eq!(::std::mem::size_of::() , 20usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for C { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/class_with_typedef.rs b/libbindgen/tests/expectations/tests/class_with_typedef.rs new file mode 100644 index 00000000..bc19f2bd --- /dev/null +++ b/libbindgen/tests/expectations/tests/class_with_typedef.rs @@ -0,0 +1,72 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub type AnotherInt = ::std::os::raw::c_int; +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C { + pub c: C_MyInt, + pub ptr: *mut C_MyInt, + pub arr: [C_MyInt; 10usize], + pub d: AnotherInt, + pub other_ptr: *mut AnotherInt, +} +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::() , 72usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +extern "C" { + #[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: C_MyInt) { C_method(&mut *self, c) } + #[inline] + pub unsafe fn methodRef(&mut self, c: *mut C_MyInt) { + C_methodRef(&mut *self, c) + } + #[inline] + pub unsafe fn complexMethodRef(&mut self, c: *mut C_Lookup) { + C_complexMethodRef(&mut *self, c) + } + #[inline] + pub unsafe fn anotherMethod(&mut self, c: AnotherInt) { + C_anotherMethod(&mut *self, c) + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct D { + pub _base: C, + pub ptr: *mut C_MyInt, +} +#[test] +fn bindgen_test_layout_D() { + assert_eq!(::std::mem::size_of::() , 80usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for D { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/complex.rs b/libbindgen/tests/expectations/tests/complex.rs new file mode 100644 index 00000000..f2a97952 --- /dev/null +++ b/libbindgen/tests/expectations/tests/complex.rs @@ -0,0 +1,64 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(C)] +pub struct __BindgenComplex { + pub re: T, + pub im: T, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct TestDouble { + pub mMember: __BindgenComplex, +} +#[test] +fn bindgen_test_layout_TestDouble() { + assert_eq!(::std::mem::size_of::() , 16usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for TestDouble { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct TestDoublePtr { + pub mMember: *mut __BindgenComplex, +} +#[test] +fn bindgen_test_layout_TestDoublePtr() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for TestDoublePtr { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct TestFloat { + pub mMember: __BindgenComplex, +} +#[test] +fn bindgen_test_layout_TestFloat() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for TestFloat { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct TestFloatPtr { + pub mMember: *mut __BindgenComplex, +} +#[test] +fn bindgen_test_layout_TestFloatPtr() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for TestFloatPtr { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/complex_global.rs b/libbindgen/tests/expectations/tests/complex_global.rs new file mode 100644 index 00000000..badc4d1f --- /dev/null +++ b/libbindgen/tests/expectations/tests/complex_global.rs @@ -0,0 +1,24 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(C)] +pub struct __BindgenComplex { + pub re: T, + pub im: T, +} +extern "C" { + #[link_name = "globalValueFloat"] + pub static mut globalValueFloat: __BindgenComplex; +} +extern "C" { + #[link_name = "globalValueDouble"] + pub static mut globalValueDouble: __BindgenComplex; +} +extern "C" { + #[link_name = "globalValueLongDouble"] + pub static mut globalValueLongDouble: __BindgenComplex; +} diff --git a/libbindgen/tests/expectations/tests/const_enum_unnamed.rs b/libbindgen/tests/expectations/tests/const_enum_unnamed.rs new file mode 100644 index 00000000..0bd3987a --- /dev/null +++ b/libbindgen/tests/expectations/tests/const_enum_unnamed.rs @@ -0,0 +1,28 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const FOO_BAR: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAR; +pub const FOO_BAZ: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAZ; +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum _bindgen_ty_1 { FOO_BAR = 0, FOO_BAZ = 1, } +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Foo { + pub _address: u8, +} +pub const Foo_FOO_BAR: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::FOO_BAR; +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Foo__bindgen_ty_1 { FOO_BAR = 10, } +#[test] +fn bindgen_test_layout_Foo() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for Foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/const_ptr.rs b/libbindgen/tests/expectations/tests/const_ptr.rs new file mode 100644 index 00000000..89400df1 --- /dev/null +++ b/libbindgen/tests/expectations/tests/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/libbindgen/tests/expectations/tests/const_resolved_ty.rs b/libbindgen/tests/expectations/tests/const_resolved_ty.rs new file mode 100644 index 00000000..77d8f438 --- /dev/null +++ b/libbindgen/tests/expectations/tests/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/libbindgen/tests/expectations/tests/const_tparam.rs b/libbindgen/tests/expectations/tests/const_tparam.rs new file mode 100644 index 00000000..3ed10d28 --- /dev/null +++ b/libbindgen/tests/expectations/tests/const_tparam.rs @@ -0,0 +1,12 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct C { + pub foo: *const T, + pub bar: *mut T, +} diff --git a/libbindgen/tests/expectations/tests/convert-floats.rs b/libbindgen/tests/expectations/tests/convert-floats.rs new file mode 100644 index 00000000..5cd38c13 --- /dev/null +++ b/libbindgen/tests/expectations/tests/convert-floats.rs @@ -0,0 +1,30 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(C)] +pub struct __BindgenComplex { + pub re: T, + pub im: T, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub bar: ::std::os::raw::c_float, + pub baz: ::std::os::raw::c_float, + pub bazz: ::std::os::raw::c_double, + pub bazzz: *mut ::std::os::raw::c_double, + pub complexFloat: __BindgenComplex<::std::os::raw::c_float>, + pub complexDouble: __BindgenComplex<::std::os::raw::c_double>, +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 48usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/crtp.rs b/libbindgen/tests/expectations/tests/crtp.rs new file mode 100644 index 00000000..e4a86b24 --- /dev/null +++ b/libbindgen/tests/expectations/tests/crtp.rs @@ -0,0 +1,43 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Base { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Derived { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_Derived() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for Derived { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug)] +pub struct BaseWithDestructor { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug)] +pub struct DerivedFromBaseWithDestructor { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_DerivedFromBaseWithDestructor() { + assert_eq!(::std::mem::size_of::() , + 1usize); + assert_eq!(::std::mem::align_of::() , + 1usize); +} diff --git a/libbindgen/tests/expectations/tests/decl_extern_int_twice.rs b/libbindgen/tests/expectations/tests/decl_extern_int_twice.rs new file mode 100644 index 00000000..603a51b1 --- /dev/null +++ b/libbindgen/tests/expectations/tests/decl_extern_int_twice.rs @@ -0,0 +1,10 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +extern "C" { + #[link_name = "foo"] + pub static mut foo: ::std::os::raw::c_int; +} diff --git a/libbindgen/tests/expectations/tests/decl_ptr_to_array.rs b/libbindgen/tests/expectations/tests/decl_ptr_to_array.rs new file mode 100644 index 00000000..b8abedb5 --- /dev/null +++ b/libbindgen/tests/expectations/tests/decl_ptr_to_array.rs @@ -0,0 +1,10 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +extern "C" { + #[link_name = "foo"] + pub static mut foo: *mut [::std::os::raw::c_int; 1usize]; +} diff --git a/libbindgen/tests/expectations/tests/duplicated_constants_in_ns.rs b/libbindgen/tests/expectations/tests/duplicated_constants_in_ns.rs new file mode 100644 index 00000000..cb69890c --- /dev/null +++ b/libbindgen/tests/expectations/tests/duplicated_constants_in_ns.rs @@ -0,0 +1,17 @@ +/* automatically generated by rust-bindgen */ + + +#![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/libbindgen/tests/expectations/tests/elaborated.rs b/libbindgen/tests/expectations/tests/elaborated.rs new file mode 100644 index 00000000..db373d41 --- /dev/null +++ b/libbindgen/tests/expectations/tests/elaborated.rs @@ -0,0 +1,11 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub type whatever_t = ::std::os::raw::c_int; +extern "C" { + #[link_name = "_Z9somethingPKi"] + pub fn something(wat: *const whatever_t); +} diff --git a/libbindgen/tests/expectations/tests/empty_template_param_name.rs b/libbindgen/tests/expectations/tests/empty_template_param_name.rs new file mode 100644 index 00000000..e10b56db --- /dev/null +++ b/libbindgen/tests/expectations/tests/empty_template_param_name.rs @@ -0,0 +1,13 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub type __void_t = ::std::os::raw::c_void; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct __iterator_traits<_Iterator> { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData<_Iterator>, +} diff --git a/libbindgen/tests/expectations/tests/enum.rs b/libbindgen/tests/expectations/tests/enum.rs new file mode 100644 index 00000000..8138d697 --- /dev/null +++ b/libbindgen/tests/expectations/tests/enum.rs @@ -0,0 +1,12 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Foo { Bar = 0, Qux = 1, } +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Neg { MinusOne = -1, One = 1, } diff --git a/libbindgen/tests/expectations/tests/enum_alias.rs b/libbindgen/tests/expectations/tests/enum_alias.rs new file mode 100644 index 00000000..7ea85598 --- /dev/null +++ b/libbindgen/tests/expectations/tests/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/libbindgen/tests/expectations/tests/enum_and_vtable_mangling.rs b/libbindgen/tests/expectations/tests/enum_and_vtable_mangling.rs new file mode 100644 index 00000000..a55c344e --- /dev/null +++ b/libbindgen/tests/expectations/tests/enum_and_vtable_mangling.rs @@ -0,0 +1,28 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const match_: _bindgen_ty_1 = _bindgen_ty_1::match_; +pub const whatever_else: _bindgen_ty_1 = _bindgen_ty_1::whatever_else; +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum _bindgen_ty_1 { match_ = 0, whatever_else = 1, } +#[repr(C)] +pub struct C__bindgen_vtable { +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C { + pub vtable_: *const C__bindgen_vtable, + pub i: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_C() { + assert_eq!(::std::mem::size_of::() , 16usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for C { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/enum_dupe.rs b/libbindgen/tests/expectations/tests/enum_dupe.rs new file mode 100644 index 00000000..322b89fc --- /dev/null +++ b/libbindgen/tests/expectations/tests/enum_dupe.rs @@ -0,0 +1,10 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const Foo_Dupe: Foo = Foo::Bar; +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Foo { Bar = 1, } diff --git a/libbindgen/tests/expectations/tests/enum_explicit_type.rs b/libbindgen/tests/expectations/tests/enum_explicit_type.rs new file mode 100644 index 00000000..4e555d3a --- /dev/null +++ b/libbindgen/tests/expectations/tests/enum_explicit_type.rs @@ -0,0 +1,24 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Foo { Bar = 0, Qux = 1, } +#[repr(i8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Neg { MinusOne = -1, One = 1, } +#[repr(u16)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Bigger { Much = 255, Larger = 256, } +#[repr(i64)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum MuchLong { MuchLow = -4294967296, } +#[repr(i64)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum MuchLongLong { I64_MIN = -9223372036854775808, } +#[repr(u64)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum MuchULongLong { MuchHigh = 4294967296, } diff --git a/libbindgen/tests/expectations/tests/enum_negative.rs b/libbindgen/tests/expectations/tests/enum_negative.rs new file mode 100644 index 00000000..74cf4f16 --- /dev/null +++ b/libbindgen/tests/expectations/tests/enum_negative.rs @@ -0,0 +1,9 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Foo { Bar = -2, Qux = 1, } diff --git a/libbindgen/tests/expectations/tests/enum_packed.rs b/libbindgen/tests/expectations/tests/enum_packed.rs new file mode 100644 index 00000000..963763e1 --- /dev/null +++ b/libbindgen/tests/expectations/tests/enum_packed.rs @@ -0,0 +1,15 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Foo { Bar = 0, Qux = 1, } +#[repr(i8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Neg { MinusOne = -1, One = 1, } +#[repr(u16)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Bigger { Much = 255, Larger = 256, } diff --git a/libbindgen/tests/expectations/tests/extern.rs b/libbindgen/tests/expectations/tests/extern.rs new file mode 100644 index 00000000..e7ac7504 --- /dev/null +++ b/libbindgen/tests/expectations/tests/extern.rs @@ -0,0 +1,9 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub type foo = + ::std::option::Option ::std::os::raw::c_int>; diff --git a/libbindgen/tests/expectations/tests/float128.rs b/libbindgen/tests/expectations/tests/float128.rs new file mode 100644 index 00000000..b4b7b2bc --- /dev/null +++ b/libbindgen/tests/expectations/tests/float128.rs @@ -0,0 +1,7 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + + diff --git a/libbindgen/tests/expectations/tests/forward-inherit-struct-with-fields.rs b/libbindgen/tests/expectations/tests/forward-inherit-struct-with-fields.rs new file mode 100644 index 00000000..84104971 --- /dev/null +++ b/libbindgen/tests/expectations/tests/forward-inherit-struct-with-fields.rs @@ -0,0 +1,17 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub _base: RootedBase, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct RootedBase { + pub foo: *mut T, + pub next: *mut Rooted, +} diff --git a/libbindgen/tests/expectations/tests/forward-inherit-struct.rs b/libbindgen/tests/expectations/tests/forward-inherit-struct.rs new file mode 100644 index 00000000..e053adcd --- /dev/null +++ b/libbindgen/tests/expectations/tests/forward-inherit-struct.rs @@ -0,0 +1,18 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct RootedBase { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} diff --git a/libbindgen/tests/expectations/tests/forward_declared_struct.rs b/libbindgen/tests/expectations/tests/forward_declared_struct.rs new file mode 100644 index 00000000..5c2764e1 --- /dev/null +++ b/libbindgen/tests/expectations/tests/forward_declared_struct.rs @@ -0,0 +1,32 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct a { + pub b: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_a() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for a { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct c { + pub d: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_c() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for c { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/func_proto.rs b/libbindgen/tests/expectations/tests/func_proto.rs new file mode 100644 index 00000000..e7ac7504 --- /dev/null +++ b/libbindgen/tests/expectations/tests/func_proto.rs @@ -0,0 +1,9 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub type foo = + ::std::option::Option ::std::os::raw::c_int>; diff --git a/libbindgen/tests/expectations/tests/func_ptr.rs b/libbindgen/tests/expectations/tests/func_ptr.rs new file mode 100644 index 00000000..87ec3e3d --- /dev/null +++ b/libbindgen/tests/expectations/tests/func_ptr.rs @@ -0,0 +1,15 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +extern "C" { + #[link_name = "foo"] + pub static mut foo: + ::std::option::Option ::std::os::raw::c_int>; +} diff --git a/libbindgen/tests/expectations/tests/func_ptr_in_struct.rs b/libbindgen/tests/expectations/tests/func_ptr_in_struct.rs new file mode 100644 index 00000000..dcae771b --- /dev/null +++ b/libbindgen/tests/expectations/tests/func_ptr_in_struct.rs @@ -0,0 +1,25 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum baz { } +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Foo { + pub bar: ::std::option::Option baz>, +} +#[test] +fn bindgen_test_layout_Foo() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for Foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/func_with_array_arg.rs b/libbindgen/tests/expectations/tests/func_with_array_arg.rs new file mode 100644 index 00000000..1528e0ba --- /dev/null +++ b/libbindgen/tests/expectations/tests/func_with_array_arg.rs @@ -0,0 +1,9 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +extern "C" { + pub fn f(x: *mut ::std::os::raw::c_int); +} diff --git a/libbindgen/tests/expectations/tests/func_with_func_ptr_arg.rs b/libbindgen/tests/expectations/tests/func_with_func_ptr_arg.rs new file mode 100644 index 00000000..4ac25286 --- /dev/null +++ b/libbindgen/tests/expectations/tests/func_with_func_ptr_arg.rs @@ -0,0 +1,9 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +extern "C" { + pub fn foo(bar: ::std::option::Option); +} diff --git a/libbindgen/tests/expectations/tests/in_class_typedef.rs b/libbindgen/tests/expectations/tests/in_class_typedef.rs new file mode 100644 index 00000000..4e95ca8c --- /dev/null +++ b/libbindgen/tests/expectations/tests/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 { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +pub type Foo_elem_type = T; +pub type Foo_ptr_type = *mut T; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo_Bar { + pub x: ::std::os::raw::c_int, + pub y: ::std::os::raw::c_int, + pub _phantom_0: ::std::marker::PhantomData, +} diff --git a/libbindgen/tests/expectations/tests/inherit-namespaced.rs b/libbindgen/tests/expectations/tests/inherit-namespaced.rs new file mode 100644 index 00000000..a58058b0 --- /dev/null +++ b/libbindgen/tests/expectations/tests/inherit-namespaced.rs @@ -0,0 +1,18 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct RootedBase { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} diff --git a/libbindgen/tests/expectations/tests/inherit_named.rs b/libbindgen/tests/expectations/tests/inherit_named.rs new file mode 100644 index 00000000..8081c649 --- /dev/null +++ b/libbindgen/tests/expectations/tests/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 { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Weeee { + pub _base: T, +} diff --git a/libbindgen/tests/expectations/tests/inherit_typedef.rs b/libbindgen/tests/expectations/tests/inherit_typedef.rs new file mode 100644 index 00000000..ca9041e2 --- /dev/null +++ b/libbindgen/tests/expectations/tests/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::() , 1usize); + assert_eq!(::std::mem::align_of::() , 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::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for Bar { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/inner_const.rs b/libbindgen/tests/expectations/tests/inner_const.rs new file mode 100644 index 00000000..666b8ce2 --- /dev/null +++ b/libbindgen/tests/expectations/tests/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::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for Foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/inner_template_self.rs b/libbindgen/tests/expectations/tests/inner_template_self.rs new file mode 100644 index 00000000..b965b92d --- /dev/null +++ b/libbindgen/tests/expectations/tests/inner_template_self.rs @@ -0,0 +1,25 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct LinkedList { + pub next: *mut LinkedList, + pub prev: *mut LinkedList, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct InstantiateIt { + pub m_list: LinkedList<::std::os::raw::c_int>, +} +#[test] +fn bindgen_test_layout_InstantiateIt() { + assert_eq!(::std::mem::size_of::() , 16usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for InstantiateIt { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/int128_t.rs b/libbindgen/tests/expectations/tests/int128_t.rs new file mode 100644 index 00000000..b4b7b2bc --- /dev/null +++ b/libbindgen/tests/expectations/tests/int128_t.rs @@ -0,0 +1,7 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + + diff --git a/libbindgen/tests/expectations/tests/jsval_layout_opaque.rs b/libbindgen/tests/expectations/tests/jsval_layout_opaque.rs new file mode 100644 index 00000000..91f898af --- /dev/null +++ b/libbindgen/tests/expectations/tests/jsval_layout_opaque.rs @@ -0,0 +1,200 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +pub const JSVAL_TAG_SHIFT: ::std::os::raw::c_uint = 47; +pub const JSVAL_PAYLOAD_MASK: ::std::os::raw::c_ulonglong = 140737488355327; +pub const JSVAL_TAG_MASK: ::std::os::raw::c_longlong = -140737488355328; +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum JSValueType { + JSVAL_TYPE_DOUBLE = 0, + JSVAL_TYPE_INT32 = 1, + JSVAL_TYPE_UNDEFINED = 2, + JSVAL_TYPE_BOOLEAN = 3, + JSVAL_TYPE_MAGIC = 4, + JSVAL_TYPE_STRING = 5, + JSVAL_TYPE_SYMBOL = 6, + JSVAL_TYPE_NULL = 7, + JSVAL_TYPE_OBJECT = 8, + JSVAL_TYPE_UNKNOWN = 32, + JSVAL_TYPE_MISSING = 33, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum JSValueTag { + JSVAL_TAG_MAX_DOUBLE = 131056, + JSVAL_TAG_INT32 = 131057, + JSVAL_TAG_UNDEFINED = 131058, + JSVAL_TAG_STRING = 131061, + JSVAL_TAG_SYMBOL = 131062, + JSVAL_TAG_BOOLEAN = 131059, + JSVAL_TAG_MAGIC = 131060, + JSVAL_TAG_NULL = 131063, + JSVAL_TAG_OBJECT = 131064, +} +#[repr(u64)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum JSValueShiftedTag { + JSVAL_SHIFTED_TAG_MAX_DOUBLE = 18444492278190833663, + JSVAL_SHIFTED_TAG_INT32 = 18444633011384221696, + JSVAL_SHIFTED_TAG_UNDEFINED = 18444773748872577024, + JSVAL_SHIFTED_TAG_STRING = 18445195961337643008, + JSVAL_SHIFTED_TAG_SYMBOL = 18445336698825998336, + JSVAL_SHIFTED_TAG_BOOLEAN = 18444914486360932352, + JSVAL_SHIFTED_TAG_MAGIC = 18445055223849287680, + JSVAL_SHIFTED_TAG_NULL = 18445477436314353664, + JSVAL_SHIFTED_TAG_OBJECT = 18445618173802708992, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum JSWhyMagic { + JS_ELEMENTS_HOLE = 0, + JS_NO_ITER_VALUE = 1, + JS_GENERATOR_CLOSING = 2, + JS_NO_CONSTANT = 3, + JS_THIS_POISON = 4, + JS_ARG_POISON = 5, + JS_SERIALIZE_NO_NODE = 6, + JS_LAZY_ARGUMENTS = 7, + JS_OPTIMIZED_ARGUMENTS = 8, + JS_IS_CONSTRUCTING = 9, + JS_OVERWRITTEN_CALLEE = 10, + JS_BLOCK_NEEDS_CLONE = 11, + JS_HASH_KEY_EMPTY = 12, + JS_ION_ERROR = 13, + JS_ION_BAILOUT = 14, + JS_OPTIMIZED_OUT = 15, + JS_UNINITIALIZED_LEXICAL = 16, + JS_GENERIC_MAGIC = 17, + JS_WHY_MAGIC_COUNT = 18, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct jsval_layout { + pub asBits: __BindgenUnionField, + pub debugView: __BindgenUnionField, + pub s: __BindgenUnionField, + pub asDouble: __BindgenUnionField, + pub asPtr: __BindgenUnionField<*mut ::std::os::raw::c_void>, + pub asWord: __BindgenUnionField, + pub asUIntPtr: __BindgenUnionField, + pub bindgen_union_field: u64, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct jsval_layout__bindgen_ty_1 { + pub _bitfield_1: u64, +} +#[test] +fn bindgen_test_layout_jsval_layout__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for jsval_layout__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +impl jsval_layout__bindgen_ty_1 { + #[inline] + pub fn payload47(&self) -> u64 { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & + (140737488355327usize as u64)) >> + 0u32) as u64) + } + } + #[inline] + pub fn set_payload47(&mut self, val: u64) { + self._bitfield_1 &= !(140737488355327usize as u64); + self._bitfield_1 |= + ((val as u64 as u64) << 0u32) & (140737488355327usize as u64); + } + #[inline] + 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: JSValueTag) { + self._bitfield_1 &= !(18446603336221196288usize as u64); + self._bitfield_1 |= + ((val as u32 as u64) << 47u32) & + (18446603336221196288usize as u64); + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct jsval_layout__bindgen_ty_2 { + pub payload: jsval_layout__bindgen_ty_2_1, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct jsval_layout__bindgen_ty_2_1 { + pub i32: __BindgenUnionField, + pub u32: __BindgenUnionField, + pub why: __BindgenUnionField, + pub bindgen_union_field: u32, +} +#[test] +fn bindgen_test_layout_jsval_layout__bindgen_ty_2_1() { + assert_eq!(::std::mem::size_of::() , + 4usize); + assert_eq!(::std::mem::align_of::() , + 4usize); +} +impl Clone for jsval_layout__bindgen_ty_2_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_jsval_layout__bindgen_ty_2() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for jsval_layout__bindgen_ty_2 { + 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, +} +#[test] +fn bindgen_test_layout_Value() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for Value { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/keywords.rs b/libbindgen/tests/expectations/tests/keywords.rs new file mode 100644 index 00000000..5b75389e --- /dev/null +++ b/libbindgen/tests/expectations/tests/keywords.rs @@ -0,0 +1,202 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +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/libbindgen/tests/expectations/tests/macro-expr-basic.rs b/libbindgen/tests/expectations/tests/macro-expr-basic.rs new file mode 100644 index 00000000..355294e7 --- /dev/null +++ b/libbindgen/tests/expectations/tests/macro-expr-basic.rs @@ -0,0 +1,15 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const FOO: ::std::os::raw::c_uint = 1; +pub const BAR: ::std::os::raw::c_uint = 4; +pub const BAZ: ::std::os::raw::c_uint = 5; +pub const MIN: ::std::os::raw::c_longlong = -9223372036854775808; +pub const BARR: ::std::os::raw::c_uint = 1; +pub const BAZZ: ::std::os::raw::c_uint = 7; +pub const I_RAN_OUT_OF_DUMB_NAMES: ::std::os::raw::c_uint = 7; +pub const HAZ_A_COMMENT: ::std::os::raw::c_uint = 1; +pub const HAZ_A_COMMENT_INSIDE: ::std::os::raw::c_uint = 2; diff --git a/libbindgen/tests/expectations/tests/macro-redef.rs b/libbindgen/tests/expectations/tests/macro-redef.rs new file mode 100644 index 00000000..881a44ae --- /dev/null +++ b/libbindgen/tests/expectations/tests/macro-redef.rs @@ -0,0 +1,9 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const FOO: ::std::os::raw::c_uint = 4; +pub const BAR: ::std::os::raw::c_uint = 5; +pub const BAZ: ::std::os::raw::c_uint = 6; diff --git a/libbindgen/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs b/libbindgen/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs new file mode 100644 index 00000000..5e9cf522 --- /dev/null +++ b/libbindgen/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs @@ -0,0 +1,45 @@ +/* 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::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for Foo { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Bar { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_Bar() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for Bar { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Baz { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_Baz() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for Baz { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/mutable.rs b/libbindgen/tests/expectations/tests/mutable.rs new file mode 100644 index 00000000..0d0d6ea3 --- /dev/null +++ b/libbindgen/tests/expectations/tests/mutable.rs @@ -0,0 +1,42 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C { + pub m_member: ::std::os::raw::c_int, + pub m_other: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_C() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for C { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug)] +pub struct NonCopiable { + pub m_member: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_NonCopiable() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +#[repr(C)] +#[derive(Debug)] +pub struct NonCopiableWithNonCopiableMutableMember { + pub m_member: NonCopiable, +} +#[test] +fn bindgen_test_layout_NonCopiableWithNonCopiableMutableMember() { + assert_eq!(::std::mem::size_of::() + , 4usize); + assert_eq!(::std::mem::align_of::() + , 4usize); +} diff --git a/libbindgen/tests/expectations/tests/namespace.rs b/libbindgen/tests/expectations/tests/namespace.rs new file mode 100644 index 00000000..bc8bae68 --- /dev/null +++ b/libbindgen/tests/expectations/tests/namespace.rs @@ -0,0 +1,85 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub mod root { + use root; + extern "C" { + #[link_name = "_Z9top_levelv"] + pub fn top_level(); + } + pub mod whatever { + use root; + pub type whatever_int_t = ::std::os::raw::c_int; + extern "C" { + #[link_name = "_ZN8whatever11in_whateverEv"] + pub fn in_whatever(); + } + } + pub mod _bindgen_mod_id_13 { + 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 A { + pub b: root::whatever::whatever_int_t, + } + #[test] + fn bindgen_test_layout_A() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); + } + impl Clone for A { + fn clone(&self) -> Self { *self } + } + } + #[repr(C)] + #[derive(Debug)] + pub struct C { + pub _base: root::_bindgen_mod_id_13::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 D { + pub m_c: root::C, + } + extern "C" { + #[link_name = "_ZN1w3hehEv"] + pub fn heh() -> root::w::whatever_int_t; + } + extern "C" { + #[link_name = "_ZN1w3fooEv"] + pub fn foo() -> root::C<::std::os::raw::c_int>; + } + extern "C" { + #[link_name = "_ZN1w4barrEv"] + pub fn barr() -> root::C; + } + } +} +extern "C" { + #[link_name = "_Z9top_levelv"] + pub fn top_level(); +} +#[repr(C)] +#[derive(Debug)] +pub struct C { + pub _base: root::_bindgen_mod_id_13::A, + pub m_c: T, + pub m_c_ptr: *mut T, + pub m_c_arr: [T; 10usize], +} diff --git a/libbindgen/tests/expectations/tests/nested.rs b/libbindgen/tests/expectations/tests/nested.rs new file mode 100644 index 00000000..fdd435aa --- /dev/null +++ b/libbindgen/tests/expectations/tests/nested.rs @@ -0,0 +1,59 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Calc { + pub w: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_Calc() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for Calc { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Test { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Test_Size { + pub mWidth: Test_Size_Dimension, + pub mHeight: Test_Size_Dimension, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Test_Size_Dimension { + pub _base: Calc, +} +#[test] +fn bindgen_test_layout_Test_Size_Dimension() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for Test_Size_Dimension { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_Test_Size() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for Test_Size { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_Test() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for Test { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/nested_vtable.rs b/libbindgen/tests/expectations/tests/nested_vtable.rs new file mode 100644 index 00000000..d74ad55f --- /dev/null +++ b/libbindgen/tests/expectations/tests/nested_vtable.rs @@ -0,0 +1,48 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct nsISupports__bindgen_vtable { +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct nsISupports { + pub vtable_: *const nsISupports__bindgen_vtable, +} +#[test] +fn bindgen_test_layout_nsISupports() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 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::() , 8usize); + assert_eq!(::std::mem::align_of::() , 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::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for Runnable { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/no-std.rs b/libbindgen/tests/expectations/tests/no-std.rs new file mode 100644 index 00000000..f50a889d --- /dev/null +++ b/libbindgen/tests/expectations/tests/no-std.rs @@ -0,0 +1,23 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + +#![no_std] +mod libc { pub type c_int = i32; pub enum c_void {} } + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub a: libc::c_int, + pub b: libc::c_int, + pub bar: *mut libc::c_void, +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::core::mem::size_of::() , 16usize); + assert_eq!(::core::mem::align_of::() , 8usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/no_copy.rs b/libbindgen/tests/expectations/tests/no_copy.rs new file mode 100644 index 00000000..53ab9677 --- /dev/null +++ b/libbindgen/tests/expectations/tests/no_copy.rs @@ -0,0 +1,13 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +/**
*/ +#[repr(C)] +#[derive(Debug)] +pub struct CopiableButWait { + pub whatever: ::std::os::raw::c_int, + pub _phantom_0: ::std::marker::PhantomData, +} diff --git a/libbindgen/tests/expectations/tests/nsStyleAutoArray.rs b/libbindgen/tests/expectations/tests/nsStyleAutoArray.rs new file mode 100644 index 00000000..c150ec46 --- /dev/null +++ b/libbindgen/tests/expectations/tests/nsStyleAutoArray.rs @@ -0,0 +1,22 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsTArray { + pub mBuff: *mut T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsStyleAutoArray { + pub mFirstElement: T, + pub mOtherElements: nsTArray, +} +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum nsStyleAutoArray_WithSingleInitialElement { + WITH_SINGLE_INITIAL_ELEMENT = 0, +} diff --git a/libbindgen/tests/expectations/tests/only_bitfields.rs b/libbindgen/tests/expectations/tests/only_bitfields.rs new file mode 100644 index 00000000..68968826 --- /dev/null +++ b/libbindgen/tests/expectations/tests/only_bitfields.rs @@ -0,0 +1,45 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C { + pub _bitfield_1: u8, +} +#[test] +fn bindgen_test_layout_C() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for C { + fn clone(&self) -> Self { *self } +} +impl C { + #[inline] + 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 as u8) << 0u32) & (1usize as u8); + } + #[inline] + pub fn b(&self) -> bool { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & (254usize as u8)) >> + 1u32) as u8) + } + } + #[inline] + 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); + } +} diff --git a/libbindgen/tests/expectations/tests/opaque_in_struct.rs b/libbindgen/tests/expectations/tests/opaque_in_struct.rs new file mode 100644 index 00000000..d537f5c7 --- /dev/null +++ b/libbindgen/tests/expectations/tests/opaque_in_struct.rs @@ -0,0 +1,33 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +/**
*/ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct opaque { + pub _bindgen_opaque_blob: u32, +} +#[test] +fn bindgen_test_layout_opaque() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for opaque { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct container { + pub contained: u32, +} +#[test] +fn bindgen_test_layout_container() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for container { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/opaque_pointer.rs b/libbindgen/tests/expectations/tests/opaque_pointer.rs new file mode 100644 index 00000000..067f55bd --- /dev/null +++ b/libbindgen/tests/expectations/tests/opaque_pointer.rs @@ -0,0 +1,45 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +/** + *
+ */ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct OtherOpaque { + pub _bindgen_opaque_blob: u32, +} +#[test] +fn bindgen_test_layout_OtherOpaque() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for OtherOpaque { + fn clone(&self) -> Self { *self } +} +/** + *
+ */ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Opaque { + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[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_WithOpaquePtr() { + assert_eq!(::std::mem::size_of::() , 16usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for WithOpaquePtr { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/opaque_typedef.rs b/libbindgen/tests/expectations/tests/opaque_typedef.rs new file mode 100644 index 00000000..c45cbc6f --- /dev/null +++ b/libbindgen/tests/expectations/tests/opaque_typedef.rs @@ -0,0 +1,15 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct RandomTemplate { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +/**
*/ +pub type ShouldBeOpaque = [u8; 0usize]; +pub type ShouldNotBeOpaque = RandomTemplate; diff --git a/libbindgen/tests/expectations/tests/overflowed_enum.rs b/libbindgen/tests/expectations/tests/overflowed_enum.rs new file mode 100644 index 00000000..9e1f8a7f --- /dev/null +++ b/libbindgen/tests/expectations/tests/overflowed_enum.rs @@ -0,0 +1,16 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(u32)] +#[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, PartialEq, Eq, Hash)] +pub enum Bar { One = 1, Big = 2, } diff --git a/libbindgen/tests/expectations/tests/overloading.rs b/libbindgen/tests/expectations/tests/overloading.rs new file mode 100644 index 00000000..4e138e7d --- /dev/null +++ b/libbindgen/tests/expectations/tests/overloading.rs @@ -0,0 +1,23 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +extern "C" { + #[link_name = "_Z8Evaluatec"] + pub fn Evaluate(r: ::std::os::raw::c_char) -> bool; +} +extern "C" { + #[link_name = "_Z8Evaluateii"] + pub fn Evaluate1(x: ::std::os::raw::c_int, y: ::std::os::raw::c_int) + -> bool; +} +extern "C" { + #[link_name = "_ZN3foo10MyFunctionEv"] + pub fn MyFunction(); +} +extern "C" { + #[link_name = "_ZN3bar10MyFunctionEv"] + pub fn MyFunction1(); +} diff --git a/libbindgen/tests/expectations/tests/private.rs b/libbindgen/tests/expectations/tests/private.rs new file mode 100644 index 00000000..c4ac37d1 --- /dev/null +++ b/libbindgen/tests/expectations/tests/private.rs @@ -0,0 +1,52 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct HasPrivate { + pub mNotPrivate: ::std::os::raw::c_int, + /**
*/ + mIsPrivate: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_HasPrivate() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for HasPrivate { + fn clone(&self) -> Self { *self } +} +/**
*/ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct VeryPrivate { + mIsPrivate: ::std::os::raw::c_int, + mIsAlsoPrivate: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_VeryPrivate() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for VeryPrivate { + fn clone(&self) -> Self { *self } +} +/**
*/ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct ContradictPrivate { + /**
*/ + pub mNotPrivate: ::std::os::raw::c_int, + mIsPrivate: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_ContradictPrivate() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for ContradictPrivate { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/redeclaration.rs b/libbindgen/tests/expectations/tests/redeclaration.rs new file mode 100644 index 00000000..0d7e585c --- /dev/null +++ b/libbindgen/tests/expectations/tests/redeclaration.rs @@ -0,0 +1,9 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +extern "C" { + pub fn foo(); +} diff --git a/libbindgen/tests/expectations/tests/ref_argument_array.rs b/libbindgen/tests/expectations/tests/ref_argument_array.rs new file mode 100644 index 00000000..c88492d7 --- /dev/null +++ b/libbindgen/tests/expectations/tests/ref_argument_array.rs @@ -0,0 +1,23 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const NSID_LENGTH: ::std::os::raw::c_uint = 10; +#[repr(C)] +pub struct nsID__bindgen_vtable { +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct nsID { + pub vtable_: *const nsID__bindgen_vtable, +} +#[test] +fn bindgen_test_layout_nsID() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for nsID { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/replace_template_alias.rs b/libbindgen/tests/expectations/tests/replace_template_alias.rs new file mode 100644 index 00000000..61a2fbcc --- /dev/null +++ b/libbindgen/tests/expectations/tests/replace_template_alias.rs @@ -0,0 +1,15 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub ptr: MaybeWrapped, +} +/// But the replacement type does use T! +/// +///
+pub type MaybeWrapped = T; diff --git a/libbindgen/tests/expectations/tests/replaces_double.rs b/libbindgen/tests/expectations/tests/replaces_double.rs new file mode 100644 index 00000000..50dafd42 --- /dev/null +++ b/libbindgen/tests/expectations/tests/replaces_double.rs @@ -0,0 +1,15 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub ptr: Rooted_MaybeWrapped, +} +/** + *
+ */ +pub type Rooted_MaybeWrapped = T; diff --git a/libbindgen/tests/expectations/tests/size_t_template.rs b/libbindgen/tests/expectations/tests/size_t_template.rs new file mode 100644 index 00000000..78351ecc --- /dev/null +++ b/libbindgen/tests/expectations/tests/size_t_template.rs @@ -0,0 +1,19 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C { + pub arr: [u32; 3usize], +} +#[test] +fn bindgen_test_layout_C() { + assert_eq!(::std::mem::size_of::() , 12usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for C { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_containing_forward_declared_struct.rs b/libbindgen/tests/expectations/tests/struct_containing_forward_declared_struct.rs new file mode 100644 index 00000000..388cc595 --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_containing_forward_declared_struct.rs @@ -0,0 +1,32 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct a { + pub val_a: *mut a_b, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct a_b { + pub val_b: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_a_b() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for a_b { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_a() { + assert_eq!(::std::mem::size_of::
() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for a { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_anon_struct.rs b/libbindgen/tests/expectations/tests/struct_with_anon_struct.rs new file mode 100644 index 00000000..1c49675d --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_anon_struct.rs @@ -0,0 +1,33 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_anon_struct_array.rs b/libbindgen/tests/expectations/tests/struct_with_anon_struct_array.rs new file mode 100644 index 00000000..6e1c0315 --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_anon_struct_array.rs @@ -0,0 +1,48 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub bar: [foo__bindgen_ty_1; 2usize], + pub baz: [[[foo__bindgen_ty_2; 4usize]; 3usize]; 2usize], +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_2 { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_2() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_2 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 208usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_anon_struct_pointer.rs b/libbindgen/tests/expectations/tests/struct_with_anon_struct_pointer.rs new file mode 100644 index 00000000..aa77d4b6 --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_anon_struct_pointer.rs @@ -0,0 +1,33 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub bar: *mut foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_anon_union.rs b/libbindgen/tests/expectations/tests/struct_with_anon_union.rs new file mode 100644 index 00000000..0d2e937a --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_anon_union.rs @@ -0,0 +1,58 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub a: __BindgenUnionField<::std::os::raw::c_uint>, + pub b: __BindgenUnionField<::std::os::raw::c_ushort>, + pub bindgen_union_field: u32, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_anon_unnamed_struct.rs b/libbindgen/tests/expectations/tests/struct_with_anon_unnamed_struct.rs new file mode 100644 index 00000000..1b77fccc --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_anon_unnamed_struct.rs @@ -0,0 +1,33 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub __bindgen_anon_1: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_uint, + pub b: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_anon_unnamed_union.rs b/libbindgen/tests/expectations/tests/struct_with_anon_unnamed_union.rs new file mode 100644 index 00000000..2914eb41 --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_anon_unnamed_union.rs @@ -0,0 +1,58 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub __bindgen_anon_1: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub a: __BindgenUnionField<::std::os::raw::c_uint>, + pub b: __BindgenUnionField<::std::os::raw::c_ushort>, + pub bindgen_union_field: u32, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_bitfields.rs b/libbindgen/tests/expectations/tests/struct_with_bitfields.rs new file mode 100644 index 00000000..3fb83a47 --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_bitfields.rs @@ -0,0 +1,122 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct bitfield { + pub _bitfield_1: u8, + pub e: ::std::os::raw::c_int, + pub _bitfield_2: u8, + pub _bitfield_3: u32, +} +#[test] +fn bindgen_test_layout_bitfield() { + assert_eq!(::std::mem::size_of::() , 16usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for bitfield { + fn clone(&self) -> Self { *self } +} +impl bitfield { + #[inline] + pub fn a(&self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & (1usize as u8)) >> + 0u32) as u16) + } + } + #[inline] + 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 { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & (2usize as u8)) >> + 1u32) as u16) + } + } + #[inline] + 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 { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & (4usize as u8)) >> + 2u32) as u16) + } + } + #[inline] + 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 { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & (8usize as u8)) >> + 3u32) as u16) + } + } + #[inline] + 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 { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & (48usize as u8)) >> + 4u32) as u16) + } + } + #[inline] + 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 { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & (192usize as u8)) >> + 6u32) as u16) + } + } + #[inline] + 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 { + unsafe { + ::std::mem::transmute(((self._bitfield_2 & (3usize as u8)) >> + 0u32) as u32) + } + } + #[inline] + 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 { + unsafe { + ::std::mem::transmute(((self._bitfield_3 & + (4294967295usize as u32)) >> 0u32) as + u32) + } + } + #[inline] + pub fn set_g(&mut self, val: ::std::os::raw::c_uint) { + self._bitfield_3 &= !(4294967295usize as u32); + self._bitfield_3 |= + ((val as u32 as u32) << 0u32) & (4294967295usize as u32); + } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_derive_debug.rs b/libbindgen/tests/expectations/tests/struct_with_derive_debug.rs new file mode 100644 index 00000000..52906a81 --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_derive_debug.rs @@ -0,0 +1,50 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct LittleArray { + pub a: [::std::os::raw::c_int; 32usize], +} +#[test] +fn bindgen_test_layout_LittleArray() { + assert_eq!(::std::mem::size_of::() , 128usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for LittleArray { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +pub struct BigArray { + pub a: [::std::os::raw::c_int; 33usize], +} +#[test] +fn bindgen_test_layout_BigArray() { + assert_eq!(::std::mem::size_of::() , 132usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct WithLittleArray { + pub a: LittleArray, +} +#[test] +fn bindgen_test_layout_WithLittleArray() { + assert_eq!(::std::mem::size_of::() , 128usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for WithLittleArray { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +pub struct WithBigArray { + pub a: BigArray, +} +#[test] +fn bindgen_test_layout_WithBigArray() { + assert_eq!(::std::mem::size_of::() , 132usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} diff --git a/libbindgen/tests/expectations/tests/struct_with_nesting.rs b/libbindgen/tests/expectations/tests/struct_with_nesting.rs new file mode 100644 index 00000000..97a0949e --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_nesting.rs @@ -0,0 +1,90 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub a: ::std::os::raw::c_uint, + pub __bindgen_anon_1: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub b: __BindgenUnionField<::std::os::raw::c_uint>, + pub __bindgen_anon_1: __BindgenUnionField, + pub __bindgen_anon_2: __BindgenUnionField, + pub bindgen_union_field: u32, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1_1 { + pub c1: ::std::os::raw::c_ushort, + pub c2: ::std::os::raw::c_ushort, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1_1() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 2usize); +} +impl Clone for foo__bindgen_ty_1_1 { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1_2 { + 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, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1_2() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for foo__bindgen_ty_1_2 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_packing.rs b/libbindgen/tests/expectations/tests/struct_with_packing.rs new file mode 100644 index 00000000..93fc3f11 --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_packing.rs @@ -0,0 +1,20 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C, packed)] +#[derive(Debug, Copy)] +pub struct a { + pub b: ::std::os::raw::c_char, + pub c: ::std::os::raw::c_short, +} +#[test] +fn bindgen_test_layout_a() { + assert_eq!(::std::mem::size_of::() , 3usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for a { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_struct.rs b/libbindgen/tests/expectations/tests/struct_with_struct.rs new file mode 100644 index 00000000..c8cdc927 --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_struct.rs @@ -0,0 +1,33 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub bar: foo__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub x: ::std::os::raw::c_uint, + pub y: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/struct_with_typedef_template_arg.rs b/libbindgen/tests/expectations/tests/struct_with_typedef_template_arg.rs new file mode 100644 index 00000000..6f8d71f1 --- /dev/null +++ b/libbindgen/tests/expectations/tests/struct_with_typedef_template_arg.rs @@ -0,0 +1,15 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Proxy { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, + pub _phantom_1: ::std::marker::PhantomData, +} +pub type Proxy_foo = + ::std::option::Option; diff --git a/libbindgen/tests/expectations/tests/template.rs b/libbindgen/tests/expectations/tests/template.rs new file mode 100644 index 00000000..76afc879 --- /dev/null +++ b/libbindgen/tests/expectations/tests/template.rs @@ -0,0 +1,170 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug)] +pub struct Foo { + pub m_member: T, + pub m_member_ptr: *mut T, + pub m_member_arr: [T; 1usize], + pub _phantom_1: ::std::marker::PhantomData, +} +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 D { + pub m_foo: D_MyFoo, + pub _phantom_0: ::std::marker::PhantomData, +} +pub type D_MyFoo = Foo<::std::os::raw::c_int, ::std::os::raw::c_int>; +#[repr(C)] +#[derive(Debug)] +pub struct D_U { + pub m_nested_foo: D_MyFoo, + pub m_baz: Z, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub prev: *mut T, + pub next: *mut Rooted<*mut ::std::os::raw::c_void>, + pub ptr: T, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct RootedContainer { + pub root: Rooted<*mut ::std::os::raw::c_void>, +} +#[test] +fn bindgen_test_layout_RootedContainer() { + assert_eq!(::std::mem::size_of::() , 24usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for RootedContainer { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug)] +pub struct WithDtor { + pub member: T, +} +pub type WithDtorIntFwd = WithDtor<::std::os::raw::c_int>; +#[repr(C)] +#[derive(Debug)] +pub struct PODButContainsDtor { + pub member: WithDtorIntFwd, +} +#[test] +fn bindgen_test_layout_PODButContainsDtor() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +/**
*/ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Opaque { + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct POD { + pub opaque_member: u32, +} +#[test] +fn bindgen_test_layout_POD() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for POD { + fn clone(&self) -> Self { *self } +} +/** + *
+ */ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NestedReplaced { + pub buff: *mut T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NestedBase { + pub buff: *mut T, + pub _phantom_1: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Incomplete { + pub d: T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NestedContainer { + pub c: T, + pub nested: NestedReplaced, + pub inc: Incomplete, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Untemplated { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_Untemplated() { + assert_eq!(::std::mem::size_of::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for Untemplated { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Templated { + pub m_untemplated: Untemplated, + pub _phantom_0: ::std::marker::PhantomData, +} +/** + * 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. + * + *
+ */ +#[repr(C)] +#[derive(Debug)] +pub struct ReplacedWithoutDestructor { + pub buff: *mut T, +} +#[repr(C)] +#[derive(Debug)] +pub struct ShouldNotBeCopiable { + pub m_member: ReplacedWithoutDestructor, +} +#[repr(C)] +#[derive(Debug)] +pub struct ShouldNotBeCopiableAsWell { + pub m_member: ReplacedWithoutDestructorFwd, +} +/** + * 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. + * + *
+ */ +#[repr(C)] +#[derive(Debug)] +pub struct ReplacedWithoutDestructorFwd { + pub buff: *mut T, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TemplateWithVar { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} diff --git a/libbindgen/tests/expectations/tests/template_alias.rs b/libbindgen/tests/expectations/tests/template_alias.rs new file mode 100644 index 00000000..6457381f --- /dev/null +++ b/libbindgen/tests/expectations/tests/template_alias.rs @@ -0,0 +1,12 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub type Wrapped = T; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Rooted { + pub ptr: Wrapped, +} diff --git a/libbindgen/tests/expectations/tests/template_alias_basic.rs b/libbindgen/tests/expectations/tests/template_alias_basic.rs new file mode 100644 index 00000000..656fff33 --- /dev/null +++ b/libbindgen/tests/expectations/tests/template_alias_basic.rs @@ -0,0 +1,7 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub type Wrapped = T; diff --git a/libbindgen/tests/expectations/tests/template_alias_namespace.rs b/libbindgen/tests/expectations/tests/template_alias_namespace.rs new file mode 100644 index 00000000..475c2b05 --- /dev/null +++ b/libbindgen/tests/expectations/tests/template_alias_namespace.rs @@ -0,0 +1,21 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub mod root { + use root; + pub mod JS { + use root; + pub mod detail { + use root; + pub type Wrapped = T; + } + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct Rooted { + pub ptr: root::JS::detail::Wrapped, + } + } +} diff --git a/libbindgen/tests/expectations/tests/template_typedef_transitive_param.rs b/libbindgen/tests/expectations/tests/template_typedef_transitive_param.rs new file mode 100644 index 00000000..166ddc3c --- /dev/null +++ b/libbindgen/tests/expectations/tests/template_typedef_transitive_param.rs @@ -0,0 +1,18 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Wrapper { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Wrapper_Wrapped { + pub t: T, +} +pub type Wrapper_Type = Wrapper_Wrapped; diff --git a/libbindgen/tests/expectations/tests/template_typedefs.rs b/libbindgen/tests/expectations/tests/template_typedefs.rs new file mode 100644 index 00000000..5f0d80b9 --- /dev/null +++ b/libbindgen/tests/expectations/tests/template_typedefs.rs @@ -0,0 +1,22 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub type foo = + ::std::option::Option; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, + pub _phantom_1: ::std::marker::PhantomData, +} +pub type Foo_Char = T; +pub type Foo_FooPtrTypedef = *mut Foo_Char; +pub type Foo_nsCOMArrayEnumFunc = + ::std::option::Option bool>; diff --git a/libbindgen/tests/expectations/tests/type_alias_empty.rs b/libbindgen/tests/expectations/tests/type_alias_empty.rs new file mode 100644 index 00000000..47e36006 --- /dev/null +++ b/libbindgen/tests/expectations/tests/type_alias_empty.rs @@ -0,0 +1,7 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub type bool_constant = (); diff --git a/libbindgen/tests/expectations/tests/typeref.rs b/libbindgen/tests/expectations/tests/typeref.rs new file mode 100644 index 00000000..da944146 --- /dev/null +++ b/libbindgen/tests/expectations/tests/typeref.rs @@ -0,0 +1,96 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[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::() , 8usize); + assert_eq!(::std::mem::align_of::() , 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::() , 1usize); + assert_eq!(::std::mem::align_of::() , 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::() , 1usize); + assert_eq!(::std::mem::align_of::() , 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::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for Bar { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StyleShapeSource { + pub __bindgen_anon_1: StyleShapeSource__bindgen_ty_1, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StyleShapeSource__bindgen_ty_1 { + pub mPosition: __BindgenUnionField<*mut Position>, + pub mFragmentOrURL: __BindgenUnionField<*mut FragmentOrURL>, + pub bindgen_union_field: u64, + pub _phantom_0: ::std::marker::PhantomData, +} diff --git a/libbindgen/tests/expectations/tests/union_dtor.rs b/libbindgen/tests/expectations/tests/union_dtor.rs new file mode 100644 index 00000000..9be626ff --- /dev/null +++ b/libbindgen/tests/expectations/tests/union_dtor.rs @@ -0,0 +1,42 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug)] +pub struct UnionWithDtor { + pub mFoo: __BindgenUnionField<::std::os::raw::c_int>, + pub mBar: __BindgenUnionField<*mut ::std::os::raw::c_void>, + pub bindgen_union_field: u64, +} +#[test] +fn bindgen_test_layout_UnionWithDtor() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} diff --git a/libbindgen/tests/expectations/tests/union_fields.rs b/libbindgen/tests/expectations/tests/union_fields.rs new file mode 100644 index 00000000..495e80f9 --- /dev/null +++ b/libbindgen/tests/expectations/tests/union_fields.rs @@ -0,0 +1,47 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct _bindgen_ty_1 { + pub mInt: __BindgenUnionField<::std::os::raw::c_int>, + pub mFloat: __BindgenUnionField, + pub mPointer: __BindgenUnionField<*mut ::std::os::raw::c_void>, + pub bindgen_union_field: u64, +} +#[test] +fn bindgen_test_layout__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 8usize); + assert_eq!(::std::mem::align_of::<_bindgen_ty_1>() , 8usize); +} +impl Clone for _bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +pub type nsStyleUnion = _bindgen_ty_1; diff --git a/libbindgen/tests/expectations/tests/union_template.rs b/libbindgen/tests/expectations/tests/union_template.rs new file mode 100644 index 00000000..fc92afb8 --- /dev/null +++ b/libbindgen/tests/expectations/tests/union_template.rs @@ -0,0 +1,62 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NastyStruct { + pub mIsSome: bool, + pub mStorage: NastyStruct__bindgen_ty_1, + pub __bindgen_anon_1: NastyStruct__bindgen_ty_2, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NastyStruct__bindgen_ty_1 { + pub mFoo: __BindgenUnionField<*mut ::std::os::raw::c_void>, + pub mDummy: __BindgenUnionField<::std::os::raw::c_ulong>, + pub bindgen_union_field: u64, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct NastyStruct__bindgen_ty_2 { + pub wat: __BindgenUnionField<::std::os::raw::c_short>, + pub wut: __BindgenUnionField<*mut ::std::os::raw::c_int>, + pub bindgen_union_field: u64, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Whatever { + pub mTPtr: __BindgenUnionField<*mut ::std::os::raw::c_void>, + pub mInt: __BindgenUnionField<::std::os::raw::c_int>, + pub bindgen_union_field: u64, + pub _phantom_0: ::std::marker::PhantomData, +} diff --git a/libbindgen/tests/expectations/tests/union_with_anon_struct.rs b/libbindgen/tests/expectations/tests/union_with_anon_struct.rs new file mode 100644 index 00000000..f0a21512 --- /dev/null +++ b/libbindgen/tests/expectations/tests/union_with_anon_struct.rs @@ -0,0 +1,58 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub bar: __BindgenUnionField, + pub bindgen_union_field: [u32; 2usize], +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub a: ::std::os::raw::c_uint, + pub b: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/union_with_anon_struct_bitfield.rs b/libbindgen/tests/expectations/tests/union_with_anon_struct_bitfield.rs new file mode 100644 index 00000000..548b0dc4 --- /dev/null +++ b/libbindgen/tests/expectations/tests/union_with_anon_struct_bitfield.rs @@ -0,0 +1,86 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub a: __BindgenUnionField<::std::os::raw::c_int>, + pub __bindgen_anon_1: __BindgenUnionField, + pub bindgen_union_field: u32, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub _bitfield_1: u32, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +impl foo__bindgen_ty_1 { + #[inline] + pub fn b(&self) -> ::std::os::raw::c_int { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & (127usize as u32)) >> + 0u32) as u32) + } + } + #[inline] + 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 { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & + (4294967168usize as u32)) >> 7u32) as + u32) + } + } + #[inline] + pub fn set_c(&mut self, val: ::std::os::raw::c_int) { + self._bitfield_1 &= !(4294967168usize as u32); + self._bitfield_1 |= + ((val as u32 as u32) << 7u32) & (4294967168usize as u32); + } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/union_with_anon_union.rs b/libbindgen/tests/expectations/tests/union_with_anon_union.rs new file mode 100644 index 00000000..95278556 --- /dev/null +++ b/libbindgen/tests/expectations/tests/union_with_anon_union.rs @@ -0,0 +1,59 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub bar: __BindgenUnionField, + pub bindgen_union_field: u32, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub a: __BindgenUnionField<::std::os::raw::c_uint>, + pub b: __BindgenUnionField<::std::os::raw::c_ushort>, + pub bindgen_union_field: u32, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/union_with_anon_unnamed_struct.rs b/libbindgen/tests/expectations/tests/union_with_anon_unnamed_struct.rs new file mode 100644 index 00000000..2d6fab97 --- /dev/null +++ b/libbindgen/tests/expectations/tests/union_with_anon_unnamed_struct.rs @@ -0,0 +1,61 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct pixel { + pub rgba: __BindgenUnionField<::std::os::raw::c_uint>, + pub __bindgen_anon_1: __BindgenUnionField, + pub bindgen_union_field: u32, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct pixel__bindgen_ty_1 { + 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, +} +#[test] +fn bindgen_test_layout_pixel__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for pixel__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_pixel() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for pixel { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/union_with_anon_unnamed_union.rs b/libbindgen/tests/expectations/tests/union_with_anon_unnamed_union.rs new file mode 100644 index 00000000..eb214017 --- /dev/null +++ b/libbindgen/tests/expectations/tests/union_with_anon_unnamed_union.rs @@ -0,0 +1,60 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub a: __BindgenUnionField<::std::os::raw::c_uint>, + pub __bindgen_anon_1: __BindgenUnionField, + pub bindgen_union_field: u32, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub b: __BindgenUnionField<::std::os::raw::c_ushort>, + pub c: __BindgenUnionField<::std::os::raw::c_uchar>, + pub bindgen_union_field: u16, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 2usize); + assert_eq!(::std::mem::align_of::() , 2usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/union_with_big_member.rs b/libbindgen/tests/expectations/tests/union_with_big_member.rs new file mode 100644 index 00000000..b921f33c --- /dev/null +++ b/libbindgen/tests/expectations/tests/union_with_big_member.rs @@ -0,0 +1,75 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Copy)] +pub struct WithBigArray { + pub a: __BindgenUnionField<::std::os::raw::c_int>, + pub b: __BindgenUnionField<[::std::os::raw::c_int; 33usize]>, + pub bindgen_union_field: [u32; 33usize], +} +#[test] +fn bindgen_test_layout_WithBigArray() { + assert_eq!(::std::mem::size_of::() , 132usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for WithBigArray { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct WithBigArray2 { + pub a: __BindgenUnionField<::std::os::raw::c_int>, + pub b: __BindgenUnionField<[::std::os::raw::c_char; 33usize]>, + pub bindgen_union_field: [u32; 9usize], +} +#[test] +fn bindgen_test_layout_WithBigArray2() { + assert_eq!(::std::mem::size_of::() , 36usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for WithBigArray2 { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Copy)] +pub struct WithBigMember { + pub a: __BindgenUnionField<::std::os::raw::c_int>, + pub b: __BindgenUnionField, + pub bindgen_union_field: [u32; 33usize], +} +#[test] +fn bindgen_test_layout_WithBigMember() { + assert_eq!(::std::mem::size_of::() , 132usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for WithBigMember { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/union_with_nesting.rs b/libbindgen/tests/expectations/tests/union_with_nesting.rs new file mode 100644 index 00000000..61c08a2a --- /dev/null +++ b/libbindgen/tests/expectations/tests/union_with_nesting.rs @@ -0,0 +1,89 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct __BindgenUnionField(::std::marker::PhantomData); +impl __BindgenUnionField { + #[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 ::std::default::Default for __BindgenUnionField { + #[inline] + fn default() -> Self { Self::new() } +} +impl ::std::clone::Clone for __BindgenUnionField { + #[inline] + fn clone(&self) -> Self { Self::new() } +} +impl ::std::marker::Copy for __BindgenUnionField { } +impl ::std::fmt::Debug for __BindgenUnionField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub a: __BindgenUnionField<::std::os::raw::c_uint>, + pub __bindgen_anon_1: __BindgenUnionField, + pub bindgen_union_field: u32, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1 { + pub __bindgen_anon_1: foo__bindgen_ty_1_1, + pub __bindgen_anon_2: foo__bindgen_ty_1_2, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1_1 { + pub b1: __BindgenUnionField<::std::os::raw::c_ushort>, + pub b2: __BindgenUnionField<::std::os::raw::c_ushort>, + pub bindgen_union_field: u16, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1_1() { + assert_eq!(::std::mem::size_of::() , 2usize); + assert_eq!(::std::mem::align_of::() , 2usize); +} +impl Clone for foo__bindgen_ty_1_1 { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_1_2 { + pub c1: __BindgenUnionField<::std::os::raw::c_ushort>, + pub c2: __BindgenUnionField<::std::os::raw::c_ushort>, + pub bindgen_union_field: u16, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1_2() { + assert_eq!(::std::mem::size_of::() , 2usize); + assert_eq!(::std::mem::align_of::() , 2usize); +} +impl Clone for foo__bindgen_ty_1_2 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_1() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 2usize); +} +impl Clone for foo__bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 4usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/unknown_attr.rs b/libbindgen/tests/expectations/tests/unknown_attr.rs new file mode 100644 index 00000000..fd9cce45 --- /dev/null +++ b/libbindgen/tests/expectations/tests/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_1 { + pub __clang_max_align_nonce1: ::std::os::raw::c_longlong, + pub __clang_max_align_nonce2: f64, +} +impl Clone for _bindgen_ty_1 { + fn clone(&self) -> Self { *self } +} +pub type max_align_t = _bindgen_ty_1; diff --git a/libbindgen/tests/expectations/tests/use-core.rs b/libbindgen/tests/expectations/tests/use-core.rs new file mode 100644 index 00000000..b0900f5f --- /dev/null +++ b/libbindgen/tests/expectations/tests/use-core.rs @@ -0,0 +1,24 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + +extern crate core; + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub a: ::std::os::raw::c_int, + pub b: ::std::os::raw::c_int, + pub bar: *mut ::std::os::raw::c_void, +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::core::mem::size_of::() , 16usize); + assert_eq!(::core::mem::align_of::() , 8usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} +pub type fooFunction = + ::core::option::Option; diff --git a/libbindgen/tests/expectations/tests/using.rs b/libbindgen/tests/expectations/tests/using.rs new file mode 100644 index 00000000..dbb6c84f --- /dev/null +++ b/libbindgen/tests/expectations/tests/using.rs @@ -0,0 +1,14 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Point { + pub x: T, + pub y: T, +} +pub type IntPoint2D = Point<::std::os::raw::c_int>; +pub type IntVec2D = Point<::std::os::raw::c_int>; diff --git a/libbindgen/tests/expectations/tests/vector.rs b/libbindgen/tests/expectations/tests/vector.rs new file mode 100644 index 00000000..b8ca5735 --- /dev/null +++ b/libbindgen/tests/expectations/tests/vector.rs @@ -0,0 +1,19 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo { + pub mMember: [::std::os::raw::c_longlong; 1usize], +} +#[test] +fn bindgen_test_layout_foo() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for foo { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/virtual_dtor.rs b/libbindgen/tests/expectations/tests/virtual_dtor.rs new file mode 100644 index 00000000..9571f084 --- /dev/null +++ b/libbindgen/tests/expectations/tests/virtual_dtor.rs @@ -0,0 +1,19 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct nsSlots__bindgen_vtable { +} +#[repr(C)] +#[derive(Debug)] +pub struct nsSlots { + pub vtable_: *const nsSlots__bindgen_vtable, +} +#[test] +fn bindgen_test_layout_nsSlots() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} diff --git a/libbindgen/tests/expectations/tests/virtual_overloaded.rs b/libbindgen/tests/expectations/tests/virtual_overloaded.rs new file mode 100644 index 00000000..7833cdbf --- /dev/null +++ b/libbindgen/tests/expectations/tests/virtual_overloaded.rs @@ -0,0 +1,22 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +pub struct C__bindgen_vtable { +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct C { + pub vtable_: *const C__bindgen_vtable, +} +#[test] +fn bindgen_test_layout_C() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for C { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/vtable_recursive_sig.rs b/libbindgen/tests/expectations/tests/vtable_recursive_sig.rs new file mode 100644 index 00000000..ce62eeb0 --- /dev/null +++ b/libbindgen/tests/expectations/tests/vtable_recursive_sig.rs @@ -0,0 +1,35 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Derived { + pub _base: Base, +} +#[test] +fn bindgen_test_layout_Derived() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for Derived { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +pub struct Base__bindgen_vtable { +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Base { + pub vtable_: *const Base__bindgen_vtable, +} +#[test] +fn bindgen_test_layout_Base() { + assert_eq!(::std::mem::size_of::() , 8usize); + assert_eq!(::std::mem::align_of::() , 8usize); +} +impl Clone for Base { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/weird_bitfields.rs b/libbindgen/tests/expectations/tests/weird_bitfields.rs new file mode 100644 index 00000000..56ee76a5 --- /dev/null +++ b/libbindgen/tests/expectations/tests/weird_bitfields.rs @@ -0,0 +1,128 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(u32)] +#[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 Weird { + pub mStrokeDasharrayLength: ::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, + pub mFillRule: ::std::os::raw::c_uchar, + pub mImageRendering: ::std::os::raw::c_uchar, + pub mPaintOrder: ::std::os::raw::c_uchar, + pub mShapeRendering: ::std::os::raw::c_uchar, + pub mStrokeLinecap: ::std::os::raw::c_uchar, + pub mStrokeLinejoin: ::std::os::raw::c_uchar, + pub mTextAnchor: ::std::os::raw::c_uchar, + pub mTextRendering: ::std::os::raw::c_uchar, + pub _bitfield_2: u16, +} +#[test] +fn bindgen_test_layout_Weird() { + assert_eq!(::std::mem::size_of::() , 24usize); + assert_eq!(::std::mem::align_of::() , 4usize); +} +impl Clone for Weird { + fn clone(&self) -> Self { *self } +} +impl Weird { + #[inline] + pub fn bitTest(&self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & (65535usize as u32)) >> + 0u32) as u32) + } + } + #[inline] + pub fn set_bitTest(&mut self, val: ::std::os::raw::c_uint) { + self._bitfield_1 &= !(65535usize as u32); + self._bitfield_1 |= + ((val as u32 as u32) << 0u32) & (65535usize as u32); + } + #[inline] + pub fn bitTest2(&self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute(((self._bitfield_1 & + (2147418112usize as u32)) >> 16u32) as + u32) + } + } + #[inline] + pub fn set_bitTest2(&mut self, val: ::std::os::raw::c_uint) { + self._bitfield_1 &= !(2147418112usize as u32); + self._bitfield_1 |= + ((val as u32 as u32) << 16u32) & (2147418112usize as u32); + } + #[inline] + 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: nsStyleSVGOpacitySource) { + self._bitfield_2 &= !(7usize as u16); + self._bitfield_2 |= ((val as u32 as u16) << 0u32) & (7usize as u16); + } + #[inline] + 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: nsStyleSVGOpacitySource) { + self._bitfield_2 &= !(56usize as u16); + self._bitfield_2 |= ((val as u32 as u16) << 3u32) & (56usize as u16); + } + #[inline] + 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 u16); + self._bitfield_2 |= ((val as u8 as u16) << 6u32) & (64usize as u16); + } + #[inline] + 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 u16); + self._bitfield_2 |= ((val as u8 as u16) << 7u32) & (128usize as u16); + } + #[inline] + 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 u16); + self._bitfield_2 |= ((val as u8 as u16) << 8u32) & (256usize as u16); + } +} diff --git a/libbindgen/tests/expectations/tests/what_is_going_on.rs b/libbindgen/tests/expectations/tests/what_is_going_on.rs new file mode 100644 index 00000000..6f1998d1 --- /dev/null +++ b/libbindgen/tests/expectations/tests/what_is_going_on.rs @@ -0,0 +1,28 @@ +/* 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::() , 1usize); + assert_eq!(::std::mem::align_of::() , 1usize); +} +impl Clone for UnknownUnits { + fn clone(&self) -> Self { *self } +} +pub type Float = f32; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct PointTyped { + pub x: F, + pub y: F, + pub _phantom_0: ::std::marker::PhantomData, +} +pub type IntPoint = PointTyped; diff --git a/libbindgen/tests/expectations/tests/whitelist_basic.rs b/libbindgen/tests/expectations/tests/whitelist_basic.rs new file mode 100644 index 00000000..0104f049 --- /dev/null +++ b/libbindgen/tests/expectations/tests/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 { + pub foo: ::std::os::raw::c_int, + pub bar: WhitelistMe_Inner, + pub _phantom_0: ::std::marker::PhantomData, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct WhitelistMe_Inner { + pub bar: T, +} diff --git a/libbindgen/tests/expectations/tests/whitelist_vars.rs b/libbindgen/tests/expectations/tests/whitelist_vars.rs new file mode 100644 index 00000000..f7af24b2 --- /dev/null +++ b/libbindgen/tests/expectations/tests/whitelist_vars.rs @@ -0,0 +1,10 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const NONE: ::std::os::raw::c_uint = 0; +pub const FOO: ::std::os::raw::c_uint = 5; +pub const FOOB: ::std::os::raw::c_int = -2; +pub const FOOBAR: ::std::os::raw::c_int = -10; diff --git a/libbindgen/tests/headers/accessors.hpp b/libbindgen/tests/headers/accessors.hpp new file mode 100644 index 00000000..4c23e35d --- /dev/null +++ b/libbindgen/tests/headers/accessors.hpp @@ -0,0 +1,46 @@ +struct SomeAccessors { + int mNoAccessor; + /**
*/ + int mBothAccessors; + /**
*/ + int mUnsafeAccessors; + /**
*/ + int mImmutableAccessor; +}; + +/**
*/ +struct AllAccessors { + int mBothAccessors; + int mAlsoBothAccessors; +}; + +/**
*/ +struct AllUnsafeAccessors { + int mBothAccessors; + int mAlsoBothAccessors; +}; + +/**
*/ +struct ContradictAccessors { + int mBothAccessors; + /**
*/ + int mNoAccessors; + /**
*/ + int mUnsafeAccessors; + /**
*/ + int mImmutableAccessor; +}; + +/**
*/ +struct Replacing { + int mAccessor; +}; + +struct Replaced { + int noOp; +}; + +/**
*/ +struct Wrapper { + Replaced mReplaced; +}; diff --git a/libbindgen/tests/headers/annotation_hide.hpp b/libbindgen/tests/headers/annotation_hide.hpp new file mode 100644 index 00000000..3c82c9a2 --- /dev/null +++ b/libbindgen/tests/headers/annotation_hide.hpp @@ -0,0 +1,16 @@ + +/** + *
+ */ +struct C; + +/** + *
+ */ +struct D { + int a; +}; + +struct NotAnnotated { + int f; +}; diff --git a/libbindgen/tests/headers/anon_enum.hpp b/libbindgen/tests/headers/anon_enum.hpp new file mode 100644 index 00000000..c7405202 --- /dev/null +++ b/libbindgen/tests/headers/anon_enum.hpp @@ -0,0 +1,5 @@ +struct Test { + int foo; + float bar; + enum { T_NONE }; +}; diff --git a/libbindgen/tests/headers/anon_enum_whitelist.h b/libbindgen/tests/headers/anon_enum_whitelist.h new file mode 100644 index 00000000..15cda6b1 --- /dev/null +++ b/libbindgen/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/libbindgen/tests/headers/anon_union.hpp b/libbindgen/tests/headers/anon_union.hpp new file mode 100644 index 00000000..126f6a6e --- /dev/null +++ b/libbindgen/tests/headers/anon_union.hpp @@ -0,0 +1,20 @@ +template +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 { +}; diff --git a/libbindgen/tests/headers/arg_keyword.hpp b/libbindgen/tests/headers/arg_keyword.hpp new file mode 100644 index 00000000..9f0af850 --- /dev/null +++ b/libbindgen/tests/headers/arg_keyword.hpp @@ -0,0 +1 @@ +void foo(const char* type); diff --git a/libbindgen/tests/headers/base-to-derived.hpp b/libbindgen/tests/headers/base-to-derived.hpp new file mode 100644 index 00000000..ea31e0f2 --- /dev/null +++ b/libbindgen/tests/headers/base-to-derived.hpp @@ -0,0 +1,19 @@ +// bindgen-flags: -- -std=c++11 + +struct false_type {}; + +template +struct __is_base_to_derived_ref; + +template +struct __is_base_to_derived_ref<_From, _To, true> +{ + typedef _To type; + + static constexpr bool value = type::value; +}; + +template +struct __is_base_to_derived_ref<_From, _To, false> +: public false_type +{ }; diff --git a/libbindgen/tests/headers/bitfield-enum-basic.h b/libbindgen/tests/headers/bitfield-enum-basic.h new file mode 100644 index 00000000..364bebf2 --- /dev/null +++ b/libbindgen/tests/headers/bitfield-enum-basic.h @@ -0,0 +1,27 @@ +// bindgen-flags: --bitfield-enum "Foo|Buz|NS_.*|DUMMY_.*" -- -std=c++11 + +enum Foo { + Bar = 1 << 1, + Baz = 1 << 2, + Duplicated = 1 << 2, + Negative = -3, +}; + +enum class Buz : signed char { + Bar = 1 << 1, + Baz = 1 << 2, + Duplicated = 1 << 2, + Negative = -3, +}; + +enum { + NS_FOO = 1 << 0, + NS_BAR = 1 << 1, +}; + +class Dummy { + enum { + DUMMY_FOO = 1 << 0, + DUMMY_BAR = 1 << 1, + }; +}; diff --git a/libbindgen/tests/headers/blocks.h b/libbindgen/tests/headers/blocks.h new file mode 100644 index 00000000..80420e6e --- /dev/null +++ b/libbindgen/tests/headers/blocks.h @@ -0,0 +1,3 @@ +// bindgen-flags: -- -fblocks + +void atexit_b(void (^)(void)); diff --git a/libbindgen/tests/headers/class.hpp b/libbindgen/tests/headers/class.hpp new file mode 100644 index 00000000..e753f186 --- /dev/null +++ b/libbindgen/tests/headers/class.hpp @@ -0,0 +1,29 @@ +class C { + int a; + // More than rust limits (32) + char big_array[33]; +}; + +class WithDtor { + int b; + + ~WithDtor() {} +}; + +union Union { + float d; + int i; +}; + +class WithUnion { + Union data; +}; + +class RealAbstractionWithTonsOfMethods { + void foo(); +public: + void bar() const; + void bar(); + void bar(int foo); + static void sta(); +}; diff --git a/libbindgen/tests/headers/class_nested.hpp b/libbindgen/tests/headers/class_nested.hpp new file mode 100644 index 00000000..ab38d500 --- /dev/null +++ b/libbindgen/tests/headers/class_nested.hpp @@ -0,0 +1,24 @@ +class A { +public: + int member_a; + class B { + int member_b; + }; +}; + +A::B var; + +class D { + A::B member; +}; + +template +class Templated { + T member; + + class Templated_inner { + public: + T* member_ptr; + void get() {} + }; +}; diff --git a/libbindgen/tests/headers/class_no_members.hpp b/libbindgen/tests/headers/class_no_members.hpp new file mode 100644 index 00000000..a4483558 --- /dev/null +++ b/libbindgen/tests/headers/class_no_members.hpp @@ -0,0 +1,16 @@ +// bindgen-flags: -- -std=c++11 + +class whatever { +}; + +class whatever_child: public whatever { +}; + +class whatever_child_with_member: public whatever { +public: + int m_member; +}; + +static_assert(sizeof(whatever) == 1, "Testing!"); +static_assert(sizeof(whatever_child) == 1, "Testing!"); +static_assert(sizeof(whatever_child_with_member) == 4, "Testing!"); diff --git a/libbindgen/tests/headers/class_static.hpp b/libbindgen/tests/headers/class_static.hpp new file mode 100644 index 00000000..21ab2321 --- /dev/null +++ b/libbindgen/tests/headers/class_static.hpp @@ -0,0 +1,7 @@ +class MyClass { +public: + static const int* example; + static const int* example_check_no_collision; +}; + +static const int* example_check_no_collision; diff --git a/libbindgen/tests/headers/class_static_const.hpp b/libbindgen/tests/headers/class_static_const.hpp new file mode 100644 index 00000000..150afe8b --- /dev/null +++ b/libbindgen/tests/headers/class_static_const.hpp @@ -0,0 +1,8 @@ +using int32_t = int; +typedef unsigned int uint32_t; + +class A { + static const int a = 0; + static const int32_t b = 077; + static const uint32_t c = 0xff; +}; diff --git a/libbindgen/tests/headers/class_use_as.hpp b/libbindgen/tests/headers/class_use_as.hpp new file mode 100644 index 00000000..a4e36ded --- /dev/null +++ b/libbindgen/tests/headers/class_use_as.hpp @@ -0,0 +1,15 @@ + +/** + *
+ */ +struct whatever_replacement { + int replacement; +}; + +struct whatever { + int b; +}; + +struct container { + whatever c; +}; diff --git a/libbindgen/tests/headers/class_with_dtor.hpp b/libbindgen/tests/headers/class_with_dtor.hpp new file mode 100644 index 00000000..b9bf74e1 --- /dev/null +++ b/libbindgen/tests/headers/class_with_dtor.hpp @@ -0,0 +1,13 @@ + + +template +class HandleWithDtor { + T* ptr; + ~HandleWithDtor() {} +}; + +typedef HandleWithDtor HandleValue; + +class WithoutDtor { + HandleValue shouldBeWithDtor; +}; diff --git a/libbindgen/tests/headers/class_with_inner_struct.hpp b/libbindgen/tests/headers/class_with_inner_struct.hpp new file mode 100644 index 00000000..ec729fe6 --- /dev/null +++ b/libbindgen/tests/headers/class_with_inner_struct.hpp @@ -0,0 +1,43 @@ +// bindgen-flags: -- -std=c++11 + +class A { + unsigned c; + struct Segment { int begin, end; }; + union { + int f; + } named_union; + union { + int d; + }; +}; + +class B { + unsigned d; + struct Segment { int begin, end; }; +}; + + +enum class StepSyntax { + Keyword, // step-start and step-end + FunctionalWithoutKeyword, // steps(...) + FunctionalWithStartKeyword, // steps(..., start) + FunctionalWithEndKeyword, // steps(..., end) +}; + +class C { + unsigned d; + union { + struct { + float mX1; + float mY1; + float mX2; + float mY2; + } mFunc; + struct { + StepSyntax mStepSyntax; + unsigned int mSteps; + }; + }; + // To ensure it doesn't collide + struct Segment { int begin, end; }; +}; diff --git a/libbindgen/tests/headers/class_with_typedef.hpp b/libbindgen/tests/headers/class_with_typedef.hpp new file mode 100644 index 00000000..8707cffe --- /dev/null +++ b/libbindgen/tests/headers/class_with_typedef.hpp @@ -0,0 +1,22 @@ +typedef int AnotherInt; + +class C { +public: + typedef int MyInt; + typedef const char* Lookup; + MyInt c; + MyInt* ptr; + MyInt arr[10]; + AnotherInt d; + AnotherInt* other_ptr; + + void method(MyInt c); + void methodRef(MyInt& c); + void complexMethodRef(Lookup& c); + void anotherMethod(AnotherInt c); +}; + +class D: public C { +public: + MyInt* ptr; +}; diff --git a/libbindgen/tests/headers/complex.h b/libbindgen/tests/headers/complex.h new file mode 100644 index 00000000..04877a4e --- /dev/null +++ b/libbindgen/tests/headers/complex.h @@ -0,0 +1,16 @@ + +#define COMPLEX_TEST(ty_, name_) \ + struct Test##name_ { \ + ty_ _Complex mMember; \ + \ + }; \ + struct Test##name_##Ptr { \ + ty_ _Complex* mMember; \ + }; + +COMPLEX_TEST(double, Double) +COMPLEX_TEST(float, Float) + +// FIXME: 128-byte-aligned in some machines +// which we can't support right now in Rust. +// COMPLEX_TEST(long double, LongDouble) diff --git a/libbindgen/tests/headers/complex_global.h b/libbindgen/tests/headers/complex_global.h new file mode 100644 index 00000000..d9f9fb01 --- /dev/null +++ b/libbindgen/tests/headers/complex_global.h @@ -0,0 +1,3 @@ +float _Complex globalValueFloat; +double _Complex globalValueDouble; +long double _Complex globalValueLongDouble; diff --git a/libbindgen/tests/headers/const_enum_unnamed.hpp b/libbindgen/tests/headers/const_enum_unnamed.hpp new file mode 100644 index 00000000..eb139434 --- /dev/null +++ b/libbindgen/tests/headers/const_enum_unnamed.hpp @@ -0,0 +1,9 @@ + +enum { + FOO_BAR, + FOO_BAZ, +}; + +class Foo { + enum { FOO_BAR = 10 }; +}; diff --git a/libbindgen/tests/headers/const_ptr.hpp b/libbindgen/tests/headers/const_ptr.hpp new file mode 100644 index 00000000..66744f8b --- /dev/null +++ b/libbindgen/tests/headers/const_ptr.hpp @@ -0,0 +1,3 @@ +extern "C" { + void foo(const void* bar); +} diff --git a/libbindgen/tests/headers/const_resolved_ty.h b/libbindgen/tests/headers/const_resolved_ty.h new file mode 100644 index 00000000..2521e61c --- /dev/null +++ b/libbindgen/tests/headers/const_resolved_ty.h @@ -0,0 +1,3 @@ +typedef unsigned char uint8_t; + +void foo(const uint8_t* foo); diff --git a/libbindgen/tests/headers/const_tparam.hpp b/libbindgen/tests/headers/const_tparam.hpp new file mode 100644 index 00000000..05f26e4a --- /dev/null +++ b/libbindgen/tests/headers/const_tparam.hpp @@ -0,0 +1,5 @@ +template +class C { + const T* const foo; + const T* bar; +}; diff --git a/libbindgen/tests/headers/convert-floats.h b/libbindgen/tests/headers/convert-floats.h new file mode 100644 index 00000000..08d9fe0b --- /dev/null +++ b/libbindgen/tests/headers/convert-floats.h @@ -0,0 +1,9 @@ +// bindgen-flags: --no-convert-floats + +struct foo { + float bar, baz; + double bazz; + long double* bazzz; + float _Complex complexFloat; + double _Complex complexDouble; +}; diff --git a/libbindgen/tests/headers/crtp.hpp b/libbindgen/tests/headers/crtp.hpp new file mode 100644 index 00000000..a5477c54 --- /dev/null +++ b/libbindgen/tests/headers/crtp.hpp @@ -0,0 +1,12 @@ +template +class Base {}; + +class Derived : public Base {}; + +template +class BaseWithDestructor { + ~BaseWithDestructor(); +}; + +class DerivedFromBaseWithDestructor : + public BaseWithDestructor {}; diff --git a/libbindgen/tests/headers/decl_extern_int_twice.h b/libbindgen/tests/headers/decl_extern_int_twice.h new file mode 100644 index 00000000..06f80e87 --- /dev/null +++ b/libbindgen/tests/headers/decl_extern_int_twice.h @@ -0,0 +1,2 @@ +extern int foo; +extern int foo; diff --git a/libbindgen/tests/headers/decl_ptr_to_array.h b/libbindgen/tests/headers/decl_ptr_to_array.h new file mode 100644 index 00000000..3222cbd4 --- /dev/null +++ b/libbindgen/tests/headers/decl_ptr_to_array.h @@ -0,0 +1 @@ +int (*foo)[1]; diff --git a/libbindgen/tests/headers/duplicated_constants_in_ns.hpp b/libbindgen/tests/headers/duplicated_constants_in_ns.hpp new file mode 100644 index 00000000..bb343641 --- /dev/null +++ b/libbindgen/tests/headers/duplicated_constants_in_ns.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --enable-cxx-namespaces +namespace foo { + const int FOO = 4; +} +namespace bar { + const int FOO = 5; +} diff --git a/libbindgen/tests/headers/elaborated.hpp b/libbindgen/tests/headers/elaborated.hpp new file mode 100644 index 00000000..4bfbff23 --- /dev/null +++ b/libbindgen/tests/headers/elaborated.hpp @@ -0,0 +1,5 @@ +namespace whatever { + typedef int whatever_t; +} + +void something(const whatever::whatever_t *wat); diff --git a/libbindgen/tests/headers/empty_template_param_name.hpp b/libbindgen/tests/headers/empty_template_param_name.hpp new file mode 100644 index 00000000..b3360bc9 --- /dev/null +++ b/libbindgen/tests/headers/empty_template_param_name.hpp @@ -0,0 +1,4 @@ +template using __void_t = void; + +template> + struct __iterator_traits { }; diff --git a/libbindgen/tests/headers/enum.h b/libbindgen/tests/headers/enum.h new file mode 100644 index 00000000..f2d301e7 --- /dev/null +++ b/libbindgen/tests/headers/enum.h @@ -0,0 +1,9 @@ +enum Foo { + Bar = 0, + Qux +}; + +enum Neg { + MinusOne = -1, + One = 1, +}; diff --git a/libbindgen/tests/headers/enum_alias.hpp b/libbindgen/tests/headers/enum_alias.hpp new file mode 100644 index 00000000..658f8fde --- /dev/null +++ b/libbindgen/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/libbindgen/tests/headers/enum_and_vtable_mangling.hpp b/libbindgen/tests/headers/enum_and_vtable_mangling.hpp new file mode 100644 index 00000000..3abd6a29 --- /dev/null +++ b/libbindgen/tests/headers/enum_and_vtable_mangling.hpp @@ -0,0 +1,11 @@ + +enum { + match, + whatever_else, +}; + +class C { + int i; +public: + virtual void match() { }; +}; diff --git a/libbindgen/tests/headers/enum_dupe.h b/libbindgen/tests/headers/enum_dupe.h new file mode 100644 index 00000000..6d3591d5 --- /dev/null +++ b/libbindgen/tests/headers/enum_dupe.h @@ -0,0 +1,4 @@ +enum Foo { + Bar = 1, + Dupe = 1 +}; diff --git a/libbindgen/tests/headers/enum_explicit_type.hpp b/libbindgen/tests/headers/enum_explicit_type.hpp new file mode 100644 index 00000000..78eadd40 --- /dev/null +++ b/libbindgen/tests/headers/enum_explicit_type.hpp @@ -0,0 +1,28 @@ +// bindgen-flags: -- -std=c++11 + +enum Foo: unsigned char { + Bar = 0, + Qux +}; + +enum Neg: char { + MinusOne = -1, + One = 1, +}; + +enum Bigger: unsigned short { + Much = 255, + Larger +}; + +enum MuchLong: long { + MuchLow = -4294967296, +}; + +enum MuchLongLong: long long { + I64_MIN = 1ll << 63, +}; + +enum MuchULongLong: unsigned long long { + MuchHigh = 4294967296, +}; diff --git a/libbindgen/tests/headers/enum_negative.h b/libbindgen/tests/headers/enum_negative.h new file mode 100644 index 00000000..6cbdfe04 --- /dev/null +++ b/libbindgen/tests/headers/enum_negative.h @@ -0,0 +1,4 @@ +enum Foo { + Bar = -2, + Qux = 1, +}; diff --git a/libbindgen/tests/headers/enum_packed.h b/libbindgen/tests/headers/enum_packed.h new file mode 100644 index 00000000..8654d110 --- /dev/null +++ b/libbindgen/tests/headers/enum_packed.h @@ -0,0 +1,14 @@ +enum __attribute__((packed)) Foo { + Bar = 0, + Qux +}; + +enum __attribute__((packed)) Neg { + MinusOne = -1, + One = 1, +}; + +enum __attribute__((packed)) Bigger { + Much = 255, + Larger +}; diff --git a/libbindgen/tests/headers/extern.hpp b/libbindgen/tests/headers/extern.hpp new file mode 100644 index 00000000..0779e038 --- /dev/null +++ b/libbindgen/tests/headers/extern.hpp @@ -0,0 +1,3 @@ +extern "C" { +#include "func_proto.h" +} diff --git a/libbindgen/tests/headers/float128.hpp b/libbindgen/tests/headers/float128.hpp new file mode 100644 index 00000000..f554e88e --- /dev/null +++ b/libbindgen/tests/headers/float128.hpp @@ -0,0 +1,13 @@ +// FIXME: libclang < 3.9 does not expose `__float128` in its interface, so this +// test will fail. Once we remove support for `--features llvm_stable` and +// require libclang >= 3.9, we can reenable this test. +// +// static __float128 global = 1.0; + +// FIXME: We have no way to get 128 bit aligned structs in Rust at the moment, +// and therefore the generated layout tests for this struct will fail. When we +// can enforce 128 bit alignment, we can re-enable this test. +// +// struct A { +// __float128 f; +// }; diff --git a/libbindgen/tests/headers/forward-inherit-struct-with-fields.hpp b/libbindgen/tests/headers/forward-inherit-struct-with-fields.hpp new file mode 100644 index 00000000..437fff5d --- /dev/null +++ b/libbindgen/tests/headers/forward-inherit-struct-with-fields.hpp @@ -0,0 +1,8 @@ +template class Rooted; +namespace js { + template class RootedBase { + T* foo; + Rooted* next; + }; +} +template class Rooted : js::RootedBase {}; diff --git a/libbindgen/tests/headers/forward-inherit-struct.hpp b/libbindgen/tests/headers/forward-inherit-struct.hpp new file mode 100644 index 00000000..ac7aef5e --- /dev/null +++ b/libbindgen/tests/headers/forward-inherit-struct.hpp @@ -0,0 +1,5 @@ +template class Rooted; +namespace js { + template class RootedBase {}; +} +template class Rooted : js::RootedBase {}; diff --git a/libbindgen/tests/headers/forward_declared_struct.h b/libbindgen/tests/headers/forward_declared_struct.h new file mode 100644 index 00000000..2a69450c --- /dev/null +++ b/libbindgen/tests/headers/forward_declared_struct.h @@ -0,0 +1,11 @@ +struct a; + +struct a { + int b; +}; + +struct c { + int d; +}; + +struct c; \ No newline at end of file diff --git a/libbindgen/tests/headers/func_proto.h b/libbindgen/tests/headers/func_proto.h new file mode 100644 index 00000000..51139ca9 --- /dev/null +++ b/libbindgen/tests/headers/func_proto.h @@ -0,0 +1 @@ +typedef int foo(int bar); diff --git a/libbindgen/tests/headers/func_ptr.h b/libbindgen/tests/headers/func_ptr.h new file mode 100644 index 00000000..a4662f3d --- /dev/null +++ b/libbindgen/tests/headers/func_ptr.h @@ -0,0 +1 @@ +int (*foo) (int x, int y); diff --git a/libbindgen/tests/headers/func_ptr_in_struct.h b/libbindgen/tests/headers/func_ptr_in_struct.h new file mode 100644 index 00000000..988db5b3 --- /dev/null +++ b/libbindgen/tests/headers/func_ptr_in_struct.h @@ -0,0 +1,6 @@ + +enum baz; + +struct Foo { + enum baz (*bar) (int x, int y); +}; diff --git a/libbindgen/tests/headers/func_with_array_arg.h b/libbindgen/tests/headers/func_with_array_arg.h new file mode 100644 index 00000000..1b81702b --- /dev/null +++ b/libbindgen/tests/headers/func_with_array_arg.h @@ -0,0 +1 @@ +void f(int x[2]); diff --git a/libbindgen/tests/headers/func_with_func_ptr_arg.h b/libbindgen/tests/headers/func_with_func_ptr_arg.h new file mode 100644 index 00000000..629c84ab --- /dev/null +++ b/libbindgen/tests/headers/func_with_func_ptr_arg.h @@ -0,0 +1 @@ +void foo(void (*bar)()); diff --git a/libbindgen/tests/headers/in_class_typedef.hpp b/libbindgen/tests/headers/in_class_typedef.hpp new file mode 100644 index 00000000..dda7472d --- /dev/null +++ b/libbindgen/tests/headers/in_class_typedef.hpp @@ -0,0 +1,10 @@ + +template +class Foo { + typedef T elem_type; + typedef T* ptr_type; + + typedef struct Bar { + int x, y; + } Bar; +}; diff --git a/libbindgen/tests/headers/inherit-namespaced.hpp b/libbindgen/tests/headers/inherit-namespaced.hpp new file mode 100644 index 00000000..61eafd5a --- /dev/null +++ b/libbindgen/tests/headers/inherit-namespaced.hpp @@ -0,0 +1,4 @@ +namespace js { + template class RootedBase {}; +} +template class Rooted : js::RootedBase {}; diff --git a/libbindgen/tests/headers/inherit_named.hpp b/libbindgen/tests/headers/inherit_named.hpp new file mode 100644 index 00000000..9881d1b6 --- /dev/null +++ b/libbindgen/tests/headers/inherit_named.hpp @@ -0,0 +1,5 @@ +template +class Wohoo {}; + +template +class Weeee : public T {}; diff --git a/libbindgen/tests/headers/inherit_typedef.hpp b/libbindgen/tests/headers/inherit_typedef.hpp new file mode 100644 index 00000000..8d699e82 --- /dev/null +++ b/libbindgen/tests/headers/inherit_typedef.hpp @@ -0,0 +1,5 @@ +struct Foo {}; + +typedef Foo TypedefedFoo; + +struct Bar: public TypedefedFoo {}; diff --git a/libbindgen/tests/headers/inner_const.hpp b/libbindgen/tests/headers/inner_const.hpp new file mode 100644 index 00000000..25c2e603 --- /dev/null +++ b/libbindgen/tests/headers/inner_const.hpp @@ -0,0 +1,6 @@ + +class Foo { + static int BOO; + static Foo whatever; + int bar; +}; diff --git a/libbindgen/tests/headers/inner_template_self.hpp b/libbindgen/tests/headers/inner_template_self.hpp new file mode 100644 index 00000000..1ae5af06 --- /dev/null +++ b/libbindgen/tests/headers/inner_template_self.hpp @@ -0,0 +1,10 @@ + +template +class LinkedList { + LinkedList* next; + LinkedList* prev; +}; + +class InstantiateIt { + LinkedList m_list; +}; diff --git a/libbindgen/tests/headers/int128_t.h b/libbindgen/tests/headers/int128_t.h new file mode 100644 index 00000000..eece252c --- /dev/null +++ b/libbindgen/tests/headers/int128_t.h @@ -0,0 +1,7 @@ +/** + * FIXME: Uncomment this once we can generate the proper alignment for the type, + * i.e., when we use u128/i128. +struct Foo { + __int128 foo; +}; + */ diff --git a/libbindgen/tests/headers/jsval_layout_opaque.hpp b/libbindgen/tests/headers/jsval_layout_opaque.hpp new file mode 100644 index 00000000..85c5be63 --- /dev/null +++ b/libbindgen/tests/headers/jsval_layout_opaque.hpp @@ -0,0 +1,424 @@ +// 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; + + +#define JS_PUNBOX64 +#define IS_LITTLE_ENDIAN + +/* + * Try to get jsvals 64-bit aligned. We could almost assert that all values are + * aligned, but MSVC and GCC occasionally break alignment. + */ +#if defined(__GNUC__) || defined(__xlc__) || defined(__xlC__) +# define JSVAL_ALIGNMENT __attribute__((aligned (8))) +#elif defined(_MSC_VER) + /* + * Structs can be aligned with MSVC, but not if they are used as parameters, + * so we just don't try to align. + */ +# define JSVAL_ALIGNMENT +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# define JSVAL_ALIGNMENT +#elif defined(__HP_cc) || defined(__HP_aCC) +# define JSVAL_ALIGNMENT +#endif + +#if defined(JS_PUNBOX64) +# define JSVAL_TAG_SHIFT 47 +#endif + +/* + * We try to use enums so that printing a jsval_layout in the debugger shows + * nice symbolic type tags, however we can only do this when we can force the + * underlying type of the enum to be the desired size. + */ +#if !defined(__SUNPRO_CC) && !defined(__xlC__) + +#if defined(_MSC_VER) +# define JS_ENUM_HEADER(id, type) enum id : type +# define JS_ENUM_FOOTER(id) +#else +# define JS_ENUM_HEADER(id, type) enum id +# define JS_ENUM_FOOTER(id) __attribute__((packed)) +#endif + +/* Remember to propagate changes to the C defines below. */ +JS_ENUM_HEADER(JSValueType, uint8_t) +{ + JSVAL_TYPE_DOUBLE = 0x00, + JSVAL_TYPE_INT32 = 0x01, + JSVAL_TYPE_UNDEFINED = 0x02, + JSVAL_TYPE_BOOLEAN = 0x03, + JSVAL_TYPE_MAGIC = 0x04, + JSVAL_TYPE_STRING = 0x05, + JSVAL_TYPE_SYMBOL = 0x06, + JSVAL_TYPE_NULL = 0x07, + JSVAL_TYPE_OBJECT = 0x08, + + /* These never appear in a jsval; they are only provided as an out-of-band value. */ + JSVAL_TYPE_UNKNOWN = 0x20, + JSVAL_TYPE_MISSING = 0x21 +} JS_ENUM_FOOTER(JSValueType); + +static_assert(sizeof(JSValueType) == 1, + "compiler typed enum support is apparently buggy"); + +#if defined(JS_NUNBOX32) + +/* Remember to propagate changes to the C defines below. */ +JS_ENUM_HEADER(JSValueTag, uint32_t) +{ + JSVAL_TAG_CLEAR = 0xFFFFFF80, + JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32, + JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED, + JSVAL_TAG_STRING = JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING, + JSVAL_TAG_SYMBOL = JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL, + JSVAL_TAG_BOOLEAN = JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN, + JSVAL_TAG_MAGIC = JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC, + JSVAL_TAG_NULL = JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL, + JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT +} JS_ENUM_FOOTER(JSValueTag); + +static_assert(sizeof(JSValueTag) == sizeof(uint32_t), + "compiler typed enum support is apparently buggy"); + +#elif defined(JS_PUNBOX64) + +/* Remember to propagate changes to the C defines below. */ +JS_ENUM_HEADER(JSValueTag, uint32_t) +{ + JSVAL_TAG_MAX_DOUBLE = 0x1FFF0, + JSVAL_TAG_INT32 = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32, + JSVAL_TAG_UNDEFINED = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED, + JSVAL_TAG_STRING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING, + JSVAL_TAG_SYMBOL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL, + JSVAL_TAG_BOOLEAN = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN, + JSVAL_TAG_MAGIC = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC, + JSVAL_TAG_NULL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL, + JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT +} JS_ENUM_FOOTER(JSValueTag); + +static_assert(sizeof(JSValueTag) == sizeof(uint32_t), + "compiler typed enum support is apparently buggy"); + +JS_ENUM_HEADER(JSValueShiftedTag, uint64_t) +{ + JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF), + JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT), + JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT), + JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT), + JSVAL_SHIFTED_TAG_SYMBOL = (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT), + JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT), + JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT), + JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT), + JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT) +} JS_ENUM_FOOTER(JSValueShiftedTag); + +static_assert(sizeof(JSValueShiftedTag) == sizeof(uint64_t), + "compiler typed enum support is apparently buggy"); + +#endif + +/* + * All our supported compilers implement C++11 |enum Foo : T| syntax, so don't + * expose these macros. (This macro exists *only* because gcc bug 51242 + * makes bit-fields of + * typed enums trigger a warning that can't be turned off. Don't expose it + * beyond this file!) + */ +#undef JS_ENUM_HEADER +#undef JS_ENUM_FOOTER + +#else /* !defined(__SUNPRO_CC) && !defined(__xlC__) */ + +typedef uint8_t JSValueType; +#define JSVAL_TYPE_DOUBLE ((uint8_t)0x00) +#define JSVAL_TYPE_INT32 ((uint8_t)0x01) +#define JSVAL_TYPE_UNDEFINED ((uint8_t)0x02) +#define JSVAL_TYPE_BOOLEAN ((uint8_t)0x03) +#define JSVAL_TYPE_MAGIC ((uint8_t)0x04) +#define JSVAL_TYPE_STRING ((uint8_t)0x05) +#define JSVAL_TYPE_SYMBOL ((uint8_t)0x06) +#define JSVAL_TYPE_NULL ((uint8_t)0x07) +#define JSVAL_TYPE_OBJECT ((uint8_t)0x08) +#define JSVAL_TYPE_UNKNOWN ((uint8_t)0x20) + +#if defined(JS_NUNBOX32) + +typedef uint32_t JSValueTag; +#define JSVAL_TAG_CLEAR ((uint32_t)(0xFFFFFF80)) +#define JSVAL_TAG_INT32 ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32)) +#define JSVAL_TAG_UNDEFINED ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED)) +#define JSVAL_TAG_STRING ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING)) +#define JSVAL_TAG_SYMBOL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL)) +#define JSVAL_TAG_BOOLEAN ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN)) +#define JSVAL_TAG_MAGIC ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC)) +#define JSVAL_TAG_NULL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL)) +#define JSVAL_TAG_OBJECT ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT)) + +#elif defined(JS_PUNBOX64) + +typedef uint32_t JSValueTag; +#define JSVAL_TAG_MAX_DOUBLE ((uint32_t)(0x1FFF0)) +#define JSVAL_TAG_INT32 (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32) +#define JSVAL_TAG_UNDEFINED (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED) +#define JSVAL_TAG_STRING (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING) +#define JSVAL_TAG_SYMBOL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL) +#define JSVAL_TAG_BOOLEAN (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN) +#define JSVAL_TAG_MAGIC (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC) +#define JSVAL_TAG_NULL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL) +#define JSVAL_TAG_OBJECT (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT) + +typedef uint64_t JSValueShiftedTag; +#define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF) +#define JSVAL_SHIFTED_TAG_INT32 (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT) +#define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT) +#define JSVAL_SHIFTED_TAG_STRING (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT) +#define JSVAL_SHIFTED_TAG_SYMBOL (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT) +#define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT) +#define JSVAL_SHIFTED_TAG_MAGIC (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT) +#define JSVAL_SHIFTED_TAG_NULL (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT) +#define JSVAL_SHIFTED_TAG_OBJECT (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT) + +#endif /* JS_PUNBOX64 */ +#endif /* !defined(__SUNPRO_CC) && !defined(__xlC__) */ + +#if defined(JS_NUNBOX32) + +#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type))) + +#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL +#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT +#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32 +#define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING + +#elif defined(JS_PUNBOX64) + +#define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL +#define JSVAL_TAG_MASK 0xFFFF800000000000LL +#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type))) +#define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64_t)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT) + +#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL +#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT +#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32 +#define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING + +#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET JSVAL_SHIFTED_TAG_NULL +#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET JSVAL_SHIFTED_TAG_OBJECT +#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET JSVAL_SHIFTED_TAG_UNDEFINED +#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET JSVAL_SHIFTED_TAG_STRING + +#endif /* JS_PUNBOX64 */ + +typedef enum JSWhyMagic +{ + /** a hole in a native object's elements */ + JS_ELEMENTS_HOLE, + + /** there is not a pending iterator value */ + JS_NO_ITER_VALUE, + + /** exception value thrown when closing a generator */ + JS_GENERATOR_CLOSING, + + /** compiler sentinel value */ + JS_NO_CONSTANT, + + /** used in debug builds to catch tracing errors */ + JS_THIS_POISON, + + /** used in debug builds to catch tracing errors */ + JS_ARG_POISON, + + /** an empty subnode in the AST serializer */ + JS_SERIALIZE_NO_NODE, + + /** lazy arguments value on the stack */ + JS_LAZY_ARGUMENTS, + + /** optimized-away 'arguments' value */ + JS_OPTIMIZED_ARGUMENTS, + + /** magic value passed to natives to indicate construction */ + JS_IS_CONSTRUCTING, + + /** arguments.callee has been overwritten */ + JS_OVERWRITTEN_CALLEE, + + /** value of static block object slot */ + JS_BLOCK_NEEDS_CLONE, + + /** see class js::HashableValue */ + JS_HASH_KEY_EMPTY, + + /** error while running Ion code */ + JS_ION_ERROR, + + /** missing recover instruction result */ + JS_ION_BAILOUT, + + /** optimized out slot */ + JS_OPTIMIZED_OUT, + + /** uninitialized lexical bindings that produce ReferenceError on touch. */ + JS_UNINITIALIZED_LEXICAL, + + /** for local use */ + JS_GENERIC_MAGIC, + + JS_WHY_MAGIC_COUNT +} JSWhyMagic; + +#if defined(IS_LITTLE_ENDIAN) +# if defined(JS_NUNBOX32) +typedef union jsval_layout +{ + uint64_t asBits; + struct { + union { + int32_t i32; + uint32_t u32; + uint32_t boo; // Don't use |bool| -- it must be four bytes. + JSString* str; + JS::Symbol* sym; + JSObject* obj; + js::gc::Cell* cell; + void* ptr; + JSWhyMagic why; + size_t word; + uintptr_t uintptr; + } payload; + JSValueTag tag; + } s; + double asDouble; + void* asPtr; +} JSVAL_ALIGNMENT jsval_layout; +# elif defined(JS_PUNBOX64) +typedef union jsval_layout +{ + uint64_t asBits; +#if !defined(_WIN64) + /* MSVC does not pack these correctly :-( */ + struct { + uint64_t payload47 : 47; + JSValueTag tag : 17; + } debugView; +#endif + struct { + union { + int32_t i32; + uint32_t u32; + JSWhyMagic why; + } payload; + } s; + double asDouble; + void* asPtr; + size_t asWord; + uintptr_t asUIntPtr; +} JSVAL_ALIGNMENT jsval_layout; +# endif /* JS_PUNBOX64 */ +#else /* defined(IS_LITTLE_ENDIAN) */ +# if defined(JS_NUNBOX32) +typedef union jsval_layout +{ + uint64_t asBits; + struct { + JSValueTag tag; + union { + int32_t i32; + uint32_t u32; + uint32_t boo; // Don't use |bool| -- it must be four bytes. + JSString* str; + JS::Symbol* sym; + JSObject* obj; + js::gc::Cell* cell; + void* ptr; + JSWhyMagic why; + size_t word; + uintptr_t uintptr; + } payload; + } s; + double asDouble; + void* asPtr; +} JSVAL_ALIGNMENT jsval_layout; +# elif defined(JS_PUNBOX64) +typedef union jsval_layout +{ + uint64_t asBits; + struct { + JSValueTag tag : 17; + uint64_t payload47 : 47; + } debugView; + struct { + uint32_t padding; + union { + int32_t i32; + uint32_t u32; + JSWhyMagic why; + } payload; + } s; + double asDouble; + void* asPtr; + size_t asWord; + uintptr_t asUIntPtr; +} JSVAL_ALIGNMENT jsval_layout; +# endif /* JS_PUNBOX64 */ +#endif /* defined(IS_LITTLE_ENDIAN) */ + +/* + * For codesize purposes on some platforms, it's important that the + * compiler know that JS::Values constructed from constant values can be + * folded to constant bit patterns at compile time, rather than + * constructed at runtime. Doing this requires a fair amount of C++11 + * features, which are not supported on all of our compilers. Set up + * some defines and helper macros in an attempt to confine the ugliness + * here, rather than scattering it all about the file. The important + * features are: + * + * - constexpr; + * - defaulted functions; + * - C99-style designated initializers. + */ +#if defined(__clang__) +# if __has_feature(cxx_constexpr) && __has_feature(cxx_defaulted_functions) +# define JS_VALUE_IS_CONSTEXPR +# endif +#elif defined(__GNUC__) +/* + * We need 4.5 for defaulted functions, 4.6 for constexpr, 4.7 because 4.6 + * doesn't understand |(X) { .field = ... }| syntax, and 4.7.3 because + * versions prior to that have bugs in the C++ front-end that cause crashes. + */ +# if MOZ_GCC_VERSION_AT_LEAST(4, 7, 3) +# define JS_VALUE_IS_CONSTEXPR +# endif +#endif + +#if defined(JS_VALUE_IS_CONSTEXPR) +# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \ + return (jsval_layout) { .asBits = (BITS) } +# define JS_VALUE_CONSTEXPR MOZ_CONSTEXPR +# define JS_VALUE_CONSTEXPR_VAR MOZ_CONSTEXPR_VAR +#else +# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \ + jsval_layout l; \ + l.asBits = (BITS); \ + return l; +# define JS_VALUE_CONSTEXPR +# define JS_VALUE_CONSTEXPR_VAR const +#endif + +struct Value { + jsval_layout data; +}; diff --git a/libbindgen/tests/headers/keywords.h b/libbindgen/tests/headers/keywords.h new file mode 100644 index 00000000..8699ce5f --- /dev/null +++ b/libbindgen/tests/headers/keywords.h @@ -0,0 +1,49 @@ +int u8; +int u16; +int u32; +int u64; +int i8; +int i16; +int i32; +int i64; +int f32; +int f64; +int usize; +int isize; +int as; +int box; +int crate; +int false; +int fn; +int impl; +int in; +int let; +int loop; +int match; +int mod; +int move; +int mut; +int pub; +int ref; +int self; +int Self; +int super; +int trait; +int true; +int type; +int unsafe; +int use; +int where; +int abstract; +int alignof; +int become; +int final; +int macro; +int offsetof; +int override; +int priv; +int proc; +int pure; +int unsized; +int virtual; +int yield; diff --git a/libbindgen/tests/headers/macro-expr-basic.h b/libbindgen/tests/headers/macro-expr-basic.h new file mode 100644 index 00000000..d2de7fdf --- /dev/null +++ b/libbindgen/tests/headers/macro-expr-basic.h @@ -0,0 +1,14 @@ +#define FOO 1 +#define BAR 4 +#define BAZ (FOO + BAR) + +#define MIN (1 << 63) + +#define BARR (1 << 0) +#define BAZZ ((1 << 1) + BAZ) +#define I_RAN_OUT_OF_DUMB_NAMES (BARR | BAZZ) + +/* I haz a comment */ +#define HAZ_A_COMMENT BARR + +#define HAZ_A_COMMENT_INSIDE (/* comment for real */ BARR + FOO) diff --git a/libbindgen/tests/headers/macro-redef.h b/libbindgen/tests/headers/macro-redef.h new file mode 100644 index 00000000..0180d2ab --- /dev/null +++ b/libbindgen/tests/headers/macro-redef.h @@ -0,0 +1,5 @@ +#define FOO 4 +#define BAR (1 + FOO) +#undef FOO +#define FOO 5 +#define BAZ (1 + FOO) diff --git a/libbindgen/tests/headers/multiple-inherit-empty-correct-layout.hpp b/libbindgen/tests/headers/multiple-inherit-empty-correct-layout.hpp new file mode 100644 index 00000000..1e2b133a --- /dev/null +++ b/libbindgen/tests/headers/multiple-inherit-empty-correct-layout.hpp @@ -0,0 +1,3 @@ +struct Foo {}; +struct Bar {}; +struct Baz : public Foo, public Bar {}; diff --git a/libbindgen/tests/headers/mutable.hpp b/libbindgen/tests/headers/mutable.hpp new file mode 100644 index 00000000..b61a1031 --- /dev/null +++ b/libbindgen/tests/headers/mutable.hpp @@ -0,0 +1,14 @@ +class C { + mutable int m_member; + int m_other; +}; + +class NonCopiable { + mutable int m_member; + + ~NonCopiable() {}; +}; + +class NonCopiableWithNonCopiableMutableMember { + mutable NonCopiable m_member; +}; diff --git a/libbindgen/tests/headers/namespace.hpp b/libbindgen/tests/headers/namespace.hpp new file mode 100644 index 00000000..65788539 --- /dev/null +++ b/libbindgen/tests/headers/namespace.hpp @@ -0,0 +1,47 @@ +// bindgen-flags: --enable-cxx-namespaces + +void top_level(); + +namespace whatever { + typedef int whatever_int_t; + + void in_whatever(); +} + +namespace { + namespace empty {} + + void foo(); + struct A { + whatever::whatever_int_t b; + public: + int lets_hope_this_works(); + }; +} + +template +class C: public A { + T m_c; + T* m_c_ptr; + T m_c_arr[10]; +}; + + +template<> +class C; + + +namespace w { + typedef unsigned int whatever_int_t; + + template + class D { + C m_c; + }; + + whatever_int_t heh(); // this should return w::whatever_int_t, and not whatever::whatever_int_t + + C foo(); + + C barr(); // <- This is the problematic one +} diff --git a/libbindgen/tests/headers/nested.hpp b/libbindgen/tests/headers/nested.hpp new file mode 100644 index 00000000..299e1768 --- /dev/null +++ b/libbindgen/tests/headers/nested.hpp @@ -0,0 +1,15 @@ + +class Calc { + int w; +}; + +class Test { +public: + struct Size; + friend struct Size; + struct Size { + struct Dimension : public Calc { + }; + Dimension mWidth, mHeight; + }; +}; diff --git a/libbindgen/tests/headers/nested_vtable.hpp b/libbindgen/tests/headers/nested_vtable.hpp new file mode 100644 index 00000000..87d6ce1f --- /dev/null +++ b/libbindgen/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/libbindgen/tests/headers/no-std.h b/libbindgen/tests/headers/no-std.h new file mode 100644 index 00000000..7bee9657 --- /dev/null +++ b/libbindgen/tests/headers/no-std.h @@ -0,0 +1,5 @@ +// bindgen-flags: --ctypes-prefix "libc" --use-core --raw-line "#![no_std]" --raw-line "mod libc { pub type c_int = i32; pub enum c_void {} }" +struct foo { + int a, b; + void* bar; +}; diff --git a/libbindgen/tests/headers/no_copy.hpp b/libbindgen/tests/headers/no_copy.hpp new file mode 100644 index 00000000..349e428e --- /dev/null +++ b/libbindgen/tests/headers/no_copy.hpp @@ -0,0 +1,6 @@ + +/**
*/ +template +class CopiableButWait { + int whatever; +}; diff --git a/libbindgen/tests/headers/nsStyleAutoArray.hpp b/libbindgen/tests/headers/nsStyleAutoArray.hpp new file mode 100644 index 00000000..950152c0 --- /dev/null +++ b/libbindgen/tests/headers/nsStyleAutoArray.hpp @@ -0,0 +1,57 @@ + +template +class nsTArray { + T* mBuff; +}; + +template +class nsStyleAutoArray +{ +public: + // This constructor places a single element in mFirstElement. + enum WithSingleInitialElement { WITH_SINGLE_INITIAL_ELEMENT }; + explicit nsStyleAutoArray(WithSingleInitialElement) {} + nsStyleAutoArray(const nsStyleAutoArray& aOther) { *this = aOther; } + nsStyleAutoArray& operator=(const nsStyleAutoArray& aOther) { + mFirstElement = aOther.mFirstElement; + mOtherElements = aOther.mOtherElements; + return *this; + } + + bool operator==(const nsStyleAutoArray& aOther) const { + return Length() == aOther.Length() && + mFirstElement == aOther.mFirstElement && + mOtherElements == aOther.mOtherElements; + } + bool operator!=(const nsStyleAutoArray& aOther) const { + return !(*this == aOther); + } + + unsigned long Length() const { + return mOtherElements.Length() + 1; + } + const T& operator[](unsigned long aIndex) const { + return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1]; + } + T& operator[](unsigned long aIndex) { + return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1]; + } + + void EnsureLengthAtLeast(unsigned long aMinLen) { + if (aMinLen > 0) { + mOtherElements.EnsureLengthAtLeast(aMinLen - 1); + } + } + + void SetLengthNonZero(unsigned long aNewLen) { + mOtherElements.SetLength(aNewLen - 1); + } + + void TruncateLengthNonZero(unsigned long aNewLen) { + mOtherElements.TruncateLength(aNewLen - 1); + } + +private: + T mFirstElement; + nsTArray mOtherElements; +}; diff --git a/libbindgen/tests/headers/only_bitfields.hpp b/libbindgen/tests/headers/only_bitfields.hpp new file mode 100644 index 00000000..84db0586 --- /dev/null +++ b/libbindgen/tests/headers/only_bitfields.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --no-unstable-rust +class C { + bool a: 1; + bool b: 7; +}; diff --git a/libbindgen/tests/headers/opaque_in_struct.hpp b/libbindgen/tests/headers/opaque_in_struct.hpp new file mode 100644 index 00000000..3cffeb20 --- /dev/null +++ b/libbindgen/tests/headers/opaque_in_struct.hpp @@ -0,0 +1,10 @@ + + +/**
*/ +typedef struct opaque { + int waht; +} opaque; + +struct container { + opaque contained; +}; diff --git a/libbindgen/tests/headers/opaque_pointer.hpp b/libbindgen/tests/headers/opaque_pointer.hpp new file mode 100644 index 00000000..53f8ce1f --- /dev/null +++ b/libbindgen/tests/headers/opaque_pointer.hpp @@ -0,0 +1,22 @@ + +/** + *
+ */ +struct OtherOpaque { + int c; +}; + +/** + *
+ */ +template +struct Opaque { + T whatever; +}; + +struct WithOpaquePtr { + Opaque* whatever; + Opaque other; + OtherOpaque t; +}; + diff --git a/libbindgen/tests/headers/opaque_typedef.hpp b/libbindgen/tests/headers/opaque_typedef.hpp new file mode 100644 index 00000000..25640738 --- /dev/null +++ b/libbindgen/tests/headers/opaque_typedef.hpp @@ -0,0 +1,17 @@ +// bindgen-flags: -- -std=c++11 +template +class RandomTemplate; + +template +class Wat; + +template +class Wat3; + +template<> +class Wat3<3>; + +/**
*/ +typedef RandomTemplate ShouldBeOpaque; + +typedef RandomTemplate ShouldNotBeOpaque; diff --git a/libbindgen/tests/headers/overflowed_enum.hpp b/libbindgen/tests/headers/overflowed_enum.hpp new file mode 100644 index 00000000..1f2075a5 --- /dev/null +++ b/libbindgen/tests/headers/overflowed_enum.hpp @@ -0,0 +1,12 @@ +// bindgen-flags: -- -std=c++11 -Wno-narrowing + +enum Foo { + BAP_ARM = 0x93fcb9, + BAP_X86 = 0xb67eed, + BAP_X86_64 = 0xba7b274f, +}; + +enum Bar: unsigned short { + One = 1, + Big = 65538, +}; diff --git a/libbindgen/tests/headers/overloading.hpp b/libbindgen/tests/headers/overloading.hpp new file mode 100644 index 00000000..3c2b0487 --- /dev/null +++ b/libbindgen/tests/headers/overloading.hpp @@ -0,0 +1,9 @@ +extern bool Evaluate(char r); +extern bool Evaluate(int x, int y); + +namespace foo { + extern void MyFunction(); +} +namespace bar { + extern void MyFunction(); +} diff --git a/libbindgen/tests/headers/private.hpp b/libbindgen/tests/headers/private.hpp new file mode 100644 index 00000000..c0f3ce7f --- /dev/null +++ b/libbindgen/tests/headers/private.hpp @@ -0,0 +1,21 @@ + +struct HasPrivate { + int mNotPrivate; + /**
*/ + int mIsPrivate; +}; + + +/**
*/ +struct VeryPrivate { + int mIsPrivate; + int mIsAlsoPrivate; +}; + + +/**
*/ +struct ContradictPrivate { + /**
*/ + int mNotPrivate; + int mIsPrivate; +}; diff --git a/libbindgen/tests/headers/redeclaration.hpp b/libbindgen/tests/headers/redeclaration.hpp new file mode 100644 index 00000000..d536b158 --- /dev/null +++ b/libbindgen/tests/headers/redeclaration.hpp @@ -0,0 +1,7 @@ +extern "C" { + void foo(); +} + +extern "C" { + void foo(); +} diff --git a/libbindgen/tests/headers/ref_argument_array.hpp b/libbindgen/tests/headers/ref_argument_array.hpp new file mode 100644 index 00000000..dc73fd62 --- /dev/null +++ b/libbindgen/tests/headers/ref_argument_array.hpp @@ -0,0 +1,6 @@ + +#define NSID_LENGTH 10 +class nsID { +public: + virtual void ToProvidedString(char (&aDest)[NSID_LENGTH]) = 0; +}; diff --git a/libbindgen/tests/headers/replace_template_alias.hpp b/libbindgen/tests/headers/replace_template_alias.hpp new file mode 100644 index 00000000..6ceae4e5 --- /dev/null +++ b/libbindgen/tests/headers/replace_template_alias.hpp @@ -0,0 +1,23 @@ +// bindgen-flags: -- --std=c++14 + +namespace JS { +namespace detail { + +/// Notice how this doesn't use T. +template +using MaybeWrapped = int; + +} + +template +class Rooted { + detail::MaybeWrapped ptr; +}; + +} + +/// But the replacement type does use T! +/// +///
+template +using replaces_MaybeWrapped = T; diff --git a/libbindgen/tests/headers/replaces_double.hpp b/libbindgen/tests/headers/replaces_double.hpp new file mode 100644 index 00000000..1a78b0d9 --- /dev/null +++ b/libbindgen/tests/headers/replaces_double.hpp @@ -0,0 +1,20 @@ +// bindgen-flags: --blacklist-type Wrapper -- --std=c++11 + +template +struct Wrapper { + struct Wrapped { + T t; + }; + using Type = Wrapped; +}; + +template +class Rooted { + using MaybeWrapped = typename Wrapper::Type; + MaybeWrapped ptr; + + /** + *
+ */ + using MaybeWrapped_simple = T; +}; diff --git a/libbindgen/tests/headers/size_t_template.hpp b/libbindgen/tests/headers/size_t_template.hpp new file mode 100644 index 00000000..6045c698 --- /dev/null +++ b/libbindgen/tests/headers/size_t_template.hpp @@ -0,0 +1,8 @@ +template +class Array { + T inner[N]; +}; + +class C { + Array arr; +}; diff --git a/libbindgen/tests/headers/struct_containing_forward_declared_struct.h b/libbindgen/tests/headers/struct_containing_forward_declared_struct.h new file mode 100644 index 00000000..d38aca2f --- /dev/null +++ b/libbindgen/tests/headers/struct_containing_forward_declared_struct.h @@ -0,0 +1,7 @@ +struct a { + struct b* val_a; +}; + +struct b { + int val_b; +}; diff --git a/libbindgen/tests/headers/struct_with_anon_struct.h b/libbindgen/tests/headers/struct_with_anon_struct.h new file mode 100644 index 00000000..1617d7a8 --- /dev/null +++ b/libbindgen/tests/headers/struct_with_anon_struct.h @@ -0,0 +1,6 @@ +struct foo { + struct { + int a; + int b; + } bar; +}; diff --git a/libbindgen/tests/headers/struct_with_anon_struct_array.h b/libbindgen/tests/headers/struct_with_anon_struct_array.h new file mode 100644 index 00000000..9ea977e8 --- /dev/null +++ b/libbindgen/tests/headers/struct_with_anon_struct_array.h @@ -0,0 +1,10 @@ +struct foo { + struct { + int a; + int b; + } bar[2]; + struct { + int a; + int b; + } baz[2][3][4]; +}; diff --git a/libbindgen/tests/headers/struct_with_anon_struct_pointer.h b/libbindgen/tests/headers/struct_with_anon_struct_pointer.h new file mode 100644 index 00000000..0c486d84 --- /dev/null +++ b/libbindgen/tests/headers/struct_with_anon_struct_pointer.h @@ -0,0 +1,6 @@ +struct foo { + struct { + int a; + int b; + } *bar; +}; diff --git a/libbindgen/tests/headers/struct_with_anon_union.h b/libbindgen/tests/headers/struct_with_anon_union.h new file mode 100644 index 00000000..3a92b940 --- /dev/null +++ b/libbindgen/tests/headers/struct_with_anon_union.h @@ -0,0 +1,6 @@ +struct foo { + union { + unsigned int a; + unsigned short b; + } bar; +}; diff --git a/libbindgen/tests/headers/struct_with_anon_unnamed_struct.h b/libbindgen/tests/headers/struct_with_anon_unnamed_struct.h new file mode 100644 index 00000000..f8ac4225 --- /dev/null +++ b/libbindgen/tests/headers/struct_with_anon_unnamed_struct.h @@ -0,0 +1,6 @@ +struct foo { + struct { + unsigned int a; + unsigned int b; + }; +}; diff --git a/libbindgen/tests/headers/struct_with_anon_unnamed_union.h b/libbindgen/tests/headers/struct_with_anon_unnamed_union.h new file mode 100644 index 00000000..7158e727 --- /dev/null +++ b/libbindgen/tests/headers/struct_with_anon_unnamed_union.h @@ -0,0 +1,6 @@ +struct foo { + union { + unsigned int a; + unsigned short b; + }; +}; diff --git a/libbindgen/tests/headers/struct_with_bitfields.h b/libbindgen/tests/headers/struct_with_bitfields.h new file mode 100644 index 00000000..107fb136 --- /dev/null +++ b/libbindgen/tests/headers/struct_with_bitfields.h @@ -0,0 +1,13 @@ +// bindgen-flags: --no-unstable-rust +struct bitfield { + unsigned short + a :1, + b :1, + c :1, + :1, + :2, + d :2; + int e; + unsigned int f : 2; + unsigned int g : 32; +}; diff --git a/libbindgen/tests/headers/struct_with_derive_debug.h b/libbindgen/tests/headers/struct_with_derive_debug.h new file mode 100644 index 00000000..98ba1b3d --- /dev/null +++ b/libbindgen/tests/headers/struct_with_derive_debug.h @@ -0,0 +1,15 @@ +struct LittleArray { + int a[32]; +}; + +struct BigArray{ + int a[33]; +}; + +struct WithLittleArray { + struct LittleArray a; +}; + +struct WithBigArray { + struct BigArray a; +}; diff --git a/libbindgen/tests/headers/struct_with_nesting.h b/libbindgen/tests/headers/struct_with_nesting.h new file mode 100644 index 00000000..9d7fa176 --- /dev/null +++ b/libbindgen/tests/headers/struct_with_nesting.h @@ -0,0 +1,17 @@ +struct foo { + unsigned int a; + union { + unsigned int b; + struct { + unsigned short c1; + unsigned short c2; + }; + + struct { + unsigned char d1; + unsigned char d2; + unsigned char d3; + unsigned char d4; + }; + }; +}; diff --git a/libbindgen/tests/headers/struct_with_packing.h b/libbindgen/tests/headers/struct_with_packing.h new file mode 100644 index 00000000..1b9fe131 --- /dev/null +++ b/libbindgen/tests/headers/struct_with_packing.h @@ -0,0 +1,4 @@ +struct a { + char b; + short c; +} __attribute__((packed)); diff --git a/libbindgen/tests/headers/struct_with_struct.h b/libbindgen/tests/headers/struct_with_struct.h new file mode 100644 index 00000000..78b1cc81 --- /dev/null +++ b/libbindgen/tests/headers/struct_with_struct.h @@ -0,0 +1,6 @@ +struct foo { + struct { + unsigned int x; + unsigned int y; + } bar; +}; diff --git a/libbindgen/tests/headers/struct_with_typedef_template_arg.hpp b/libbindgen/tests/headers/struct_with_typedef_template_arg.hpp new file mode 100644 index 00000000..7fed21ab --- /dev/null +++ b/libbindgen/tests/headers/struct_with_typedef_template_arg.hpp @@ -0,0 +1,4 @@ +template +struct Proxy { + typedef void (*foo)(T* bar); +}; diff --git a/libbindgen/tests/headers/template.hpp b/libbindgen/tests/headers/template.hpp new file mode 100644 index 00000000..c13643c3 --- /dev/null +++ b/libbindgen/tests/headers/template.hpp @@ -0,0 +1,144 @@ +template class Foo { + T m_member; + T* m_member_ptr; + T m_member_arr[1]; +}; + +void bar(Foo foo); + +template +class D { + typedef Foo MyFoo; + + MyFoo m_foo; + + template + class U { + MyFoo m_nested_foo; + Z m_baz; + }; +}; + +template +class Rooted { + T* prev; + Rooted* next; + T ptr; +}; + +class RootedContainer { + Rooted root; +}; + +template +class WithDtor; + +typedef WithDtor WithDtorIntFwd; + +template +class WithDtor { + T member; + ~WithDtor() {} +}; + +class PODButContainsDtor { + WithDtorIntFwd member; +}; + + +/**
*/ +template +class Opaque { + T member; +}; + +class POD { + Opaque opaque_member; +}; + +/** + *
+ */ +template +class Nested { + T* buff; +}; + +template +class NestedBase { + T* buff; +}; + +template +class NestedReplaced: public NestedBase { +}; + +template +class Incomplete; + +template +class NestedContainer { + T c; +private: + NestedReplaced nested; + Incomplete inc; +}; + +template +class Incomplete { + T d; +}; + +class Untemplated {}; + +template +class Templated { + Untemplated m_untemplated; +}; + +/** + * 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. + * + *
+ */ +template +class ReplacedWithDestructor { + T* buff; + ~ReplacedWithDestructor() {}; +}; + +template +class ReplacedWithoutDestructor { + T* buff; +}; + +template +class ReplacedWithoutDestructorFwd; + +template +class ShouldNotBeCopiable { + ReplacedWithoutDestructor m_member; +}; + +template +class ShouldNotBeCopiableAsWell { + ReplacedWithoutDestructorFwd m_member; +}; + +/** + * 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. + * + *
+ */ +template +class ReplacedWithDestructorDeclaredAfter { + T* buff; + ~ReplacedWithDestructorDeclaredAfter() {}; +}; + +template +class TemplateWithVar { + static T var = 0; +}; diff --git a/libbindgen/tests/headers/template_alias.hpp b/libbindgen/tests/headers/template_alias.hpp new file mode 100644 index 00000000..646d9f40 --- /dev/null +++ b/libbindgen/tests/headers/template_alias.hpp @@ -0,0 +1,13 @@ +// bindgen-flags: -- -std=c++14 + +namespace JS { +namespace detail { + template + using Wrapped = T; +} + +template +struct Rooted { + detail::Wrapped ptr; +}; +} diff --git a/libbindgen/tests/headers/template_alias_basic.hpp b/libbindgen/tests/headers/template_alias_basic.hpp new file mode 100644 index 00000000..964f6e27 --- /dev/null +++ b/libbindgen/tests/headers/template_alias_basic.hpp @@ -0,0 +1,4 @@ +// bindgen-flags: -- -std=c++11 + +template +using Wrapped = T; diff --git a/libbindgen/tests/headers/template_alias_namespace.hpp b/libbindgen/tests/headers/template_alias_namespace.hpp new file mode 100644 index 00000000..bd637166 --- /dev/null +++ b/libbindgen/tests/headers/template_alias_namespace.hpp @@ -0,0 +1,13 @@ +// bindgen-flags: --enable-cxx-namespaces -- -std=c++14 + +namespace JS { +namespace detail { + template + using Wrapped = T; +} + +template +struct Rooted { + detail::Wrapped ptr; +}; +} diff --git a/libbindgen/tests/headers/template_typedef_transitive_param.hpp b/libbindgen/tests/headers/template_typedef_transitive_param.hpp new file mode 100644 index 00000000..2269ac36 --- /dev/null +++ b/libbindgen/tests/headers/template_typedef_transitive_param.hpp @@ -0,0 +1,7 @@ +template +struct Wrapper { + struct Wrapped { + T t; + }; + using Type = Wrapped; +}; diff --git a/libbindgen/tests/headers/template_typedefs.hpp b/libbindgen/tests/headers/template_typedefs.hpp new file mode 100644 index 00000000..5e13dcd8 --- /dev/null +++ b/libbindgen/tests/headers/template_typedefs.hpp @@ -0,0 +1,8 @@ +typedef void (*foo)(int); + +template +class Foo { + typedef T Char; + typedef Char* FooPtrTypedef; + typedef bool (*nsCOMArrayEnumFunc)(T* aElement, void* aData); +}; diff --git a/libbindgen/tests/headers/type_alias_empty.hpp b/libbindgen/tests/headers/type_alias_empty.hpp new file mode 100644 index 00000000..f0760c8f --- /dev/null +++ b/libbindgen/tests/headers/type_alias_empty.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --whitelist-type bool_constant -- -std=c++11 + +// NB: The --whitelist-type is done to trigger the traversal of the types on +// codegen in order to trigger #67. + +template +struct integral_constant {}; + +template +using bool_constant = integral_constant; diff --git a/libbindgen/tests/headers/typeref.hpp b/libbindgen/tests/headers/typeref.hpp new file mode 100644 index 00000000..b94c98ef --- /dev/null +++ b/libbindgen/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 +struct StyleShapeSource { + union { + Position* mPosition; + FragmentOrURL* mFragmentOrURL; + }; +}; + +} // namespace mozilla + +struct nsFoo { + mozilla::StyleShapeSource mBar; +}; diff --git a/libbindgen/tests/headers/union_dtor.hpp b/libbindgen/tests/headers/union_dtor.hpp new file mode 100644 index 00000000..399dc89d --- /dev/null +++ b/libbindgen/tests/headers/union_dtor.hpp @@ -0,0 +1,5 @@ +union UnionWithDtor { + ~UnionWithDtor(); + int mFoo; + void* mBar; +}; diff --git a/libbindgen/tests/headers/union_fields.hpp b/libbindgen/tests/headers/union_fields.hpp new file mode 100644 index 00000000..aec3a7fd --- /dev/null +++ b/libbindgen/tests/headers/union_fields.hpp @@ -0,0 +1,5 @@ +typedef union { + int mInt; + float mFloat; + void* mPointer; +} nsStyleUnion; diff --git a/libbindgen/tests/headers/union_template.hpp b/libbindgen/tests/headers/union_template.hpp new file mode 100644 index 00000000..0d0a9bb3 --- /dev/null +++ b/libbindgen/tests/headers/union_template.hpp @@ -0,0 +1,19 @@ +template +struct NastyStruct { + bool mIsSome; + union { + void* mFoo; + unsigned long mDummy; + } mStorage; + + union { + short wat; + int* wut; + }; +}; + +template +union Whatever { + void* mTPtr; + int mInt; +}; diff --git a/libbindgen/tests/headers/union_with_anon_struct.h b/libbindgen/tests/headers/union_with_anon_struct.h new file mode 100644 index 00000000..7f8dec95 --- /dev/null +++ b/libbindgen/tests/headers/union_with_anon_struct.h @@ -0,0 +1,6 @@ +union foo { + struct { + unsigned int a; + unsigned int b; + } bar; +}; diff --git a/libbindgen/tests/headers/union_with_anon_struct_bitfield.h b/libbindgen/tests/headers/union_with_anon_struct_bitfield.h new file mode 100644 index 00000000..24c7dce8 --- /dev/null +++ b/libbindgen/tests/headers/union_with_anon_struct_bitfield.h @@ -0,0 +1,8 @@ +// bindgen-flags: --no-unstable-rust +union foo { + int a; + struct { + int b : 7; + int c : 25; + }; +}; diff --git a/libbindgen/tests/headers/union_with_anon_union.h b/libbindgen/tests/headers/union_with_anon_union.h new file mode 100644 index 00000000..212431b8 --- /dev/null +++ b/libbindgen/tests/headers/union_with_anon_union.h @@ -0,0 +1,6 @@ +union foo { + union { + unsigned int a; + unsigned short b; + } bar; +}; diff --git a/libbindgen/tests/headers/union_with_anon_unnamed_struct.h b/libbindgen/tests/headers/union_with_anon_unnamed_struct.h new file mode 100644 index 00000000..79558049 --- /dev/null +++ b/libbindgen/tests/headers/union_with_anon_unnamed_struct.h @@ -0,0 +1,9 @@ +union pixel { + unsigned int rgba; + struct { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + }; +}; diff --git a/libbindgen/tests/headers/union_with_anon_unnamed_union.h b/libbindgen/tests/headers/union_with_anon_unnamed_union.h new file mode 100644 index 00000000..7580771a --- /dev/null +++ b/libbindgen/tests/headers/union_with_anon_unnamed_union.h @@ -0,0 +1,7 @@ +union foo { + unsigned int a; + union { + unsigned short b; + unsigned char c; + }; +}; diff --git a/libbindgen/tests/headers/union_with_big_member.h b/libbindgen/tests/headers/union_with_big_member.h new file mode 100644 index 00000000..6347d6ca --- /dev/null +++ b/libbindgen/tests/headers/union_with_big_member.h @@ -0,0 +1,14 @@ +union WithBigArray { + int a; + int b[33]; +}; + +union WithBigArray2 { + int a; + char b[33]; +}; + +union WithBigMember { + int a; + union WithBigArray b; +}; diff --git a/libbindgen/tests/headers/union_with_nesting.h b/libbindgen/tests/headers/union_with_nesting.h new file mode 100644 index 00000000..cd907d57 --- /dev/null +++ b/libbindgen/tests/headers/union_with_nesting.h @@ -0,0 +1,14 @@ +union foo { + unsigned int a; + struct { + union { + unsigned short b1; + unsigned short b2; + }; + + union { + unsigned short c1; + unsigned short c2; + }; + }; +}; diff --git a/libbindgen/tests/headers/unknown_attr.h b/libbindgen/tests/headers/unknown_attr.h new file mode 100644 index 00000000..f87e9f0b --- /dev/null +++ b/libbindgen/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/libbindgen/tests/headers/use-core.h b/libbindgen/tests/headers/use-core.h new file mode 100644 index 00000000..42bb10d9 --- /dev/null +++ b/libbindgen/tests/headers/use-core.h @@ -0,0 +1,8 @@ +// bindgen-flags: --use-core --raw-line "extern crate core;" + +struct foo { + int a, b; + void* bar; +}; + +typedef void (*fooFunction)(int bar); diff --git a/libbindgen/tests/headers/using.hpp b/libbindgen/tests/headers/using.hpp new file mode 100644 index 00000000..ba07b9c8 --- /dev/null +++ b/libbindgen/tests/headers/using.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: -- -std=c++11 + +template +class Point { + T x; + T y; +}; + +typedef Point IntPoint2D; + +using IntVec2D = Point; diff --git a/libbindgen/tests/headers/vector.hpp b/libbindgen/tests/headers/vector.hpp new file mode 100644 index 00000000..4707f77f --- /dev/null +++ b/libbindgen/tests/headers/vector.hpp @@ -0,0 +1,3 @@ +struct foo { + __attribute__((__vector_size__(1 * sizeof(long long)))) long long mMember; +}; diff --git a/libbindgen/tests/headers/virtual_dtor.hpp b/libbindgen/tests/headers/virtual_dtor.hpp new file mode 100644 index 00000000..c35dcab1 --- /dev/null +++ b/libbindgen/tests/headers/virtual_dtor.hpp @@ -0,0 +1,3 @@ +struct nsSlots { + virtual ~nsSlots(); +}; diff --git a/libbindgen/tests/headers/virtual_overloaded.hpp b/libbindgen/tests/headers/virtual_overloaded.hpp new file mode 100644 index 00000000..8aea8a19 --- /dev/null +++ b/libbindgen/tests/headers/virtual_overloaded.hpp @@ -0,0 +1,5 @@ +class C { +public: + virtual void do_thing(char) { }; + virtual void do_thing(int) { }; +}; diff --git a/libbindgen/tests/headers/vtable_recursive_sig.hpp b/libbindgen/tests/headers/vtable_recursive_sig.hpp new file mode 100644 index 00000000..8729be00 --- /dev/null +++ b/libbindgen/tests/headers/vtable_recursive_sig.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: -- -std=c++11 + +class Derived; +class Base { +public: + virtual Derived* AsDerived() { return nullptr; } +}; + +class Derived final : public Base { + virtual Derived* AsDerived() override { return this; } +}; diff --git a/libbindgen/tests/headers/weird_bitfields.hpp b/libbindgen/tests/headers/weird_bitfields.hpp new file mode 100644 index 00000000..755681c1 --- /dev/null +++ b/libbindgen/tests/headers/weird_bitfields.hpp @@ -0,0 +1,35 @@ +// bindgen-flags: --no-unstable-rust +// You can guess where this is taken from... +enum nsStyleSVGOpacitySource { + eStyleSVGOpacitySource_Normal, + eStyleSVGOpacitySource_ContextFillOpacity, + eStyleSVGOpacitySource_ContextStrokeOpacity +}; + +class Weird { + unsigned int mStrokeDasharrayLength; + unsigned int bitTest: 16; + unsigned int bitTest2: 15; + unsigned char mClipRule; // [inherited] + unsigned char mColorInterpolation; // [inherited] see nsStyleConsts.h + unsigned char mColorInterpolationFilters; // [inherited] see nsStyleConsts.h + unsigned char mFillRule; // [inherited] see nsStyleConsts.h + unsigned char mImageRendering; // [inherited] see nsStyleConsts.h + unsigned char mPaintOrder; // [inherited] see nsStyleConsts.h + unsigned char mShapeRendering; // [inherited] see nsStyleConsts.h + unsigned char mStrokeLinecap; // [inherited] see nsStyleConsts.h + unsigned char mStrokeLinejoin; // [inherited] see nsStyleConsts.h + unsigned char mTextAnchor; // [inherited] see nsStyleConsts.h + unsigned char mTextRendering; // [inherited] see nsStyleConsts.h + + // In SVG glyphs, whether we inherit fill or stroke opacity from the outer + // text object. + // Use 3 bits to avoid signedness problems in MSVC. + nsStyleSVGOpacitySource mFillOpacitySource : 3; + nsStyleSVGOpacitySource mStrokeOpacitySource : 3; + + // SVG glyph outer object inheritance for other properties + bool mStrokeDasharrayFromObject : 1; + bool mStrokeDashoffsetFromObject : 1; + bool mStrokeWidthFromObject : 1; +}; diff --git a/libbindgen/tests/headers/what_is_going_on.hpp b/libbindgen/tests/headers/what_is_going_on.hpp new file mode 100644 index 00000000..078c1ad5 --- /dev/null +++ b/libbindgen/tests/headers/what_is_going_on.hpp @@ -0,0 +1,19 @@ + +struct UnknownUnits {}; +typedef float Float; + +template +struct PointTyped { + F x; + F y; + + static PointTyped FromUnknownPoint(const PointTyped& aPoint) { + return PointTyped(aPoint.x, aPoint.y); + } + + PointTyped ToUnknownPoint() const { + return PointTyped(this->x, this->y); + } +}; + +typedef PointTyped IntPoint; diff --git a/libbindgen/tests/headers/whitelist_basic.hpp b/libbindgen/tests/headers/whitelist_basic.hpp new file mode 100644 index 00000000..8424f75a --- /dev/null +++ b/libbindgen/tests/headers/whitelist_basic.hpp @@ -0,0 +1,16 @@ +// bindgen-flags: --whitelist-type WhitelistMe + +template +class WhitelistMe { + class Inner { + T bar; + }; + + int foo; + Inner bar; +}; + +struct DontWhitelistMe { + void* foo; + double _Complex noComplexGenerated; +}; diff --git a/libbindgen/tests/headers/whitelist_vars.h b/libbindgen/tests/headers/whitelist_vars.h new file mode 100644 index 00000000..07fa2815 --- /dev/null +++ b/libbindgen/tests/headers/whitelist_vars.h @@ -0,0 +1,4 @@ +#define NONE 0 +#define FOO 5 +#define FOOB -2 +#define FOOBAR (-10) diff --git a/libbindgen/tests/tests.rs b/libbindgen/tests/tests.rs new file mode 100644 index 00000000..c9826260 --- /dev/null +++ b/libbindgen/tests/tests.rs @@ -0,0 +1,138 @@ +extern crate clap; +extern crate diff; +#[macro_use] +extern crate env_logger; +extern crate libbindgen; +extern crate log; +extern crate shlex; + +use std::env; +use std::fs; +use std::io::{BufRead, BufReader, Error, ErrorKind, Read}; +use std::path::{Path, PathBuf}; + +#[path="../../src/options.rs"] +mod options; +use options::builder_from_flags; + +fn compare_generated_header(header: &PathBuf, + builder: libbindgen::Builder) + -> Result<(), Error> { + let file_name = try!(header.file_name() + .ok_or(Error::new(ErrorKind::Other, "spawn_bindgen expects a file"))); + + let mut expected = PathBuf::from(header); + expected.pop(); + expected.pop(); + expected.push("expectations"); + expected.push("tests"); + expected.push(file_name); + expected.set_extension("rs"); + + // We skip the generate() error here so we get a full diff below + let output = match builder.generate() { + Ok(bindings) => bindings.to_string(), + Err(_) => "".to_string(), + }; + + let mut buffer = String::new(); + let f = try!(fs::File::open(&expected)); + let _ = try!(BufReader::new(f).read_to_string(&mut buffer)); + + if output == buffer { + return Ok(()); + } + + println!("diff expected generated"); + println!("--- expected: {:?}", expected); + println!("+++ generated from: {:?}", header); + + for diff in diff::lines(&buffer, &output) { + match diff { + diff::Result::Left(l) => println!("-{}", l), + diff::Result::Both(l, _) => println!(" {}", l), + diff::Result::Right(r) => println!("+{}", r), + } + } + Err(Error::new(ErrorKind::Other, "Header and binding differ!")) +} + +fn create_bindgen_builder(header: &PathBuf) + -> Result { + let source = try!(fs::File::open(header)); + let reader = BufReader::new(source); + + // Scoop up bindgen-flags from test header + let line: String = try!(reader.lines().take(1).collect()); + let flags: Vec = if line.contains("bindgen-flags:") { + line.split("bindgen-flags:").last().and_then(shlex::split) + } else { + None + }.unwrap_or(Vec::with_capacity(2)); + + // Fool builder_from_flags() into believing it has real env::args_os... + // - add "bindgen" as executable name 0th element + // - add header filename as 1st element + // - prepend raw lines so they're in the right order for expected output + // - append the test header's bindgen flags + let header_str = try!(header.to_str() + .ok_or(Error::new(ErrorKind::Other, "Invalid header file name"))); + + let prepend = [ + "bindgen", + header_str, + "--raw-line", "", + "--raw-line", "#![allow(non_snake_case)]", + "--raw-line", "", + ]; + + let args = prepend.into_iter() + .map(ToString::to_string) + .chain(flags.into_iter()); + + builder_from_flags(args).map(|(builder, _)| builder.no_unstable_rust()) +} + +#[test] +fn run_bindgen_tests() { + 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 manifest_env = env::var("CARGO_MANIFEST_DIR") + .expect("CARGO_MANIFEST_DIR not set!"); + let manifest_dir = Path::new(&manifest_env); + let headers_dir = manifest_dir.join("tests").join("headers"); + + let entries = fs::read_dir(&headers_dir) + .expect("Couldn't read headers dir") + .map(|result| result.expect("Couldn't read header file")); + + let headers: Vec<_> = entries.filter_map(|entry| { + match entry.path().extension().and_then(|s| s.to_str()) { + Some("h") | Some("hpp") => Some(entry.path()), + _ => None, + } + }) + .collect(); + + let failures: Vec<_> = headers.iter() + .filter_map(|header| { + create_bindgen_builder(header) + .and_then(|builder| compare_generated_header(header, builder)) + .err() + }) + .collect(); + + let num_failures = failures.len(); + + if num_failures > 0 { + panic!("{} test{} failed!", + num_failures, + if num_failures > 1 {"s"} else {""}); + } +} diff --git a/libbindgen/tests/uses/.gitignore b/libbindgen/tests/uses/.gitignore new file mode 100644 index 00000000..40d7cb4c --- /dev/null +++ b/libbindgen/tests/uses/.gitignore @@ -0,0 +1,2 @@ +*.c +*.cpp diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs deleted file mode 100755 index 14e882bc..00000000 --- a/src/bin/bindgen.rs +++ /dev/null @@ -1,87 +0,0 @@ -#![crate_name = "bindgen"] -#![crate_type = "bin"] - -extern crate bindgen; -extern crate env_logger; -#[macro_use] -extern crate log; -extern crate clang_sys; -extern crate clap; -extern crate rustc_serialize; - -use bindgen::clang_version; -use std::env; - -mod options; -use options::builder_from_flags; - -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(); - - let version = clang_version(); - let expected_version = if cfg!(feature = "llvm_stable") { - (3, 8) - } else { - (3, 9) - }; - - info!("Clang Version: {}", version.full); - - match version.parsed { - None => warn!("Couldn't parse libclang version"), - Some(version) if version != expected_version => { - error!("Using clang {:?}, expected {:?}", - version, - expected_version); - } - _ => {} - } - - if let Some(clang) = clang_sys::support::Clang::find(None) { - let has_clang_args = - bind_args.iter().rposition(|arg| *arg == "--").is_some(); - if !has_clang_args { - bind_args.push("--".to_owned()); - } - - // If --target is specified, assume caller knows what they're doing and - // don't mess with - // include paths for them - let has_target_arg = bind_args.iter() - .rposition(|arg| arg.starts_with("--target")) - .is_some(); - if !has_target_arg { - // TODO: distinguish C and C++ paths? C++'s should be enough, I - // guess. - for path in clang.cpp_search_paths.into_iter() { - if let Ok(path) = path.into_os_string().into_string() { - bind_args.push("-isystem".to_owned()); - bind_args.push(path); - } - } - } - } - - match builder_from_flags(bind_args.into_iter()) { - Ok((builder, output)) => { - let mut bindings = builder.generate() - .expect("Unable to generate bindings"); - bindings.write(output) - .expect("Unable to write output"); - bindings.write_dummy_uses() - .expect("Unable to write dummy uses to file."); - } - Err(error) => { - println!("{}", error); - std::process::exit(1); - } - }; -} diff --git a/src/bin/options.rs b/src/bin/options.rs deleted file mode 100644 index 9f746fd0..00000000 --- a/src/bin/options.rs +++ /dev/null @@ -1,269 +0,0 @@ - - -use bindgen::{Builder, builder}; - -use clap::{App, Arg}; -use std::fs::File; -use std::io::{self, Error, ErrorKind}; - -/// Construct a new [`Builder`](./struct.Builder.html) from command line flags. -pub fn builder_from_flags(args: I) - -> Result<(Builder, Box), io::Error> - where I: Iterator, -{ - let matches = App::new("bindgen") - .version(env!("CARGO_PKG_VERSION")) - .about("Generates Rust bindings from C/C++ headers.") - .usage("bindgen [FLAGS] [OPTIONS]
-- ...") - .args(&[ - Arg::with_name("header") - .help("C or C++ header file") - .required(true), - Arg::with_name("bitfield-enum") - .long("bitfield-enum") - .help("Mark any enum whose name matches as a set of \ - bitfield flags instead of an enumeration.") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("blacklist-type") - .long("blacklist-type") - .help("Mark a type as hidden.") - .value_name("type") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("builtins") - .long("builtins") - .help("Output bindings for builtin definitions, e.g. \ - __builtin_va_list."), - Arg::with_name("ctypes-prefix") - .long("ctypes-prefix") - .help("Use the given prefix before raw types instead of \ - ::std::os::raw.") - .value_name("prefix") - .takes_value(true), - // All positional arguments after the end of options marker, `--` - Arg::with_name("clang-args") - .multiple(true), - Arg::with_name("dummy-uses") - .long("dummy-uses") - .help("For testing purposes, generate a C/C++ file containing \ - dummy uses of all types defined in the input header.") - .takes_value(true), - Arg::with_name("emit-clang-ast") - .long("emit-clang-ast") - .help("Output the Clang AST for debugging purposes."), - Arg::with_name("enable-cxx-namespaces") - .long("enable-cxx-namespaces") - .help("Enable support for C++ namespaces."), - Arg::with_name("framework") - .long("framework-link") - .help("Link to framework.") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("ignore-functions") - .long("ignore-functions") - .help("Do not generate bindings for functions or methods. This \ - is useful when you only care about struct layouts."), - Arg::with_name("ignore-methods") - .long("ignore-methods") - .help("Do not generate bindings for methods."), - Arg::with_name("dynamic") - .short("l") - .long("link") - .help("Link to dynamic library.") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("no-convert-floats") - .long("no-convert-floats") - .help("Don't automatically convert floats to f32/f64."), - Arg::with_name("no-unstable-rust") - .long("no-unstable-rust") - .help("Do not generate unstable Rust code.") - .multiple(true), // FIXME: Pass legacy test suite - Arg::with_name("opaque-type") - .long("opaque-type") - .help("Mark a type as opaque.") - .value_name("type") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("output") - .short("o") - .long("output") - .help("Write Rust bindings to .") - .takes_value(true), - Arg::with_name("raw-line") - .long("raw-line") - .help("Add a raw line of Rust code at the beginning of output.") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("static") - .long("static-link") - .help("Link to static library.") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("use-core") - .long("use-core") - .help("Use types from Rust core instead of std."), - Arg::with_name("use-msvc-mangling") - .long("use-msvc-mangling") - .help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."), - Arg::with_name("whitelist-function") - .long("whitelist-function") - .help("Whitelist all the free-standing functions matching \ - . Other non-whitelisted functions will not be \ - generated.") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("whitelist-type") - .long("whitelist-type") - .help("Whitelist the type. Other non-whitelisted types will \ - not be generated.") - .value_name("type") - .takes_value(true) - .multiple(true) - .number_of_values(1), - Arg::with_name("whitelist-var") - .long("whitelist-var") - .help("Whitelist all the free-standing variables matching \ - . Other non-whitelisted variables will not be \ - generated.") - .value_name("regex") - .takes_value(true) - .multiple(true) - .number_of_values(1), - ]) // .args() - .get_matches_from(args); - - let mut builder = builder(); - - if let Some(header) = matches.value_of("header") { - builder = builder.header(header); - } else { - return Err(Error::new(ErrorKind::Other, "Header not found")); - } - - if let Some(bitfields) = matches.values_of("bitfield-enum") { - for regex in bitfields { - builder = builder.bitfield_enum(regex); - } - } - - if let Some(hidden_types) = matches.values_of("blacklist-type") { - for ty in hidden_types { - builder = builder.hide_type(ty); - } - } - - if matches.is_present("builtins") { - builder = builder.emit_builtins(); - } - - if let Some(prefix) = matches.value_of("ctypes-prefix") { - builder = builder.ctypes_prefix(prefix); - } - - if let Some(dummy) = matches.value_of("dummy-uses") { - builder = builder.dummy_uses(dummy); - } - - if let Some(links) = matches.values_of("dynamic") { - for library in links { - builder = builder.link(library); - } - } - - if matches.is_present("emit-clang-ast") { - builder = builder.emit_clang_ast(); - } - - if matches.is_present("enable-cxx-namespaces") { - builder = builder.enable_cxx_namespaces(); - } - - if let Some(links) = matches.values_of("framework") { - for framework in links { - builder = builder.link_framework(framework); - } - } - - if matches.is_present("ignore-functions") { - builder = builder.ignore_functions(); - } - - if matches.is_present("ignore-methods") { - builder = builder.ignore_methods(); - } - - if matches.is_present("no-unstable-rust") { - builder = builder.no_unstable_rust(); - } - - if matches.is_present("no-convert-floats") { - builder = builder.no_convert_floats(); - } - - if let Some(opaque_types) = matches.values_of("opaque-type") { - for ty in opaque_types { - builder = builder.opaque_type(ty); - } - } - - if let Some(lines) = matches.values_of("raw-line") { - for line in lines { - builder = builder.raw_line(line); - } - } - - if let Some(links) = matches.values_of("static") { - for library in links { - builder = builder.link_static(library); - } - } - - if matches.is_present("use-core") { - builder = builder.use_core(); - } - - if let Some(whitelist) = matches.values_of("whitelist-function") { - for regex in whitelist { - builder = builder.whitelisted_function(regex); - } - } - - if let Some(whitelist) = matches.values_of("whitelist-type") { - for regex in whitelist { - builder = builder.whitelisted_type(regex); - } - } - - if let Some(whitelist) = matches.values_of("whitelist-var") { - for regex in whitelist { - builder = builder.whitelisted_var(regex); - } - } - - if let Some(args) = matches.values_of("clang-args") { - for arg in args { - builder = builder.clang_arg(arg); - } - } - - let output = if let Some(path) = matches.value_of("output") { - let file = try!(File::create(path)); - Box::new(io::BufWriter::new(file)) as Box - } else { - Box::new(io::BufWriter::new(io::stdout())) as Box - }; - - Ok((builder, output)) -} diff --git a/src/chooser.rs b/src/chooser.rs deleted file mode 100644 index 10a77dc9..00000000 --- a/src/chooser.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! A public API for more fine-grained customization of bindgen behavior. - -pub use ir::int::IntKind; -use std::fmt; - -/// A trait to allow configuring different kinds of types in different -/// situations. -pub trait TypeChooser: fmt::Debug { - /// The integer kind an integer macro should have, given a name and the - /// value of that macro, or `None` if you want the default to be chosen. - fn int_macro(&self, _name: &str, _value: i64) -> Option { - None - } -} diff --git a/src/clang.rs b/src/clang.rs deleted file mode 100755 index 7da755ea..00000000 --- a/src/clang.rs +++ /dev/null @@ -1,1259 +0,0 @@ -//! A higher level Clang API built on top of the generated bindings in the -//! `clangll` module. - -#![allow(non_upper_case_globals, dead_code)] - - -use cexpr; -use clangll::*; -use std::{mem, ptr, slice}; -use std::ffi::{CStr, CString}; -use std::fmt; -use std::hash::Hash; -use std::hash::Hasher; -use std::os::raw::{c_char, c_int, c_uint, c_ulong}; - -/// A cursor into the Clang AST, pointing to an AST node. -/// -/// We call the AST node pointed to by the cursor the cursor's "referent". -#[derive(Copy, Clone)] -pub struct Cursor { - x: CXCursor, -} - -impl fmt::Debug for Cursor { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, - "Cursor({} kind: {}, loc: {}, usr: {:?})", - self.spelling(), - kind_to_str(self.kind()), - self.location(), - self.usr()) - } -} - -impl Cursor { - /// Get the Unified Symbol Resolution for this cursor's referent, if - /// available. - /// - /// The USR can be used to compare entities across translation units. - pub fn usr(&self) -> Option { - let s: String = unsafe { clang_getCursorUSR(self.x) }.into(); - if s.is_empty() { None } else { Some(s) } - } - - /// Is this cursor's referent a declaration? - pub fn is_declaration(&self) -> bool { - unsafe { clang_isDeclaration(self.kind()) != 0 } - } - - /// Get the null cursor, which has no referent. - pub fn null() -> Self { - Cursor { - x: unsafe { clang_getNullCursor() }, - } - } - - /// Get this cursor's referent's spelling. - pub fn spelling(&self) -> String { - unsafe { clang_getCursorSpelling(self.x).into() } - } - - /// Get this cursor's referent's display name. - /// - /// This is not necessarily a valid identifier. It includes extra - /// information, such as parameters for a function, etc. - pub fn display_name(&self) -> String { - unsafe { clang_getCursorDisplayName(self.x).into() } - } - - /// Get the mangled name of this cursor's referent. - pub fn mangling(&self) -> String { - unsafe { clang_Cursor_getMangling(self.x).into() } - } - - /// Get the `Cursor` for this cursor's referent's lexical parent. - /// - /// The lexical parent is the parent of the definition. The semantic parent - /// is the parent of the declaration. Generally, the lexical parent doesn't - /// have any effect on semantics, while the semantic parent does. - /// - /// In the following snippet, the `Foo` class would be the semantic parent - /// of the out-of-line `method` definition, while the lexical parent is the - /// translation unit. - /// - /// ```c++ - /// class Foo { - /// void method(); - /// }; - /// - /// void Foo::method() { /* ... */ } - /// ``` - pub fn lexical_parent(&self) -> Cursor { - unsafe { - Cursor { - x: clang_getCursorLexicalParent(self.x), - } - } - } - - /// Get the referent's semantic parent, if one is available. - /// - /// See documentation for `lexical_parent` for details on semantic vs - /// lexical parents. - pub fn fallible_semantic_parent(&self) -> Option { - let sp = unsafe { - Cursor { - x: clang_getCursorSemanticParent(self.x), - } - }; - if sp == *self || !sp.is_valid() { - return None; - } - Some(sp) - } - - /// Get the referent's semantic parent. - /// - /// See documentation for `lexical_parent` for details on semantic vs - /// lexical parents. - pub fn semantic_parent(&self) -> Cursor { - self.fallible_semantic_parent().unwrap() - } - - /// Return the number of template arguments used by this cursor's referent, - /// if the referent is either a template specialization or - /// declaration. Returns -1 otherwise. - /// - /// NOTE: This may not return `Some` for some non-fully specialized - /// templates, see #193 and #194. - pub fn num_template_args(&self) -> Option { - let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; - - if n >= 0 { - Some(n as u32) - } else { - debug_assert_eq!(n, -1); - None - } - } - - /// Get a cursor pointing to this referent's containing translation unit. - /// - /// 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 - /// disposes 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 - } - } - - /// Is the referent a top level construct? - pub fn is_toplevel(&self) -> bool { - let mut semantic_parent = self.fallible_semantic_parent(); - - while semantic_parent.is_some() && - (semantic_parent.unwrap().kind() == CXCursor_Namespace || - semantic_parent.unwrap().kind() == CXCursor_NamespaceAlias || - semantic_parent.unwrap().kind() == CXCursor_NamespaceRef) { - semantic_parent = semantic_parent.unwrap() - .fallible_semantic_parent(); - } - - let tu = self.translation_unit(); - // Yes, this can happen with, e.g., macro definitions. - semantic_parent == tu.fallible_semantic_parent() - } - - /// Get the kind of referent this cursor is pointing to. - pub fn kind(&self) -> Enum_CXCursorKind { - unsafe { clang_getCursorKind(self.x) } - } - - /// Is the referent an anonymous record definition? - pub fn is_anonymous(&self) -> bool { - unsafe { clang_Cursor_isAnonymous(self.x) != 0 } - } - - /// Is the referent a template specialization? - pub fn is_template(&self) -> bool { - self.specialized().is_some() - } - - /// Is the referent a fully specialized template specialization without any - /// remaining free template arguments? - pub fn is_fully_specialized_template(&self) -> bool { - self.is_template() && self.num_template_args().unwrap_or(0) > 0 - } - - /// Is the referent a template specialization that still has remaining free - /// template arguments? - pub fn is_in_non_fully_specialized_template(&self) -> bool { - if self.is_toplevel() { - return false; - } - let parent = self.semantic_parent(); - (parent.is_template() && !parent.is_fully_specialized_template()) || - parent.is_in_non_fully_specialized_template() - } - - /// Is this cursor pointing a valid referent? - pub fn is_valid(&self) -> bool { - unsafe { clang_isInvalid(self.kind()) == 0 } - } - - /// Get the source location for the referent. - pub fn location(&self) -> SourceLocation { - unsafe { - SourceLocation { - x: clang_getCursorLocation(self.x), - } - } - } - - /// Get the source location range for the referent. - pub fn extent(&self) -> CXSourceRange { - unsafe { clang_getCursorExtent(self.x) } - } - - /// Get the raw declaration comment for this referent, if one exists. - pub fn raw_comment(&self) -> Option { - let s: String = - unsafe { clang_Cursor_getRawCommentText(self.x).into() }; - if s.is_empty() { None } else { Some(s) } - } - - /// Get the referent's parsed comment. - pub fn comment(&self) -> Comment { - unsafe { - Comment { - x: clang_Cursor_getParsedComment(self.x), - } - } - } - - /// Get the referent's type. - pub fn cur_type(&self) -> Type { - unsafe { - Type { - x: clang_getCursorType(self.x), - } - } - } - - /// Given that this cursor's referent is a reference to another type, or is - /// a declaration, get the cursor pointing to the referenced type or type of - /// the declared thing. - pub fn definition(&self) -> Option { - unsafe { - let ret = Cursor { - x: clang_getCursorDefinition(self.x), - }; - - if ret.is_valid() { Some(ret) } else { None } - } - } - - /// Given that this cursor's referent is reference type, get the cursor - /// pointing to the referenced type. - pub fn referenced(&self) -> Option { - unsafe { - let ret = Cursor { - x: clang_getCursorReferenced(self.x), - }; - - if ret.is_valid() { Some(ret) } else { None } - } - } - - /// Get the canonical cursor for this referent. - /// - /// Many types can be declared multiple times before finally being properly - /// defined. This method allows us to get the canonical cursor for the - /// referent type. - pub fn canonical(&self) -> Cursor { - unsafe { - Cursor { - x: clang_getCanonicalCursor(self.x), - } - } - } - - /// Given that this cursor points to a template specialization, get a cursor - /// pointing to the template definition that is being specialized. - pub fn specialized(&self) -> Option { - unsafe { - let ret = Cursor { - x: clang_getSpecializedCursorTemplate(self.x), - }; - if ret.is_valid() { Some(ret) } else { None } - } - } - - /// Assuming that this cursor's referent is a template declaration, get the - /// kind of cursor that would be generated for its specializations. - pub fn template_kind(&self) -> Enum_CXCursorKind { - unsafe { clang_getTemplateCursorKind(self.x) } - } - - /// Traverse this cursor's referent and its children. - /// - /// Call the given function on each AST node traversed. - pub fn visit(&self, mut visitor: Visitor) - where Visitor: FnMut(Cursor) -> Enum_CXChildVisitResult, - { - unsafe { - clang_visitChildren(self.x, - Some(visit_children::), - mem::transmute(&mut visitor)); - } - } - - /// Returns whether the given location contains a cursor with the given - /// kind in the first level of nesting underneath (doesn't look - /// recursively). - pub fn contains_cursor(&self, kind: Enum_CXCursorKind) -> bool { - let mut found = false; - - self.visit(|c| { - if c.kind() == kind { - found = true; - CXChildVisit_Break - } else { - CXChildVisit_Continue - } - }); - - found - } - - /// Is the referent an inlined function? - #[cfg(not(feature="llvm_stable"))] - pub fn is_inlined_function(&self) -> bool { - unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 } - } - - // TODO: Remove this when LLVM 3.9 is released. - // - // This is currently used for CI purposes. - - /// Is the referent an inlined function? - #[cfg(feature="llvm_stable")] - pub fn is_inlined_function(&self) -> bool { - false - } - - /// Get the width of this cursor's referent bit field, or `None` if the - /// referent is not a bit field. - pub fn bit_width(&self) -> Option { - unsafe { - let w = clang_getFieldDeclBitWidth(self.x); - if w == -1 { None } else { Some(w as u32) } - } - } - - /// Get the integer representation type used to hold this cursor's referent - /// enum type. - pub fn enum_type(&self) -> Type { - unsafe { - Type { - x: clang_getEnumDeclIntegerType(self.x), - } - } - } - - /// Get the signed constant value for this cursor's enum variant referent. - /// - /// Returns None if the cursor's referent is not an enum variant. - pub fn enum_val_signed(&self) -> Option { - unsafe { - if self.kind() == CXCursor_EnumConstantDecl { - Some(clang_getEnumConstantDeclValue(self.x) as i64) - } else { - None - } - } - } - - /// Get the unsigned constant value for this cursor's enum variant referent. - /// - /// Returns None if the cursor's referent is not an enum variant. - pub fn enum_val_unsigned(&self) -> Option { - unsafe { - if self.kind() == CXCursor_EnumConstantDecl { - Some(clang_getEnumConstantDeclUnsignedValue(self.x) as u64) - } else { - None - } - } - } - - /// Given that this cursor's referent is a `typedef`, get the `Type` that is - /// being aliased. - pub fn typedef_type(&self) -> Type { - unsafe { - Type { - x: clang_getTypedefDeclUnderlyingType(self.x), - } - } - } - - /// Get the linkage kind for this cursor's referent. - /// - /// This only applies to functions and variables. - pub fn linkage(&self) -> Enum_CXLinkageKind { - unsafe { clang_getCursorLinkage(self.x) } - } - - /// Get the visibility of this cursor's referent. - pub fn visibility(&self) -> Enum_CXVisibilityKind { - unsafe { clang_getCursorVisibility(self.x) } - } - - /// Given that this cursor's referent is a function, return cursors to its - /// parameters. - pub fn args(&self) -> Vec { - unsafe { - let num = self.num_args().expect("expected value, got none") as u32; - let mut args = vec![]; - for i in 0..num { - args.push(Cursor { - x: clang_Cursor_getArgument(self.x, i as c_uint), - }); - } - args - } - } - - /// Given that this cursor's referent is a function/method call or - /// declaration, return the number of arguments it takes. - /// - /// Returns -1 if the cursor's referent is not a function/method call or - /// declaration. - pub fn num_args(&self) -> Result { - unsafe { - let w = clang_Cursor_getNumArguments(self.x); - if w == -1 { Err(()) } else { Ok(w as u32) } - } - } - - /// Get the access specifier for this cursor's referent. - pub fn access_specifier(&self) -> Enum_CX_CXXAccessSpecifier { - unsafe { clang_getCXXAccessSpecifier(self.x) } - } - - /// Is this cursor's referent a field declaration that is marked as - /// `mutable`? - pub fn is_mutable_field(&self) -> bool { - unsafe { clang_CXXField_isMutable(self.x) != 0 } - } - - /// Is this cursor's referent a member function that is declared `static`? - pub fn method_is_static(&self) -> bool { - unsafe { clang_CXXMethod_isStatic(self.x) != 0 } - } - - /// Is this cursor's referent a member function that is declared `const`? - pub fn method_is_const(&self) -> bool { - unsafe { clang_CXXMethod_isConst(self.x) != 0 } - } - - /// Is this cursor's referent a member function that is declared `const`? - pub fn method_is_virtual(&self) -> bool { - unsafe { clang_CXXMethod_isVirtual(self.x) != 0 } - } - - /// Is this cursor's referent a struct or class with virtual members? - pub fn is_virtual_base(&self) -> bool { - unsafe { clang_isVirtualBase(self.x) != 0 } - } -} - -extern "C" fn visit_children(cur: CXCursor, - _parent: CXCursor, - data: CXClientData) - -> Enum_CXChildVisitResult - where Visitor: FnMut(Cursor) -> Enum_CXChildVisitResult, -{ - let func: &mut Visitor = unsafe { mem::transmute(data) }; - let child = Cursor { - x: cur, - }; - - (*func)(child) -} - -impl PartialEq for Cursor { - fn eq(&self, other: &Cursor) -> bool { - unsafe { clang_equalCursors(self.x, other.x) == 1 } - } -} - -impl Eq for Cursor {} - -impl Hash for Cursor { - fn hash(&self, state: &mut H) { - unsafe { clang_hashCursor(self.x) }.hash(state) - } -} - -/// The type of a node in clang's AST. -#[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()) - } -} - -/// An error about the layout of a struct, class, or type. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum LayoutError { - /// Asked for the layout of an invalid type. - Invalid, - /// Asked for the layout of an incomplete type. - Incomplete, - /// Asked for the layout of a dependent type. - Dependent, - /// Asked for the layout of a type that does not have constant size. - NotConstantSize, - /// Asked for the layout of a field in a type that does not have such a - /// field. - InvalidFieldName, - /// An unknown layout error. - Unknown, -} - -impl ::std::convert::From for LayoutError { - fn from(val: i32) -> Self { - use self::LayoutError::*; - match val { - CXTypeLayoutError_Invalid => Invalid, - CXTypeLayoutError_Incomplete => Incomplete, - CXTypeLayoutError_Dependent => Dependent, - CXTypeLayoutError_NotConstantSize => NotConstantSize, - CXTypeLayoutError_InvalidFieldName => InvalidFieldName, - _ => Unknown, - } - } -} - -impl Type { - /// Get this type's kind. - pub fn kind(&self) -> Enum_CXTypeKind { - self.x.kind - } - - /// Get a cursor pointing to this type's declaration. - pub fn declaration(&self) -> Cursor { - unsafe { - Cursor { - x: clang_getTypeDeclaration(self.x), - } - } - } - - /// Get a raw display name for this type. - pub fn spelling(&self) -> String { - unsafe { clang_getTypeSpelling(self.x).into() } - } - - /// Is this type const qualified? - pub fn is_const(&self) -> bool { - unsafe { clang_isConstQualifiedType(self.x) != 0 } - } - - /// What is the size of this type? Paper over invalid types by returning `0` - /// for them. - pub fn size(&self) -> usize { - unsafe { - let val = clang_Type_getSizeOf(self.x); - if val < 0 { 0 } else { val as usize } - } - } - - /// What is the size of this type? - pub fn fallible_size(&self) -> Result { - let val = unsafe { clang_Type_getSizeOf(self.x) }; - if val < 0 { - Err(LayoutError::from(val as i32)) - } else { - Ok(val as usize) - } - } - - /// What is the alignment of this type? Paper over invalid types by - /// returning `0`. - pub fn align(&self) -> usize { - unsafe { - let val = clang_Type_getAlignOf(self.x); - if val < 0 { 0 } else { val as usize } - } - } - - /// What is the alignment of this type? - pub fn fallible_align(&self) -> Result { - unsafe { - let val = clang_Type_getAlignOf(self.x); - if val < 0 { - Err(LayoutError::from(val as i32)) - } else { - Ok(val as usize) - } - } - } - - /// Get the layout for this type, or an error describing why it does not - /// have a valid layout. - 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)) - } - - /// If this type is a class template specialization, return its - /// template arguments. Otherwise, return None. - pub fn template_args(&self) -> Option { - let n = unsafe { clang_Type_getNumTemplateArguments(self.x) }; - if n >= 0 { - Some(TypeTemplateArgIterator { - x: self.x, - length: n as u32, - index: 0, - }) - } else { - debug_assert_eq!(n, -1); - None - } - } - - /// Given that this type is a pointer type, return the type that it points - /// to. - pub fn pointee_type(&self) -> Option { - match self.kind() { - CXType_Pointer | - CXType_RValueReference | - CXType_LValueReference | - CXType_MemberPointer => { - let ret = Type { - x: unsafe { clang_getPointeeType(self.x) }, - }; - debug_assert!(ret.is_valid()); - Some(ret) - } - _ => None, - } - } - - /// Given that this type is an array, vector, or complex type, return the - /// type of its elements. - pub fn elem_type(&self) -> Option { - let current_type = Type { - x: unsafe { clang_getElementType(self.x) }, - }; - if current_type.is_valid() { - Some(current_type) - } else { - None - } - } - - /// Given that this type is an array or vector type, return its number of - /// elements. - pub fn num_elements(&self) -> Option { - let num_elements_returned = unsafe { clang_getNumElements(self.x) }; - if num_elements_returned != -1 { - Some(num_elements_returned as usize) - } else { - None - } - } - - /// Get the canonical version of this type. This sees through `typdef`s and - /// aliases to get the underlying, canonical type. - pub fn canonical_type(&self) -> Type { - unsafe { - Type { - x: clang_getCanonicalType(self.x), - } - } - } - - /// Is this type a variadic function type? - pub fn is_variadic(&self) -> bool { - unsafe { clang_isFunctionTypeVariadic(self.x) != 0 } - } - - /// Given that this type is a function type, get the type of its return - /// value. - pub fn ret_type(&self) -> Option { - let rt = Type { - x: unsafe { clang_getResultType(self.x) }, - }; - if rt.is_valid() { Some(rt) } else { None } - } - - /// Given that this type is a function type, get its calling convention. If - /// this is not a function type, `CXCallingConv_Invalid` is returned. - pub fn call_conv(&self) -> Enum_CXCallingConv { - unsafe { clang_getFunctionTypeCallingConv(self.x) } - } - - /// For elaborated types (types which use `class`, `struct`, or `union` to - /// disambiguate types from local bindings), get the underlying type. - #[cfg(not(feature="llvm_stable"))] - pub fn named(&self) -> Type { - unsafe { - Type { - x: clang_Type_getNamedType(self.x), - } - } - } - - /// Is this a valid type? - pub fn is_valid(&self) -> bool { - self.kind() != CXType_Invalid - } - - /// Is this a valid and exposed type? - pub fn is_valid_and_exposed(&self) -> bool { - self.is_valid() && self.kind() != CXType_Unexposed - } -} - -/// An iterator for a type's template arguments. -pub struct TypeTemplateArgIterator { - x: CXType, - length: u32, - index: u32, -} - -impl Iterator for TypeTemplateArgIterator { - type Item = Type; - fn next(&mut self) -> Option { - if self.index < self.length { - let idx = self.index as c_int; - self.index += 1; - Some(Type { - x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) }, - }) - } else { - None - } - } -} - -impl ExactSizeIterator for TypeTemplateArgIterator { - fn len(&self) -> usize { - assert!(self.index <= self.length); - (self.length - self.index) as usize - } -} - -/// A `SourceLocation` is a file, line, column, and byte offset location for -/// some source text. -pub struct SourceLocation { - x: CXSourceLocation, -} - -impl SourceLocation { - /// Get the (file, line, column, byte offset) tuple for this source - /// location. - pub fn location(&self) -> (File, usize, usize, usize) { - unsafe { - let mut file = ptr::null_mut(); - let mut line = 0; - let mut col = 0; - let mut off = 0; - clang_getSpellingLocation(self.x, - &mut file, - &mut line, - &mut col, - &mut off); - (File { - x: file, - }, - line as usize, - col as usize, - off as usize) - } - } -} - -impl fmt::Display for SourceLocation { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let (file, line, col, _) = self.location(); - if let Some(name) = file.name() { - write!(f, "{}:{}:{}", name, line, col) - } else { - "builtin definitions".fmt(f) - } - } -} - -/// A comment in the source text. -/// -/// Comments are sort of parsed by Clang, and have a tree structure. -pub struct Comment { - x: CXComment, -} - -impl Comment { - /// What kind of comment is this? - pub fn kind(&self) -> Enum_CXCommentKind { - unsafe { clang_Comment_getKind(self.x) } - } - - /// Get this comment's children comment - pub fn get_children(&self) -> CommentChildrenIterator { - CommentChildrenIterator { - parent: self.x, - length: unsafe { clang_Comment_getNumChildren(self.x) }, - index: 0, - } - } - - /// Given that this comment is the start or end of an HTML tag, get its tag - /// name. - pub fn get_tag_name(&self) -> String { - unsafe { clang_HTMLTagComment_getTagName(self.x).into() } - } - - /// Given that this comment is an HTML start tag, get its attributes. - pub fn get_tag_attrs(&self) -> CommentAttributesIterator { - CommentAttributesIterator { - x: self.x, - length: unsafe { clang_HTMLStartTag_getNumAttrs(self.x) }, - index: 0, - } - } -} - -/// An iterator for a comment's children -pub struct CommentChildrenIterator { - parent: CXComment, - length: c_uint, - index: c_uint, -} - -impl Iterator for CommentChildrenIterator { - type Item = Comment; - fn next(&mut self) -> Option { - if self.index < self.length { - let idx = self.index; - self.index += 1; - Some(Comment { - x: unsafe { clang_Comment_getChild(self.parent, idx) }, - }) - } else { - None - } - } -} - -/// An HTML start tag comment attribute -pub struct CommentAttribute { - /// HTML start tag attribute name - pub name: String, - /// HTML start tag attribute value - pub value: String, -} - -/// An iterator for a comment's attributes -pub struct CommentAttributesIterator { - x: CXComment, - length: c_uint, - index: c_uint, -} - -impl Iterator for CommentAttributesIterator { - type Item = CommentAttribute; - fn next(&mut self) -> Option { - if self.index < self.length { - let idx = self.index; - self.index += 1; - Some(CommentAttribute { - name: unsafe { - clang_HTMLStartTag_getAttrName(self.x, idx).into() - }, - value: unsafe { - clang_HTMLStartTag_getAttrValue(self.x, idx).into() - }, - }) - } else { - None - } - } -} - -/// A source file. -pub struct File { - x: CXFile, -} - -impl File { - /// Get the name of this source file. - pub fn name(&self) -> Option { - if self.x.is_null() { - return None; - } - unsafe { Some(clang_getFileName(self.x).into()) } - } -} - -impl Into for CXString { - fn into(self) -> String { - if self.data.is_null() { - return "".to_owned(); - } - unsafe { - let c_str = CStr::from_ptr(clang_getCString(self) as *const _); - c_str.to_string_lossy().into_owned() - } - } -} - -/// An `Index` is an environment for a set of translation units that will -/// typically end up linked together in one final binary. -pub struct Index { - x: CXIndex, -} - -impl Index { - /// Construct a new `Index`. - /// - /// The `pch` parameter controls whether declarations in pre-compiled - /// headers are included when enumerating a translation unit's "locals". - /// - /// The `diag` parameter controls whether debugging diagnostics are enabled. - pub fn new(pch: bool, diag: bool) -> Index { - unsafe { - Index { - x: clang_createIndex(pch as c_int, diag as c_int), - } - } - } -} - -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); - } - } -} - -/// A token emitted by clang's lexer. -#[derive(Debug)] -pub struct Token { - /// The kind of token this is. - pub kind: CXTokenKind, - /// A display name for this token. - pub spelling: String, -} - -/// A translation unit (or "compilation unit"). -pub struct TranslationUnit { - x: CXTranslationUnit, -} - -impl fmt::Debug for TranslationUnit { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "TranslationUnit {{ }}") - } -} - -impl TranslationUnit { - /// Parse a source file into a translation unit. - pub fn parse(ix: &Index, - file: &str, - cmd_args: &[String], - unsaved: &[UnsavedFile], - opts: ::libc::c_uint) - -> Option { - let fname = CString::new(file).unwrap(); - let _c_args: Vec = - cmd_args.iter().map(|s| CString::new(s.clone()).unwrap()).collect(); - let c_args: Vec<*const c_char> = - _c_args.iter().map(|s| s.as_ptr()).collect(); - let mut c_unsaved: Vec = - unsaved.iter().map(|f| f.x).collect(); - let tu = unsafe { - clang_parseTranslationUnit(ix.x, - fname.as_ptr(), - c_args.as_ptr(), - c_args.len() as c_int, - c_unsaved.as_mut_ptr(), - c_unsaved.len() as c_uint, - opts) - }; - if tu.is_null() { - None - } else { - Some(TranslationUnit { - x: tu, - }) - } - } - - /// Reparse this translation unit, maybe because the file changed on disk or - /// something like that. - pub fn reparse(&self, unsaved: &[UnsavedFile], opts: usize) -> bool { - let mut c_unsaved: Vec = - unsaved.iter().map(|f| f.x).collect(); - - unsafe { - clang_reparseTranslationUnit(self.x, - c_unsaved.len() as c_uint, - c_unsaved.as_mut_ptr(), - opts as c_uint) == 0 - } - } - - /// Get the Clang diagnostic information associated with this translation - /// unit. - pub fn diags(&self) -> Vec { - unsafe { - let num = clang_getNumDiagnostics(self.x) as usize; - let mut diags = vec![]; - for i in 0..num { - diags.push(Diagnostic { - x: clang_getDiagnostic(self.x, i as c_uint), - }); - } - diags - } - } - - /// Get a cursor pointing to the root of this translation unit's AST. - pub fn cursor(&self) -> Cursor { - unsafe { - Cursor { - x: clang_getTranslationUnitCursor(self.x), - } - } - } - - /// Is this the null translation unit? - pub fn is_null(&self) -> bool { - self.x.is_null() - } - - /// Invoke Clang's lexer on this translation unit and get the stream of - /// tokens that come out. - pub fn tokens(&self, cursor: &Cursor) -> Option> { - let range = cursor.extent(); - let mut tokens = vec![]; - unsafe { - let mut token_ptr = ptr::null_mut(); - let mut num_tokens: c_uint = 0; - clang_tokenize(self.x, range, &mut token_ptr, &mut num_tokens); - if token_ptr.is_null() { - return None; - } - - let token_array = slice::from_raw_parts(token_ptr, - num_tokens as usize); - for &token in token_array.iter() { - let kind = clang_getTokenKind(token); - let spelling = clang_getTokenSpelling(self.x, token).into(); - - tokens.push(Token { - kind: kind, - spelling: spelling, - }); - } - clang_disposeTokens(self.x, token_ptr, num_tokens); - } - Some(tokens) - } - - /// Convert a set of tokens from clang into `cexpr` tokens, for further - /// processing. - pub fn cexpr_tokens(&self, - cursor: &Cursor) - -> Option> { - use cexpr::token; - - let mut tokens = match self.tokens(cursor) { - Some(tokens) => tokens, - None => return None, - }; - - // FIXME(emilio): LLVM 3.9 at least always include an extra token for no - // good reason (except if we're at EOF). So we do this kind of hack, - // where we skip known-to-cause problems trailing punctuation and - // trailing keywords. - // - // This is sort of unfortunate, though :(. - // - // I'll try to get it fixed in LLVM if I have the time to submit a - // patch. - let mut trim_last_token = false; - if let Some(token) = tokens.last() { - // The starting of the next macro. - trim_last_token |= token.spelling == "#" && - token.kind == CXToken_Punctuation; - - // A following keyword of any kind, like a following declaration. - trim_last_token |= token.kind == CXToken_Keyword; - } - - if trim_last_token { - tokens.pop().unwrap(); - } - - Some(tokens.into_iter() - .filter_map(|token| { - let kind = match token.kind { - CXToken_Punctuation => token::Kind::Punctuation, - CXToken_Literal => token::Kind::Literal, - CXToken_Identifier => token::Kind::Identifier, - CXToken_Keyword => token::Kind::Keyword, - // NB: cexpr is not too happy about comments inside - // expressions, so we strip them down here. - CXToken_Comment => return None, - _ => panic!("Found unexpected token kind: {}", token.kind), - }; - - Some(token::Token { - kind: kind, - raw: token.spelling.into_bytes().into_boxed_slice(), - }) - }) - .collect::>()) - } -} - -impl Drop for TranslationUnit { - fn drop(&mut self) { - unsafe { - clang_disposeTranslationUnit(self.x); - } - } -} - - -/// A diagnostic message generated while parsing a translation unit. -pub struct Diagnostic { - x: CXDiagnostic, -} - -impl Diagnostic { - /// Get the default diagnostic display option bit flags. - pub fn default_opts() -> usize { - unsafe { clang_defaultDiagnosticDisplayOptions() as usize } - } - - /// Format this diagnostic message as a string, using the given option bit - /// flags. - pub fn format(&self, opts: usize) -> String { - unsafe { clang_formatDiagnostic(self.x, opts as c_uint).into() } - } - - /// What is the severity of this diagnostic message? - pub fn severity(&self) -> Enum_CXDiagnosticSeverity { - unsafe { clang_getDiagnosticSeverity(self.x) } - } -} - -impl Drop for Diagnostic { - /// Destroy this diagnostic message. - fn drop(&mut self) { - unsafe { - clang_disposeDiagnostic(self.x); - } - } -} - -/// A file which has not been saved to disk. -pub struct UnsavedFile { - x: Struct_CXUnsavedFile, - name: CString, - contents: CString, -} - -impl UnsavedFile { - /// Construct a new unsaved file with the given `name` and `contents`. - pub fn new(name: &str, contents: &str) -> UnsavedFile { - let name = CString::new(name).unwrap(); - let contents = CString::new(contents).unwrap(); - let x = Struct_CXUnsavedFile { - Filename: name.as_ptr(), - Contents: contents.as_ptr(), - Length: contents.as_bytes().len() as c_ulong, - }; - UnsavedFile { - x: x, - name: name, - contents: contents, - } - } -} - -/// Convert a cursor kind into a static string. -pub fn kind_to_str(x: Enum_CXCursorKind) -> String { - unsafe { clang_getCursorKindSpelling(x) }.into() -} - -/// Convert a type kind to a static string. -pub fn type_to_str(x: Enum_CXTypeKind) -> String { - unsafe { clang_getTypeKindSpelling(x).into() } -} - -/// Dump the Clang AST to stdout for debugging purposes. -pub fn ast_dump(c: &Cursor, depth: isize) -> Enum_CXVisitorResult { - fn print_indent(depth: isize, s: &str) { - let mut i = 0; - while i < depth { - print!("\t"); - i += 1; - } - println!("{}", s); - } - let ct = c.cur_type().kind(); - print_indent(depth, - &format!("({} {} {}", - kind_to_str(c.kind()), - c.spelling(), - type_to_str(ct))); - c.visit(|s| ast_dump(&s, depth + 1)); - print_indent(depth, ")"); - CXChildVisit_Continue -} - -/// Try to extract the clang version to a string -pub fn extract_clang_version() -> String { - unsafe { clang_getClangVersion().into() } -} diff --git a/src/clangll.rs b/src/clangll.rs deleted file mode 100644 index b9743117..00000000 --- a/src/clangll.rs +++ /dev/null @@ -1,1439 +0,0 @@ -/* automatically generated by rust-bindgen */ - -#![allow(non_camel_case_types)] -#![allow(dead_code)] -#![allow(unused_attributes)] -#![allow(non_snake_case)] -#![allow(non_upper_case_globals)] -#![cfg_attr(rustfmt, rustfmt_skip)] - -use ::std::os::raw::{ c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void}; - -pub type ptrdiff_t = c_long; -pub type size_t = c_ulong; -pub type wchar_t = c_int; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXString { - pub data: *const c_void, - pub private_flags: c_uint, -} -pub type CXIndex = *mut c_void; -pub enum Struct_CXTranslationUnitImpl { } -pub type CXTranslationUnit = *mut Struct_CXTranslationUnitImpl; -pub type CXClientData = *mut c_void; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Struct_CXUnsavedFile { - pub Filename: *const c_char, - pub Contents: *const c_char, - pub Length: c_ulong, -} -pub type Enum_CXAvailabilityKind = c_uint; -pub const CXAvailability_Available: c_uint = 0; -pub const CXAvailability_Deprecated: c_uint = 1; -pub const CXAvailability_NotAvailable: c_uint = 2; -pub const CXAvailability_NotAccessible: c_uint = 3; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Struct_CXVersion { - pub Major: c_int, - pub Minor: c_int, - pub Subminor: c_int, -} -pub type CXVersion = Struct_CXVersion; -pub type CXGlobalOptFlags = c_uint; -pub const CXGlobalOpt_None: c_uint = 0; -pub const CXGlobalOpt_ThreadBackgroundPriorityForIndexing: c_uint = - 1; -pub const CXGlobalOpt_ThreadBackgroundPriorityForEditing: c_uint = 2; -pub const CXGlobalOpt_ThreadBackgroundPriorityForAll: c_uint = 3; -pub type CXFile = *mut c_void; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXFileUniqueID { - pub data: [c_ulonglong; 3], -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXSourceLocation { - pub ptr_data: [*const c_void; 2], - pub int_data: c_uint, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXSourceRange { - pub ptr_data: [*const c_void; 2], - pub begin_int_data: c_uint, - pub end_int_data: c_uint, -} -pub type Enum_CXDiagnosticSeverity = c_uint; -pub const CXDiagnostic_Ignored: c_uint = 0; -pub const CXDiagnostic_Note: c_uint = 1; -pub const CXDiagnostic_Warning: c_uint = 2; -pub const CXDiagnostic_Error: c_uint = 3; -pub const CXDiagnostic_Fatal: c_uint = 4; -pub type CXDiagnostic = *mut c_void; -pub type CXDiagnosticSet = *mut c_void; -pub type Enum_CXLoadDiag_Error = c_uint; -pub const CXLoadDiag_None: c_uint = 0; -pub const CXLoadDiag_Unknown: c_uint = 1; -pub const CXLoadDiag_CannotLoad: c_uint = 2; -pub const CXLoadDiag_InvalidFile: c_uint = 3; -pub type Enum_CXDiagnosticDisplayOptions = c_uint; -pub const CXDiagnostic_DisplaySourceLocation: c_uint = 1; -pub const CXDiagnostic_DisplayColumn: c_uint = 2; -pub const CXDiagnostic_DisplaySourceRanges: c_uint = 4; -pub const CXDiagnostic_DisplayOption: c_uint = 8; -pub const CXDiagnostic_DisplayCategoryId: c_uint = 16; -pub const CXDiagnostic_DisplayCategoryName: c_uint = 32; -pub type Enum_CXTranslationUnit_Flags = c_uint; -pub const CXTranslationUnit_None: c_uint = 0; -pub const CXTranslationUnit_DetailedPreprocessingRecord: c_uint = 1; -pub const CXTranslationUnit_Incomplete: c_uint = 2; -pub const CXTranslationUnit_PrecompiledPreamble: c_uint = 4; -pub const CXTranslationUnit_CacheCompletionResults: c_uint = 8; -pub const CXTranslationUnit_ForSerialization: c_uint = 16; -pub const CXTranslationUnit_CXXChainedPCH: c_uint = 32; -pub const CXTranslationUnit_SkipFunctionBodies: c_uint = 64; -pub const CXTranslationUnit_IncludeBriefCommentsInCodeCompletion: - c_uint = - 128; -pub type Enum_CXSaveTranslationUnit_Flags = c_uint; -pub const CXSaveTranslationUnit_None: c_uint = 0; -pub type Enum_CXSaveError = c_uint; -pub const CXSaveError_None: c_uint = 0; -pub const CXSaveError_Unknown: c_uint = 1; -pub const CXSaveError_TranslationErrors: c_uint = 2; -pub const CXSaveError_InvalidTU: c_uint = 3; -pub type Enum_CXReparse_Flags = c_uint; -pub const CXReparse_None: c_uint = 0; -pub type Enum_CXTUResourceUsageKind = c_uint; -pub const CXTUResourceUsage_AST: c_uint = 1; -pub const CXTUResourceUsage_Identifiers: c_uint = 2; -pub const CXTUResourceUsage_Selectors: c_uint = 3; -pub const CXTUResourceUsage_GlobalCompletionResults: c_uint = 4; -pub const CXTUResourceUsage_SourceManagerContentCache: c_uint = 5; -pub const CXTUResourceUsage_AST_SideTables: c_uint = 6; -pub const CXTUResourceUsage_SourceManager_Membuffer_Malloc: c_uint = - 7; -pub const CXTUResourceUsage_SourceManager_Membuffer_MMap: c_uint = 8; -pub const CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc: - c_uint = - 9; -pub const CXTUResourceUsage_ExternalASTSource_Membuffer_MMap: c_uint - = - 10; -pub const CXTUResourceUsage_Preprocessor: c_uint = 11; -pub const CXTUResourceUsage_PreprocessingRecord: c_uint = 12; -pub const CXTUResourceUsage_SourceManager_DataStructures: c_uint = - 13; -pub const CXTUResourceUsage_Preprocessor_HeaderSearch: c_uint = 14; -pub const CXTUResourceUsage_MEMORY_IN_BYTES_BEGIN: c_uint = 1; -pub const CXTUResourceUsage_MEMORY_IN_BYTES_END: c_uint = 14; -pub const CXTUResourceUsage_First: c_uint = 1; -pub const CXTUResourceUsage_Last: c_uint = 14; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Struct_CXTUResourceUsageEntry { - pub kind: Enum_CXTUResourceUsageKind, - pub amount: c_ulong, -} -pub type CXTUResourceUsageEntry = Struct_CXTUResourceUsageEntry; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Struct_CXTUResourceUsage { - pub data: *mut c_void, - pub numEntries: c_uint, - pub entries: *mut CXTUResourceUsageEntry, -} -pub type CXTUResourceUsage = Struct_CXTUResourceUsage; -pub type Enum_CXCursorKind = c_uint; -pub const CXCursor_UnexposedDecl: c_uint = 1; -pub const CXCursor_StructDecl: c_uint = 2; -pub const CXCursor_UnionDecl: c_uint = 3; -pub const CXCursor_ClassDecl: c_uint = 4; -pub const CXCursor_EnumDecl: c_uint = 5; -pub const CXCursor_FieldDecl: c_uint = 6; -pub const CXCursor_EnumConstantDecl: c_uint = 7; -pub const CXCursor_FunctionDecl: c_uint = 8; -pub const CXCursor_VarDecl: c_uint = 9; -pub const CXCursor_ParmDecl: c_uint = 10; -pub const CXCursor_ObjCInterfaceDecl: c_uint = 11; -pub const CXCursor_ObjCCategoryDecl: c_uint = 12; -pub const CXCursor_ObjCProtocolDecl: c_uint = 13; -pub const CXCursor_ObjCPropertyDecl: c_uint = 14; -pub const CXCursor_ObjCIvarDecl: c_uint = 15; -pub const CXCursor_ObjCInstanceMethodDecl: c_uint = 16; -pub const CXCursor_ObjCClassMethodDecl: c_uint = 17; -pub const CXCursor_ObjCImplementationDecl: c_uint = 18; -pub const CXCursor_ObjCCategoryImplDecl: c_uint = 19; -pub const CXCursor_TypedefDecl: c_uint = 20; -pub const CXCursor_CXXMethod: c_uint = 21; -pub const CXCursor_Namespace: c_uint = 22; -pub const CXCursor_LinkageSpec: c_uint = 23; -pub const CXCursor_Constructor: c_uint = 24; -pub const CXCursor_Destructor: c_uint = 25; -pub const CXCursor_ConversionFunction: c_uint = 26; -pub const CXCursor_TemplateTypeParameter: c_uint = 27; -pub const CXCursor_NonTypeTemplateParameter: c_uint = 28; -pub const CXCursor_TemplateTemplateParameter: c_uint = 29; -pub const CXCursor_FunctionTemplate: c_uint = 30; -pub const CXCursor_ClassTemplate: c_uint = 31; -pub const CXCursor_ClassTemplatePartialSpecialization: c_uint = 32; -pub const CXCursor_NamespaceAlias: c_uint = 33; -pub const CXCursor_UsingDirective: c_uint = 34; -pub const CXCursor_UsingDeclaration: c_uint = 35; -pub const CXCursor_TypeAliasDecl: c_uint = 36; -pub const CXCursor_ObjCSynthesizeDecl: c_uint = 37; -pub const CXCursor_ObjCDynamicDecl: c_uint = 38; -pub const CXCursor_CXXAccessSpecifier: c_uint = 39; -pub const CXCursor_FirstDecl: c_uint = 1; -pub const CXCursor_LastDecl: c_uint = 39; -pub const CXCursor_FirstRef: c_uint = 40; -pub const CXCursor_ObjCSuperClassRef: c_uint = 40; -pub const CXCursor_ObjCProtocolRef: c_uint = 41; -pub const CXCursor_ObjCClassRef: c_uint = 42; -pub const CXCursor_TypeRef: c_uint = 43; -pub const CXCursor_CXXBaseSpecifier: c_uint = 44; -pub const CXCursor_TemplateRef: c_uint = 45; -pub const CXCursor_NamespaceRef: c_uint = 46; -pub const CXCursor_MemberRef: c_uint = 47; -pub const CXCursor_LabelRef: c_uint = 48; -pub const CXCursor_OverloadedDeclRef: c_uint = 49; -pub const CXCursor_VariableRef: c_uint = 50; -pub const CXCursor_LastRef: c_uint = 50; -pub const CXCursor_FirstInvalid: c_uint = 70; -pub const CXCursor_InvalidFile: c_uint = 70; -pub const CXCursor_NoDeclFound: c_uint = 71; -pub const CXCursor_NotImplemented: c_uint = 72; -pub const CXCursor_InvalidCode: c_uint = 73; -pub const CXCursor_LastInvalid: c_uint = 73; -pub const CXCursor_FirstExpr: c_uint = 100; -pub const CXCursor_UnexposedExpr: c_uint = 100; -pub const CXCursor_DeclRefExpr: c_uint = 101; -pub const CXCursor_MemberRefExpr: c_uint = 102; -pub const CXCursor_CallExpr: c_uint = 103; -pub const CXCursor_ObjCMessageExpr: c_uint = 104; -pub const CXCursor_BlockExpr: c_uint = 105; -pub const CXCursor_IntegerLiteral: c_uint = 106; -pub const CXCursor_FloatingLiteral: c_uint = 107; -pub const CXCursor_ImaginaryLiteral: c_uint = 108; -pub const CXCursor_StringLiteral: c_uint = 109; -pub const CXCursor_CharacterLiteral: c_uint = 110; -pub const CXCursor_ParenExpr: c_uint = 111; -pub const CXCursor_UnaryOperator: c_uint = 112; -pub const CXCursor_ArraySubscriptExpr: c_uint = 113; -pub const CXCursor_BinaryOperator: c_uint = 114; -pub const CXCursor_CompoundAssignOperator: c_uint = 115; -pub const CXCursor_ConditionalOperator: c_uint = 116; -pub const CXCursor_CStyleCastExpr: c_uint = 117; -pub const CXCursor_CompoundLiteralExpr: c_uint = 118; -pub const CXCursor_InitListExpr: c_uint = 119; -pub const CXCursor_AddrLabelExpr: c_uint = 120; -pub const CXCursor_StmtExpr: c_uint = 121; -pub const CXCursor_GenericSelectionExpr: c_uint = 122; -pub const CXCursor_GNUNullExpr: c_uint = 123; -pub const CXCursor_CXXStaticCastExpr: c_uint = 124; -pub const CXCursor_CXXDynamicCastExpr: c_uint = 125; -pub const CXCursor_CXXReinterpretCastExpr: c_uint = 126; -pub const CXCursor_CXXConstCastExpr: c_uint = 127; -pub const CXCursor_CXXFunctionalCastExpr: c_uint = 128; -pub const CXCursor_CXXTypeidExpr: c_uint = 129; -pub const CXCursor_CXXBoolLiteralExpr: c_uint = 130; -pub const CXCursor_CXXNullPtrLiteralExpr: c_uint = 131; -pub const CXCursor_CXXThisExpr: c_uint = 132; -pub const CXCursor_CXXThrowExpr: c_uint = 133; -pub const CXCursor_CXXNewExpr: c_uint = 134; -pub const CXCursor_CXXDeleteExpr: c_uint = 135; -pub const CXCursor_UnaryExpr: c_uint = 136; -pub const CXCursor_ObjCStringLiteral: c_uint = 137; -pub const CXCursor_ObjCEncodeExpr: c_uint = 138; -pub const CXCursor_ObjCSelectorExpr: c_uint = 139; -pub const CXCursor_ObjCProtocolExpr: c_uint = 140; -pub const CXCursor_ObjCBridgedCastExpr: c_uint = 141; -pub const CXCursor_PackExpansionExpr: c_uint = 142; -pub const CXCursor_SizeOfPackExpr: c_uint = 143; -pub const CXCursor_LambdaExpr: c_uint = 144; -pub const CXCursor_ObjCBoolLiteralExpr: c_uint = 145; -pub const CXCursor_ObjCSelfExpr: c_uint = 146; -pub const CXCursor_LastExpr: c_uint = 146; -pub const CXCursor_FirstStmt: c_uint = 200; -pub const CXCursor_UnexposedStmt: c_uint = 200; -pub const CXCursor_LabelStmt: c_uint = 201; -pub const CXCursor_CompoundStmt: c_uint = 202; -pub const CXCursor_CaseStmt: c_uint = 203; -pub const CXCursor_DefaultStmt: c_uint = 204; -pub const CXCursor_IfStmt: c_uint = 205; -pub const CXCursor_SwitchStmt: c_uint = 206; -pub const CXCursor_WhileStmt: c_uint = 207; -pub const CXCursor_DoStmt: c_uint = 208; -pub const CXCursor_ForStmt: c_uint = 209; -pub const CXCursor_GotoStmt: c_uint = 210; -pub const CXCursor_IndirectGotoStmt: c_uint = 211; -pub const CXCursor_ContinueStmt: c_uint = 212; -pub const CXCursor_BreakStmt: c_uint = 213; -pub const CXCursor_ReturnStmt: c_uint = 214; -pub const CXCursor_GCCAsmStmt: c_uint = 215; -pub const CXCursor_AsmStmt: c_uint = 215; -pub const CXCursor_ObjCAtTryStmt: c_uint = 216; -pub const CXCursor_ObjCAtCatchStmt: c_uint = 217; -pub const CXCursor_ObjCAtFinallyStmt: c_uint = 218; -pub const CXCursor_ObjCAtThrowStmt: c_uint = 219; -pub const CXCursor_ObjCAtSynchronizedStmt: c_uint = 220; -pub const CXCursor_ObjCAutoreleasePoolStmt: c_uint = 221; -pub const CXCursor_ObjCForCollectionStmt: c_uint = 222; -pub const CXCursor_CXXCatchStmt: c_uint = 223; -pub const CXCursor_CXXTryStmt: c_uint = 224; -pub const CXCursor_CXXForRangeStmt: c_uint = 225; -pub const CXCursor_SEHTryStmt: c_uint = 226; -pub const CXCursor_SEHExceptStmt: c_uint = 227; -pub const CXCursor_SEHFinallyStmt: c_uint = 228; -pub const CXCursor_MSAsmStmt: c_uint = 229; -pub const CXCursor_NullStmt: c_uint = 230; -pub const CXCursor_DeclStmt: c_uint = 231; -pub const CXCursor_OMPParallelDirective: c_uint = 232; -pub const CXCursor_LastStmt: c_uint = 232; -pub const CXCursor_TranslationUnit: c_uint = 300; -pub const CXCursor_FirstAttr: c_uint = 400; -pub const CXCursor_UnexposedAttr: c_uint = 400; -pub const CXCursor_IBActionAttr: c_uint = 401; -pub const CXCursor_IBOutletAttr: c_uint = 402; -pub const CXCursor_IBOutletCollectionAttr: c_uint = 403; -pub const CXCursor_CXXFinalAttr: c_uint = 404; -pub const CXCursor_CXXOverrideAttr: c_uint = 405; -pub const CXCursor_AnnotateAttr: c_uint = 406; -pub const CXCursor_AsmLabelAttr: c_uint = 407; -pub const CXCursor_PackedAttr: c_uint = 408; -pub const CXCursor_LastAttr: c_uint = 408; -pub const CXCursor_PreprocessingDirective: c_uint = 500; -pub const CXCursor_MacroDefinition: c_uint = 501; -pub const CXCursor_MacroExpansion: c_uint = 502; -pub const CXCursor_MacroInstantiation: c_uint = 502; -pub const CXCursor_InclusionDirective: c_uint = 503; -pub const CXCursor_FirstPreprocessing: c_uint = 500; -pub const CXCursor_LastPreprocessing: c_uint = 503; -pub const CXCursor_ModuleImportDecl: c_uint = 600; -pub const CXCursor_TypeAliasTemplateDecl: c_uint = 601; -pub const CXCursor_StaticAssert: c_uint = 602; -pub const CXCursor_FirstExtraDecl: c_uint = 600; -pub const CXCursor_LastExtraDecl: c_uint = 602; -pub const CXCursor_OverloadCandidate: c_uint = 700; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXCursor { - pub kind: Enum_CXCursorKind, - pub xdata: c_int, - pub data: [*const c_void; 3], -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXComment { - pub ASTNode: *const c_void, - pub TranslationUnit: CXTranslationUnit, -} -pub type Enum_CXLinkageKind = ::libc::c_uint; -pub const CXLinkage_Invalid: ::libc::c_uint = 0; -pub const CXLinkage_NoLinkage: ::libc::c_uint = 1; -pub const CXLinkage_Internal: ::libc::c_uint = 2; -pub const CXLinkage_UniqueExternal: ::libc::c_uint = 3; -pub const CXLinkage_External: ::libc::c_uint = 4; -pub type Enum_CXVisibilityKind = ::libc::c_uint; -pub const CXVisibility_Invalid: ::libc::c_uint = 0; -pub const CXVisibility_Hidden: ::libc::c_uint = 1; -pub const CXVisibility_Protected: ::libc::c_uint = 2; -pub const CXVisibility_Default: ::libc::c_uint = 3; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct Struct_CXPlatformAvailability { - pub Platform: CXString, - pub Introduced: CXVersion, - pub Deprecated: CXVersion, - pub Obsoleted: CXVersion, - pub Unavailable: c_int, - pub Message: CXString, -} -pub type CXPlatformAvailability = Struct_CXPlatformAvailability; -pub type Enum_CXLanguageKind = c_uint; -pub const CXLanguage_Invalid: c_uint = 0; -pub const CXLanguage_C: c_uint = 1; -pub const CXLanguage_ObjC: c_uint = 2; -pub const CXLanguage_CPlusPlus: c_uint = 3; -pub enum Struct_CXCursorSetImpl { } -pub type CXCursorSet = *mut Struct_CXCursorSetImpl; -pub type Enum_CXTypeKind = c_uint; -pub const CXType_Invalid: c_uint = 0; -pub const CXType_Unexposed: c_uint = 1; -pub const CXType_Void: c_uint = 2; -pub const CXType_Bool: c_uint = 3; -pub const CXType_Char_U: c_uint = 4; -pub const CXType_UChar: c_uint = 5; -pub const CXType_Char16: c_uint = 6; -pub const CXType_Char32: c_uint = 7; -pub const CXType_UShort: c_uint = 8; -pub const CXType_UInt: c_uint = 9; -pub const CXType_ULong: c_uint = 10; -pub const CXType_ULongLong: c_uint = 11; -pub const CXType_UInt128: c_uint = 12; -pub const CXType_Char_S: c_uint = 13; -pub const CXType_SChar: c_uint = 14; -pub const CXType_WChar: c_uint = 15; -pub const CXType_Short: c_uint = 16; -pub const CXType_Int: c_uint = 17; -pub const CXType_Long: c_uint = 18; -pub const CXType_LongLong: c_uint = 19; -pub const CXType_Int128: c_uint = 20; -pub const CXType_Float: c_uint = 21; -pub const CXType_Double: c_uint = 22; -pub const CXType_LongDouble: c_uint = 23; -pub const CXType_NullPtr: c_uint = 24; -pub const CXType_Overload: c_uint = 25; -pub const CXType_Dependent: c_uint = 26; -pub const CXType_ObjCId: c_uint = 27; -pub const CXType_ObjCClass: c_uint = 28; -pub const CXType_ObjCSel: c_uint = 29; -pub const CXType_Float128: c_uint = 30; -pub const CXType_FirstBuiltin: c_uint = 2; -pub const CXType_LastBuiltin: c_uint = 29; -pub const CXType_Complex: c_uint = 100; -pub const CXType_Pointer: c_uint = 101; -pub const CXType_BlockPointer: c_uint = 102; -pub const CXType_LValueReference: c_uint = 103; -pub const CXType_RValueReference: c_uint = 104; -pub const CXType_Record: c_uint = 105; -pub const CXType_Enum: c_uint = 106; -pub const CXType_Typedef: c_uint = 107; -pub const CXType_ObjCInterface: c_uint = 108; -pub const CXType_ObjCObjectPointer: c_uint = 109; -pub const CXType_FunctionNoProto: c_uint = 110; -pub const CXType_FunctionProto: c_uint = 111; -pub const CXType_ConstantArray: c_uint = 112; -pub const CXType_Vector: c_uint = 113; -pub const CXType_IncompleteArray: c_uint = 114; -pub const CXType_VariableArray: c_uint = 115; -pub const CXType_DependentSizedArray: c_uint = 116; -pub const CXType_MemberPointer: c_uint = 117; -#[cfg(not(feature="llvm_stable"))] -pub const CXType_Auto: c_uint = 118; -#[cfg(not(feature="llvm_stable"))] -pub const CXType_Elaborated: c_uint = 119; -pub type Enum_CXCallingConv = c_uint; -pub const CXCallingConv_Default: c_uint = 0; -pub const CXCallingConv_C: c_uint = 1; -pub const CXCallingConv_X86StdCall: c_uint = 2; -pub const CXCallingConv_X86FastCall: c_uint = 3; -pub const CXCallingConv_X86ThisCall: c_uint = 4; -pub const CXCallingConv_X86Pascal: c_uint = 5; -pub const CXCallingConv_AAPCS: c_uint = 6; -pub const CXCallingConv_AAPCS_VFP: c_uint = 7; -pub const CXCallingConv_PnaclCall: c_uint = 8; -pub const CXCallingConv_IntelOclBicc: c_uint = 9; -pub const CXCallingConv_X86_64Win64: c_uint = 10; -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, Hash)] -pub struct CXType { - pub kind: Enum_CXTypeKind, - pub data: [*mut c_void; 2], -} -pub type Enum_CXTypeLayoutError = c_int; -pub const CXTypeLayoutError_Invalid: c_int = -1; -pub const CXTypeLayoutError_Incomplete: c_int = -2; -pub const CXTypeLayoutError_Dependent: c_int = -3; -pub const CXTypeLayoutError_NotConstantSize: c_int = -4; -pub const CXTypeLayoutError_InvalidFieldName: c_int = -5; -pub type Enum_CXRefQualifierKind = c_uint; -pub const CXRefQualifier_None: c_uint = 0; -pub const CXRefQualifier_LValue: c_uint = 1; -pub const CXRefQualifier_RValue: c_uint = 2; -pub type Enum_CX_CXXAccessSpecifier = c_uint; -pub const CX_CXXInvalidAccessSpecifier: c_uint = 0; -pub const CX_CXXPublic: c_uint = 1; -pub const CX_CXXProtected: c_uint = 2; -pub const CX_CXXPrivate: c_uint = 3; -pub type Enum_CXChildVisitResult = c_uint; -pub const CXChildVisit_Break: c_uint = 0; -pub const CXChildVisit_Continue: c_uint = 1; -pub const CXChildVisit_Recurse: c_uint = 2; -pub type CXCursorVisitor = - ::std::option::Option Enum_CXChildVisitResult>; -pub type CXObjCPropertyAttrKind = c_uint; -pub const CXObjCPropertyAttr_noattr: c_uint = 0; -pub const CXObjCPropertyAttr_readonly: c_uint = 1; -pub const CXObjCPropertyAttr_getter: c_uint = 2; -pub const CXObjCPropertyAttr_assign: c_uint = 4; -pub const CXObjCPropertyAttr_readwrite: c_uint = 8; -pub const CXObjCPropertyAttr_retain: c_uint = 16; -pub const CXObjCPropertyAttr_copy: c_uint = 32; -pub const CXObjCPropertyAttr_nonatomic: c_uint = 64; -pub const CXObjCPropertyAttr_setter: c_uint = 128; -pub const CXObjCPropertyAttr_atomic: c_uint = 256; -pub const CXObjCPropertyAttr_weak: c_uint = 512; -pub const CXObjCPropertyAttr_strong: c_uint = 1024; -pub const CXObjCPropertyAttr_unsafe_unretained: c_uint = 2048; -pub type CXObjCDeclQualifierKind = c_uint; -pub const CXObjCDeclQualifier_None: c_uint = 0; -pub const CXObjCDeclQualifier_In: c_uint = 1; -pub const CXObjCDeclQualifier_Inout: c_uint = 2; -pub const CXObjCDeclQualifier_Out: c_uint = 4; -pub const CXObjCDeclQualifier_Bycopy: c_uint = 8; -pub const CXObjCDeclQualifier_Byref: c_uint = 16; -pub const CXObjCDeclQualifier_Oneway: c_uint = 32; -pub type CXModule = *mut c_void; -pub type Enum_CXCommentKind = c_uint; -pub const CXComment_Null: c_uint = 0; -pub const CXComment_Text: c_uint = 1; -pub const CXComment_InlineCommand: c_uint = 2; -pub const CXComment_HTMLStartTag: c_uint = 3; -pub const CXComment_HTMLEndTag: c_uint = 4; -pub const CXComment_Paragraph: c_uint = 5; -pub const CXComment_BlockCommand: c_uint = 6; -pub const CXComment_ParamCommand: c_uint = 7; -pub const CXComment_TParamCommand: c_uint = 8; -pub const CXComment_VerbatimBlockCommand: c_uint = 9; -pub const CXComment_VerbatimBlockLine: c_uint = 10; -pub const CXComment_VerbatimLine: c_uint = 11; -pub const CXComment_FullComment: c_uint = 12; -pub type Enum_CXCommentInlineCommandRenderKind = c_uint; -pub const CXCommentInlineCommandRenderKind_Normal: c_uint = 0; -pub const CXCommentInlineCommandRenderKind_Bold: c_uint = 1; -pub const CXCommentInlineCommandRenderKind_Monospaced: c_uint = 2; -pub const CXCommentInlineCommandRenderKind_Emphasized: c_uint = 3; -pub type Enum_CXCommentParamPassDirection = c_uint; -pub const CXCommentParamPassDirection_In: c_uint = 0; -pub const CXCommentParamPassDirection_Out: c_uint = 1; -pub const CXCommentParamPassDirection_InOut: c_uint = 2; -pub type Enum_CXNameRefFlags = c_uint; -pub const CXNameRange_WantQualifier: c_uint = 1; -pub const CXNameRange_WantTemplateArgs: c_uint = 2; -pub const CXNameRange_WantSinglePiece: c_uint = 4; -pub type Enum_CXTokenKind = c_uint; -pub const CXToken_Punctuation: c_uint = 0; -pub const CXToken_Keyword: c_uint = 1; -pub const CXToken_Identifier: c_uint = 2; -pub const CXToken_Literal: c_uint = 3; -pub const CXToken_Comment: c_uint = 4; -pub type CXTokenKind = Enum_CXTokenKind; -pub type Enum_CXTemplateArgumentKind = c_uint; -pub const CXTemplateArgumentKind_Null: c_uint = 0; -pub const CXTemplateArgumentKind_Type: c_uint = 1; -pub const CXTemplateArgumentKind_Declaration: c_uint = 2; -pub const CXTemplateArgumentKind_NullPtr: c_uint = 3; -pub const CXTemplateArgumentKind_Integral: c_uint = 4; -pub const CXTemplateArgumentKind_Template: c_uint = 5; -pub const CXTemplateArgumentKind_TemplateExpansion: c_uint = 6; -pub const CXTemplateArgumentKind_Expression: c_uint = 7; -pub const CXTemplateArgumentKind_Pack: c_uint = 8; -pub const CXTemplateArgumentKind_Invalid: c_uint = 9; -pub type CXTemplateArgumentKind = Enum_CXTemplateArgumentKind; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXToken { - pub int_data: [c_uint; 4], - pub ptr_data: *mut c_void, -} -pub type CXCompletionString = *mut c_void; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXCompletionResult { - pub CursorKind: Enum_CXCursorKind, - pub CompletionString: CXCompletionString, -} -pub type Enum_CXCompletionChunkKind = c_uint; -pub const CXCompletionChunk_Optional: c_uint = 0; -pub const CXCompletionChunk_TypedText: c_uint = 1; -pub const CXCompletionChunk_Text: c_uint = 2; -pub const CXCompletionChunk_Placeholder: c_uint = 3; -pub const CXCompletionChunk_Informative: c_uint = 4; -pub const CXCompletionChunk_CurrentParameter: c_uint = 5; -pub const CXCompletionChunk_LeftParen: c_uint = 6; -pub const CXCompletionChunk_RightParen: c_uint = 7; -pub const CXCompletionChunk_LeftBracket: c_uint = 8; -pub const CXCompletionChunk_RightBracket: c_uint = 9; -pub const CXCompletionChunk_LeftBrace: c_uint = 10; -pub const CXCompletionChunk_RightBrace: c_uint = 11; -pub const CXCompletionChunk_LeftAngle: c_uint = 12; -pub const CXCompletionChunk_RightAngle: c_uint = 13; -pub const CXCompletionChunk_Comma: c_uint = 14; -pub const CXCompletionChunk_ResultType: c_uint = 15; -pub const CXCompletionChunk_Colon: c_uint = 16; -pub const CXCompletionChunk_SemiColon: c_uint = 17; -pub const CXCompletionChunk_Equal: c_uint = 18; -pub const CXCompletionChunk_HorizontalSpace: c_uint = 19; -pub const CXCompletionChunk_VerticalSpace: c_uint = 20; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXCodeCompleteResults { - pub Results: *mut CXCompletionResult, - pub NumResults: c_uint, -} -pub type Enum_CXCodeComplete_Flags = c_uint; -pub const CXCodeComplete_IncludeMacros: c_uint = 1; -pub const CXCodeComplete_IncludeCodePatterns: c_uint = 2; -pub const CXCodeComplete_IncludeBriefComments: c_uint = 4; -pub type Enum_CXCompletionContext = c_uint; -pub const CXCompletionContext_Unexposed: c_uint = 0; -pub const CXCompletionContext_AnyType: c_uint = 1; -pub const CXCompletionContext_AnyValue: c_uint = 2; -pub const CXCompletionContext_ObjCObjectValue: c_uint = 4; -pub const CXCompletionContext_ObjCSelectorValue: c_uint = 8; -pub const CXCompletionContext_CXXClassTypeValue: c_uint = 16; -pub const CXCompletionContext_DotMemberAccess: c_uint = 32; -pub const CXCompletionContext_ArrowMemberAccess: c_uint = 64; -pub const CXCompletionContext_ObjCPropertyAccess: c_uint = 128; -pub const CXCompletionContext_EnumTag: c_uint = 256; -pub const CXCompletionContext_UnionTag: c_uint = 512; -pub const CXCompletionContext_StructTag: c_uint = 1024; -pub const CXCompletionContext_ClassTag: c_uint = 2048; -pub const CXCompletionContext_Namespace: c_uint = 4096; -pub const CXCompletionContext_NestedNameSpecifier: c_uint = 8192; -pub const CXCompletionContext_ObjCInterface: c_uint = 16384; -pub const CXCompletionContext_ObjCProtocol: c_uint = 32768; -pub const CXCompletionContext_ObjCCategory: c_uint = 65536; -pub const CXCompletionContext_ObjCInstanceMessage: c_uint = 131072; -pub const CXCompletionContext_ObjCClassMessage: c_uint = 262144; -pub const CXCompletionContext_ObjCSelectorName: c_uint = 524288; -pub const CXCompletionContext_MacroName: c_uint = 1048576; -pub const CXCompletionContext_NaturalLanguage: c_uint = 2097152; -pub const CXCompletionContext_Unknown: c_uint = 4194303; -pub type CXInclusionVisitor = - ::std::option::Option; -pub type CXRemapping = *mut c_void; -pub type Enum_CXVisitorResult = c_uint; -pub const CXVisit_Break: c_uint = 0; -pub const CXVisit_Continue: c_uint = 1; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXCursorAndRangeVisitor { - pub context: *mut c_void, - pub visit: ::std::option::Option Enum_CXVisitorResult>, -} -pub type CXResult = c_uint; -pub const CXResult_Success: c_uint = 0; -pub const CXResult_Invalid: c_uint = 1; -pub const CXResult_VisitBreak: c_uint = 2; -pub type CXIdxClientFile = *mut c_void; -pub type CXIdxClientEntity = *mut c_void; -pub type CXIdxClientContainer = *mut c_void; -pub type CXIdxClientASTFile = *mut c_void; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxLoc { - pub ptr_data: [*mut c_void; 2], - pub int_data: c_uint, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxIncludedFileInfo { - pub hashLoc: CXIdxLoc, - pub filename: *const c_char, - pub file: CXFile, - pub isImport: c_int, - pub isAngled: c_int, - pub isModuleImport: c_int, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxImportedASTFileInfo { - pub file: CXFile, - pub module: CXModule, - pub loc: CXIdxLoc, - pub isImplicit: c_int, -} -pub type CXIdxEntityKind = c_uint; -pub const CXIdxEntity_Unexposed: c_uint = 0; -pub const CXIdxEntity_Typedef: c_uint = 1; -pub const CXIdxEntity_Function: c_uint = 2; -pub const CXIdxEntity_Variable: c_uint = 3; -pub const CXIdxEntity_Field: c_uint = 4; -pub const CXIdxEntity_EnumConstant: c_uint = 5; -pub const CXIdxEntity_ObjCClass: c_uint = 6; -pub const CXIdxEntity_ObjCProtocol: c_uint = 7; -pub const CXIdxEntity_ObjCCategory: c_uint = 8; -pub const CXIdxEntity_ObjCInstanceMethod: c_uint = 9; -pub const CXIdxEntity_ObjCClassMethod: c_uint = 10; -pub const CXIdxEntity_ObjCProperty: c_uint = 11; -pub const CXIdxEntity_ObjCIvar: c_uint = 12; -pub const CXIdxEntity_Enum: c_uint = 13; -pub const CXIdxEntity_Struct: c_uint = 14; -pub const CXIdxEntity_Union: c_uint = 15; -pub const CXIdxEntity_CXXClass: c_uint = 16; -pub const CXIdxEntity_CXXNamespace: c_uint = 17; -pub const CXIdxEntity_CXXNamespaceAlias: c_uint = 18; -pub const CXIdxEntity_CXXStaticVariable: c_uint = 19; -pub const CXIdxEntity_CXXStaticMethod: c_uint = 20; -pub const CXIdxEntity_CXXInstanceMethod: c_uint = 21; -pub const CXIdxEntity_CXXConstructor: c_uint = 22; -pub const CXIdxEntity_CXXDestructor: c_uint = 23; -pub const CXIdxEntity_CXXConversionFunction: c_uint = 24; -pub const CXIdxEntity_CXXTypeAlias: c_uint = 25; -pub const CXIdxEntity_CXXInterface: c_uint = 26; -pub type CXIdxEntityLanguage = c_uint; -pub const CXIdxEntityLang_None: c_uint = 0; -pub const CXIdxEntityLang_C: c_uint = 1; -pub const CXIdxEntityLang_ObjC: c_uint = 2; -pub const CXIdxEntityLang_CXX: c_uint = 3; -pub type CXIdxEntityCXXTemplateKind = c_uint; -pub const CXIdxEntity_NonTemplate: c_uint = 0; -pub const CXIdxEntity_Template: c_uint = 1; -pub const CXIdxEntity_TemplatePartialSpecialization: c_uint = 2; -pub const CXIdxEntity_TemplateSpecialization: c_uint = 3; -pub type CXIdxAttrKind = c_uint; -pub const CXIdxAttr_Unexposed: c_uint = 0; -pub const CXIdxAttr_IBAction: c_uint = 1; -pub const CXIdxAttr_IBOutlet: c_uint = 2; -pub const CXIdxAttr_IBOutletCollection: c_uint = 3; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxAttrInfo { - pub kind: CXIdxAttrKind, - pub cursor: CXCursor, - pub loc: CXIdxLoc, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxEntityInfo { - pub kind: CXIdxEntityKind, - pub templateKind: CXIdxEntityCXXTemplateKind, - pub lang: CXIdxEntityLanguage, - pub name: *const c_char, - pub USR: *const c_char, - pub cursor: CXCursor, - pub attributes: *const *const CXIdxAttrInfo, - pub numAttributes: c_uint, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxContainerInfo { - pub cursor: CXCursor, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxIBOutletCollectionAttrInfo { - pub attrInfo: *const CXIdxAttrInfo, - pub objcClass: *const CXIdxEntityInfo, - pub classCursor: CXCursor, - pub classLoc: CXIdxLoc, -} -pub type CXIdxDeclInfoFlags = c_uint; -pub const CXIdxDeclFlag_Skipped: c_uint = 1; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxDeclInfo { - pub entityInfo: *const CXIdxEntityInfo, - pub cursor: CXCursor, - pub loc: CXIdxLoc, - pub semanticContainer: *const CXIdxContainerInfo, - pub lexicalContainer: *const CXIdxContainerInfo, - pub isRedeclaration: c_int, - pub isDefinition: c_int, - pub isContainer: c_int, - pub declAsContainer: *const CXIdxContainerInfo, - pub isImplicit: c_int, - pub attributes: *const *const CXIdxAttrInfo, - pub numAttributes: c_uint, - pub flags: c_uint, -} -pub type CXIdxObjCContainerKind = c_uint; -pub const CXIdxObjCContainer_ForwardRef: c_uint = 0; -pub const CXIdxObjCContainer_Interface: c_uint = 1; -pub const CXIdxObjCContainer_Implementation: c_uint = 2; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxObjCContainerDeclInfo { - pub declInfo: *const CXIdxDeclInfo, - pub kind: CXIdxObjCContainerKind, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxBaseClassInfo { - pub base: *const CXIdxEntityInfo, - pub cursor: CXCursor, - pub loc: CXIdxLoc, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxObjCProtocolRefInfo { - pub protocol: *const CXIdxEntityInfo, - pub cursor: CXCursor, - pub loc: CXIdxLoc, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxObjCProtocolRefListInfo { - pub protocols: *const *const CXIdxObjCProtocolRefInfo, - pub numProtocols: c_uint, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxObjCInterfaceDeclInfo { - pub containerInfo: *const CXIdxObjCContainerDeclInfo, - pub superInfo: *const CXIdxBaseClassInfo, - pub protocols: *const CXIdxObjCProtocolRefListInfo, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxObjCCategoryDeclInfo { - pub containerInfo: *const CXIdxObjCContainerDeclInfo, - pub objcClass: *const CXIdxEntityInfo, - pub classCursor: CXCursor, - pub classLoc: CXIdxLoc, - pub protocols: *const CXIdxObjCProtocolRefListInfo, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxObjCPropertyDeclInfo { - pub declInfo: *const CXIdxDeclInfo, - pub getter: *const CXIdxEntityInfo, - pub setter: *const CXIdxEntityInfo, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxCXXClassDeclInfo { - pub declInfo: *const CXIdxDeclInfo, - pub bases: *const *const CXIdxBaseClassInfo, - pub numBases: c_uint, -} -pub type CXIdxEntityRefKind = c_uint; -pub const CXIdxEntityRef_Direct: c_uint = 1; -pub const CXIdxEntityRef_Implicit: c_uint = 2; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CXIdxEntityRefInfo { - pub kind: CXIdxEntityRefKind, - pub cursor: CXCursor, - pub loc: CXIdxLoc, - pub referencedEntity: *const CXIdxEntityInfo, - pub parentEntity: *const CXIdxEntityInfo, - pub container: *const CXIdxContainerInfo, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct IndexerCallbacks { - pub abortQuery: ::std::option::Option c_int>, - pub diagnostic: ::std::option::Option, - pub enteredMainFile: ::std::option::Option CXIdxClientFile>, - pub ppIncludedFile: ::std::option::Option CXIdxClientFile>, - pub importedASTFile: ::std::option::Option CXIdxClientASTFile>, - pub startedTranslationUnit: ::std::option::Option - CXIdxClientContainer>, - pub indexDeclaration: ::std::option::Option, - pub indexEntityReference: ::std::option::Option, -} -pub type CXIndexAction = *mut c_void; -pub type CXIndexOptFlags = c_uint; -pub const CXIndexOpt_None: c_uint = 0; -pub const CXIndexOpt_SuppressRedundantRefs: c_uint = 1; -pub const CXIndexOpt_IndexFunctionLocalSymbols: c_uint = 2; -pub const CXIndexOpt_IndexImplicitTemplateInstantiations: c_uint = 4; -pub const CXIndexOpt_SuppressWarnings: c_uint = 8; -pub const CXIndexOpt_SkipParsedBodiesInSession: c_uint = 16; -extern "C" { - pub fn clang_getCString(string: CXString) -> *const c_char; - pub fn clang_disposeString(string: CXString); - pub fn clang_createIndex(excludeDeclarationsFromPCH: c_int, - displayDiagnostics: c_int) -> CXIndex; - pub fn clang_disposeIndex(index: CXIndex); - pub fn clang_CXIndex_setGlobalOptions(arg1: CXIndex, - options: c_uint); - pub fn clang_CXIndex_getGlobalOptions(arg1: CXIndex) -> c_uint; - pub fn clang_getFileName(SFile: CXFile) -> CXString; - pub fn clang_getFileTime(SFile: CXFile) -> ::libc::time_t; - pub fn clang_getFileUniqueID(file: CXFile, outID: *mut CXFileUniqueID) -> - c_int; - pub fn clang_isFileMultipleIncludeGuarded(tu: CXTranslationUnit, - file: CXFile) -> c_uint; - pub fn clang_getFile(tu: CXTranslationUnit, - file_name: *const c_char) -> CXFile; - pub fn clang_getNullLocation() -> CXSourceLocation; - pub fn clang_equalLocations(loc1: CXSourceLocation, - loc2: CXSourceLocation) -> c_uint; - pub fn clang_getLocation(tu: CXTranslationUnit, file: CXFile, - line: c_uint, column: c_uint) -> - CXSourceLocation; - pub fn clang_getLocationForOffset(tu: CXTranslationUnit, file: CXFile, - offset: c_uint) -> - CXSourceLocation; - pub fn clang_Location_isInSystemHeader(location: CXSourceLocation) -> - c_int; - pub fn clang_Location_isFromMainFile(location: CXSourceLocation) -> - c_int; - pub fn clang_getNullRange() -> CXSourceRange; - pub fn clang_getRange(begin: CXSourceLocation, end: CXSourceLocation) -> - CXSourceRange; - pub fn clang_equalRanges(range1: CXSourceRange, range2: CXSourceRange) -> - c_uint; - pub fn clang_Range_isNull(range: CXSourceRange) -> c_int; - pub fn clang_getExpansionLocation(location: CXSourceLocation, - file: *mut CXFile, - line: *mut c_uint, - column: *mut c_uint, - offset: *mut c_uint); - pub fn clang_getPresumedLocation(location: CXSourceLocation, - filename: *mut CXString, - line: *mut c_uint, - column: *mut c_uint); - pub fn clang_getInstantiationLocation(location: CXSourceLocation, - file: *mut CXFile, - line: *mut c_uint, - column: *mut c_uint, - offset: *mut c_uint); - pub fn clang_getSpellingLocation(location: CXSourceLocation, - file: *mut CXFile, - line: *mut c_uint, - column: *mut c_uint, - offset: *mut c_uint); - pub fn clang_getFileLocation(location: CXSourceLocation, - file: *mut CXFile, line: *mut c_uint, - column: *mut c_uint, - offset: *mut c_uint); - pub fn clang_getRangeStart(range: CXSourceRange) -> CXSourceLocation; - pub fn clang_getRangeEnd(range: CXSourceRange) -> CXSourceLocation; - pub fn clang_getNumDiagnosticsInSet(Diags: CXDiagnosticSet) -> - c_uint; - pub fn clang_getDiagnosticInSet(Diags: CXDiagnosticSet, - Index: c_uint) -> CXDiagnostic; - pub fn clang_loadDiagnostics(file: *const c_char, - error: *mut Enum_CXLoadDiag_Error, - errorString: *mut CXString) -> - CXDiagnosticSet; - pub fn clang_disposeDiagnosticSet(Diags: CXDiagnosticSet); - pub fn clang_getChildDiagnostics(D: CXDiagnostic) -> CXDiagnosticSet; - pub fn clang_getNumDiagnostics(Unit: CXTranslationUnit) -> c_uint; - pub fn clang_getDiagnostic(Unit: CXTranslationUnit, Index: c_uint) - -> CXDiagnostic; - pub fn clang_getDiagnosticSetFromTU(Unit: CXTranslationUnit) -> - CXDiagnosticSet; - pub fn clang_disposeDiagnostic(Diagnostic: CXDiagnostic); - pub fn clang_formatDiagnostic(Diagnostic: CXDiagnostic, - Options: c_uint) -> CXString; - pub fn clang_defaultDiagnosticDisplayOptions() -> c_uint; - pub fn clang_getDiagnosticSeverity(arg1: CXDiagnostic) -> - Enum_CXDiagnosticSeverity; - pub fn clang_getDiagnosticLocation(arg1: CXDiagnostic) -> - CXSourceLocation; - pub fn clang_getDiagnosticSpelling(arg1: CXDiagnostic) -> CXString; - pub fn clang_getDiagnosticOption(Diag: CXDiagnostic, - Disable: *mut CXString) -> CXString; - pub fn clang_getDiagnosticCategory(arg1: CXDiagnostic) -> c_uint; - pub fn clang_getDiagnosticCategoryName(Category: c_uint) -> - CXString; - pub fn clang_getDiagnosticCategoryText(arg1: CXDiagnostic) -> CXString; - pub fn clang_getDiagnosticNumRanges(arg1: CXDiagnostic) -> c_uint; - pub fn clang_getDiagnosticRange(Diagnostic: CXDiagnostic, - Range: c_uint) -> CXSourceRange; - pub fn clang_getDiagnosticNumFixIts(Diagnostic: CXDiagnostic) -> - c_uint; - pub fn clang_getDiagnosticFixIt(Diagnostic: CXDiagnostic, - FixIt: c_uint, - ReplacementRange: *mut CXSourceRange) -> - CXString; - pub fn clang_getTranslationUnitSpelling(CTUnit: CXTranslationUnit) -> - CXString; - pub fn clang_createTranslationUnitFromSourceFile(CIdx: CXIndex, - source_filename: - *const c_char, - num_clang_command_line_args: - c_int, - clang_command_line_args: - *const *const c_char, - num_unsaved_files: - c_uint, - unsaved_files: - *mut Struct_CXUnsavedFile) - -> CXTranslationUnit; - pub fn clang_createTranslationUnit(arg1: CXIndex, - ast_filename: *const c_char) -> - CXTranslationUnit; - pub fn clang_defaultEditingTranslationUnitOptions() -> c_uint; - pub fn clang_parseTranslationUnit(CIdx: CXIndex, - source_filename: *const c_char, - command_line_args: - *const *const c_char, - num_command_line_args: c_int, - unsaved_files: - *mut Struct_CXUnsavedFile, - num_unsaved_files: c_uint, - options: c_uint) -> - CXTranslationUnit; - pub fn clang_defaultSaveOptions(TU: CXTranslationUnit) -> c_uint; - pub fn clang_saveTranslationUnit(TU: CXTranslationUnit, - FileName: *const c_char, - options: c_uint) -> - c_int; - pub fn clang_disposeTranslationUnit(arg1: CXTranslationUnit); - pub fn clang_defaultReparseOptions(TU: CXTranslationUnit) -> - c_uint; - pub fn clang_reparseTranslationUnit(TU: CXTranslationUnit, - num_unsaved_files: c_uint, - unsaved_files: - *mut Struct_CXUnsavedFile, - options: c_uint) -> - c_int; - pub fn clang_getTUResourceUsageName(kind: Enum_CXTUResourceUsageKind) -> - *const c_char; - pub fn clang_getCXTUResourceUsage(TU: CXTranslationUnit) -> - CXTUResourceUsage; - pub fn clang_disposeCXTUResourceUsage(usage: CXTUResourceUsage); - pub fn clang_getNullCursor() -> CXCursor; - pub fn clang_getTranslationUnitCursor(arg1: CXTranslationUnit) -> - CXCursor; - pub fn clang_equalCursors(arg1: CXCursor, arg2: CXCursor) -> - c_uint; - pub fn clang_Cursor_isNull(cursor: CXCursor) -> c_int; - pub fn clang_hashCursor(arg1: CXCursor) -> c_uint; - pub fn clang_getCursorKind(arg1: CXCursor) -> Enum_CXCursorKind; - pub fn clang_isDeclaration(arg1: Enum_CXCursorKind) -> c_uint; - pub fn clang_isReference(arg1: Enum_CXCursorKind) -> c_uint; - pub fn clang_isExpression(arg1: Enum_CXCursorKind) -> c_uint; - pub fn clang_isStatement(arg1: Enum_CXCursorKind) -> c_uint; - pub fn clang_isAttribute(arg1: Enum_CXCursorKind) -> c_uint; - pub fn clang_isInvalid(arg1: Enum_CXCursorKind) -> c_uint; - pub fn clang_isTranslationUnit(arg1: Enum_CXCursorKind) -> c_uint; - pub fn clang_isPreprocessing(arg1: Enum_CXCursorKind) -> c_uint; - pub fn clang_isUnexposed(arg1: Enum_CXCursorKind) -> c_uint; - pub fn clang_getCursorLinkage(cursor: CXCursor) -> Enum_CXLinkageKind; - pub fn clang_getCursorVisibility(cursor: CXCursor) -> Enum_CXVisibilityKind; - pub fn clang_getCursorAvailability(cursor: CXCursor) -> - Enum_CXAvailabilityKind; - pub fn clang_getCursorPlatformAvailability(cursor: CXCursor, - always_deprecated: - *mut c_int, - deprecated_message: - *mut CXString, - always_unavailable: - *mut c_int, - unavailable_message: - *mut CXString, - availability: - *mut CXPlatformAvailability, - availability_size: - c_int) -> - c_int; - pub fn clang_disposeCXPlatformAvailability(availability: - *mut CXPlatformAvailability); - pub fn clang_getCursorLanguage(cursor: CXCursor) -> Enum_CXLanguageKind; - pub fn clang_Cursor_getTranslationUnit(arg1: CXCursor) -> - CXTranslationUnit; - pub fn clang_createCXCursorSet() -> CXCursorSet; - pub fn clang_disposeCXCursorSet(cset: CXCursorSet); - pub fn clang_CXCursorSet_contains(cset: CXCursorSet, cursor: CXCursor) -> - c_uint; - pub fn clang_CXCursorSet_insert(cset: CXCursorSet, cursor: CXCursor) -> - c_uint; - pub fn clang_getCursorSemanticParent(cursor: CXCursor) -> CXCursor; - pub fn clang_getCursorLexicalParent(cursor: CXCursor) -> CXCursor; - pub fn clang_getOverriddenCursors(cursor: CXCursor, - overridden: *mut *mut CXCursor, - num_overridden: *mut c_uint); - pub fn clang_disposeOverriddenCursors(overridden: *mut CXCursor); - pub fn clang_getIncludedFile(cursor: CXCursor) -> CXFile; - pub fn clang_getCursor(arg1: CXTranslationUnit, arg2: CXSourceLocation) -> - CXCursor; - pub fn clang_getCursorLocation(arg1: CXCursor) -> CXSourceLocation; - pub fn clang_getCursorExtent(arg1: CXCursor) -> CXSourceRange; - pub fn clang_getCursorType(C: CXCursor) -> CXType; - pub fn clang_getTypeSpelling(CT: CXType) -> CXString; - pub fn clang_getTypedefDeclUnderlyingType(C: CXCursor) -> CXType; - pub fn clang_getEnumDeclIntegerType(C: CXCursor) -> CXType; - pub fn clang_getEnumConstantDeclValue(C: CXCursor) -> c_longlong; - pub fn clang_getEnumConstantDeclUnsignedValue(C: CXCursor) -> - c_ulonglong; - pub fn clang_getFieldDeclBitWidth(C: CXCursor) -> c_int; - 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) -> - c_longlong; - pub fn clang_Cursor_getTemplateArgumentUnsignedValue(C: CXCursor, i: c_uint) -> - c_ulonglong; - pub fn clang_equalTypes(A: CXType, B: CXType) -> c_uint; - pub fn clang_getCanonicalType(T: CXType) -> CXType; - pub fn clang_isConstQualifiedType(T: CXType) -> c_uint; - pub fn clang_isVolatileQualifiedType(T: CXType) -> c_uint; - pub fn clang_isRestrictQualifiedType(T: CXType) -> c_uint; - pub fn clang_getPointeeType(T: CXType) -> CXType; - pub fn clang_getTypeDeclaration(T: CXType) -> CXCursor; - pub fn clang_getDeclObjCTypeEncoding(C: CXCursor) -> CXString; - pub fn clang_getTypeKindSpelling(K: Enum_CXTypeKind) -> CXString; - pub fn clang_getFunctionTypeCallingConv(T: CXType) -> Enum_CXCallingConv; - pub fn clang_getResultType(T: CXType) -> CXType; - pub fn clang_getNumArgTypes(T: CXType) -> c_int; - pub fn clang_getArgType(T: CXType, i: c_uint) -> CXType; - pub fn clang_isFunctionTypeVariadic(T: CXType) -> c_uint; - pub fn clang_getCursorResultType(C: CXCursor) -> CXType; - pub fn clang_isPODType(T: CXType) -> c_uint; - pub fn clang_getElementType(T: CXType) -> CXType; - pub fn clang_getNumElements(T: CXType) -> c_longlong; - pub fn clang_getArrayElementType(T: CXType) -> CXType; - pub fn clang_getArraySize(T: CXType) -> c_longlong; - pub fn clang_Type_getAlignOf(T: CXType) -> c_longlong; - pub fn clang_Type_getClassType(T: CXType) -> CXType; - pub fn clang_Type_getSizeOf(T: CXType) -> c_longlong; - pub fn clang_Type_getOffsetOf(T: CXType, S: *const c_char) -> - c_longlong; - pub fn clang_Type_getCXXRefQualifier(T: CXType) -> - Enum_CXRefQualifierKind; - pub fn clang_Type_getNumTemplateArguments(T: CXType) -> c_int; - pub fn clang_Type_getTemplateArgumentAsType(T: CXType, i: c_int) -> - CXType; - #[cfg(not(feature="llvm_stable"))] - pub fn clang_Type_getNamedType(CT: CXType) -> CXType; - pub fn clang_Cursor_isBitField(C: CXCursor) -> c_uint; - #[cfg(not(feature="llvm_stable"))] - pub fn clang_Cursor_isFunctionInlined(C: CXCursor) -> c_uint; - pub fn clang_isVirtualBase(arg1: CXCursor) -> c_uint; - pub fn clang_getCXXAccessSpecifier(arg1: CXCursor) -> - Enum_CX_CXXAccessSpecifier; - pub fn clang_getNumOverloadedDecls(cursor: CXCursor) -> c_uint; - pub fn clang_getOverloadedDecl(cursor: CXCursor, index: c_uint) -> - CXCursor; - pub fn clang_getIBOutletCollectionType(arg1: CXCursor) -> CXType; - pub fn clang_visitChildren(parent: CXCursor, visitor: CXCursorVisitor, - client_data: CXClientData) -> c_uint; - pub fn clang_getCursorUSR(arg1: CXCursor) -> CXString; - pub fn clang_constructUSR_ObjCClass(class_name: *const c_char) -> - CXString; - pub fn clang_constructUSR_ObjCCategory(class_name: *const c_char, - category_name: - *const c_char) -> - CXString; - pub fn clang_constructUSR_ObjCProtocol(protocol_name: - *const c_char) -> - CXString; - pub fn clang_constructUSR_ObjCIvar(name: *const c_char, - classUSR: CXString) -> CXString; - pub fn clang_constructUSR_ObjCMethod(name: *const c_char, - isInstanceMethod: c_uint, - classUSR: CXString) -> CXString; - pub fn clang_constructUSR_ObjCProperty(property: *const c_char, - classUSR: CXString) -> CXString; - pub fn clang_getCursorSpelling(arg1: CXCursor) -> CXString; - pub fn clang_Cursor_getSpellingNameRange(arg1: CXCursor, - 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; - pub fn clang_isCursorDefinition(arg1: CXCursor) -> c_uint; - pub fn clang_getCanonicalCursor(arg1: CXCursor) -> CXCursor; - pub fn clang_Cursor_getObjCSelectorIndex(arg1: CXCursor) -> c_int; - pub fn clang_Cursor_isDynamicCall(C: CXCursor) -> c_int; - pub fn clang_Cursor_getReceiverType(C: CXCursor) -> CXType; - pub fn clang_Cursor_getObjCPropertyAttributes(C: CXCursor, - reserved: c_uint) -> - c_uint; - pub fn clang_Cursor_getObjCDeclQualifiers(C: CXCursor) -> c_uint; - pub fn clang_Cursor_isObjCOptional(C: CXCursor) -> c_uint; - pub fn clang_Cursor_isVariadic(C: CXCursor) -> c_uint; - pub fn clang_Cursor_getCommentRange(C: CXCursor) -> CXSourceRange; - pub fn clang_Cursor_getRawCommentText(C: CXCursor) -> CXString; - pub fn clang_Cursor_getBriefCommentText(C: CXCursor) -> CXString; - 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; - pub fn clang_Module_getFullName(Module: CXModule) -> CXString; - pub fn clang_Module_getNumTopLevelHeaders(arg1: CXTranslationUnit, - Module: CXModule) -> - c_uint; - pub fn clang_Module_getTopLevelHeader(arg1: CXTranslationUnit, - Module: CXModule, - Index: c_uint) -> CXFile; - pub fn clang_Comment_getKind(Comment: CXComment) -> Enum_CXCommentKind; - pub fn clang_Comment_getNumChildren(Comment: CXComment) -> c_uint; - pub fn clang_Comment_getChild(Comment: CXComment, - ChildIdx: c_uint) -> CXComment; - pub fn clang_Comment_isWhitespace(Comment: CXComment) -> c_uint; - pub fn clang_InlineContentComment_hasTrailingNewline(Comment: CXComment) - -> c_uint; - pub fn clang_TextComment_getText(Comment: CXComment) -> CXString; - pub fn clang_InlineCommandComment_getCommandName(Comment: CXComment) -> - CXString; - pub fn clang_InlineCommandComment_getRenderKind(Comment: CXComment) -> - Enum_CXCommentInlineCommandRenderKind; - pub fn clang_InlineCommandComment_getNumArgs(Comment: CXComment) -> - c_uint; - pub fn clang_InlineCommandComment_getArgText(Comment: CXComment, - ArgIdx: c_uint) -> - CXString; - pub fn clang_HTMLTagComment_getTagName(Comment: CXComment) -> CXString; - pub fn clang_HTMLStartTagComment_isSelfClosing(Comment: CXComment) -> - c_uint; - pub fn clang_HTMLStartTag_getNumAttrs(Comment: CXComment) -> - c_uint; - pub fn clang_HTMLStartTag_getAttrName(Comment: CXComment, - AttrIdx: c_uint) -> - CXString; - pub fn clang_HTMLStartTag_getAttrValue(Comment: CXComment, - AttrIdx: c_uint) -> - CXString; - pub fn clang_BlockCommandComment_getCommandName(Comment: CXComment) -> - CXString; - pub fn clang_BlockCommandComment_getNumArgs(Comment: CXComment) -> - c_uint; - pub fn clang_BlockCommandComment_getArgText(Comment: CXComment, - ArgIdx: c_uint) -> - CXString; - pub fn clang_BlockCommandComment_getParagraph(Comment: CXComment) -> - CXComment; - pub fn clang_ParamCommandComment_getParamName(Comment: CXComment) -> - CXString; - pub fn clang_ParamCommandComment_isParamIndexValid(Comment: CXComment) -> - c_uint; - pub fn clang_ParamCommandComment_getParamIndex(Comment: CXComment) -> - c_uint; - pub fn clang_ParamCommandComment_isDirectionExplicit(Comment: CXComment) - -> c_uint; - pub fn clang_ParamCommandComment_getDirection(Comment: CXComment) -> - Enum_CXCommentParamPassDirection; - pub fn clang_TParamCommandComment_getParamName(Comment: CXComment) -> - CXString; - pub fn clang_TParamCommandComment_isParamPositionValid(Comment: CXComment) - -> c_uint; - pub fn clang_TParamCommandComment_getDepth(Comment: CXComment) -> - c_uint; - pub fn clang_TParamCommandComment_getIndex(Comment: CXComment, - Depth: c_uint) -> - c_uint; - pub fn clang_VerbatimBlockLineComment_getText(Comment: CXComment) -> - CXString; - pub fn clang_VerbatimLineComment_getText(Comment: CXComment) -> CXString; - pub fn clang_HTMLTagComment_getAsString(Comment: CXComment) -> CXString; - 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; - pub fn clang_getTemplateCursorKind(C: CXCursor) -> Enum_CXCursorKind; - pub fn clang_getSpecializedCursorTemplate(C: CXCursor) -> CXCursor; - pub fn clang_getCursorReferenceNameRange(C: CXCursor, - NameFlags: c_uint, - PieceIndex: c_uint) -> - CXSourceRange; - pub fn clang_getTokenKind(arg1: CXToken) -> CXTokenKind; - pub fn clang_getTokenSpelling(arg1: CXTranslationUnit, arg2: CXToken) -> - CXString; - pub fn clang_getTokenLocation(arg1: CXTranslationUnit, arg2: CXToken) -> - CXSourceLocation; - pub fn clang_getTokenExtent(arg1: CXTranslationUnit, arg2: CXToken) -> - CXSourceRange; - pub fn clang_tokenize(TU: CXTranslationUnit, Range: CXSourceRange, - Tokens: *mut *mut CXToken, - NumTokens: *mut c_uint); - pub fn clang_annotateTokens(TU: CXTranslationUnit, Tokens: *mut CXToken, - NumTokens: c_uint, - Cursors: *mut CXCursor); - pub fn clang_disposeTokens(TU: CXTranslationUnit, Tokens: *mut CXToken, - NumTokens: c_uint); - pub fn clang_getCursorKindSpelling(Kind: Enum_CXCursorKind) -> CXString; - pub fn clang_getDefinitionSpellingAndExtent(arg1: CXCursor, - startBuf: - *mut *const c_char, - endBuf: - *mut *const c_char, - startLine: - *mut c_uint, - startColumn: - *mut c_uint, - endLine: *mut c_uint, - endColumn: - *mut c_uint); - pub fn clang_enableStackTraces(); - pub fn clang_executeOnThread(_fn: - ::std::option::Option, - user_data: *mut c_void, - stack_size: c_uint); - pub fn clang_getCompletionChunkKind(completion_string: CXCompletionString, - chunk_number: c_uint) -> - Enum_CXCompletionChunkKind; - pub fn clang_getCompletionChunkText(completion_string: CXCompletionString, - chunk_number: c_uint) -> - CXString; - pub fn clang_getCompletionChunkCompletionString(completion_string: - CXCompletionString, - chunk_number: - c_uint) -> - CXCompletionString; - pub fn clang_getNumCompletionChunks(completion_string: CXCompletionString) - -> c_uint; - pub fn clang_getCompletionPriority(completion_string: CXCompletionString) - -> c_uint; - pub fn clang_getCompletionAvailability(completion_string: - CXCompletionString) -> - Enum_CXAvailabilityKind; - pub fn clang_getCompletionNumAnnotations(completion_string: - CXCompletionString) -> - c_uint; - pub fn clang_getCompletionAnnotation(completion_string: - CXCompletionString, - annotation_number: c_uint) -> - CXString; - pub fn clang_getCompletionParent(completion_string: CXCompletionString, - kind: *mut Enum_CXCursorKind) -> - CXString; - pub fn clang_getCompletionBriefComment(completion_string: - CXCompletionString) -> - CXString; - pub fn clang_getCursorCompletionString(cursor: CXCursor) -> - CXCompletionString; - pub fn clang_defaultCodeCompleteOptions() -> c_uint; - pub fn clang_codeCompleteAt(TU: CXTranslationUnit, - complete_filename: *const c_char, - complete_line: c_uint, - complete_column: c_uint, - unsaved_files: *mut Struct_CXUnsavedFile, - num_unsaved_files: c_uint, - options: c_uint) -> - *mut CXCodeCompleteResults; - pub fn clang_sortCodeCompletionResults(Results: *mut CXCompletionResult, - NumResults: c_uint); - pub fn clang_disposeCodeCompleteResults(Results: - *mut CXCodeCompleteResults); - pub fn clang_codeCompleteGetNumDiagnostics(Results: - *mut CXCodeCompleteResults) - -> c_uint; - pub fn clang_codeCompleteGetDiagnostic(Results: - *mut CXCodeCompleteResults, - Index: c_uint) -> - CXDiagnostic; - pub fn clang_codeCompleteGetContexts(Results: *mut CXCodeCompleteResults) - -> c_ulonglong; - pub fn clang_codeCompleteGetContainerKind(Results: - *mut CXCodeCompleteResults, - IsIncomplete: - *mut c_uint) -> - Enum_CXCursorKind; - pub fn clang_codeCompleteGetContainerUSR(Results: - *mut CXCodeCompleteResults) - -> CXString; - pub fn clang_codeCompleteGetObjCSelector(Results: - *mut CXCodeCompleteResults) - -> CXString; - pub fn clang_getClangVersion() -> CXString; - pub fn clang_toggleCrashRecovery(isEnabled: c_uint); - pub fn clang_getInclusions(tu: CXTranslationUnit, - visitor: CXInclusionVisitor, - client_data: CXClientData); - pub fn clang_getRemappings(path: *const c_char) -> CXRemapping; - pub fn clang_getRemappingsFromFileList(filePaths: - *mut *const c_char, - numFiles: c_uint) -> - CXRemapping; - pub fn clang_remap_getNumFiles(arg1: CXRemapping) -> c_uint; - pub fn clang_remap_getFilenames(arg1: CXRemapping, index: c_uint, - original: *mut CXString, - transformed: *mut CXString); - pub fn clang_remap_dispose(arg1: CXRemapping); - pub fn clang_findReferencesInFile(cursor: CXCursor, file: CXFile, - visitor: CXCursorAndRangeVisitor) -> - CXResult; - pub fn clang_findIncludesInFile(TU: CXTranslationUnit, file: CXFile, - visitor: CXCursorAndRangeVisitor) -> - CXResult; - pub fn clang_index_isEntityObjCContainerKind(arg1: CXIdxEntityKind) -> - c_int; - pub fn clang_index_getObjCContainerDeclInfo(arg1: *const CXIdxDeclInfo) -> - *const CXIdxObjCContainerDeclInfo; - pub fn clang_index_getObjCInterfaceDeclInfo(arg1: *const CXIdxDeclInfo) -> - *const CXIdxObjCInterfaceDeclInfo; - pub fn clang_index_getObjCCategoryDeclInfo(arg1: *const CXIdxDeclInfo) -> - *const CXIdxObjCCategoryDeclInfo; - pub fn clang_index_getObjCProtocolRefListInfo(arg1: *const CXIdxDeclInfo) - -> *const CXIdxObjCProtocolRefListInfo; - pub fn clang_index_getObjCPropertyDeclInfo(arg1: *const CXIdxDeclInfo) -> - *const CXIdxObjCPropertyDeclInfo; - pub fn clang_index_getIBOutletCollectionAttrInfo(arg1: - *const CXIdxAttrInfo) - -> *const CXIdxIBOutletCollectionAttrInfo; - pub fn clang_index_getCXXClassDeclInfo(arg1: *const CXIdxDeclInfo) -> - *const CXIdxCXXClassDeclInfo; - pub fn clang_index_getClientContainer(arg1: *const CXIdxContainerInfo) -> - CXIdxClientContainer; - pub fn clang_index_setClientContainer(arg1: *const CXIdxContainerInfo, - arg2: CXIdxClientContainer); - pub fn clang_index_getClientEntity(arg1: *const CXIdxEntityInfo) -> - CXIdxClientEntity; - pub fn clang_index_setClientEntity(arg1: *const CXIdxEntityInfo, - arg2: CXIdxClientEntity); - pub fn clang_IndexAction_create(CIdx: CXIndex) -> CXIndexAction; - pub fn clang_IndexAction_dispose(arg1: CXIndexAction); - pub fn clang_indexSourceFile(arg1: CXIndexAction, - client_data: CXClientData, - index_callbacks: *mut IndexerCallbacks, - index_callbacks_size: c_uint, - index_options: c_uint, - source_filename: *const c_char, - command_line_args: - *const *const c_char, - num_command_line_args: c_int, - unsaved_files: *mut Struct_CXUnsavedFile, - num_unsaved_files: c_uint, - out_TU: *mut CXTranslationUnit, - TU_options: c_uint) -> c_int; - pub fn clang_indexTranslationUnit(arg1: CXIndexAction, - client_data: CXClientData, - index_callbacks: *mut IndexerCallbacks, - index_callbacks_size: c_uint, - index_options: c_uint, - arg2: CXTranslationUnit) -> - c_int; - pub fn clang_indexLoc_getFileLocation(loc: CXIdxLoc, - indexFile: *mut CXIdxClientFile, - file: *mut CXFile, - line: *mut c_uint, - column: *mut c_uint, - offset: *mut c_uint); - pub fn clang_indexLoc_getCXSourceLocation(loc: CXIdxLoc) -> - CXSourceLocation; -} diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs deleted file mode 100644 index 6e5a6f0e..00000000 --- a/src/codegen/helpers.rs +++ /dev/null @@ -1,135 +0,0 @@ -//! Helpers for code generation that don't need macro expansion. - -use aster; -use ir::layout::Layout; -use syntax::ast; -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 { - 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 { - aster::ty::TyBuilder::new().array(data_len).build(inner_ty) - } - } -} - -pub mod ast_ty { - use aster; - use ir::context::BindgenContext; - use ir::ty::FloatKind; - use syntax::ast; - use syntax::ptr::P; - - pub fn raw_type(ctx: &BindgenContext, name: &str) -> P { - let ident = ctx.rust_ident_raw(&name); - match ctx.options().ctypes_prefix { - Some(ref prefix) => { - let prefix = ctx.rust_ident_raw(prefix); - quote_ty!(ctx.ext_cx(), $prefix::$ident) - } - None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident), - } - } - - pub fn float_kind_rust_type(ctx: &BindgenContext, - fk: FloatKind) - -> P { - macro_rules! raw { - ($ty: ident) => { - raw_type(ctx, stringify!($ty)) - } - } - // TODO: we probably should just take the type layout into - // account? - // - // Also, maybe this one shouldn't be the default? - // - // FIXME: `c_longdouble` doesn't seem to be defined in some - // systems, so we use `c_double` directly. - match (fk, ctx.options().convert_floats) { - (FloatKind::Float, true) => aster::ty::TyBuilder::new().f32(), - (FloatKind::Double, true) | - (FloatKind::LongDouble, true) => aster::ty::TyBuilder::new().f64(), - (FloatKind::Float, false) => raw!(c_float), - (FloatKind::Double, false) | - (FloatKind::LongDouble, false) => raw!(c_double), - (FloatKind::Float128, _) => { - aster::ty::TyBuilder::new().array(16).u8() - } - } - } - - pub fn int_expr(val: i64) -> P { - use std::i64; - let expr = aster::AstBuilder::new().expr(); - - // This is not representable as an i64 if it's negative, so we - // special-case it. - // - // Fix in aster incoming. - if val == i64::MIN { - expr.neg().uint(1u64 << 63) - } else { - expr.int(val) - } - } -} diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs deleted file mode 100755 index 8e04fd7c..00000000 --- a/src/codegen/mod.rs +++ /dev/null @@ -1,2121 +0,0 @@ -mod helpers; - - -use aster; - -use ir::annotations::FieldAccessorKind; -use ir::comp::{CompInfo, CompKind, Field, Method}; -use ir::context::{BindgenContext, ItemId}; -use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; -use ir::function::{Function, FunctionSig}; -use ir::int::IntKind; -use ir::item::{Item, ItemCanonicalName, ItemCanonicalPath}; -use ir::item_kind::ItemKind; -use ir::layout::Layout; -use ir::module::Module; -use ir::ty::{Type, TypeKind}; -use ir::type_collector::ItemSet; -use ir::var::Var; -use self::helpers::{BlobTyBuilder, attributes}; - -use std::borrow::Cow; -use std::collections::HashSet; -use std::collections::hash_map::{Entry, HashMap}; -use std::fmt::Write; -use std::mem; -use std::ops; -use syntax::abi::Abi; -use syntax::ast; -use syntax::codemap::{Span, respan}; -use syntax::ptr::P; - -fn root_import(ctx: &BindgenContext) -> P { - 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>, - saw_union: bool, - items_seen: HashSet, - /// The set of generated function/var names, needed because in C/C++ is - /// legal to do something like: - /// - /// ```c++ - /// extern "C" { - /// void foo(); - /// extern int bar; - /// } - /// - /// extern "C" { - /// void foo(); - /// extern int bar; - /// } - /// ``` - /// - /// Being these two different declarations. - functions_seen: HashSet, - vars_seen: HashSet, - - /// Used for making bindings to overloaded functions. Maps from a canonical - /// function name to the number of overloads we have already codegen'd for - /// that name. This lets us give each overload a unique suffix. - overload_counters: HashMap, -} - -impl CodegenResult { - fn new() -> Self { - CodegenResult { - items: vec![], - saw_union: false, - items_seen: Default::default(), - functions_seen: Default::default(), - vars_seen: Default::default(), - overload_counters: 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()); - } - - /// Get the overload number for the given function name. Increments the - /// counter internally so the next time we ask for the overload for this - /// name, we get the incremented value, and so on. - fn overload_number(&mut self, name: &str) -> u32 { - let mut counter = - self.overload_counters.entry(name.into()).or_insert(0); - let number = *counter; - *counter += 1; - number - } - - fn seen_var(&self, name: &str) -> bool { - self.vars_seen.contains(name) - } - - fn saw_var(&mut self, name: &str) { - self.vars_seen.insert(name.into()); - } - - fn inner(&mut self, cb: F) -> Vec> - 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>; - - 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(mut self, items: I) -> Self - where I: IntoIterator, - { - self.inner.items.extend(items.into_iter()); - self - } - - fn build(self, ctx: &BindgenContext) -> P { - 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; -} - -impl ToPtr for P { - 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 canonical_name = item.canonical_name(ctx); - - if result.seen_var(&canonical_name) { - return; - } - result.saw_var(&canonical_name); - - let ty = self.ty().to_rust_ty(ctx); - - if let Some(val) = self.val() { - let const_item = aster::AstBuilder::new() - .item() - .pub_() - .const_(canonical_name) - .expr() - .build(helpers::ast_ty::int_expr(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 canonical_name != self.name() { - attrs.push(attributes::link_name(self.name())); - } - - let item = ast::ForeignItem { - ident: ctx.rust_ident_raw(&canonical_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::Complex(..) | - TypeKind::Array(..) | - TypeKind::Pointer(..) | - TypeKind::BlockPointer | - 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::TemplateAlias(inner, _) => { - // NB: The inner Alias will pick the correct - // applicable_template_args. - let inner_item = ctx.resolve_item(inner); - inner_item.expect_type().codegen(ctx, result, inner_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 \ - parameter: {:?}", 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.canonical_name(ctx)) - } -} - -impl<'a> ItemToRustTy for Vtable<'a> { - fn to_rust_ty(&self, ctx: &BindgenContext) -> P { - 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, - methods: &mut Vec) { - 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; - let prefix = ctx.trait_prefix(); - // 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 { - ::$prefix::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 is_union = self.kind() == CompKind::Union; - let mut derives = vec![]; - let ty = item.expect_type(); - if ty.can_derive_debug(ctx) { - derives.push("Debug"); - } - - if item.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 = if is_union && ctx.options().unstable_rust { - aster::AstBuilder::new() - .item() - .pub_() - .with_attrs(attributes) - .union_(&canonical_name) - } else { - 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_id) in applicable_template_args.iter().enumerate() { - let template_arg_ty = ctx.resolve_type(*ty_id); - if base_ty.signature_contains_named_type(ctx, template_arg_ty) { - template_args_used[i] = true; - } - } - - let inner = base.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); - } - 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 = 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_id) in applicable_template_args.iter().enumerate() { - let template_arg = ctx.resolve_type(*ty_id); - if field_ty.signature_contains_named_type(ctx, template_arg) { - template_args_used[i] = true; - } - } - - let ty = field.ty().to_rust_ty(ctx); - - // NB: In unstable rust we use proper `union` types. - let ty = if is_union && !ctx.options().unstable_rust { - 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 && !ctx.options().unstable_rust { - 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 prefix = ctx.trait_prefix(); - let phantom = quote_ty!(ctx.ext_cx(), - ::$prefix::marker::PhantomData<$ident>); - let field = - StructFieldBuilder::named(format!("_phantom_{}", i)) - .pub_() - .build_ty(phantom); - fields.push(field) - } - } - - - let mut generics = aster::AstBuilder::new().generics(); - 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 = format!("bindgen_test_layout_{}", canonical_name); - let fn_name = ctx.rust_ident_raw(&fn_name); - let ident = ctx.rust_ident_raw(&canonical_name); - let prefix = ctx.trait_prefix(); - let size_of_expr = quote_expr!(ctx.ext_cx(), - ::$prefix::mem::size_of::<$ident>()); - let align_of_expr = quote_expr!(ctx.ext_cx(), - ::$prefix::mem::align_of::<$ident>()); - let size = layout.size; - let align = layout.align; - let item = quote_item!(ctx.ext_cx(), - #[test] - fn $fn_name() { - assert_eq!($size_of_expr, $size); - 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, - method_names: &mut HashMap, - result: &mut CodegenResult, - parent: &Item); -} - -impl MethodCodegen for Method { - fn codegen_method(&self, - ctx: &BindgenContext, - methods: &mut Vec, - method_names: &mut HashMap, - 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::>(); - - 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); - } -} - -/// A helper type to construct enums, either bitfield ones or rust-style ones. -enum EnumBuilder<'a> { - Rust(aster::item::ItemEnumBuilder), - Bitfield { - canonical_name: &'a str, - aster: P, - }, -} - -impl<'a> EnumBuilder<'a> { - /// Create a new enum given an item builder, a canonical name, a name for - /// the representation, and whether it should be represented as a rust enum. - fn new(aster: aster::item::ItemBuilder, - name: &'a str, - repr_name: &str, - is_rust: bool) - -> Self { - if is_rust { - EnumBuilder::Rust(aster.enum_(name)) - } else { - EnumBuilder::Bitfield { - canonical_name: name, - aster: aster.tuple_struct(name) - .field() - .pub_() - .ty() - .id(repr_name) - .build(), - } - } - } - - /// Add a variant to this enum. - fn with_variant(self, - ctx: &BindgenContext, - variant: &EnumVariant, - mangling_prefix: Option<&String>, - rust_ty: P, - result: &mut CodegenResult) - -> Self { - let variant_name = ctx.rust_mangle(variant.name()); - let expr = aster::AstBuilder::new().expr(); - let expr = match variant.val() { - EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v), - EnumVariantValue::Unsigned(v) => expr.uint(v), - }; - - match self { - EnumBuilder::Rust(b) => { - EnumBuilder::Rust(b.with_variant_(ast::Variant_ { - name: ctx.rust_ident(&*variant_name), - attrs: vec![], - data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), - disr_expr: Some(expr), - })) - } - EnumBuilder::Bitfield { canonical_name, .. } => { - let constant_name = match mangling_prefix { - Some(prefix) => { - Cow::Owned(format!("{}_{}", prefix, variant_name)) - } - None => variant_name, - }; - - let constant = aster::AstBuilder::new() - .item() - .pub_() - .const_(&*constant_name) - .expr() - .call() - .id(canonical_name) - .arg() - .build(expr) - .build() - .build(rust_ty); - result.push(constant); - self - } - } - } - - fn build(self, - ctx: &BindgenContext, - rust_ty: P, - result: &mut CodegenResult) - -> P { - match self { - EnumBuilder::Rust(b) => b.build(), - EnumBuilder::Bitfield { canonical_name, aster } => { - let rust_ty_name = ctx.rust_ident_raw(canonical_name); - let prefix = ctx.trait_prefix(); - - let impl_ = quote_item!(ctx.ext_cx(), - impl ::$prefix::ops::BitOr<$rust_ty> for $rust_ty { - type Output = Self; - - #[inline] - fn bitor(self, other: Self) -> Self { - $rust_ty_name(self.0 | other.0) - } - } - ) - .unwrap(); - - result.push(impl_); - aster - } - } - } -} - -impl CodeGenerator for Enum { - type Extra = Item; - - fn codegen(&self, - ctx: &BindgenContext, - result: &mut CodegenResult, - item: &Item) { - let name = item.canonical_name(ctx); - let enum_ty = item.expect_type(); - let layout = enum_ty.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_(); - - let is_bitfield = { - ctx.options().bitfield_enums.matches(&name) || - (enum_ty.name().is_none() && - self.variants() - .iter() - .any(|v| ctx.options().bitfield_enums.matches(&v.name()))) - }; - - let is_rust_enum = !is_bitfield; - - // FIXME: Rust forbids repr with empty enums. Remove this condition when - // this is allowed. - if is_rust_enum { - if !self.variants().is_empty() { - builder = builder.with_attr(attributes::repr(repr_name)); - } - } else { - builder = builder.with_attr(attributes::repr("C")); - } - - 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); - - 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, - 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); - } - - let mut builder = - EnumBuilder::new(builder, &name, repr_name, is_rust_enum); - - // A map where we keep a value -> variant relation. - let mut seen_values = HashMap::<_, String>::new(); - let enum_rust_ty = item.to_rust_ty(ctx); - let is_toplevel = item.is_toplevel(ctx); - - // Used to mangle the constants we generate in the unnamed-enum case. - let parent_canonical_name = if is_toplevel { - None - } else { - Some(item.parent_id().canonical_name(ctx)) - }; - - let constant_mangling_prefix = if enum_ty.name().is_none() { - parent_canonical_name.as_ref().map(|n| &*n) - } else { - Some(&name) - }; - - for variant in self.variants().iter() { - match seen_values.entry(variant.val()) { - Entry::Occupied(ref entry) => { - if is_rust_enum { - 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); - } else { - builder = builder.with_variant(ctx, - variant, - constant_mangling_prefix, - enum_rust_ty.clone(), - result); - } - } - Entry::Vacant(entry) => { - builder = builder.with_variant(ctx, - variant, - constant_mangling_prefix, - enum_rust_ty.clone(), - result); - - let variant_name = ctx.rust_mangle(variant.name()); - - // If it's an unnamed enum, we also generate a constant so - // it can be properly accessed. - if is_rust_enum && enum_ty.name().is_none() { - // NB: if we want to do this for other kind of nested - // enums we can probably mangle the name. - let mangled_name = if is_toplevel { - variant_name.clone() - } else { - let parent_name = parent_canonical_name.as_ref() - .unwrap(); - - Cow::Owned( - format!("{}_{}", parent_name, variant_name)) - }; - - add_constant(enum_ty, - &name, - &mangled_name, - &variant_name, - enum_rust_ty.clone(), - result); - } - - entry.insert(variant_name.into_owned()); - } - } - } - - let enum_ = builder.build(ctx, enum_rust_ty, result); - result.push(enum_); - } -} - -trait ToRustTy { - type Extra; - - fn to_rust_ty(&self, - ctx: &BindgenContext, - extra: &Self::Extra) - -> P; -} - -trait ItemToRustTy { - fn to_rust_ty(&self, ctx: &BindgenContext) -> P; -} - -// Convenience implementation. -impl ItemToRustTy for ItemId { - fn to_rust_ty(&self, ctx: &BindgenContext) -> P { - ctx.resolve_item(*self).to_rust_ty(ctx) - } -} - -impl ItemToRustTy for Item { - fn to_rust_ty(&self, ctx: &BindgenContext) -> P { - self.kind().expect_type().to_rust_ty(ctx, self) - } -} - -impl ToRustTy for Type { - type Extra = Item; - - fn to_rust_ty(&self, ctx: &BindgenContext, item: &Item) -> P { - use self::helpers::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 => raw!(c_void).to_ptr(true, ctx.span()), - 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::I8 => aster::ty::TyBuilder::new().i8(), - IntKind::U8 => aster::ty::TyBuilder::new().u8(), - IntKind::I16 => aster::ty::TyBuilder::new().i16(), - IntKind::U16 => aster::ty::TyBuilder::new().u16(), - IntKind::I32 => aster::ty::TyBuilder::new().i32(), - IntKind::U32 => aster::ty::TyBuilder::new().u32(), - IntKind::I64 => aster::ty::TyBuilder::new().i64(), - IntKind::U64 => aster::ty::TyBuilder::new().u64(), - IntKind::Custom { name, .. } => { - let ident = ctx.rust_ident_raw(name); - quote_ty!(ctx.ext_cx(), $ident) - } - // FIXME: This doesn't generate the proper alignment, but we - // can't do better right now. We should be able to use - // i128/u128 when they're available. - IntKind::U128 | IntKind::I128 => { - aster::ty::TyBuilder::new().array(2).u64() - } - } - } - TypeKind::Float(fk) => float_kind_rust_type(ctx, fk), - TypeKind::Complex(fk) => { - let float_path = float_kind_rust_type(ctx, fk); - - ctx.generated_bindegen_complex(); - quote_ty!(ctx.ext_cx(), __BindgenComplex<$float_path>) - } - TypeKind::Function(ref fs) => { - let ty = fs.to_rust_ty(ctx, item); - let prefix = ctx.trait_prefix(); - quote_ty!(ctx.ext_cx(), ::$prefix::option::Option<$ty>) - } - TypeKind::Array(item, len) => { - let inner = item.to_rust_ty(ctx); - aster::ty::TyBuilder::new().array(len).build(inner) - } - TypeKind::Enum(..) => { - let path = item.canonical_path(ctx); - aster::AstBuilder::new().ty().path().ids(path).build() - } - TypeKind::TemplateAlias(inner, ref template_args) | - 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 { - let template_args = template_args.iter() - .map(|arg| arg.to_rust_ty(ctx)) - .collect(); - - path.segments.last_mut().unwrap().parameters = - ast::PathParameters::AngleBracketed( - ast::AngleBracketedParameterData { - lifetimes: vec![], - types: P::from_vec(template_args), - 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 \ - type template params or opaque, expect \ - dragons!"); - aster::AstBuilder::new().ty().unit() - } - }; - } - - utils::build_templated_path(item, ctx, false) - } - TypeKind::BlockPointer => { - let void = raw!(c_void); - void.to_ptr(/* is_const = */ - false, - ctx.span()) - } - TypeKind::Pointer(inner) | - TypeKind::Reference(inner) => { - let inner = ctx.resolve_item(inner); - let inner_ty = inner.expect_type(); - let ty = inner.to_rust_ty(ctx); - - // Avoid the first function pointer level, since it's already - // represented in Rust. - if inner_ty.canonical_type(ctx).is_function() { - ty - } else { - let is_const = self.is_const() || - inner.expect_type().is_const(); - ty.to_ptr(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 { - // 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[1]: - // - // 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. - // - // [1]: http://c0x.coding-guidelines.com/6.7.5.3.html - 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::>(); - - 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 mut canonical_name = item.canonical_name(ctx); - let mangled_name = self.mangled_name(); - - { - let seen_symbol_name = mangled_name.unwrap_or(&canonical_name); - - // TODO: Maybe warn here if there's a type/argument mismatch, or - // something? - if result.seen_function(seen_symbol_name) { - return; - } - result.saw_function(seen_symbol_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) = 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()); - - // Handle overloaded functions by giving each overload its own unique - // suffix. - let times_seen = result.overload_number(&canonical_name); - if times_seen > 0 { - write!(&mut canonical_name, "{}", times_seen).unwrap(); - } - - 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); - } -} - -// Return true if any of the ancestors of `id` are in the whitelisted items set, -// false otherwise. -fn ancestor_is_whitelisted(ctx: &BindgenContext, - whitelisted_items: &ItemSet, - id: ItemId) - -> bool { - let item = ctx.resolve_item(id); - let mut last = id; - let mut current = item.parent_id(); - - while last != current { - if whitelisted_items.contains(¤t) { - return true; - } - last = current; - current = ctx.resolve_item(current).parent_id(); - } - - false -} - -pub fn codegen(context: &mut BindgenContext) -> Vec> { - context.gen(|context| { - let mut result = CodegenResult::new(); - - debug!("codegen: {:?}", context.options()); - - let whitelisted_items: ItemSet = context.whitelisted_items().collect(); - - for &id in whitelisted_items.iter() { - let item = context.resolve_item(id); - - // Non-toplevel items' parents are responsible one for generating - // their children. However, if we find an orphaned reference to a - // non-toplevel item whose parent is not in our whitelisted set, we - // need to take responsibility for generating it. - if item.is_toplevel(context) || - !ancestor_is_whitelisted(context, &whitelisted_items, id) { - item.codegen(context, &mut result, &()); - } - } - - let saw_union = result.saw_union; - let mut result = result.items; - if saw_union && !context.options().unstable_rust { - utils::prepend_union_types(context, &mut result); - } - if context.need_bindegen_complex_type() { - utils::prepend_complex_type(context, &mut result); - } - result - }) -} - -mod utils { - use aster; - use ir::context::{BindgenContext, ItemId}; - use ir::item::{Item, ItemCanonicalPath}; - use ir::ty::TypeKind; - use std::mem; - use super::ItemToRustTy; - use syntax::ast; - use syntax::ptr::P; - - pub fn prepend_union_types(ctx: &BindgenContext, - result: &mut Vec>) { - let prefix = ctx.trait_prefix(); - - // TODO(emilio): The fmt::Debug impl could be way nicer with - // std::intrinsics::type_name, but... - let union_field_decl = quote_item!(ctx.ext_cx(), - #[repr(C)] - pub struct __BindgenUnionField( - ::$prefix::marker::PhantomData); - ) - .unwrap(); - - let union_field_impl = quote_item!(&ctx.ext_cx(), - impl __BindgenUnionField { - #[inline] - pub fn new() -> Self { - __BindgenUnionField(::$prefix::marker::PhantomData) - } - - #[inline] - pub unsafe fn as_ref(&self) -> &T { - ::$prefix::mem::transmute(self) - } - - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::$prefix::mem::transmute(self) - } - } - ) - .unwrap(); - - let union_field_default_impl = quote_item!(&ctx.ext_cx(), - impl ::$prefix::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { - Self::new() - } - } - ) - .unwrap(); - - let union_field_clone_impl = quote_item!(&ctx.ext_cx(), - impl ::$prefix::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { - Self::new() - } - } - ) - .unwrap(); - - let union_field_copy_impl = quote_item!(&ctx.ext_cx(), - impl ::$prefix::marker::Copy for __BindgenUnionField {} - ) - .unwrap(); - - let union_field_debug_impl = quote_item!(ctx.ext_cx(), - impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) - -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } - } - ) - .unwrap(); - - let items = vec![ - union_field_decl, union_field_impl, - union_field_default_impl, - union_field_clone_impl, - union_field_copy_impl, - union_field_debug_impl, - ]; - - let old_items = mem::replace(result, items); - result.extend(old_items.into_iter()); - } - - pub fn prepend_complex_type(ctx: &BindgenContext, - result: &mut Vec>) { - let complex_type = quote_item!(ctx.ext_cx(), - #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] - #[repr(C)] - pub struct __BindgenComplex { - pub re: T, - pub im: T - } - ) - .unwrap(); - - let items = vec![complex_type]; - 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 { - 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::>() - } else { - item.applicable_template_args(ctx) - .iter() - .map(|arg| arg.to_rust_ty(ctx)) - .collect::>() - }; - - // 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 { - 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> { - // 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 { - 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/ir/annotations.rs b/src/ir/annotations.rs deleted file mode 100644 index 58308d6d..00000000 --- a/src/ir/annotations.rs +++ /dev/null @@ -1,157 +0,0 @@ -//! Types and functions related to bindgen annotation comments. -//! -//! Users can add annotations in doc comments to types that they would like to -//! replace other types with, mark as opaque, etc. This module deals with all of -//! that stuff. - -use clang; - -/// What kind of accessor should we provide for a field? -#[derive(Copy, PartialEq, Clone, Debug)] -pub enum FieldAccessorKind { - /// No accessor. - None, - /// Plain accessor. - Regular, - /// Unsafe accessor. - Unsafe, - /// Immutable accessor. - 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, - /// 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, - /// 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, -} - -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 { - /// Construct new annotations for the given cursor and its bindgen comments - /// (if any). - pub fn new(cursor: &clang::Cursor) -> Option { - let mut anno = Annotations::default(); - let mut matched_one = false; - anno.parse(&cursor.comment(), &mut matched_one); - - if matched_one { Some(anno) } else { None } - } - - /// Should this type be hidden? - pub fn hide(&self) -> bool { - self.hide - } - - /// Should this type be opaque? - pub fn opaque(&self) -> bool { - self.opaque - } - - /// For a given type, indicates the type it should replace. - /// - /// For example, in the following code: - /// - /// ```cpp - /// - /// /**
*/ - /// struct Foo { int x; }; - /// - /// struct Bar { char foo; }; - /// ``` - /// - /// the generated code would look something like: - /// - /// ``` - /// /**
*/ - /// struct Bar { - /// x: ::std::os::raw::c_int, - /// }; - /// ``` - /// - /// 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) - } - - /// Should we avoid implementing the `Copy` trait? - pub fn disallow_copy(&self) -> bool { - self.disallow_copy - } - - /// Should the fields be private? - pub fn private_fields(&self) -> Option { - self.private_fields - } - - /// What kind of accessors should we provide for this type's fields? - pub fn accessor_kind(&self) -> Option { - 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_tag_attrs() - .next() - .map_or(false, |attr| attr.name == "rustbindgen") { - *matched = true; - for attr in comment.get_tag_attrs() { - match attr.name.as_str() { - "opaque" => self.opaque = true, - "hide" => self.hide = true, - "nocopy" => self.disallow_copy = true, - "replaces" => self.use_instead_of = Some(attr.value), - "private" => { - self.private_fields = Some(attr.value != "false") - } - "accessor" => { - self.accessor_kind = Some(parse_accessor(&attr.value)) - } - _ => {} - } - } - } - - for child in comment.get_children() { - self.parse(&child, matched); - } - } -} diff --git a/src/ir/comp.rs b/src/ir/comp.rs deleted file mode 100644 index d19d1209..00000000 --- a/src/ir/comp.rs +++ /dev/null @@ -1,871 +0,0 @@ -//! Compound types (unions and structs) in our intermediate representation. - -use clang; -use parse::{ClangItemParser, ParseError}; -use std::cell::Cell; -use std::cmp; -use super::annotations::Annotations; -use super::context::{BindgenContext, ItemId}; -use super::item::Item; -use super::layout::Layout; -use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type}; -use super::type_collector::{ItemSet, TypeCollector}; - -/// The kind of compound type. -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum CompKind { - /// A struct. - Struct, - /// A union. - Union, -} - -/// The kind of C++ method. -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum MethodKind { - /// A static method. - Static, - /// A normal method. - Normal, - /// A virtual method. - 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 { - /// Construct a new `Method`. - fn new(kind: MethodKind, signature: ItemId, is_const: bool) -> Self { - Method { - kind: kind, - signature: signature, - is_const: is_const, - } - } - - /// What kind of method is this? - pub fn kind(&self) -> MethodKind { - self.kind - } - - /// Is this a virtual method? - pub fn is_virtual(&self) -> bool { - self.kind == MethodKind::Virtual - } - - /// Is this a static method? - pub fn is_static(&self) -> bool { - self.kind == MethodKind::Static - } - - /// Get the `ItemId` for the `Function` signature for this method. - pub fn signature(&self) -> ItemId { - self.signature - } - - /// Is this a const qualified method? - 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, - /// The inner type. - ty: ItemId, - /// The doc comment on the field if any. - comment: Option, - /// 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, - /// If the C++ field is marked as `mutable` - mutable: bool, -} - -impl Field { - /// Construct a new `Field`. - pub fn new(name: Option, - ty: ItemId, - comment: Option, - annotations: Option, - bitfield: Option, - mutable: bool) - -> Field { - Field { - name: name, - ty: ty, - comment: comment, - annotations: annotations.unwrap_or_default(), - bitfield: bitfield, - mutable: mutable, - } - } - - /// Get the name of this field. - pub fn name(&self) -> Option<&str> { - self.name.as_ref().map(|n| &**n) - } - - /// Get the type of this field. - pub fn ty(&self) -> ItemId { - self.ty - } - - /// Get the comment for this field. - pub fn comment(&self) -> Option<&str> { - self.comment.as_ref().map(|c| &**c) - } - - /// If this is a bitfield, how many bits does it need? - pub fn bitfield(&self) -> Option { - self.bitfield - } - - /// Is this field marked as `mutable`? - pub fn is_mutable(&self) -> bool { - self.mutable - } - - /// Get the annotations for this field. - pub fn annotations(&self) -> &Annotations { - &self.annotations - } -} - -/// A compound type. -/// -/// Either a struct or union, a compound type is built up from the combination -/// of fields which also are associated with their own (potentially compound) -/// type. -#[derive(Debug)] -pub struct CompInfo { - /// Whether this is a struct or a union. - kind: CompKind, - - /// The members of this struct or union. - fields: Vec, - - /// 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, - - /// The method declarations inside this class, if in C++ mode. - methods: Vec, - - /// Vector of classes this one inherits from. - base_members: Vec, - - /// The parent reference template if any. - ref_template: Option, - - /// 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, - - /// Set of static constants declared inside this class. - inner_vars: Vec, - - /// 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, - - /// Used to detect if we've run in a has_destructor cycle while cycling - /// around the template arguments. - detect_has_destructor_cycle: Cell, -} - -impl CompInfo { - /// Construct a new compound type. - 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), - } - } - - /// Can we derive the `Debug` trait for this compound type? - pub fn can_derive_debug(&self, - ctx: &BindgenContext, - layout: Option) - -> 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 { - if ctx.options().unstable_rust { - return false; - } - - 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.base_members - .iter() - .all(|ty| ctx.resolve_type(*ty).can_derive_debug(ctx)) && - self.template_args - .iter() - .all(|ty| ctx.resolve_type(*ty).can_derive_debug(ctx)) && - self.fields - .iter() - .all(|f| ctx.resolve_type(f.ty).can_derive_debug(ctx)) && - self.ref_template.map_or(true, |template| { - ctx.resolve_type(template).can_derive_debug(ctx) - }) - }; - - self.detect_derive_debug_cycle.set(false); - - can_derive_debug - } - - /// Is this compound type unsized? - pub fn is_unsized(&self, ctx: &BindgenContext) -> bool { - !self.has_vtable(ctx) && self.fields.is_empty() && - self.base_members.iter().all(|base| { - ctx.resolve_type(*base).canonical_type(ctx).is_unsized(ctx) - }) && - self.ref_template - .map_or(true, |template| ctx.resolve_type(template).is_unsized(ctx)) - } - - /// Does this compound type have a destructor? - pub fn has_destructor(&self, ctx: &BindgenContext) -> 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| { - ctx.resolve_type(*t).has_destructor(ctx) - }) || - self.template_args - .iter() - .any(|t| ctx.resolve_type(*t).has_destructor(ctx)) || - self.base_members - .iter() - .any(|t| ctx.resolve_type(*t).has_destructor(ctx)) || - self.fields.iter().any(|field| { - ctx.resolve_type(field.ty) - .has_destructor(ctx) - }) - } - }; - - self.detect_has_destructor_cycle.set(false); - - has_destructor - } - - /// Can we derive the `Copy` trait for this type? - pub fn can_derive_copy(&self, ctx: &BindgenContext, item: &Item) -> 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(ctx) { - return false; - } - - if self.kind == CompKind::Union { - if !ctx.options().unstable_rust { - return true; - } - - // https://github.com/rust-lang/rust/issues/36640 - if !self.template_args.is_empty() || self.ref_template.is_some() || - !item.applicable_template_args(ctx).is_empty() { - return false; - } - } - - // With template args, use a safe subset of the types, - // since copyability depends on the types itself. - self.ref_template - .as_ref() - .map_or(true, |t| ctx.resolve_item(*t).can_derive_copy(ctx)) && - self.base_members - .iter() - .all(|t| ctx.resolve_item(*t).can_derive_copy(ctx)) && - self.fields.iter().all(|field| { - ctx.resolve_item(field.ty) - .can_derive_copy(ctx) - }) - } - - /// Is this type a template specialization? - pub fn is_template_specialization(&self) -> bool { - self.ref_template.is_some() - } - - /// Get the template declaration this specialization is specializing. - pub fn specialized_template(&self) -> Option { - self.ref_template - } - - /// Compute 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, ctx: &BindgenContext) -> Option { - 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 = ctx.resolve_type(field.ty) - .layout(ctx); - - 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)) - } - - /// Get this type's set of fields. - pub fn fields(&self) -> &[Field] { - &self.fields - } - - /// Get this type's set of free template arguments. Empty if this is not a - /// template. - pub fn template_args(&self) -> &[ItemId] { - &self.template_args - } - - /// Does this type have any template parameters that aren't types - /// (e.g. int)? - pub fn has_non_type_template_params(&self) -> bool { - self.has_non_type_template_params - } - - /// Does this type have a virtual table? - pub fn has_vtable(&self, ctx: &BindgenContext) -> bool { - self.has_vtable || - self.base_members().iter().any(|base| { - ctx.resolve_type(*base) - .has_vtable(ctx) - }) || - self.ref_template.map_or(false, |template| { - ctx.resolve_type(template).has_vtable(ctx) - }) - } - - /// Get this type's set of methods. - pub fn methods(&self) -> &[Method] { - &self.methods - } - - /// What kind of compound type is this? - pub fn kind(&self) -> CompKind { - self.kind - } - - /// The set of types that this one inherits from. - pub fn base_members(&self) -> &[ItemId] { - &self.base_members - } - - /// Construct a new compound type from a Clang type. - pub fn from_ty(potential_id: ItemId, - ty: &clang::Type, - location: Option, - ctx: &mut BindgenContext) - -> Result { - 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.template_args() { - // In forward declarations and not specializations, - // etc, they are in - // the ast, we'll meet them in - // CXCursor_TemplateTypeParameter - None => vec![], - Some(arg_types) => { - let num_arg_types = arg_types.len(); - - let args = arg_types.filter(|t| t.kind() != CXType_Invalid) - .map(|t| Item::from_ty_or_ref(t, None, None, ctx)) - .collect::>(); - - if args.len() != num_arg_types { - ci.has_non_type_template_params = true; - warn!("warning: Template parameter is not a type"); - } - - args - } - }; - - ci.ref_template = cursor.specialized() - .and_then(|c| Item::parse(c, None, ctx).ok()); - - let mut maybe_anonymous_struct_field = None; - cursor.visit(|cur| { - if cur.kind() != CXCursor_FieldDecl { - if let Some((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 { - let ty = cur.cur_type(); - maybe_anonymous_struct_field = Some((inner, ty)); - } - } - 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(), Some(cur), 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 - }; - - let method = - Method::new(method_kind, method_signature, is_const); - - ci.methods.push(method); - } - 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 comp 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 { - use clangll::*; - Ok(match cursor.kind() { - CXCursor_UnionDecl => CompKind::Union, - CXCursor_ClassDecl | - CXCursor_StructDecl => CompKind::Struct, - CXCursor_CXXBaseSpecifier | - 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); - } - }) - } - - /// Do any of the types that participate in this type's "signature" use the - /// named type `ty`? - /// - /// See also documentation for `ir::Item::signature_contains_named_type`. - pub fn signature_contains_named_type(&self, - ctx: &BindgenContext, - ty: &Type) - -> bool { - // We don't generate these, so rather don't make the codegen step to - // think we got it covered. - if self.has_non_type_template_params() { - return false; - } - self.template_args.iter().any(|arg| { - ctx.resolve_type(*arg) - .signature_contains_named_type(ctx, ty) - }) - } - - /// Get the set of types that were declared within this compound type - /// (e.g. nested class definitions). - pub fn inner_types(&self) -> &[ItemId] { - &self.inner_types - } - - /// Get the set of static variables declared within this compound type. - pub fn inner_vars(&self) -> &[ItemId] { - &self.inner_vars - } - - /// Have we found a field with an opaque type that could potentially mess up - /// the layout of this compound type? - pub fn found_unknown_attr(&self) -> bool { - self.found_unknown_attr - } - - /// Is this compound type packed? - 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, ctx: &BindgenContext) -> bool { - self.has_vtable(ctx) && - !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. - ctx.resolve_type(*base) - .canonical_type(ctx) - .as_comp() - .map_or(false, |ci| ci.has_vtable(ctx)) - }) - } -} - -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() { - types.insert(template); - } - - let applicable_template_args = item.applicable_template_args(context); - for arg in applicable_template_args { - types.insert(arg); - } - - for &base in self.base_members() { - types.insert(base); - } - - for field in self.fields() { - types.insert(field.ty()); - } - - for &ty in self.inner_types() { - types.insert(ty); - } - - // FIXME(emilio): Methods, VTable? - } -} diff --git a/src/ir/context.rs b/src/ir/context.rs deleted file mode 100644 index 85721978..00000000 --- a/src/ir/context.rs +++ /dev/null @@ -1,1055 +0,0 @@ -//! Common context that is passed around during parsing and codegen. - -use BindgenOptions; -use cexpr; -use clang::{self, Cursor}; -use parse::ClangItemParser; -use std::borrow::Cow; -use std::cell::Cell; -use std::collections::{HashMap, hash_map}; -use std::collections::btree_map::{self, BTreeMap}; -use std::fmt; -use super::int::IntKind; -use super::item::{Item, ItemCanonicalName}; -use super::item_kind::ItemKind; -use super::module::Module; -use super::ty::{FloatKind, Type, TypeKind}; -use super::type_collector::{ItemSet, TypeCollector}; -use syntax::ast::Ident; -use syntax::codemap::{DUMMY_SP, Span}; -use syntax::ext::base::ExtCtxt; - -/// 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 ItemId { - /// Get a numeric representation of this id. - pub fn as_usize(&self) -> usize { - self.0 - } -} - -/// A key used to index a resolved type, so we only process it once. -/// -/// This is almost always a USR string (an unique identifier generated by -/// clang), but it can also be the canonical declaration if the type is unnamed, -/// in which case clang may generate the same USR for multiple nested unnamed -/// types. -#[derive(Eq, PartialEq, Hash, Debug)] -enum TypeKey { - USR(String), - Declaration(Cursor), -} - -// 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, - - /// The next item id to use during this bindings regeneration. - next_item_id: ItemId, - - /// Clang USR to type map. This is needed to be able to associate types with - /// item ids during parsing. - types: HashMap, - - /// A cursor to module map. Similar reason than above. - modules: HashMap, - - /// 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, as well to allow macro - /// expression parsing. - parsed_macros: HashMap, cexpr::expr::EvalResult>, - - /// The active replacements collected from replaces="xxx" annotations. - replacements: HashMap, - - 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, - - /// Whether a bindgen complex was generated - generated_bindegen_complex: Cell, -} - -impl<'ctx> BindgenContext<'ctx> { - /// Construct the context for the given `options`. - pub fn new(options: BindgenOptions) -> Self { - use clangll; - - let index = clang::Index::new(false, true); - - let parse_options = - clangll::CXTranslationUnit_DetailedPreprocessingRecord; - let translation_unit = - clang::TranslationUnit::parse(&index, - "", - &options.clang_args, - &[], - parse_options) - .expect("TranslationUnit::parse"); - - let root_module = Self::build_root_module(ItemId(0)); - let mut me = BindgenContext { - items: Default::default(), - types: Default::default(), - modules: Default::default(), - next_item_id: ItemId(1), - 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, - generated_bindegen_complex: Cell::new(false), - }; - - me.add_item(root_module, None, None); - - me - } - - /// Define a new item. - /// - /// This inserts it into the internal items set, and its type into the - /// internal types set. - pub fn add_item(&mut self, - item: Item, - declaration: Option, - location: Option) { - 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 is_unnamed = is_type && item.expect_type().name().is_none(); - let old_item = self.items.insert(id, item); - assert!(old_item.is_none(), "Inserted type twice?"); - - // Unnamed items can have an USR, but they can't be referenced from - // other sites explicitly and the USR can match if the unnamed items are - // nested, so don't bother tracking them. - if is_type && declaration.is_some() { - let mut declaration = declaration.unwrap(); - if !declaration.is_valid() { - if let Some(location) = location { - if location.kind() == CXCursor_ClassTemplate || - location.kind() == - CXCursor_ClassTemplatePartialSpecialization { - declaration = location; - } - } - } - declaration = declaration.canonical(); - if !declaration.is_valid() { - // 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()); - return; - } - - let key = if is_unnamed { - TypeKey::Declaration(declaration) - } else if let Some(usr) = declaration.usr() { - TypeKey::USR(usr) - } else { - error!("Valid declaration with no USR: {:?}, {:?}", - declaration, - location); - return; - }; - - let old = self.types.insert(key, id); - debug_assert_eq!(old, None); - } - } - - // TODO: Move all this syntax crap to other part of the code. - - /// Given that we are in the codegen phase, get the syntex context. - pub fn ext_cx(&self) -> &ExtCtxt<'ctx> { - &self.gen_ctx.expect("Not in gen phase").0 - } - - /// Given that we are in the codegen phase, get the current syntex span. - 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)) - } - - /// Returns a mangled name as a rust identifier. - pub fn rust_ident_raw(&self, name: &str) -> Ident { - self.ext_cx().ident_of(name) - } - - /// Iterate over all items that have been defined. - pub fn items<'a>(&'a self) -> btree_map::Iter<'a, ItemId, Item> { - self.items.iter() - } - - /// Have we collected all unresolved type references yet? - pub fn collected_typerefs(&self) -> bool { - self.collected_typerefs - } - - /// Gather all the unresolved type references. - fn collect_typerefs - (&mut self) - -> Vec<(ItemId, clang::Type, Option, Option)> { - 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, parent_id) => { - typerefs.push((*id, ty.clone(), loc, parent_id)); - } - _ => {} - }; - } - typerefs - } - - /// Collect all of our unresolved type references and resolve them. - fn resolve_typerefs(&mut self) { - let typerefs = self.collect_typerefs(); - - for (id, ty, loc, parent_id) in typerefs { - let _resolved = { - let resolved = Item::from_ty(&ty, loc, parent_id, 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?"); - } - } - - /// Iterate over all items and replace any item that has been named in a - /// `replaces="SomeType"` annotation with the replacement type. - fn process_replacements(&mut self) { - if self.replacements.is_empty() { - debug!("No replacements to process"); - 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() { - // Calls to `canonical_name` are expensive, so eagerly filter out - // items that cannot be replaced. - let ty = match item.kind().as_type() { - Some(ty) => ty, - None => continue, - }; - - match *ty.kind() { - TypeKind::Comp(ref ci) if !ci.is_template_specialization() => {} - TypeKind::TemplateAlias(_, _) | - TypeKind::Alias(_, _) => {} - _ => continue, - } - - let name = item.real_canonical_name(self, - self.options() - .enable_cxx_namespaces, - true); - let replacement = self.replacements.get(&name); - - if let Some(replacement) = replacement { - 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 { - debug!("Replacing {:?} with {:?}", id, replacement); - - let mut item = self.items.get_mut(&id).unwrap(); - *item.kind_mut().as_type_mut().unwrap().kind_mut() = - TypeKind::ResolvedTypeRef(replacement); - } - } - - /// Enter the code generation phase, invoke the given callback `cb`, and - /// leave the code generation phase. - pub fn gen(&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::DummyResolver; - 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) }); - - if !self.collected_typerefs() { - 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!("add_builtin_item: 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(id: ItemId) -> Item { - let module = Module::new(Some("root".into())); - Item::new(id, None, None, id, ItemKind::Module(module)) - } - - /// Get the root module. - pub fn root_module(&self) -> ItemId { - self.root_module - } - - /// Resolve the given `ItemId` as a type. - /// - /// Panics if there is no item for the given `ItemId` or if the resolved - /// item is not a `Type`. - pub fn resolve_type(&self, type_id: ItemId) -> &Type { - self.items.get(&type_id).unwrap().kind().expect_type() - } - - /// Resolve the given `ItemId` as a type, or `None` if there is no item with - /// the given id. - /// - /// Panics if the id resolves to an item that is not a type. - pub fn safe_resolve_type(&self, type_id: ItemId) -> Option<&Type> { - self.items.get(&type_id).map(|t| t.kind().expect_type()) - } - - /// Resolve the given `ItemId` into an `Item`, or `None` if no such item - /// exists. - pub fn resolve_item_fallible(&self, item_id: ItemId) -> Option<&Item> { - self.items.get(&item_id) - } - - /// Resolve the given `ItemId` into an `Item`. - /// - /// Panics if the given id does not resolve to any item. - 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), - } - } - - /// Get the current module. - 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: - /// - /// ```c++ - /// template - /// class Incomplete { - /// T p; - /// }; - /// - /// template - /// class Foo { - /// Incomplete bar; - /// }; - /// ``` - fn build_template_wrapper(&mut self, - with_id: ItemId, - wrapping: ItemId, - parent_id: ItemId, - ty: &clang::Type, - location: clang::Cursor, - declaration: clang::Cursor) - -> ItemId { - use clangll::*; - let mut args = vec![]; - location.visit(|c| { - if c.kind() == CXCursor_TypeRef { - // The `with_id` id will potentially end up unused if we give up - // on this type (for example, its a tricky partial template - // specialization), so if we pass `with_id` as the parent, it is - // potentially a dangling reference. Instead, use the canonical - // template declaration as the parent. It is already parsed and - // has a known-resolvable `ItemId`. - let new_ty = Item::from_ty_or_ref(c.cur_type(), - Some(c), - Some(wrapping), - self); - args.push(new_ty); - } - CXChildVisit_Continue - }); - - let item = { - let wrapping_type = self.resolve_type(wrapping); - if let TypeKind::Comp(ref ci) = *wrapping_type.kind() { - let old_args = ci.template_args(); - - // 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, - // which sucks. The same happens for specialized type alias - // template declarations, where we have that ugly hack up there. - // - // This flaw was already on the old parser, but I now think it - // has no clear solution (apart from patching libclang to - // somehow expose them, of course). - // - // For an easy example in which there's no way at all of getting - // the `int` type, except manually parsing the spelling: - // - // template - // class Incomplete { - // T d; - // U p; - // }; - // - // template - // class Foo { - // Incomplete 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; - } - } else { - assert_eq!(declaration.kind(), - ::clangll::CXCursor_TypeAliasTemplateDecl, - "Expected wrappable type"); - } - - 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(with_id, None, None, parent_id, ItemKind::Type(ty)) - }; - - // Bypass all the validations in add_item explicitly. - debug!("build_template_wrapper: inserting item: {:?}", item); - debug_assert!(with_id == item.id()); - self.items.insert(with_id, item); - with_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, - with_id: ItemId, - parent_id: Option, - ty: &clang::Type, - location: Option) - -> Option { - use clangll::{CXCursor_ClassTemplate, - CXCursor_ClassTemplatePartialSpecialization, - CXCursor_TypeAliasTemplateDecl, - CXCursor_TypeRef}; - 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() { - let id = self.types - .get(&TypeKey::Declaration(canonical_declaration)) - .map(|id| *id) - .or_else(|| { - canonical_declaration.usr() - .and_then(|usr| self.types.get(&TypeKey::USR(usr))) - .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 || - declaration.kind() == CXCursor_TypeAliasTemplateDecl) && - *ty != canonical_declaration.cur_type() && - location.is_some() && - parent_id.is_some() { - // For specialized type aliases, there's no way to get the - // template parameters as of this writing (for a struct - // specialization we wouldn't be in this branch anyway). - // - // Explicitly return `None` if there aren't any - // unspecialized parameters (contains any `TypeRef`) so we - // resolve the canonical type if there is one and it's - // exposed. - // - // This is _tricky_, I know :( - if declaration.kind() == CXCursor_TypeAliasTemplateDecl && - !location.unwrap().contains_cursor(CXCursor_TypeRef) && - ty.canonical_type().is_valid_and_exposed() { - return None; - } - - return Some(self.build_template_wrapper(with_id, - id, - parent_id.unwrap(), - ty, - location.unwrap(), - declaration)); - } - - return Some(self.build_ty_wrapper(with_id, 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, - with_id: ItemId, - wrapped_id: ItemId, - parent_id: Option, - ty: &clang::Type) - -> ItemId { - 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(with_id, - None, - None, - parent_id.unwrap_or(self.current_module), - ItemKind::Type(ty)); - self.add_builtin_item(item); - with_id - } - - /// Returns the next item id to be used for an item. - pub fn next_item_id(&mut self) -> ItemId { - let ret = self.next_item_id; - self.next_item_id = ItemId(self.next_item_id.0 + 1); - ret - } - - fn build_builtin_ty(&mut self, - ty: &clang::Type, - _declaration: Cursor) - -> Option { - 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_Int128 => TypeKind::Int(IntKind::I128), - CXType_UInt128 => TypeKind::Int(IntKind::U128), - CXType_Float => TypeKind::Float(FloatKind::Float), - CXType_Double => TypeKind::Float(FloatKind::Double), - CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble), - CXType_Float128 => TypeKind::Float(FloatKind::Float128), - CXType_Complex => { - let float_type = ty.elem_type() - .expect("Not able to resolve complex type?"); - let float_kind = match float_type.kind() { - CXType_Float => FloatKind::Float, - CXType_Double => FloatKind::Double, - CXType_LongDouble => FloatKind::LongDouble, - _ => panic!("Non floating-type complex?"), - }; - TypeKind::Complex(float_kind) - } - _ => 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 = self.next_item_id(); - let item = - Item::new(id, None, None, self.root_module, ItemKind::Type(ty)); - self.add_builtin_item(item); - Some(id) - } - - /// Get the current Clang translation unit that is being processed. - pub fn translation_unit(&self) -> &clang::TranslationUnit { - &self.translation_unit - } - - /// Have we parsed the macro named `macro_name` already? - pub fn parsed_macro(&self, macro_name: &[u8]) -> bool { - self.parsed_macros.contains_key(macro_name) - } - - /// Get the currently parsed macros. - pub fn parsed_macros(&self) -> &HashMap, cexpr::expr::EvalResult> { - debug_assert!(!self.in_codegen_phase()); - &self.parsed_macros - } - - /// Mark the macro named `macro_name` as parsed. - pub fn note_parsed_macro(&mut self, - id: Vec, - value: cexpr::expr::EvalResult) { - self.parsed_macros.insert(id, value); - } - - /// Are we in the codegen phase? - pub fn in_codegen_phase(&self) -> bool { - self.gen_ctx.is_some() - } - - /// Mark the type with the given `name` as replaced by the type with id - /// `potential_ty`. - /// - /// Replacement types are declared using the `replaces="xxx"` annotation, - /// and implies that the original type is hidden. - pub fn replace(&mut self, name: &str, potential_ty: ItemId) { - match self.replacements.entry(name.into()) { - hash_map::Entry::Vacant(entry) => { - debug!("Defining replacement for {} as {:?}", - name, - potential_ty); - entry.insert(potential_ty); - } - hash_map::Entry::Occupied(occupied) => { - warn!("Replacement for {} already defined as {:?}; \ - ignoring duplicate replacement definition as {:?}}}", - name, - occupied.get(), - potential_ty); - } - } - } - - /// Is the item with the given `name` hidden? Or is the item with the given - /// `name` and `id` replaced by another type, and effectively hidden? - pub fn hidden_by_name(&self, name: &str, id: ItemId) -> bool { - debug_assert!(self.in_codegen_phase(), - "You're not supposed to call this yet"); - self.options.hidden_types.contains(name) || - self.is_replaced_type(name, id) - } - - /// Has the item with the given `name` and `id` been replaced by another - /// type? - pub fn is_replaced_type(&self, name: &str, id: ItemId) -> bool { - match self.replacements.get(name) { - Some(replaced_by) if *replaced_by != id => true, - _ => false, - } - } - - /// Is the type with the given `name` marked as opaque? - 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) - } - - /// Get the options used to configure this bindgen context. - 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(); - if let Some(id) = self.modules.get(&cursor) { - return *id; - } - - let module_id = self.next_item_id(); - 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 - } - - /// Start traversing the module with the given `module_id`, invoke the - /// callback `cb`, and then return to traversing the original module. - pub fn with_module(&mut self, module_id: ItemId, cb: F) - where F: FnOnce(&mut Self, &mut Vec), - { - 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; - } - - /// Iterate over all (explicitly or transitively) whitelisted items. - /// - /// If no items are explicitly whitelisted, then all items are considered - /// whitelisted. - pub fn whitelisted_items<'me>(&'me self) - -> WhitelistedItemsIter<'me, 'ctx> { - assert!(self.in_codegen_phase()); - assert!(self.current_module == self.root_module); - - let roots = self.items() - .filter(|&(_, item)| { - // If nothing is explicitly whitelisted, then everything is fair - // game. - if self.options().whitelisted_types.is_empty() && - self.options().whitelisted_functions.is_empty() && - self.options().whitelisted_vars.is_empty() { - return true; - } - - let name = item.canonical_name(self); - match *item.kind() { - ItemKind::Module(..) => false, - ItemKind::Function(_) => { - self.options().whitelisted_functions.matches(&name) - } - ItemKind::Var(_) => { - self.options().whitelisted_vars.matches(&name) - } - ItemKind::Type(ref ty) => { - if self.options().whitelisted_types.matches(&name) { - return true; - } - - // 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() && - enum_.variants().iter().any(|variant| { - self.options() - .whitelisted_vars - .matches(&variant.name()) - }) { - return true; - } - } - - false - } - } - }) - .map(|(&id, _)| id); - - let seen: ItemSet = roots.collect(); - - // The .rev() preserves the expected ordering traversal, resulting in - // more stable-ish bindgen-generated names for anonymous types (like - // unions). - let to_iterate = seen.iter().cloned().rev().collect(); - - WhitelistedItemsIter { - ctx: self, - seen: seen, - to_iterate: to_iterate, - } - } - - /// Convenient method for getting the prefix to use for most traits in - /// codegen depending on the `use_core` option. - pub fn trait_prefix(&self) -> Ident { - if self.options().use_core { - self.rust_ident_raw("core") - } else { - self.rust_ident_raw("std") - } - } - - /// Call if a binden complex is generated - pub fn generated_bindegen_complex(&self) { - self.generated_bindegen_complex.set(true) - } - - /// Whether we need to generate the binden complex type - pub fn need_bindegen_complex_type(&self) -> bool { - self.generated_bindegen_complex.get() - } -} - -/// An iterator over whitelisted items. -/// -/// See `BindgenContext::whitelisted_items` for more information. -pub struct WhitelistedItemsIter<'ctx, 'gen> - where 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, - - // The set of whitelisted items we have seen. If you think of traversing - // whitelisted items like GC tracing, this is the mark bits, and contains - // both black and gray items. - seen: ItemSet, - - // The set of whitelisted items that we have seen but have yet to iterate - // over and collect transitive references from. To return to the GC analogy, - // this is the mark stack, containing the set of gray items which we have - // not finished tracing yet. - to_iterate: Vec, -} - -impl<'ctx, 'gen> Iterator for WhitelistedItemsIter<'ctx, 'gen> - where 'gen: 'ctx, -{ - type Item = ItemId; - - fn next(&mut self) -> Option { - let id = match self.to_iterate.pop() { - None => return None, - Some(id) => id, - }; - - debug_assert!(self.seen.contains(&id)); - debug_assert!(self.ctx.items.contains_key(&id)); - - let mut sub_types = ItemSet::new(); - id.collect_types(self.ctx, &mut sub_types, &()); - - for id in sub_types { - if self.seen.insert(id) { - self.to_iterate.push(id); - } - } - - Some(id) - } -} diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs deleted file mode 100644 index 6085833d..00000000 --- a/src/ir/enum_ty.rs +++ /dev/null @@ -1,137 +0,0 @@ -//! Intermediate representation for C/C++ enumerations. - -use clang; -use parse::{ClangItemParser, ParseError}; -use super::context::{BindgenContext, ItemId}; -use super::item::Item; -use super::ty::TypeKind; - -/// A C/C++ enumeration. -#[derive(Debug)] -pub struct Enum { - /// The representation used for this enum; it should be an `IntKind` type or - /// an alias to one. - /// - /// 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, - - /// The different variants, with explicit values. - variants: Vec, -} - -impl Enum { - /// Construct a new `Enum` with the given representation and variants. - pub fn new(repr: Option, variants: Vec) -> Self { - Enum { - repr: repr, - variants: variants, - } - } - - /// Get this enumeration's representation. - pub fn repr(&self) -> Option { - self.repr - } - - /// Get this enumeration's variants. - pub fn variants(&self) -> &[EnumVariant] { - &self.variants - } - - /// Construct an enumeration from the given Clang type. - pub fn from_ty(ty: &clang::Type, - ctx: &mut BindgenContext) - -> Result { - 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 value = if is_signed { - cursor.enum_val_signed().map(EnumVariantValue::Signed) - } else { - cursor.enum_val_unsigned().map(EnumVariantValue::Unsigned) - }; - if let Some(val) = value { - let name = cursor.spelling(); - let comment = cursor.raw_comment(); - 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, - - /// The integer value of the variant. - val: EnumVariantValue, -} - -/// A constant value assigned to an enumeration variant. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum EnumVariantValue { - /// A signed constant. - Signed(i64), - - /// An unsigned constant. - Unsigned(u64), -} - -impl EnumVariant { - /// Construct a new enumeration variant from the given parts. - pub fn new(name: String, - comment: Option, - val: EnumVariantValue) - -> Self { - EnumVariant { - name: name, - comment: comment, - val: val, - } - } - - /// Get this variant's name. - pub fn name(&self) -> &str { - &self.name - } - - /// Get this variant's value. - pub fn val(&self) -> EnumVariantValue { - self.val - } -} diff --git a/src/ir/function.rs b/src/ir/function.rs deleted file mode 100644 index eacb6c0e..00000000 --- a/src/ir/function.rs +++ /dev/null @@ -1,282 +0,0 @@ -//! Intermediate representation for C/C++ functions and methods. - -use clang; -use clangll::Enum_CXCallingConv; -use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; -use super::context::{BindgenContext, ItemId}; -use super::item::Item; -use super::ty::TypeKind; -use super::type_collector::{ItemSet, TypeCollector}; -use syntax::abi; - -/// 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 { - /// The name of this function. - name: String, - - /// The mangled name, that is, the symbol. - mangled_name: Option, - - /// The id pointing to the current function signature. - signature: ItemId, - - /// The doc comment on the function, if any. - comment: Option, -} - -impl Function { - /// Construct a new function. - pub fn new(name: String, - mangled_name: Option, - sig: ItemId, - comment: Option) - -> Self { - Function { - name: name, - mangled_name: mangled_name, - signature: sig, - comment: comment, - } - } - - /// Get this function's name. - pub fn name(&self) -> &str { - &self.name - } - - /// Get this function's name. - pub fn mangled_name(&self) -> Option<&str> { - self.mangled_name.as_ref().map(|n| &**n) - } - - /// Get this function's signature. - 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, 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), - } -} - -/// Get the mangled name for the cursor's referent. -pub fn cursor_mangling(cursor: &clang::Cursor) -> Option { - // We early return here because libclang may crash in some case - // if we pass in a variable inside a partial specialized template. - // See servo/rust-bindgen#67. - if cursor.is_in_non_fully_specialized_template() { - return None; - } - - let mut mangling = cursor.mangling(); - if mangling.is_empty() { - return None; - } - - // Try to undo backend linkage munging (prepended _, generally) - if cfg!(target_os = "macos") { - mangling.remove(0); - } - - Some(mangling) -} - -impl FunctionSig { - /// Construct a new function signature. - pub fn new(return_type: ItemId, - arguments: Vec<(Option, ItemId)>, - is_variadic: bool, - abi: abi::Abi) - -> Self { - FunctionSig { - return_type: return_type, - argument_types: arguments, - is_variadic: is_variadic, - abi: abi, - } - } - - /// Construct a new function signature from the given Clang type. - pub fn from_ty(ty: &clang::Type, - cursor: &clang::Cursor, - ctx: &mut BindgenContext) - -> Result { - 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 ty_ret_type = try!(ty.ret_type().ok_or(ParseError::Continue)); - 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)) - } - - /// Get this function signature's return type. - pub fn return_type(&self) -> ItemId { - self.return_type - } - - /// Get this function signature's argument (name, type) pairs. - pub fn argument_types(&self) -> &[(Option, ItemId)] { - &self.argument_types - } - - /// Get this function signature's ABI. - pub fn abi(&self) -> abi::Abi { - self.abi - } - - /// Is this function signature variadic? - 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, 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))) - } -} - -impl TypeCollector for FunctionSig { - type Extra = Item; - - fn collect_types(&self, - _context: &BindgenContext, - types: &mut ItemSet, - _item: &Item) { - types.insert(self.return_type()); - - for &(_, ty) in self.argument_types() { - types.insert(ty); - } - } -} diff --git a/src/ir/int.rs b/src/ir/int.rs deleted file mode 100644 index 2d85db83..00000000 --- a/src/ir/int.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! Intermediate representation for integral types. - -/// Which integral type are we dealing with? -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum IntKind { - /// A `bool`. - Bool, - - /// A `char`. - Char, - - /// An `unsigned char`. - UChar, - - /// A `short`. - Short, - - /// An `unsigned short`. - UShort, - - /// An `int`. - Int, - - /// An `unsigned int`. - UInt, - - /// A `long`. - Long, - - /// An `unsigned long`. - ULong, - - /// A `long long`. - LongLong, - - /// An `unsigned long long`. - ULongLong, - - /// A 8-bit signed integer. - I8, - - /// A 8-bit unsigned integer. - U8, - - /// A 16-bit signed integer. - I16, - - /// Either a `char16_t` or a `wchar_t`. - U16, - - /// A 32-bit signed integer. - I32, - - /// A 32-bit unsigned integer. - U32, - - /// A 64-bit signed integer. - I64, - - /// A 64-bit unsigned integer. - U64, - - /// An `int128_t` - I128, - - /// A `uint128_t`. - U128, - - /// A custom integer type, used to allow custom macro types depending on - /// range. - Custom { - /// The name of the type, which would be used without modification. - name: &'static str, - /// Whether the type is signed or not. - is_signed: bool, - }, -} - -impl IntKind { - /// Is this integral type signed? - pub fn is_signed(&self) -> bool { - use self::IntKind::*; - match *self { - Bool | UChar | UShort | UInt | ULong | ULongLong | U8 | U16 | - U32 | U64 | U128 => false, - - Char | Short | Int | Long | LongLong | I8 | I16 | I32 | I64 | - I128 => true, - - Custom { is_signed, .. } => is_signed, - } - } -} diff --git a/src/ir/item.rs b/src/ir/item.rs deleted file mode 100644 index 1f05f92f..00000000 --- a/src/ir/item.rs +++ /dev/null @@ -1,1172 +0,0 @@ -//! Bindgen's core intermediate representation type. - -use clang; -use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; -use regex::Regex; -use std::cell::{Cell, RefCell}; -use super::annotations::Annotations; -use super::context::{BindgenContext, ItemId}; -use super::function::Function; -use super::item_kind::ItemKind; -use super::module::Module; -use super::ty::{Type, TypeKind}; -use super::type_collector::{ItemSet, TypeCollector}; - -/// 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 { - /// Get the canonical name for this item. - 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: -/// -/// ```c++ -/// namespace foo { -/// const BAR = 3; -/// } -/// ``` -/// -/// For bar, the canonical path is `vec!["foo", "BAR"]`, while the canonical -/// name is just `"BAR"`. -pub trait ItemCanonicalPath { - /// Get the canonical path for this item. - fn canonical_path(&self, ctx: &BindgenContext) -> Vec; -} - -/// A trait for iterating over an item and its parents and up its ancestor chain -/// up to (but not including) the implicit root module. -pub trait ItemAncestors { - /// Get an iterable over this item's ancestors. - fn ancestors<'a, 'b>(&self, - ctx: &'a BindgenContext<'b>) - -> ItemAncestorsIter<'a, 'b>; -} - -/// An iterator over an item and its ancestors. -pub struct ItemAncestorsIter<'a, 'b> - where 'b: 'a, -{ - item: ItemId, - ctx: &'a BindgenContext<'b>, -} - -impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> - where 'b: 'a, -{ - type Item = ItemId; - - fn next(&mut self) -> Option { - let item = self.ctx.resolve_item(self.item); - if item.parent_id() == self.item { - None - } else { - self.item = item.parent_id(); - Some(item.id()) - } - } -} - -// 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 { - debug_assert!(ctx.in_codegen_phase(), - "You're not supposed to call this yet"); - ctx.resolve_item(*self).canonical_path(ctx) - } -} - -impl ItemAncestors for ItemId { - fn ancestors<'a, 'b>(&self, - ctx: &'a BindgenContext<'b>) - -> ItemAncestorsIter<'a, 'b> { - ItemAncestorsIter { - item: *self, - ctx: ctx, - } - } -} - -impl ItemAncestors for Item { - fn ancestors<'a, 'b>(&self, - ctx: &'a BindgenContext<'b>) - -> ItemAncestorsIter<'a, 'b> { - self.id().ancestors(ctx) - } -} - -impl TypeCollector for ItemId { - type Extra = (); - - fn collect_types(&self, - ctx: &BindgenContext, - types: &mut ItemSet, - extra: &()) { - ctx.resolve_item(*self).collect_types(ctx, types, extra); - } -} - -impl TypeCollector for Item { - type Extra = (); - - fn collect_types(&self, - ctx: &BindgenContext, - types: &mut ItemSet, - _extra: &()) { - if self.is_hidden(ctx) || types.contains(&self.id()) { - return; - } - - match *self.kind() { - ItemKind::Type(ref ty) => { - if !self.is_opaque(ctx) { - ty.collect_types(ctx, types, self); - } - } - _ => {} // FIXME. - } - } -} - -/// An item is the base of the bindgen representation, it can be either a -/// module, a type, a function, or a variable (see `ItemKind` for more -/// information). -/// -/// Items refer to each other by `ItemId`. Every item has its parent's -/// id. Depending on the kind of item this is, it may also refer to other items, -/// such as a compound type item referring to other types. Collectively, these -/// references form a graph. -/// -/// The entry-point to this graph is the "root module": a meta-item used to hold -/// all top-level items. -/// -/// An item may have a comment, and annotations (see the `annotations` module). -/// -/// Note that even though we parse all the types of annotations in comments, not -/// all of them apply to every item. Those rules are described in the -/// `annotations` module. -#[derive(Debug)] -pub struct Item { - /// This item's id. - id: ItemId, - - /// The item's local id, unique only amongst its siblings. Only used for - /// anonymous items. - /// - /// Lazily initialized in local_id(). - /// - /// Note that only structs, unions, and enums get a local type id. In any - /// case this is an implementation detail. - local_id: Cell>, - - /// The next local id to use for a child.. - next_child_local_id: Cell, - - /// A cached copy of the canonical name, as returned by `canonical_name`. - /// - /// This is a fairly used operation during codegen so this makes bindgen - /// considerably faster in those cases. - canonical_name_cache: RefCell>, - - /// A doc comment over the item, if any. - comment: Option, - /// 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 { - /// Construct a new `Item`. - pub fn new(id: ItemId, - comment: Option, - annotations: Option, - parent_id: ItemId, - kind: ItemKind) - -> Self { - debug_assert!(id != parent_id || kind.is_module()); - Item { - id: id, - local_id: Cell::new(None), - next_child_local_id: Cell::new(1), - canonical_name_cache: RefCell::new(None), - parent_id: parent_id, - comment: comment, - annotations: annotations.unwrap_or_default(), - kind: kind, - } - } - - /// Get this `Item`'s identifier. - pub fn id(&self) -> ItemId { - self.id - } - - /// Get this `Item`'s parent's identifier. - /// - /// For the root module, the parent's ID is its own ID. - pub fn parent_id(&self) -> ItemId { - self.parent_id - } - - /// Get this `Item`'s comment, if it has any. - pub fn comment(&self) -> Option<&str> { - self.comment.as_ref().map(|c| &**c) - } - - /// What kind of item is this? - pub fn kind(&self) -> &ItemKind { - &self.kind - } - - /// Get a mutable reference to this item's kind. - pub fn kind_mut(&mut self) -> &mut ItemKind { - &mut self.kind - } - - /// Get an identifier that differentiates this item from its siblings. - /// - /// This should stay relatively stable in the face of code motion outside or - /// below this item's lexical scope, meaning that this can be useful for - /// generating relatively stable identifiers within a scope. - pub fn local_id(&self, ctx: &BindgenContext) -> usize { - if self.local_id.get().is_none() { - let parent = ctx.resolve_item(self.parent_id); - let local_id = parent.next_child_local_id.get(); - parent.next_child_local_id.set(local_id + 1); - self.local_id.set(Some(local_id)); - } - self.local_id.get().unwrap() - } - - /// Returns whether this item is a top-level item, from the point of view of - /// bindgen. - /// - /// This point of view changes depending on whether namespaces are enabled - /// or not. That way, in the following example: - /// - /// ```c++ - /// namespace foo { - /// static int var; - /// } - /// ``` - /// - /// `var` would be a toplevel item if namespaces are disabled, but won't if - /// they aren't. - /// - /// This function is used to determine when the codegen phase should call - /// `codegen` on an item, since any item that is not top-level will be - /// generated by its parent. - 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(); - } - } - - /// Get a reference to this item's underlying `Type`. Panic if this is some - /// other kind of item. - pub fn expect_type(&self) -> &Type { - self.kind().expect_type() - } - - /// Get a reference to this item's underlying `Type`, or `None` if this is - /// some other kind of item. - pub fn as_type(&self) -> Option<&Type> { - self.kind().as_type() - } - - /// Get a reference to this item's underlying `Function`. Panic if this is - /// some other kind of item. - pub fn expect_function(&self) -> &Function { - self.kind().expect_function() - } - - /// Checks whether an item contains in its "type signature" some named type. - /// - /// This function is used to avoid unused template parameter errors in Rust - /// when generating typedef declarations, and also to know whether we need - /// to generate a `PhantomData` member for a template parameter. - /// - /// For example, in code like the following: - /// - /// ```c++ - /// template - /// struct Foo { - /// T bar; - /// - /// struct Baz { - /// U bas; - /// }; - /// }; - /// ``` - /// - /// Both `Foo` and `Baz` contain both `T` and `U` template parameters in - /// their signature: - /// - /// * `Foo` - /// * `Bar` - /// - /// But the Rust structure for `Foo` would look like: - /// - /// ```rust - /// struct Foo { - /// bar: T, - /// _phantom0: ::std::marker::PhantomData, - /// } - /// ``` - /// - /// because none of its member fields contained the `U` type in the - /// signature. Similarly, `Bar` would contain a `PhantomData` type, for - /// the same reason. - /// - /// Note that this is somewhat similar to `applicable_template_args`, but - /// this also takes into account other kind of types, like arrays, - /// (`[T; 40]`), pointers: `*mut T`, etc... - /// - /// Normally we could do this check just in the `Type` kind, but we also - /// need to check the `applicable_template_args` more generally, since we - /// could need a type transitively from our parent, see the test added in - /// commit 2a3f93074dd2898669dbbce6e97e5cc4405d7cb1. - /// - /// It's kind of unfortunate (in the sense that it's a sort of complex - /// process), but I think it should get all the cases. - fn signature_contains_named_type(&self, - ctx: &BindgenContext, - ty: &Type) - -> bool { - debug_assert!(ty.is_named()); - self.expect_type().signature_contains_named_type(ctx, ty) || - self.applicable_template_args(ctx).iter().any(|template| { - ctx.resolve_type(*template).signature_contains_named_type(ctx, ty) - }) - } - - /// Returns the template arguments that apply to a struct. This is a concept - /// needed because of type declarations inside templates, for example: - /// - /// ```c++ - /// template - /// class Foo { - /// typedef T element_type; - /// typedef int Bar; - /// - /// template - /// class Baz { - /// }; - /// }; - /// ``` - /// - /// In this case, the applicable template arguments for the different types - /// would be: - /// - /// * `Foo`: [`T`] - /// * `Foo::element_type`: [`T`] - /// * `Foo::Bar`: [`T`] - /// * `Foo::Baz`: [`T`, `U`] - /// - /// You might notice that we can't generate something like: - /// - /// ```rust,ignore - /// type Foo_Bar = ::std::os::raw::c_int; - /// ``` - /// - /// since that would be invalid Rust. Still, conceptually, `Bar` *could* use - /// the template parameter type `T`, and that's exactly what this method - /// represents. The unused template parameters get stripped in the - /// `signature_contains_named_type` check. - pub fn applicable_template_args(&self, - ctx: &BindgenContext) - -> Vec { - 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::ResolvedTypeRef(inner) => { - ctx.resolve_item(inner).applicable_template_args(ctx) - } - TypeKind::Alias(_, inner) => { - let parent_args = ctx.resolve_item(self.parent_id()) - .applicable_template_args(ctx); - let inner = ctx.resolve_item(inner); - - // Avoid unused type parameters, sigh. - parent_args.iter() - .cloned() - .filter(|arg| { - let arg = ctx.resolve_type(*arg); - arg.is_named() && - inner.signature_contains_named_type(ctx, arg) - }) - .collect() - } - // XXX Is this completely correct? Partial template specialization - // is hard anyways, sigh... - TypeKind::TemplateAlias(_, ref args) | - TypeKind::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, - } - } - - /// Get this item's annotations. - pub fn annotations(&self) -> &Annotations { - &self.annotations - } - - /// Whether this item should be hidden. - /// - /// This may be due to either annotations or 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, true), self.id) - } - - /// Is this item opaque? - 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, true)) - } - - /// Is this a reference to another type? - pub fn is_type_ref(&self) -> bool { - self.as_type().map_or(false, |ty| ty.is_type_ref()) - } - - /// Get the canonical name without taking into account the replaces - /// annotation. - /// - /// This is the base logic used to implement hiding and replacing via - /// annotations, and also to implement proper name mangling. - /// - /// The idea is that each generated type in the same "level" (read: module - /// or namespace) has a unique canonical name. - /// - /// This name should be derived from the immutable state contained in the - /// type and the parent chain, since it should be consistent. - pub fn real_canonical_name(&self, - ctx: &BindgenContext, - count_namespaces: bool, - for_name_checking: 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(); - } - // We call codegen on the inner type, but we do not want - // this alias's name to appear in the canonical name just - // because it is in the inner type's parent chain, so we use - // an empty base name. - // - // Note that this would be incorrect if this type could be - // referenced from, let's say, a member variable, but in - // that case the referenced type is the inner alias, so - // we're good there. If we wouldn't, a more complex solution - // would be needed. - TypeKind::TemplateAlias(inner, _) => { - if for_name_checking { - return ctx.resolve_item(inner) - .real_canonical_name(ctx, - count_namespaces, - false); - } - Some("") - } - // Else use the proper name, or fallback to a name with an - // id. - _ => { - ty.name() - } - }.map(ToOwned::to_owned) - } - 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()); - } - } - } - Some(base) - } - ItemKind::Var(ref var) => Some(var.name().to_owned()), - ItemKind::Module(ref module) => { - module.name().map(ToOwned::to_owned) - } - }; - - 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) { - let base_name = self.make_exposed_name(None, base_name, ctx); - return ctx.rust_mangle(&base_name).into_owned(); - } - - // TODO: allow modification of the mangling functions, maybe even per - // item type? - let parent_name = parent.canonical_name(ctx); - self.make_exposed_name(Some(parent_name), base_name, ctx) - } - - fn exposed_id(&self, ctx: &BindgenContext) -> String { - // Only use local ids for enums, classes, structs and union types. All - // other items use their global id. - let ty_kind = self.kind().as_type().map(|t| t.kind()); - if let Some(ty_kind) = ty_kind { - match *ty_kind { - TypeKind::Comp(..) | - TypeKind::Enum(..) => return self.local_id(ctx).to_string(), - _ => {} - } - } - - // Note that this `id_` prefix prevents (really unlikely) collisions - // between the global id and the local id of an item with the same - // parent. - format!("id_{}", self.id().as_usize()) - } - - fn make_exposed_name(&self, - parent_name: Option, - base_name: Option, - ctx: &BindgenContext) - -> String { - lazy_static! { - static ref RE_ENDS_WITH_BINDGEN_TY: Regex = - Regex::new(r"_bindgen_ty(_\d+)+$").unwrap(); - - static ref RE_ENDS_WITH_BINDGEN_MOD: Regex = - Regex::new(r"_bindgen_mod(_\d+)+$").unwrap(); - } - - let (re, kind) = match *self.kind() { - ItemKind::Module(..) => (&*RE_ENDS_WITH_BINDGEN_MOD, "mod"), - _ => (&*RE_ENDS_WITH_BINDGEN_TY, "ty"), - }; - - let parent_name = - parent_name.and_then(|n| if n.is_empty() { None } else { Some(n) }); - match (parent_name, base_name) { - (Some(parent), Some(base)) => format!("{}_{}", parent, base), - (Some(parent), None) => { - if re.is_match(parent.as_str()) { - format!("{}_{}", parent, self.exposed_id(ctx)) - } else { - format!("{}__bindgen_{}_{}", - parent, - kind, - self.exposed_id(ctx)) - } - } - (None, Some(base)) => base, - (None, None) => { - format!("_bindgen_{}_{}", kind, self.exposed_id(ctx)) - } - } - } - - /// Get a mutable reference to this item's `Module`, or `None` if this is - /// not a `Module` item. - pub fn as_module_mut(&mut self) -> Option<&mut Module> { - match self.kind { - ItemKind::Module(ref mut module) => Some(module), - _ => None, - } - } - - /// Can we derive an implementation of the `Copy` trait for this type? - pub fn can_derive_copy(&self, ctx: &BindgenContext) -> bool { - self.expect_type().can_derive_copy(ctx, self) - } - - /// Can we derive an implementation of the `Copy` trait for an array of this - /// type? - /// - /// See `Type::can_derive_copy_in_array` for details. - pub fn can_derive_copy_in_array(&self, ctx: &BindgenContext) -> bool { - self.expect_type().can_derive_copy_in_array(ctx, self) - } -} - -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 = ctx.next_item_id(); - 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, - ctx: &mut BindgenContext) - -> Result { - use ir::function::Function; - use ir::module::Module; - use ir::var::Var; - use clangll::*; - - if !cursor.is_valid() { - return Err(ParseError::Continue); - } - - let comment = cursor.raw_comment(); - let annotations = Annotations::new(&cursor); - - let current_module = ctx.current_module(); - let relevant_parent_id = parent_id.unwrap_or(current_module); - - macro_rules! try_parse { - ($what:ident) => { - match $what::parse(cursor, ctx) { - Ok(ParseResult::New(item, declaration)) => { - let id = ctx.next_item_id(); - - ctx.add_item(Item::new(id, comment, annotations, - relevant_parent_id, - 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 applicable_cursor = cursor.definition().unwrap_or(cursor); - match Self::from_ty(&applicable_cursor.cur_type(), - Some(applicable_cursor), - parent_id, - ctx) { - 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() == CXCursor_UnexposedDecl { - Err(ParseError::Recurse) - } else { - // We whitelist cursors here known to be unhandled, to prevent being - // too noisy about this. - match cursor.kind() { - CXCursor_MacroDefinition | - CXCursor_MacroExpansion | - CXCursor_UsingDeclaration | - CXCursor_StaticAssert | - CXCursor_InclusionDirective => { - debug!("Unhandled cursor kind {:?}: {:?}", - cursor.kind(), - cursor); - } - _ => { - error!("Unhandled cursor kind {:?}: {:?}", - cursor.kind(), - cursor); - } - } - - Err(ParseError::Continue) - } - } - - fn from_ty_or_ref(ty: clang::Type, - location: Option, - parent_id: Option, - ctx: &mut BindgenContext) - -> ItemId { - let id = ctx.next_item_id(); - Self::from_ty_or_ref_with_id(id, - ty, - location, - parent_id, - ctx) - } - - /// Parse a C++ type. If we find a reference to a type that has not been - /// defined yet, use `UnresolvedTypeRef` as a placeholder. - /// - /// This logic is needed to avoid parsing items with the incorrect parent - /// and it's sort of complex to explain, so I'll just point to - /// `tests/headers/typeref.hpp` to see the kind of constructs that forced - /// this. - /// - /// Typerefs are resolved once parsing is completely done, see - /// `BindgenContext::resolve_typerefs`. - fn from_ty_or_ref_with_id(potential_id: ItemId, - ty: clang::Type, - location: Option, - parent_id: Option, - ctx: &mut BindgenContext) - -> ItemId { - debug!("from_ty_or_ref_with_id: {:?} {:?}, {:?}, {:?}", - potential_id, - ty, - location, - parent_id); - - if ctx.collected_typerefs() { - debug!("refs already collected, resolving directly"); - return Self::from_ty_with_id(potential_id, - &ty, - location, - parent_id, - ctx) - .expect("Unable to resolve type"); - } - - if let Some(ty) = ctx.builtin_or_resolved_ty(potential_id, - 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, parent_id); - let current_module = ctx.current_module(); - ctx.add_item(Item::new(potential_id, - None, - None, - parent_id.unwrap_or(current_module), - ItemKind::Type(Type::new(None, - None, - kind, - is_const))), - Some(clang::Cursor::null()), - None); - potential_id - } - - - fn from_ty(ty: &clang::Type, - location: Option, - parent_id: Option, - ctx: &mut BindgenContext) - -> Result { - let id = ctx.next_item_id(); - Self::from_ty_with_id(id, ty, location, parent_id, ctx) - } - - /// This is one of the trickiest methods you'll find (probably along with - /// some of the ones that handle templates in `BindgenContext`). - /// - /// This method parses a type, given the potential id of that type (if - /// parsing it was correct), an optional location we're scanning, which is - /// critical some times to obtain information, an optional parent item id, - /// that will, if it's `None`, become the current module id, and the - /// context. - fn from_ty_with_id(id: ItemId, - ty: &clang::Type, - location: Option, - parent_id: Option, - ctx: &mut BindgenContext) - -> Result { - use clangll::*; - - let decl = { - let decl = ty.declaration(); - decl.definition().unwrap_or(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 annotations) = annotations { - if let Some(ref replaced) = annotations.use_instead_of() { - ctx.replace(replaced, id); - } - } - - if let Some(ty) = - ctx.builtin_or_resolved_ty(id, 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)) = ctx.currently_parsed_types - .iter() - .find(|&&(d, _)| d == declaration_to_look_for) { - debug!("Avoiding recursion parsing type: {:?}", ty); - return Ok(item_id); - } - } - - let current_module = ctx.current_module(); - if valid_decl { - ctx.currently_parsed_types.push((declaration_to_look_for, id)); - } - - let result = Type::from_clang_ty(id, ty, location, parent_id, ctx); - let relevant_parent_id = parent_id.unwrap_or(current_module); - let ret = match result { - Ok(ParseResult::AlreadyResolved(ty)) => Ok(ty), - Ok(ParseResult::New(item, declaration)) => { - ctx.add_item(Item::new(id, - comment, - annotations, - relevant_parent_id, - 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, _) = - ctx.currently_parsed_types.pop().unwrap(); - assert_eq!(popped_decl, declaration_to_look_for); - } - - location.visit(|cur| { - use clangll::*; - result = Item::from_ty_with_id(id, - ty, - Some(cur), - parent_id, - ctx); - match result { - Ok(..) => CXChildVisit_Break, - Err(ParseError::Recurse) => CXChildVisit_Recurse, - Err(ParseError::Continue) => CXChildVisit_Continue, - } - }); - - if valid_decl { - ctx.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 { - warn!("Unknown type, assuming named template type: id = {:?}; spelling = {}", - id, - ty.spelling()); - Ok(Self::named_type_with_id(id, - ty.spelling(), - None, - relevant_parent_id, - ctx)) - } else { - result - } - } - }; - - if valid_decl { - let (popped_decl, _) = ctx.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. 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(id: ItemId, - name: S, - default: Option, - parent_id: ItemId, - ctx: &mut BindgenContext) - -> ItemId - where S: Into, - { - // see tests/headers/const_tparam.hpp - // and tests/headers/variadic_tname.hpp - let name = name.into().replace("const ", "").replace(".", ""); - - ctx.add_item(Item::new(id, - None, - None, - parent_id, - ItemKind::Type(Type::named(name, default))), - None, - None); - - id - } - - fn named_type(name: S, - default: Option, - parent_id: ItemId, - ctx: &mut BindgenContext) - -> ItemId - where S: Into, - { - let id = ctx.next_item_id(); - Self::named_type_with_id(id, name, default, parent_id, ctx) - } -} - -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(); - } - if self.canonical_name_cache.borrow().is_none() { - *self.canonical_name_cache.borrow_mut() = - Some(self.real_canonical_name(ctx, - ctx.options() - .enable_cxx_namespaces, - false)); - } - return self.canonical_name_cache.borrow().as_ref().unwrap().clone(); - } -} - -impl ItemCanonicalPath for Item { - fn canonical_path(&self, ctx: &BindgenContext) -> Vec { - 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); - if parent_path.last() - .map_or(false, |parent_name| parent_name.is_empty()) { - // This only happens (or should only happen) when we're an alias, - // and our parent is a templated alias, in which case the last - // component of the path will be empty. - let is_alias = match *self.expect_type().kind() { - TypeKind::Alias(..) => true, - _ => false, - }; - debug_assert!(is_alias, "How can this ever happen?"); - parent_path.pop().unwrap(); - } - parent_path.push(self.real_canonical_name(ctx, true, false)); - - parent_path - } -} diff --git a/src/ir/item_kind.rs b/src/ir/item_kind.rs deleted file mode 100644 index d9e4690c..00000000 --- a/src/ir/item_kind.rs +++ /dev/null @@ -1,114 +0,0 @@ -//! Different variants of an `Item` in our intermediate representation. - -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 { - /// Get a reference to this `ItemKind`'s underying `Module`, or `None` if it - /// is some other kind. - pub fn as_module(&self) -> Option<&Module> { - match *self { - ItemKind::Module(ref module) => Some(module), - _ => None, - } - } - - /// Is this a module? - pub fn is_module(&self) -> bool { - self.as_module().is_some() - } - - /// Get a reference to this `ItemKind`'s underying `Module`, or panic if it - /// is some other kind. - pub fn expect_module(&self) -> &Module { - self.as_module().expect("Not a module") - } - - /// Get a reference to this `ItemKind`'s underying `Function`, or `None` if - /// it is some other kind. - pub fn as_function(&self) -> Option<&Function> { - match *self { - ItemKind::Function(ref func) => Some(func), - _ => None, - } - } - - /// Is this a function? - pub fn is_function(&self) -> bool { - self.as_function().is_some() - } - - /// Get a reference to this `ItemKind`'s underying `Function`, or panic if - /// it is some other kind. - pub fn expect_function(&self) -> &Function { - self.as_function().expect("Not a function") - } - - /// Get a reference to this `ItemKind`'s underying `Type`, or `None` if - /// it is some other kind. - pub fn as_type(&self) -> Option<&Type> { - match *self { - ItemKind::Type(ref ty) => Some(ty), - _ => None, - } - } - - /// Get a mutable reference to this `ItemKind`'s underying `Type`, or `None` - /// if it is some other kind. - pub fn as_type_mut(&mut self) -> Option<&mut Type> { - match *self { - ItemKind::Type(ref mut ty) => Some(ty), - _ => None, - } - } - - /// Is this a type? - pub fn is_type(&self) -> bool { - self.as_type().is_some() - } - - /// Get a reference to this `ItemKind`'s underying `Type`, or panic if it is - /// some other kind. - pub fn expect_type(&self) -> &Type { - self.as_type().expect("Not a type") - } - - /// Get a reference to this `ItemKind`'s underying `Var`, or `None` if it is - /// some other kind. - pub fn as_var(&self) -> Option<&Var> { - match *self { - ItemKind::Var(ref v) => Some(v), - _ => None, - } - } - - /// Is this a variable? - pub fn is_var(&self) -> bool { - self.as_var().is_some() - } - - /// Get a reference to this `ItemKind`'s underying `Var`, or panic if it is - /// some other kind. - 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 deleted file mode 100644 index 3ac4a5f4..00000000 --- a/src/ir/layout.rs +++ /dev/null @@ -1,34 +0,0 @@ -//! Intermediate representation for the physical layout of some type. - -/// A type that represents the struct layout of a type. -#[derive(Debug, Clone, Copy)] -pub struct Layout { - /// The size (in bytes) of this layout. - pub size: usize, - /// The alignment (in bytes) of this layout. - pub align: usize, - /// Whether this layout's members are packed or not. - pub packed: bool, -} - -impl Layout { - /// Construct a new `Layout` with the given `size` and `align`. It is not - /// packed. - pub fn new(size: usize, align: usize) -> Self { - Layout { - size: size, - align: align, - packed: false, - } - } - - /// Is this a zero-sized layout? - pub fn is_zero(&self) -> bool { - self.size == 0 && self.align == 0 - } - - /// Construct a zero-sized layout. - pub fn zero() -> Self { - Self::new(0, 0) - } -} diff --git a/src/ir/mod.rs b/src/ir/mod.rs deleted file mode 100644 index 3c658a4a..00000000 --- a/src/ir/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! The ir module defines bindgen's intermediate representation. -//! -//! Parsing C/C++ generates the IR, while code generation outputs Rust code from -//! the IR. - -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 type_collector; -pub mod var; diff --git a/src/ir/module.rs b/src/ir/module.rs deleted file mode 100644 index c5d8cfa7..00000000 --- a/src/ir/module.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! Intermediate representation for modules (AKA C++ namespaces). - -use clang; -use parse::{ClangSubItemParser, ParseError, ParseResult}; -use parse_one; -use super::context::{BindgenContext, ItemId}; - -/// 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, - /// The children of this module, just here for convenience. - children_ids: Vec, -} - -impl Module { - /// Construct a new `Module`. - pub fn new(name: Option) -> Self { - Module { - name: name, - children_ids: vec![], - } - } - - /// Get this module's name. - pub fn name(&self) -> Option<&str> { - self.name.as_ref().map(|n| &**n) - } - - /// Get a mutable reference to this module's children. - pub fn children_mut(&mut self) -> &mut Vec { - &mut self.children_ids - } - - /// Get this module's children. - pub fn children(&self) -> &[ItemId] { - &self.children_ids - } -} - -impl ClangSubItemParser for Module { - fn parse(cursor: clang::Cursor, - ctx: &mut BindgenContext) - -> Result, 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 deleted file mode 100644 index 34af2db5..00000000 --- a/src/ir/ty.rs +++ /dev/null @@ -1,869 +0,0 @@ -//! Everything related to types in our intermediate representation. - -use clang::{self, Cursor}; -use parse::{ClangItemParser, ParseError, ParseResult}; -use super::comp::CompInfo; -use super::context::{BindgenContext, ItemId}; -use super::enum_ty::Enum; -use super::function::FunctionSig; -use super::int::IntKind; -use super::item::Item; -use super::layout::Layout; -use super::type_collector::{ItemSet, TypeCollector}; - -/// The base representation of a type in bindgen. -/// -/// A type has an optional name, which if present cannot be empty, a `layout` -/// (size, alignment and packedness) if known, a `Kind`, which determines which -/// kind of type it is, and whether the type is const. -#[derive(Debug)] -pub struct Type { - /// The name of the type, or None if it was an unnamed struct or union. - name: Option, - /// The layout of the type, if known. - layout: Option, - /// The inner kind of the type - kind: TypeKind, - /// Whether this type is const-qualified. - is_const: bool, -} - -/// The maximum number of items in an array for which Rust implements common -/// traits, and so if we have a type containing an array with more than this -/// many items, we won't be able to derive common traits on that type. -/// -/// We need type-level integers yesterday :'( -pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32; - -impl Type { - /// Get the underlying `CompInfo` for this type, or `None` if this is some - /// other kind of type. - pub fn as_comp(&self) -> Option<&CompInfo> { - match self.kind { - TypeKind::Comp(ref ci) => Some(ci), - _ => None, - } - } - - /// Construct a new `Type`. - pub fn new(name: Option, - layout: Option, - kind: TypeKind, - is_const: bool) - -> Self { - Type { - name: name, - layout: layout, - kind: kind, - is_const: is_const, - } - } - - /// Which kind of type is this? - pub fn kind(&self) -> &TypeKind { - &self.kind - } - - /// Get a mutable reference to this type's kind. - pub fn kind_mut(&mut self) -> &mut TypeKind { - &mut self.kind - } - - /// Get this type's name. - pub fn name(&self) -> Option<&str> { - self.name.as_ref().map(|name| &**name) - } - - /// Is this a compound type? - pub fn is_comp(&self) -> bool { - match self.kind { - TypeKind::Comp(..) => true, - _ => false, - } - } - - /// Is this a named type? - pub fn is_named(&self) -> bool { - match self.kind { - TypeKind::Named(..) => true, - _ => false, - } - } - - /// Is this a function type? - pub fn is_function(&self) -> bool { - match self.kind { - TypeKind::Function(..) => true, - _ => false, - } - } - - /// Is this either a builtin or named type? - pub fn is_builtin_or_named(&self) -> bool { - match self.kind { - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::Function(..) | - TypeKind::Array(..) | - TypeKind::Reference(..) | - TypeKind::Pointer(..) | - TypeKind::BlockPointer | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Named(..) => true, - _ => false, - } - } - - /// Creates a new named type, with name `name`. - pub fn named(name: String, default: Option) -> 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) - } - - /// Is this an integer type? - pub fn is_integer(&self) -> bool { - match self.kind { - TypeKind::Int(..) => true, - _ => false, - } - } - - /// Is this a `const` qualified type? - pub fn is_const(&self) -> bool { - self.is_const - } - - /// Is this a reference to another type? - pub fn is_type_ref(&self) -> bool { - match self.kind { - TypeKind::ResolvedTypeRef(_) | - TypeKind::UnresolvedTypeRef(_, _, _) => true, - _ => false, - } - } - - /// What is the layout of this type? - pub fn layout(&self, ctx: &BindgenContext) -> Option { - use std::mem; - - self.layout.or_else(|| { - match self.kind { - TypeKind::Comp(ref ci) => ci.layout(ctx), - // FIXME(emilio): This is a hack for anonymous union templates. - // Use the actual pointer size! - TypeKind::Pointer(..) | - TypeKind::BlockPointer => { - Some(Layout::new(mem::size_of::<*mut ()>(), - mem::align_of::<*mut ()>())) - } - TypeKind::ResolvedTypeRef(inner) => { - ctx.resolve_type(inner).layout(ctx) - } - _ => None, - } - }) - } - - /// Wether we can derive rust's `Debug` annotation in Rust. This should - /// ideally be a no-op that just returns `true`, but instead needs to be a - /// recursive method that checks whether all the proper members can derive - /// debug or not, because of the limit rust has on 32 items as max in the - /// array. - pub fn can_derive_debug(&self, ctx: &BindgenContext) -> bool { - match self.kind { - TypeKind::Array(t, len) => { - len <= RUST_DERIVE_IN_ARRAY_LIMIT && - ctx.resolve_type(t).can_derive_debug(ctx) - } - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(_, t) => ctx.resolve_type(t).can_derive_debug(ctx), - TypeKind::Comp(ref info) => { - info.can_derive_debug(ctx, self.layout(ctx)) - } - _ => 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.: - /// - /// ```rust - /// #[derive(Copy, Clone)] - /// struct A { - /// member: T, - /// } - /// ``` - /// - /// is fine, while: - /// - /// ```rust,ignore - /// #[derive(Copy, Clone)] - /// struct A { - /// member: [T; 1], - /// } - /// ``` - /// - /// is an error. - /// - /// That's the whole point of the existence of `can_derive_copy_in_array`. - pub fn can_derive_copy_in_array(&self, - ctx: &BindgenContext, - item: &Item) - -> bool { - match self.kind { - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(_, t) | - TypeKind::Array(t, _) => { - ctx.resolve_item(t) - .can_derive_copy_in_array(ctx) - } - TypeKind::Named(..) => false, - _ => self.can_derive_copy(ctx, item), - } - } - - /// Wether we'd be able to derive the `Copy` trait in Rust or not. Same - /// rationale than `can_derive_debug`. - pub fn can_derive_copy(&self, ctx: &BindgenContext, item: &Item) -> bool { - match self.kind { - TypeKind::Array(t, len) => { - len <= RUST_DERIVE_IN_ARRAY_LIMIT && - ctx.resolve_item(t).can_derive_copy_in_array(ctx) - } - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::TemplateRef(t, _) | - TypeKind::Alias(_, t) => ctx.resolve_item(t).can_derive_copy(ctx), - TypeKind::Comp(ref info) => info.can_derive_copy(ctx, item), - _ => true, - } - } - - /// Whether this type has a vtable. - pub fn has_vtable(&self, ctx: &BindgenContext) -> bool { - // FIXME: Can we do something about template parameters? Huh... - match self.kind { - TypeKind::TemplateRef(t, _) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(_, t) | - TypeKind::ResolvedTypeRef(t) => ctx.resolve_type(t).has_vtable(ctx), - TypeKind::Comp(ref info) => info.has_vtable(ctx), - _ => false, - } - - } - - /// Returns whether this type has a destructor. - pub fn has_destructor(&self, ctx: &BindgenContext) -> bool { - match self.kind { - TypeKind::TemplateRef(t, _) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(_, t) | - TypeKind::ResolvedTypeRef(t) => { - ctx.resolve_type(t).has_destructor(ctx) - } - TypeKind::Comp(ref info) => info.has_destructor(ctx), - _ => false, - } - } - - /// See the comment in `Item::signature_contains_named_type`. - pub fn signature_contains_named_type(&self, - ctx: &BindgenContext, - 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) | - TypeKind::Alias(_, t) => { - ctx.resolve_type(t) - .signature_contains_named_type(ctx, ty) - } - TypeKind::Function(ref sig) => { - sig.argument_types().iter().any(|&(_, arg)| { - ctx.resolve_type(arg) - .signature_contains_named_type(ctx, ty) - }) || - ctx.resolve_type(sig.return_type()) - .signature_contains_named_type(ctx, ty) - } - TypeKind::TemplateAlias(_, ref template_args) | - TypeKind::TemplateRef(_, ref template_args) => { - template_args.iter().any(|arg| { - ctx.resolve_type(*arg) - .signature_contains_named_type(ctx, ty) - }) - } - TypeKind::Comp(ref ci) => ci.signature_contains_named_type(ctx, ty), - _ => false, - } - } - - /// See safe_canonical_type. - pub fn canonical_type<'tr>(&'tr self, - ctx: &'tr BindgenContext) - -> &'tr Type { - self.safe_canonical_type(ctx) - .expect("Should have been resolved after parsing!") - } - - /// Returns the canonical type of this type, that is, the "inner type". - /// - /// For example, for a `typedef`, the canonical type would be the - /// `typedef`ed type, for a template specialization, would be the template - /// its specializing, and so on. Return None if the type is unresolved. - pub fn safe_canonical_type<'tr>(&'tr self, - ctx: &'tr BindgenContext) - -> Option<&'tr Type> { - match self.kind { - TypeKind::Named(..) | - TypeKind::Array(..) | - TypeKind::Comp(..) | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) | - TypeKind::Function(..) | - TypeKind::Enum(..) | - TypeKind::Reference(..) | - TypeKind::Void | - TypeKind::NullPtr | - TypeKind::BlockPointer | - TypeKind::Pointer(..) => Some(self), - - TypeKind::ResolvedTypeRef(inner) | - TypeKind::Alias(_, inner) | - TypeKind::TemplateAlias(inner, _) | - TypeKind::TemplateRef(inner, _) => { - ctx.resolve_type(inner).safe_canonical_type(ctx) - } - - TypeKind::UnresolvedTypeRef(..) => None, - } - } -} - -/// The kind of float this type represents. -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum FloatKind { - /// A `float`. - Float, - /// A `double`. - Double, - /// A `long double`. - LongDouble, - /// A `__float128`. - Float128, -} - -/// The different kinds of types that we can parse. -#[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 complex floating point type. - Complex(FloatKind), - - /// A type alias, with a name, that points to another type. - Alias(String, ItemId), - - /// A templated alias, pointing to an inner `Alias` type, with template - /// parameters. - TemplateAlias(ItemId, Vec), - - /// 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 pointer to an Apple block. - BlockPointer, - - /// 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), - - /// 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, - /* parent_id */ - Option), - - /// An indirection to another type. - /// - /// These are generated after we resolve a forward declaration, or when we - /// replace one type with another. - ResolvedTypeRef(ItemId), - - /// A named type, that is, a template parameter, with an optional default - /// type. - Named(String, Option), -} - -impl Type { - /// Whether this type is unsized, that is, has no members. This is used to - /// derive whether we should generate a dummy `_address` field for structs, - /// to comply to the C and C++ layouts, that specify that every type needs - /// to be addressable. - pub fn is_unsized(&self, ctx: &BindgenContext) -> bool { - debug_assert!(ctx.in_codegen_phase(), "Not yet"); - - match self.kind { - TypeKind::Void => true, - TypeKind::Comp(ref ci) => ci.is_unsized(ctx), - TypeKind::Array(inner, size) => { - size == 0 || ctx.resolve_type(inner).is_unsized(ctx) - } - TypeKind::ResolvedTypeRef(inner) | - TypeKind::Alias(_, inner) | - TypeKind::TemplateAlias(inner, _) | - TypeKind::TemplateRef(inner, _) => { - ctx.resolve_type(inner).is_unsized(ctx) - } - TypeKind::Named(..) | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) | - TypeKind::Function(..) | - TypeKind::Enum(..) | - TypeKind::Reference(..) | - TypeKind::NullPtr | - TypeKind::BlockPointer | - TypeKind::Pointer(..) => false, - - TypeKind::UnresolvedTypeRef(..) => { - unreachable!("Should have been resolved after parsing!"); - } - } - } - - /// This is another of the nasty methods. This one is the one that takes - /// care of the core logic of converting a clang type to a `Type`. - /// - /// It's sort of nasty and full of special-casing, but hopefully the - /// comments in every special case justify why they're there. - pub fn from_clang_ty(potential_id: ItemId, - ty: &clang::Type, - location: Option, - parent_id: Option, - ctx: &mut BindgenContext) - -> Result, ParseError> { - use clangll::*; - { - let already_resolved = - ctx.builtin_or_resolved_ty(potential_id, - parent_id, - ty, - location); - if let Some(ty) = already_resolved { - 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().is_some() { - 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.template_args().map_or(false, |x| x.len() > 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_CXXBaseSpecifier | - CXCursor_ClassTemplate => { - if location.kind() == CXCursor_CXXBaseSpecifier { - // In the case we're parsing a base specifier - // inside an unexposed or invalid type, it means - // that we're parsing one of two things: - // - // * A template parameter. - // * A complex class that isn't exposed. - // - // This means, unfortunately, that there's no - // good way to differentiate between them. - // - // Probably we could try to look at the - // declaration and complicate more this logic, - // but we'll keep it simple... if it's a valid - // C++ identifier, we'll consider it as a - // template parameter. - // - // This is because: - // - // * We expect every other base that is a - // proper identifier (that is, a simple - // struct/union declaration), to be exposed, - // so this path can't be reached in that - // case. - // - // * Quite conveniently, complex base - // specifiers preserve their full names (that - // is: Foo instead of Foo). We can take - // advantage of this. - // - // If we find some edge case where this doesn't - // work (which I guess is unlikely, see the - // different test cases[1][2][3][4]), we'd need - // to find more creative ways of differentiating - // these two cases. - // - // [1]: inherit_named.hpp - // [2]: forward-inherit-struct-with-fields.hpp - // [3]: forward-inherit-struct.hpp - // [4]: inherit-namespaced.hpp - if location.spelling() - .chars() - .all(|c| c.is_alphanumeric() || c == '_') { - return Err(ParseError::Recurse); - } - } else { - name = location.spelling(); - } - let complex = CompInfo::from_ty(potential_id, - ty, - Some(location), - ctx) - .expect("C'mon"); - TypeKind::Comp(complex) - } - CXCursor_TypeAliasTemplateDecl => { - debug!("TypeAliasTemplateDecl"); - - // We need to manually unwind this one. - let mut inner = Err(ParseError::Continue); - let mut args = vec![]; - - location.visit(|cur| { - match cur.kind() { - CXCursor_TypeAliasDecl => { - debug_assert!(cur.cur_type().kind() == - CXType_Typedef); - inner = - Item::from_ty(&cur.cur_type(), - Some(cur), - Some(potential_id), - ctx); - } - CXCursor_TemplateTypeParameter => { - // See the comment in src/ir/comp.rs - // about the same situation. - 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); - args.push(param); - } - _ => {} - } - CXChildVisit_Continue - }); - - if inner.is_err() { - error!("Failed to parse templated alias {:?}", - location); - return Err(ParseError::Continue); - } - - // NB: `args` may be empty here (if for example the - // template parameters are constants). - // - // We can't reject it here then because inner points - // to `potential_id` now, so either we remove - // `inner` and return an error, or carry on. - // - // In this case, we just carry on, since it seems - // easier if than removing every possible reference - // to `item` from `ctx`, and it doesn't give any - // problems that we didn't have anyway. - TypeKind::TemplateAlias(inner.unwrap(), args) - } - CXCursor_TemplateRef => { - let referenced = location.referenced().expect("expected value, got none"); - let referenced_ty = referenced.cur_type(); - let referenced_declaration = - Some(referenced_ty.declaration()); - - return Self::from_clang_ty(potential_id, - &referenced_ty, - referenced_declaration, - parent_id, - ctx); - } - CXCursor_TypeRef => { - let referenced = location.referenced().expect("expected value, got none"); - let referenced_ty = referenced.cur_type(); - let referenced_declaration = - Some(referenced_ty.declaration()); - - let item = - Item::from_ty_or_ref_with_id( - potential_id, - referenced_ty, - referenced_declaration, - parent_id, - ctx); - return Ok(ParseResult::AlreadyResolved(item)); - } - _ => { - if ty.kind() == CXType_Unexposed { - warn!("Unexposed type {:?}, recursing inside, \ - loc: {:?}", - ty, - location); - return Err(ParseError::Recurse); - } - - // If the type name is empty we're probably - // over-recursing to find a template parameter name - // or something like that, so just don't be too - // noisy with it since it causes confusion, see for - // example the discussion in: - // - // https://github.com/jamesmunns/teensy3-rs/issues/9 - if !ty.spelling().is_empty() { - error!("invalid type {:?}", ty); - } else { - warn!("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); - } - - if !ty.spelling().is_empty() { - error!("invalid type {:?}", ty); - } else { - warn!("invalid type {:?}", ty); - } - 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().unwrap(), - location, - parent_id, - ctx); - TypeKind::Pointer(inner) - } - CXType_BlockPointer => TypeKind::BlockPointer, - // 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().unwrap(), - location, - parent_id, - ctx); - TypeKind::Reference(inner) - } - // XXX DependentSizedArray is wrong - CXType_VariableArray | - CXType_DependentSizedArray | - CXType_IncompleteArray => { - let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(), - 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) - } - // FIXME: We stub vectors as arrays since in 99% of the cases the - // layout is going to be correct, and there's no way we can generate - // vector types properly in Rust for now. - // - // That being said, that should be fixed eventually. - CXType_Vector | - CXType_ConstantArray => { - let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(), - location, - parent_id, - ctx) - .expect("Not able to resolve array element?"); - TypeKind::Array(inner, ty.num_elements().unwrap()) - } - #[cfg(not(feature="llvm_stable"))] - CXType_Elaborated => { - return Self::from_clang_ty(potential_id, - &ty.named(), - location, - parent_id, - ctx); - } - _ => { - error!("unsupported type: kind = {:?}; ty = {:?}; at {:?}", - ty.kind(), - 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()))) - } -} - -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::TemplateAlias(inner, _) | - TypeKind::Alias(_, inner) | - TypeKind::Named(_, Some(inner)) | - TypeKind::ResolvedTypeRef(inner) => { - types.insert(inner); - } - - TypeKind::TemplateRef(inner, ref template_args) => { - types.insert(inner); - for &item in template_args { - types.insert(item); - } - } - 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!("::collect_types: Ignoring: {:?}", other); - } - } - } -} diff --git a/src/ir/type_collector.rs b/src/ir/type_collector.rs deleted file mode 100644 index 0f10152d..00000000 --- a/src/ir/type_collector.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! Collecting type items. - -use std::collections::BTreeSet; -use super::context::{BindgenContext, ItemId}; - -/// A set of items. -pub type ItemSet = BTreeSet; - -/// Collect all the type items referenced by this item. -pub trait TypeCollector { - /// If a particular type needs extra information beyond what it has in - /// `self` and `context` to find its referenced type items, its - /// implementation can define this associated type, forcing callers to pass - /// the needed information through. - type Extra; - - /// Add each type item referenced by `self` into the `types` set. - fn collect_types(&self, - context: &BindgenContext, - types: &mut ItemSet, - extra: &Self::Extra); -} diff --git a/src/ir/var.rs b/src/ir/var.rs deleted file mode 100644 index d0c4d9ca..00000000 --- a/src/ir/var.rs +++ /dev/null @@ -1,246 +0,0 @@ -//! Intermediate representation of variables. - -use cexpr; -use clang; -use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; -use std::num::Wrapping; -use super::context::{BindgenContext, ItemId}; -use super::function::cursor_mangling; -use super::int::IntKind; -use super::item::Item; -use super::ty::TypeKind; - -/// A `Var` is our intermediate representation of a variable. -#[derive(Debug)] -pub struct Var { - /// The name of the variable. - name: String, - /// The mangled name of the variable. - mangled_name: Option, - /// The type of the variable. - ty: ItemId, - /// TODO: support non-integer constants? - /// The integer value of the variable. - val: Option, - /// Whether this variable is const. - is_const: bool, -} - -impl Var { - /// Construct a new `Var`. - pub fn new(name: String, - mangled: Option, - ty: ItemId, - val: Option, - is_const: bool) - -> Var { - assert!(!name.is_empty()); - Var { - name: name, - mangled_name: mangled, - ty: ty, - val: val, - is_const: is_const, - } - } - - /// Is this variable `const` qualified? - pub fn is_const(&self) -> bool { - self.is_const - } - - /// The value of this constant variable, if any. - pub fn val(&self) -> Option { - self.val - } - - /// Get this variable's type. - pub fn ty(&self) -> ItemId { - self.ty - } - - /// Get this variable's name. - pub fn name(&self) -> &str { - &self.name - } - - /// Get this variable's mangled 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, - ctx: &mut BindgenContext) - -> Result, ParseError> { - use clangll::*; - use cexpr::expr::EvalResult; - match cursor.kind() { - CXCursor_MacroDefinition => { - let value = parse_macro(ctx, &cursor, ctx.translation_unit()); - - let (id, value) = match value { - Some(v) => v, - None => return Err(ParseError::Continue), - }; - - assert!(!id.is_empty(), "Empty macro name?"); - - let previously_defined = ctx.parsed_macro(&id); - - // NB: It's important to "note" the macro even if the result is - // not an integer, otherwise we might loose other kind of - // derived macros. - ctx.note_parsed_macro(id.clone(), value.clone()); - - if previously_defined { - let name = String::from_utf8(id).unwrap(); - warn!("Duplicated macro definition: {}", name); - return Err(ParseError::Continue); - } - - // NOTE: Unwrapping, here and above, is safe, because the - // identifier of a token comes straight from clang, and we - // enforce utf8 there, so we should have already panicked at - // this point. - let name = String::from_utf8(id).unwrap(); - let (int_kind, val) = match value { - // TODO(emilio): Handle the non-invalid ones! - EvalResult::Float(..) | - EvalResult::Char(..) | - EvalResult::Str(..) | - EvalResult::Invalid => return Err(ParseError::Continue), - - EvalResult::Int(Wrapping(value)) => { - let kind = ctx.options() - .type_chooser - .as_ref() - .and_then(|c| c.int_macro(&name, value)) - .unwrap_or_else(|| { - if value < 0 { - if value < i32::min_value() as i64 { - IntKind::LongLong - } else { - IntKind::Int - } - } else if value > u32::max_value() as i64 { - IntKind::ULongLong - } else { - IntKind::UInt - } - }); - - (kind, value) - } - }; - - let ty = Item::builtin_type(TypeKind::Int(int_kind), true, ctx); - - Ok(ParseResult::New(Var::new(name, None, ty, Some(val), 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, ctx) - .expect("Unable to resolve constant type?"); - - // 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. - let value = ctx.safe_resolve_type(ty) - .and_then(|t| t.safe_canonical_type(ctx)) - .and_then(|t| if t.is_integer() { Some(t) } else { None }) - .and_then(|_| { - get_integer_literal_from_cursor(&cursor, - ctx.translation_unit()) - }); - - 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) - } - } - } -} - -/// Try and parse a macro using all the macros parsed until now. -fn parse_macro(ctx: &BindgenContext, - cursor: &clang::Cursor, - unit: &clang::TranslationUnit) - -> Option<(Vec, cexpr::expr::EvalResult)> { - use cexpr::{expr, nom}; - - let cexpr_tokens = match unit.cexpr_tokens(cursor) { - None => return None, - Some(tokens) => tokens, - }; - - let parser = expr::IdentifierParser::new(ctx.parsed_macros()); - let result = parser.macro_definition(&cexpr_tokens); - - match result { - nom::IResult::Done(_, (id, val)) => Some((id.into(), val)), - _ => None, - } -} - -fn parse_int_literal_tokens(cursor: &clang::Cursor, - unit: &clang::TranslationUnit) - -> Option { - use cexpr::{expr, nom}; - use cexpr::expr::EvalResult; - - let cexpr_tokens = match unit.cexpr_tokens(cursor) { - None => return None, - Some(tokens) => tokens, - }; - - // TODO(emilio): We can try to parse other kinds of literals. - match expr::expr(&cexpr_tokens) { - nom::IResult::Done(_, EvalResult::Int(Wrapping(val))) => Some(val), - _ => None, - } -} - -fn get_integer_literal_from_cursor(cursor: &clang::Cursor, - unit: &clang::TranslationUnit) - -> Option { - use clangll::*; - let mut value = None; - cursor.visit(|c| { - match c.kind() { - CXCursor_IntegerLiteral | - CXCursor_UnaryOperator => { - value = parse_int_literal_tokens(&c, unit); - } - CXCursor_UnexposedExpr => { - value = get_integer_literal_from_cursor(&c, unit); - } - _ => (), - } - if value.is_some() { - CXChildVisit_Break - } else { - CXChildVisit_Continue - } - }); - value -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100755 index b56cb468..00000000 --- a/src/lib.rs +++ /dev/null @@ -1,614 +0,0 @@ -//! Generate Rust bindings for C and C++ libraries. -//! -//! Provide a C/C++ header file, receive Rust FFI code to call into C/C++ -//! functions and use types defined in the header. -//! -//! See the [Builder](./struct.Builder.html) struct for usage. - -#![crate_name = "bindgen"] -#![crate_type = "dylib"] - -#![cfg_attr(feature = "clippy", feature(plugin))] -#![cfg_attr(feature = "clippy", plugin(clippy))] - -#![deny(missing_docs)] -#![deny(warnings)] - -// We internally use the deprecated BindgenOptions all over the place. Once we -// remove its `pub` declaration, we can un-deprecate it and remove this pragma. -#![allow(deprecated)] - -// To avoid rather annoying warnings when matching with CXCursor_xxx as a -// constant. -#![allow(non_upper_case_globals)] - -#[macro_use] -extern crate cfg_if; -extern crate cexpr; -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; -#[macro_use] -extern crate lazy_static; - -// A macro to declare an internal module for which we *must* provide -// documentation for. If we are building with the "_docs" feature, then the -// module is declared public, and our `#![deny(missing_docs)]` pragma applies to -// it. This feature is used in CI, so we won't let anything slip by -// undocumented. Normal builds, however, will leave the module private, so that -// we don't expose internals to library consumers. -macro_rules! doc_mod { - ($m:ident, $doc_mod_name:ident) => { - cfg_if! { - if #[cfg(feature = "_docs")] { - pub mod $doc_mod_name { - //! Autogenerated documentation module. - pub use super::$m::*; - } - } else { - } - } - }; -} - -mod clangll; -mod clang; -mod ir; -mod parse; -mod regex_set; -mod uses; - -pub mod chooser; - -#[cfg(rustfmt)] -mod codegen; - -doc_mod!(clang, clang_docs); -doc_mod!(ir, ir_docs); -doc_mod!(parse, parse_docs); -doc_mod!(regex_set, regex_set_docs); -doc_mod!(uses, uses_docs); - -mod codegen { - include!(concat!(env!("OUT_DIR"), "/codegen.rs")); -} - -use ir::context::{BindgenContext, ItemId}; -use ir::item::Item; -use parse::{ClangItemParser, ParseError}; -use regex_set::RegexSet; - -use std::borrow::Borrow; -use std::collections::HashSet; -use std::fs::OpenOptions; -use std::io::{self, Write}; -use std::path::Path; - -use syntax::ast; -use syntax::codemap::{DUMMY_SP, Span}; -use syntax::print::pp::eof; -use syntax::print::pprust; -use syntax::ptr::P; - -/// Configure and generate Rust bindings for a C/C++ header. -/// -/// This is the main entry point to the library. -/// -/// ```ignore -/// use bindgen::builder; -/// -/// // Configure and generate bindings. -/// let bindings = try!(builder().header("path/to/input/header") -/// .whitelisted_type("SomeCoolClass") -/// .whitelisted_function("do_some_cool_thing") -/// .generate()); -/// -/// // Write the generated bindings to an output file. -/// try!(bindings.write_to_file("path/to/output.rs")); -/// ``` -#[derive(Debug,Default)] -pub struct Builder { - options: BindgenOptions, -} - -/// Construct a new [`Builder`](./struct.Builder.html). -pub fn builder() -> Builder { - Default::default() -} - -impl Builder { - /// Set the input C/C++ header. - pub fn header>(mut self, header: T) -> Builder { - let header = header.into(); - self.options.input_header = Some(header.clone()); - self.clang_arg(header) - } - - /// Generate a C/C++ file that includes the header and has dummy uses of - /// every type defined in the header. - pub fn dummy_uses>(mut self, dummy_uses: T) -> Builder { - self.options.dummy_uses = Some(dummy_uses.into()); - self - } - - /// Hide the given type from the generated bindings. - pub fn hide_type>(mut self, arg: T) -> Builder { - self.options.hidden_types.insert(arg.into()); - self - } - - /// Treat the given type as opaque in the generated bindings. - pub fn opaque_type>(mut self, arg: T) -> Builder { - self.options.opaque_types.insert(arg.into()); - self - } - - /// Whitelist the given type so that it (and all types that it transitively - /// refers to) appears in the generated bindings. - pub fn whitelisted_type>(mut self, arg: T) -> Builder { - self.options.whitelisted_types.insert(&arg); - self - } - - /// Whitelist the given function so that it (and all types that it - /// transitively refers to) appears in the generated bindings. - pub fn whitelisted_function>(mut self, arg: T) -> Builder { - self.options.whitelisted_functions.insert(&arg); - self - } - - /// Whitelist the given variable so that it (and all types that it - /// transitively refers to) appears in the generated bindings. - pub fn whitelisted_var>(mut self, arg: T) -> Builder { - self.options.whitelisted_vars.insert(&arg); - self - } - - /// Mark the given enum (or set of enums, if using a pattern) as being - /// bitfield-like. - /// - /// This makes bindgen generate a type that isn't a rust `enum`. - pub fn bitfield_enum>(mut self, arg: T) -> Builder { - self.options.bitfield_enums.insert(&arg); - self - } - - /// Add a string to prepend to the generated bindings. The string is passed - /// through without any modification. - pub fn raw_line>(mut self, arg: T) -> Builder { - self.options.raw_lines.push(arg.into()); - self - } - - /// Add an argument to be passed straight through to clang. - pub fn clang_arg>(mut self, arg: T) -> Builder { - self.options.clang_args.push(arg.into()); - self - } - - /// Make the generated bindings link the given shared library. - pub fn link>(mut self, library: T) -> Builder { - self.options.links.push((library.into(), LinkType::Default)); - self - } - - /// Make the generated bindings link the given static library. - pub fn link_static>(mut self, library: T) -> Builder { - self.options.links.push((library.into(), LinkType::Static)); - self - } - - /// Make the generated bindings link the given framework. - pub fn link_framework>(mut self, library: T) -> Builder { - self.options.links.push((library.into(), LinkType::Framework)); - self - } - - /// Emit bindings for builtin definitions (for example `__builtin_va_list`) - /// in the generated Rust. - pub fn emit_builtins(mut self) -> Builder { - self.options.builtins = true; - self - } - - /// Avoid converting floats to f32/f64 by default. - pub fn no_convert_floats(mut self) -> Self { - self.options.convert_floats = false; - self - } - - /// Emit Clang AST. - pub fn emit_clang_ast(mut self) -> Builder { - self.options.emit_ast = true; - self - } - - /// Enable C++ namespaces. - pub fn enable_cxx_namespaces(mut self) -> Builder { - self.options.enable_cxx_namespaces = true; - self - } - - /// Ignore functions. - pub fn ignore_functions(mut self) -> Builder { - self.options.ignore_functions = true; - self - } - - /// Ignore methods. - pub fn ignore_methods(mut self) -> Builder { - self.options.ignore_methods = true; - self - } - - /// Avoid generating any unstable Rust in the generated bindings. - pub fn no_unstable_rust(mut self) -> Builder { - self.options.unstable_rust = false; - self - } - - /// Use core instead of libstd in the generated bindings. - pub fn use_core(mut self) -> Builder { - self.options.use_core = true; - self - } - - /// Use the given prefix for the raw types instead of `::std::os::raw`. - pub fn ctypes_prefix>(mut self, prefix: T) -> Builder { - self.options.ctypes_prefix = Some(prefix.into()); - self - } - - /// Allows configuring types in different situations, see the `TypeChooser` - /// documentation. - pub fn type_chooser(mut self, cb: Box) -> Self { - self.options.type_chooser = Some(cb); - self - } - - /// Generate the Rust bindings using the options built up thus far. - pub fn generate<'ctx>(self) -> Result, ()> { - Bindings::generate(self.options, None) - } -} - -/// Configuration options for generated bindings. -/// -/// Deprecated: use a `Builder` instead. -#[derive(Debug)] -#[deprecated] -pub struct BindgenOptions { - /// The set of types that have been blacklisted and should not appear - /// anywhere in the generated code. - pub hidden_types: HashSet, - - /// The set of types that should be treated as opaque structures in the - /// generated code. - pub opaque_types: HashSet, - - /// The set of types that we should have bindings for in the generated - /// code. - /// - /// This includes all types transitively reachable from any type in this - /// set. One might think of whitelisted types/vars/functions as GC roots, - /// and the generated Rust code as including everything that gets marked. - pub whitelisted_types: RegexSet, - - /// Whitelisted functions. See docs for `whitelisted_types` for more. - pub whitelisted_functions: RegexSet, - - /// Whitelisted variables. See docs for `whitelisted_types` for more. - pub whitelisted_vars: RegexSet, - - /// The enum patterns to mark an enum as bitfield. - pub bitfield_enums: RegexSet, - - /// Whether we should generate builtins or not. - pub builtins: bool, - - /// The set of libraries we should link in the generated Rust code. - pub links: Vec<(String, LinkType)>, - - /// True if we should dump the Clang AST for debugging purposes. - pub emit_ast: bool, - - /// True if we should ignore functions and only generate bindings for - /// structures, types, and methods. - pub ignore_functions: bool, - - /// True if we should avoid generating bindings for methods, and instead - /// just generate code for structures and types. - pub ignore_methods: bool, - - /// True if we should emulate C++ namespaces with Rust modules in the - /// generated bindings. - pub enable_cxx_namespaces: bool, - - /// True if we shold derive Debug trait implementations for C/C++ structures - /// and types. - pub derive_debug: bool, - - /// True if we can use unstable Rust code in the bindings, false if we - /// cannot. - pub unstable_rust: bool, - - /// True if we should avoid using libstd to use libcore instead. - pub use_core: bool, - - /// An optional prefix for the "raw" types, like `c_int`, `c_void`... - pub ctypes_prefix: Option, - - /// True if we should generate constant names that are **directly** under - /// namespaces. - pub namespaced_constants: bool, - - /// True if we should use MSVC name mangling rules. - pub msvc_mangling: bool, - - /// Whether we should convert float types to f32/f64 types. - pub convert_floats: bool, - - /// The set of raw lines to prepend to the generated Rust code. - pub raw_lines: Vec, - - /// The set of arguments to pass straight through to Clang. - pub clang_args: Vec, - - /// The input header file. - pub input_header: Option, - - /// Generate a dummy C/C++ file that includes the header and has dummy uses - /// of all types defined therein. See the `uses` module for more. - pub dummy_uses: Option, - - /// A user-provided type chooser to allow customizing different kinds of - /// situations. - pub type_chooser: Option>, -} - -impl Default for BindgenOptions { - fn default() -> BindgenOptions { - BindgenOptions { - hidden_types: Default::default(), - opaque_types: Default::default(), - whitelisted_types: Default::default(), - whitelisted_functions: Default::default(), - whitelisted_vars: Default::default(), - bitfield_enums: Default::default(), - builtins: false, - links: vec![], - emit_ast: false, - ignore_functions: false, - ignore_methods: false, - derive_debug: true, - enable_cxx_namespaces: false, - unstable_rust: true, - use_core: false, - ctypes_prefix: None, - namespaced_constants: true, - msvc_mangling: false, - convert_floats: true, - raw_lines: vec![], - clang_args: vec![], - input_header: None, - dummy_uses: None, - type_chooser: None, - } - } -} - -/// The linking type to use with a given library. -/// -/// TODO: #104: This is ignored at the moment, but shouldn't be. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum LinkType { - /// Use shared library linking. This is the default. - Default, - /// Use static linking. - Static, - /// The library is an OSX framework. - Framework, -} - -/// Generated Rust bindings. -#[derive(Debug)] -pub struct Bindings<'ctx> { - context: BindgenContext<'ctx>, - module: ast::Mod, -} - -impl<'ctx> Bindings<'ctx> { - /// Generate bindings for the given options. - /// - /// Deprecated - use a `Builder` instead - #[deprecated] - pub fn generate(options: BindgenOptions, - span: Option) - -> Result, ()> { - let span = span.unwrap_or(DUMMY_SP); - - let mut context = BindgenContext::new(options); - parse(&mut context); - - let module = ast::Mod { - inner: span, - items: codegen::codegen(&mut context), - }; - - Ok(Bindings { - context: context, - module: module, - }) - } - - /// Convert these bindings into a Rust AST. - pub fn into_ast(self) -> Vec> { - self.module.items - } - - /// Convert these bindings into source text (with raw lines prepended). - pub fn to_string(&self) -> String { - let mut mod_str = vec![]; - { - let ref_writer = Box::new(mod_str.by_ref()) as Box; - self.write(ref_writer).expect("Could not write bindings to string"); - } - String::from_utf8(mod_str).unwrap() - } - - /// Write these bindings as source text to a file. - pub fn write_to_file>(&self, path: P) -> io::Result<()> { - let file = try!(OpenOptions::new() - .write(true) - .truncate(true) - .create(true) - .open(path)); - self.write(Box::new(file)) - } - - /// Write these bindings as source text to the given `Write`able. - // https://github.com/Manishearth/rust-clippy/issues/740 - #[cfg_attr(feature = "clippy", allow(needless_lifetimes))] - pub fn write<'a>(&self, mut writer: Box) -> io::Result<()> { - try!(writer.write("/* automatically generated by rust-bindgen */\n\n" - .as_bytes())); - - for line in self.context.options().raw_lines.iter() { - try!(writer.write(line.as_bytes())); - try!(writer.write("\n".as_bytes())); - } - if !self.context.options().raw_lines.is_empty() { - try!(writer.write("\n".as_bytes())); - } - - let mut ps = pprust::rust_printer(writer); - try!(ps.print_mod(&self.module, &[])); - try!(ps.print_remaining_comments()); - try!(eof(&mut ps.s)); - ps.s.out.flush() - } - - /// Generate and write dummy uses of all the types we parsed, if we've been - /// requested to do so in the options. - /// - /// See the `uses` module for more information. - pub fn write_dummy_uses(&mut self) -> io::Result<()> { - let file = - if let Some(ref dummy_path) = self.context.options().dummy_uses { - Some(try!(OpenOptions::new() - .write(true) - .truncate(true) - .create(true) - .open(dummy_path))) - } else { - None - }; - - if let Some(file) = file { - try!(uses::generate_dummy_uses(&mut self.context, file)); - } - - 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, - } -} - -/// Parse one `Item` from the Clang cursor. -pub fn parse_one(ctx: &mut BindgenContext, - cursor: clang::Cursor, - parent: Option, - children: &mut Vec) - -> 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 -} - -/// Parse the Clang AST into our `Item` internal representation. -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?"); -} - -/// Extracted Clang version data -#[derive(Debug)] -pub struct ClangVersion { - /// Major and minor semvar, if parsing was successful - pub parsed: Option<(u32, u32)>, - /// full version string - pub full: String, -} - -/// Get the major and the minor semvar numbers of Clang's version -pub fn clang_version() -> ClangVersion { - let raw_v: String = clang::extract_clang_version(); - let split_v: Option> = raw_v.split_whitespace() - .nth(2) - .map(|v| v.split('.').collect()); - match split_v { - Some(v) => { - if v.len() >= 2 { - let maybe_major = v[0].parse::(); - let maybe_minor = v[1].parse::(); - match (maybe_major, maybe_minor) { - (Ok(major), Ok(minor)) => { - return ClangVersion { - parsed: Some((major, minor)), - full: raw_v.clone(), - } - } - _ => {} - } - } - } - None => {} - }; - ClangVersion { - parsed: None, - full: raw_v.clone(), - } -} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 00000000..8cbff63b --- /dev/null +++ b/src/main.rs @@ -0,0 +1,84 @@ +extern crate libbindgen; +extern crate env_logger; +#[macro_use] +extern crate log; +extern crate clang_sys; +extern crate clap; +extern crate rustc_serialize; + +use libbindgen::clang_version; +use std::env; + +mod options; +use options::builder_from_flags; + +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(); + + let version = clang_version(); + let expected_version = if cfg!(feature = "llvm_stable") { + (3, 8) + } else { + (3, 9) + }; + + info!("Clang Version: {}", version.full); + + match version.parsed { + None => warn!("Couldn't parse libclang version"), + Some(version) if version != expected_version => { + error!("Using clang {:?}, expected {:?}", + version, + expected_version); + } + _ => {} + } + + if let Some(clang) = clang_sys::support::Clang::find(None) { + let has_clang_args = + bind_args.iter().rposition(|arg| *arg == "--").is_some(); + if !has_clang_args { + bind_args.push("--".to_owned()); + } + + // If --target is specified, assume caller knows what they're doing and + // don't mess with + // include paths for them + let has_target_arg = bind_args.iter() + .rposition(|arg| arg.starts_with("--target")) + .is_some(); + if !has_target_arg { + // TODO: distinguish C and C++ paths? C++'s should be enough, I + // guess. + for path in clang.cpp_search_paths.into_iter() { + if let Ok(path) = path.into_os_string().into_string() { + bind_args.push("-isystem".to_owned()); + bind_args.push(path); + } + } + } + } + + match builder_from_flags(bind_args.into_iter()) { + Ok((builder, output)) => { + let mut bindings = builder.generate() + .expect("Unable to generate bindings"); + bindings.write(output) + .expect("Unable to write output"); + bindings.write_dummy_uses() + .expect("Unable to write dummy uses to file."); + } + Err(error) => { + println!("{}", error); + std::process::exit(1); + } + }; +} diff --git a/src/options.rs b/src/options.rs new file mode 100644 index 00000000..c3c6a1f2 --- /dev/null +++ b/src/options.rs @@ -0,0 +1,266 @@ +use clap::{App, Arg}; +use libbindgen::{Builder, builder}; +use std::fs::File; +use std::io::{self, Error, ErrorKind}; + +/// Construct a new [`Builder`](./struct.Builder.html) from command line flags. +pub fn builder_from_flags(args: I) + -> Result<(Builder, Box), io::Error> + where I: Iterator, +{ + let matches = App::new("bindgen") + .version(env!("CARGO_PKG_VERSION")) + .about("Generates Rust bindings from C/C++ headers.") + .usage("bindgen [FLAGS] [OPTIONS]
-- ...") + .args(&[ + Arg::with_name("header") + .help("C or C++ header file") + .required(true), + Arg::with_name("bitfield-enum") + .long("bitfield-enum") + .help("Mark any enum whose name matches as a set of \ + bitfield flags instead of an enumeration.") + .value_name("regex") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("blacklist-type") + .long("blacklist-type") + .help("Mark a type as hidden.") + .value_name("type") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("builtins") + .long("builtins") + .help("Output bindings for builtin definitions, e.g. \ + __builtin_va_list."), + Arg::with_name("ctypes-prefix") + .long("ctypes-prefix") + .help("Use the given prefix before raw types instead of \ + ::std::os::raw.") + .value_name("prefix") + .takes_value(true), + // All positional arguments after the end of options marker, `--` + Arg::with_name("clang-args") + .multiple(true), + Arg::with_name("dummy-uses") + .long("dummy-uses") + .help("For testing purposes, generate a C/C++ file containing \ + dummy uses of all types defined in the input header.") + .takes_value(true), + Arg::with_name("emit-clang-ast") + .long("emit-clang-ast") + .help("Output the Clang AST for debugging purposes."), + Arg::with_name("enable-cxx-namespaces") + .long("enable-cxx-namespaces") + .help("Enable support for C++ namespaces."), + Arg::with_name("framework") + .long("framework-link") + .help("Link to framework.") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("ignore-functions") + .long("ignore-functions") + .help("Do not generate bindings for functions or methods. This \ + is useful when you only care about struct layouts."), + Arg::with_name("ignore-methods") + .long("ignore-methods") + .help("Do not generate bindings for methods."), + Arg::with_name("dynamic") + .short("l") + .long("link") + .help("Link to dynamic library.") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("no-convert-floats") + .long("no-convert-floats") + .help("Don't automatically convert floats to f32/f64."), + Arg::with_name("no-unstable-rust") + .long("no-unstable-rust") + .help("Do not generate unstable Rust code.") + .multiple(true), // FIXME: Pass legacy test suite + Arg::with_name("opaque-type") + .long("opaque-type") + .help("Mark a type as opaque.") + .value_name("type") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("output") + .short("o") + .long("output") + .help("Write Rust bindings to .") + .takes_value(true), + Arg::with_name("raw-line") + .long("raw-line") + .help("Add a raw line of Rust code at the beginning of output.") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("static") + .long("static-link") + .help("Link to static library.") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("use-core") + .long("use-core") + .help("Use types from Rust core instead of std."), + Arg::with_name("use-msvc-mangling") + .long("use-msvc-mangling") + .help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."), + Arg::with_name("whitelist-function") + .long("whitelist-function") + .help("Whitelist all the free-standing functions matching \ + . Other non-whitelisted functions will not be \ + generated.") + .value_name("regex") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("whitelist-type") + .long("whitelist-type") + .help("Whitelist the type. Other non-whitelisted types will \ + not be generated.") + .value_name("type") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("whitelist-var") + .long("whitelist-var") + .help("Whitelist all the free-standing variables matching \ + . Other non-whitelisted variables will not be \ + generated.") + .value_name("regex") + .takes_value(true) + .multiple(true) + .number_of_values(1), + ]) // .args() + .get_matches_from(args); + + let mut builder = builder(); + + if let Some(header) = matches.value_of("header") { + builder = builder.header(header); + } else { + return Err(Error::new(ErrorKind::Other, "Header not found")); + } + + if let Some(bitfields) = matches.values_of("bitfield-enum") { + for regex in bitfields { + builder = builder.bitfield_enum(regex); + } + } + + if let Some(hidden_types) = matches.values_of("blacklist-type") { + for ty in hidden_types { + builder = builder.hide_type(ty); + } + } + + if matches.is_present("builtins") { + builder = builder.emit_builtins(); + } + + if let Some(prefix) = matches.value_of("ctypes-prefix") { + builder = builder.ctypes_prefix(prefix); + } + + if let Some(dummy) = matches.value_of("dummy-uses") { + builder = builder.dummy_uses(dummy); + } + + if let Some(links) = matches.values_of("dynamic") { + for library in links { + builder = builder.link(library); + } + } + + if matches.is_present("emit-clang-ast") { + builder = builder.emit_clang_ast(); + } + + if matches.is_present("enable-cxx-namespaces") { + builder = builder.enable_cxx_namespaces(); + } + + if let Some(links) = matches.values_of("framework") { + for framework in links { + builder = builder.link_framework(framework); + } + } + + if matches.is_present("ignore-functions") { + builder = builder.ignore_functions(); + } + + if matches.is_present("ignore-methods") { + builder = builder.ignore_methods(); + } + + if matches.is_present("no-unstable-rust") { + builder = builder.no_unstable_rust(); + } + + if matches.is_present("no-convert-floats") { + builder = builder.no_convert_floats(); + } + + if let Some(opaque_types) = matches.values_of("opaque-type") { + for ty in opaque_types { + builder = builder.opaque_type(ty); + } + } + + if let Some(lines) = matches.values_of("raw-line") { + for line in lines { + builder = builder.raw_line(line); + } + } + + if let Some(links) = matches.values_of("static") { + for library in links { + builder = builder.link_static(library); + } + } + + if matches.is_present("use-core") { + builder = builder.use_core(); + } + + if let Some(whitelist) = matches.values_of("whitelist-function") { + for regex in whitelist { + builder = builder.whitelisted_function(regex); + } + } + + if let Some(whitelist) = matches.values_of("whitelist-type") { + for regex in whitelist { + builder = builder.whitelisted_type(regex); + } + } + + if let Some(whitelist) = matches.values_of("whitelist-var") { + for regex in whitelist { + builder = builder.whitelisted_var(regex); + } + } + + if let Some(args) = matches.values_of("clang-args") { + for arg in args { + builder = builder.clang_arg(arg); + } + } + + let output = if let Some(path) = matches.value_of("output") { + let file = try!(File::create(path)); + Box::new(io::BufWriter::new(file)) as Box + } else { + Box::new(io::BufWriter::new(io::stdout())) as Box + }; + + Ok((builder, output)) +} diff --git a/src/parse.rs b/src/parse.rs deleted file mode 100644 index 28e65759..00000000 --- a/src/parse.rs +++ /dev/null @@ -1,106 +0,0 @@ -//! Common traits and types related to parsing our IR from Clang cursors. - -use clang; -use ir::context::{BindgenContext, ItemId}; -use ir::ty::TypeKind; - -/// Not so much an error in the traditional sense, but a control flow message -/// when walking over Clang's AST with a cursor. -#[derive(Debug)] -pub enum ParseError { - /// Recurse down the current AST node's children. - Recurse, - /// Continue on to the next sibling AST node, or back up to the parent's - /// siblings if we've exhausted all of this node's siblings (and so on). - Continue, -} - -/// The result of parsing a Clang AST node. -#[derive(Debug)] -pub enum ParseResult { - /// We've already resolved this item before, here is the extant `ItemId` for - /// it. - AlreadyResolved(ItemId), - - /// This is a newly parsed item. If the cursor is `Some`, it points to the - /// AST node where the new `T` was declared. - New(T, Option), -} - -/// An intermediate representation "sub-item" (i.e. one of the types contained -/// inside an `ItemKind` variant) that can be parsed from a Clang cursor. -pub trait ClangSubItemParser: Sized { - /// Attempt to parse this type from the given cursor. - /// - /// The fact that is a reference guarantees it's held by the context, and - /// allow returning already existing types. - fn parse(cursor: clang::Cursor, - context: &mut BindgenContext) - -> Result, ParseError>; -} - -/// An intermediate representation item that can be parsed from a Clang cursor. -pub trait ClangItemParser: Sized { - /// Parse this item from the given Clang cursor. - fn parse(cursor: clang::Cursor, - parent: Option, - context: &mut BindgenContext) - -> Result; - - /// Parse this item from the given Clang type. - fn from_ty(ty: &clang::Type, - location: Option, - parent: Option, - ctx: &mut BindgenContext) - -> Result; - - /// Identical to `from_ty`, but use the given `id` as the `ItemId` for the - /// newly parsed item. - fn from_ty_with_id(id: ItemId, - ty: &clang::Type, - location: Option, - parent: Option, - ctx: &mut BindgenContext) - -> Result; - - /// Parse this item from the given Clang type, or if we haven't resolved all - /// the other items this one depends on, an unresolved reference. - fn from_ty_or_ref(ty: clang::Type, - location: Option, - parent_id: Option, - context: &mut BindgenContext) - -> ItemId; - - /// Identical to `from_ty_or_ref`, but use the given `potential_id` as the - /// `ItemId` for the newly parsed item. - fn from_ty_or_ref_with_id(potential_id: ItemId, - ty: clang::Type, - location: Option, - parent_id: Option, - context: &mut BindgenContext) - -> ItemId; - - /// Create a named template type. - fn named_type(name: S, - default: Option, - parent: ItemId, - context: &mut BindgenContext) - -> ItemId - where S: Into; - - /// Identical to `named_type`, but use `id` as the resulting item's - /// `ItemId`. - fn named_type_with_id(id: ItemId, - name: S, - default: Option, - parent: ItemId, - context: &mut BindgenContext) - -> ItemId - where S: Into; - - /// Create a builtin type. - fn builtin_type(kind: TypeKind, - is_const: bool, - context: &mut BindgenContext) - -> ItemId; -} diff --git a/src/regex_set.rs b/src/regex_set.rs deleted file mode 100644 index 93130590..00000000 --- a/src/regex_set.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! A type that represents the union of a set of regular expressions. - -use regex::Regex; -use std::borrow::Borrow; - -// Yeah, I'm aware this is sorta crappy, should be cheaper to compile a regex -// ORing all the patterns, I guess... - -/// A dynamic set of regular expressions. -#[derive(Debug)] -pub struct RegexSet { - items: Vec, -} - -impl RegexSet { - /// Is this set empty? - pub fn is_empty(&self) -> bool { - self.items.is_empty() - } - - /// Extend this set with every regex in the iterator. - pub fn extend(&mut self, iter: I) - where I: IntoIterator, - { - for s in iter.into_iter() { - self.insert(&s) - } - } - - /// Insert a new regex into this set. - pub fn insert(&mut self, string: &S) - where S: Borrow, - { - let s = string.borrow(); - match Regex::new(&format!("^{}$", s)) { - Ok(r) => { - self.items.push(r); - } - Err(err) => { - error!("Invalid pattern provided: {}, {:?}", s, err); - } - } - } - - /// Does the given `string` match any of the regexes in this set? - pub fn matches(&self, string: &S) -> bool - where S: Borrow, - { - 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/uses.rs b/src/uses.rs deleted file mode 100644 index 47f72da6..00000000 --- a/src/uses.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! Take in our IR and output a C/C++ file with dummy uses of each IR type. -//! -//! Say that we had this C++ header, `header.hpp`: -//! -//! ```c++ -//! class Point { -//! int x; -//! int y; -//! } -//! -//! enum Bar { -//! THIS, -//! THAT, -//! OTHER -//! } -//! ``` -//! -//! If we generated dummy uses for this header, we would get a `.cpp` file like -//! this: -//! -//! ```c++ -//! #include "header.hpp" -//! -//! void dummy(Point*) {} -//! void dummy(Bar*) {} -//! ``` -//! -//! This is useful because we can compile this `.cpp` file into an object file, -//! and then compare its debugging information to the debugging information -//! generated for our Rust bindings. These two sets of debugging information had -//! better agree on the C/C++ types' physical layout, or else our bindings are -//! incorrect! -//! -//! "But you still haven't explained why we have to generate the dummy uses" you -//! complain. Well if the types are never used, then they are elided when the -//! C/C++ compiler generates debugging information. - -use ir::context::BindgenContext; -use ir::item::{Item, ItemAncestors, ItemCanonicalName}; -use std::io; - -// Like `canonical_path`, except we always take namespaces into account, ignore -// the generated names of anonymous items, and return a `String`. -// -// TODO: Would it be easier to try and demangle the USR? -fn namespaced_name(ctx: &BindgenContext, item: &Item) -> String { - let mut names: Vec<_> = item.ancestors(ctx) - .map(|id| ctx.resolve_item(id).canonical_name(ctx)) - .filter(|name| !name.starts_with("_bindgen_")) - .collect(); - names.reverse(); - names.join("::") -} - -/// Generate the dummy uses for all the items in the given context, and write -/// the dummy uses to `dest`. -pub fn generate_dummy_uses(ctx: &mut BindgenContext, - mut dest: W) - -> io::Result<()> - where W: io::Write, -{ - ctx.gen(|ctx| { - let input_header = ctx.options() - .input_header - .as_ref() - .expect("Should not generate dummy uses without an input header"); - - try!(writeln!(dest, "/* automatically generated by rust-bindgen */")); - try!(writeln!(dest, "")); - try!(writeln!(dest, "#include \"{}\"", input_header)); - try!(writeln!(dest, "")); - - let type_items = ctx.whitelisted_items() - .map(|id| ctx.resolve_item(id)) - .filter(|item| { - // We only want type items. - if let Some(ty) = item.kind().as_type() { - // However, we don't want anonymous types, as we can't - // generate dummy uses for them. - ty.name().is_some() && - // Nor do we want builtin types or named template type - // arguments. Again, we can't generate dummy uses for - // these. - !ty.is_builtin_or_named() && - // And finally, we won't be creating any dummy - // specializations, so ignore template declarations and - // partial specializations. - item.applicable_template_args(ctx).is_empty() - } else { - false - } - }) - .map(|item| namespaced_name(ctx, item)) - .enumerate(); - - for (idx, name) in type_items { - try!(writeln!(dest, "void dummy{}({}*) {{ }}", idx, name)); - } - - Ok(()) - }) -} diff --git a/tests/expectations/Cargo.toml b/tests/expectations/Cargo.toml deleted file mode 100644 index 53f1b14f..00000000 --- a/tests/expectations/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "tests_expectations" -description = "bindgen results when ran on ../headers/*" -version = "0.1.0" -authors = [ - "Jyun-Yan You ", - "Emilio Cobos Álvarez ", - "The Servo project developers", -] - -[dependencies] diff --git a/tests/expectations/src/lib.rs b/tests/expectations/src/lib.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/expectations/tests/accessors.rs b/tests/expectations/tests/accessors.rs deleted file mode 100644 index b721980c..00000000 --- a/tests/expectations/tests/accessors.rs +++ /dev/null @@ -1,204 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct SomeAccessors { - pub mNoAccessor: ::std::os::raw::c_int, - /**
*/ - pub mBothAccessors: ::std::os::raw::c_int, - /**
*/ - pub mUnsafeAccessors: ::std::os::raw::c_int, - /**
*/ - pub mImmutableAccessor: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_SomeAccessors() { - assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() , 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 - } - #[inline] - 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 - } - #[inline] - pub fn get_mImmutableAccessor(&self) -> &::std::os::raw::c_int { - &self.mImmutableAccessor - } -} -/**
*/ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct AllAccessors { - pub mBothAccessors: ::std::os::raw::c_int, - pub mAlsoBothAccessors: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_AllAccessors() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 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 - } - #[inline] - 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 - } -} -/**
*/ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct AllUnsafeAccessors { - pub mBothAccessors: ::std::os::raw::c_int, - pub mAlsoBothAccessors: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_AllUnsafeAccessors() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 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 - } - #[inline] - 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 - } -} -/**
*/ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct ContradictAccessors { - pub mBothAccessors: ::std::os::raw::c_int, - /**
*/ - pub mNoAccessors: ::std::os::raw::c_int, - /**
*/ - pub mUnsafeAccessors: ::std::os::raw::c_int, - /**
*/ - pub mImmutableAccessor: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_ContradictAccessors() { - assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() , 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 - } - #[inline] - 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 - } - #[inline] - pub fn get_mImmutableAccessor(&self) -> &::std::os::raw::c_int { - &self.mImmutableAccessor - } -} -/**
*/ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Replaced { - pub mAccessor: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Replaced() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 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 - } -} -/**
*/ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Wrapper { - pub mReplaced: Replaced, -} -#[test] -fn bindgen_test_layout_Wrapper() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for Wrapper { - fn clone(&self) -> Self { *self } -} -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/tests/annotation_hide.rs b/tests/expectations/tests/annotation_hide.rs deleted file mode 100644 index dcaf7997..00000000 --- a/tests/expectations/tests/annotation_hide.rs +++ /dev/null @@ -1,35 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -/** - *
- */ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct D { - pub _bindgen_opaque_blob: u32, -} -#[test] -fn bindgen_test_layout_D() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for D { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct NotAnnotated { - pub f: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_NotAnnotated() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for NotAnnotated { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/anon_enum.rs b/tests/expectations/tests/anon_enum.rs deleted file mode 100644 index 075830e6..00000000 --- a/tests/expectations/tests/anon_enum.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* 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, -} -pub const Test_T_NONE: Test__bindgen_ty_1 = Test__bindgen_ty_1::T_NONE; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Test__bindgen_ty_1 { T_NONE = 0, } -#[test] -fn bindgen_test_layout_Test() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for Test { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/anon_enum_whitelist.rs b/tests/expectations/tests/anon_enum_whitelist.rs deleted file mode 100644 index b32396a0..00000000 --- a/tests/expectations/tests/anon_enum_whitelist.rs +++ /dev/null @@ -1,11 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub const NODE_FLAG_FOO: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_FOO; -pub const NODE_FLAG_BAR: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_BAR; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { NODE_FLAG_FOO = 0, NODE_FLAG_BAR = 1, } diff --git a/tests/expectations/tests/anon_union.rs b/tests/expectations/tests/anon_union.rs deleted file mode 100644 index 8af416c3..00000000 --- a/tests/expectations/tests/anon_union.rs +++ /dev/null @@ -1,77 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct TErrorResult { - pub mResult: ::std::os::raw::c_int, - pub __bindgen_anon_1: TErrorResult__bindgen_ty_1, - pub mMightHaveUnreported: bool, - pub mUnionState: TErrorResult_UnionState, - pub _phantom_0: ::std::marker::PhantomData, -} -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 { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct TErrorResult_DOMExceptionInfo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct TErrorResult__bindgen_ty_1 { - pub mMessage: __BindgenUnionField<*mut TErrorResult_Message>, - pub mDOMExceptionInfo: __BindgenUnionField<*mut TErrorResult_DOMExceptionInfo>, - pub bindgen_union_field: u64, - pub _phantom_0: ::std::marker::PhantomData, -} -#[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::() , 24usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for ErrorResult { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/arg_keyword.rs b/tests/expectations/tests/arg_keyword.rs deleted file mode 100644 index cb1cc432..00000000 --- a/tests/expectations/tests/arg_keyword.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* 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/tests/base-to-derived.rs b/tests/expectations/tests/base-to-derived.rs deleted file mode 100644 index c2af2c43..00000000 --- a/tests/expectations/tests/base-to-derived.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct false_type { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_false_type() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for false_type { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/bitfield-enum-basic.rs b/tests/expectations/tests/bitfield-enum-basic.rs deleted file mode 100644 index 03e07de6..00000000 --- a/tests/expectations/tests/bitfield-enum-basic.rs +++ /dev/null @@ -1,77 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub const Foo_Bar: Foo = Foo(2); -pub const Foo_Baz: Foo = Foo(4); -pub const Foo_Duplicated: Foo = Foo(4); -pub const Foo_Negative: Foo = Foo(-3); -impl ::std::ops::BitOr for Foo { - type - Output - = - Self; - #[inline] - fn bitor(self, other: Self) -> Self { Foo(self.0 | other.0) } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Foo(pub i32); -pub const Buz_Bar: Buz = Buz(2); -pub const Buz_Baz: Buz = Buz(4); -pub const Buz_Duplicated: Buz = Buz(4); -pub const Buz_Negative: Buz = Buz(-3); -impl ::std::ops::BitOr for Buz { - type - Output - = - Self; - #[inline] - fn bitor(self, other: Self) -> Self { Buz(self.0 | other.0) } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Buz(pub i8); -pub const NS_FOO: _bindgen_ty_1 = _bindgen_ty_1(1); -pub const NS_BAR: _bindgen_ty_1 = _bindgen_ty_1(2); -impl ::std::ops::BitOr<_bindgen_ty_1> for _bindgen_ty_1 { - type - Output - = - Self; - #[inline] - fn bitor(self, other: Self) -> Self { _bindgen_ty_1(self.0 | other.0) } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct _bindgen_ty_1(pub u32); -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Dummy { - pub _address: u8, -} -pub const Dummy_DUMMY_FOO: Dummy__bindgen_ty_1 = Dummy__bindgen_ty_1(1); -pub const Dummy_DUMMY_BAR: Dummy__bindgen_ty_1 = Dummy__bindgen_ty_1(2); -impl ::std::ops::BitOr for Dummy__bindgen_ty_1 { - type - Output - = - Self; - #[inline] - fn bitor(self, other: Self) -> Self { - Dummy__bindgen_ty_1(self.0 | other.0) - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Dummy__bindgen_ty_1(pub u32); -#[test] -fn bindgen_test_layout_Dummy() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for Dummy { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/blocks.rs b/tests/expectations/tests/blocks.rs deleted file mode 100644 index 528ea518..00000000 --- a/tests/expectations/tests/blocks.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -extern "C" { - pub fn atexit_b(arg1: *mut ::std::os::raw::c_void); -} diff --git a/tests/expectations/tests/class.rs b/tests/expectations/tests/class.rs deleted file mode 100644 index 579c24a4..00000000 --- a/tests/expectations/tests/class.rs +++ /dev/null @@ -1,127 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -pub struct C { - pub a: ::std::os::raw::c_int, - pub big_array: [::std::os::raw::c_char; 33usize], -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!(::std::mem::size_of::() , 40usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -#[repr(C)] -#[derive(Debug)] -pub struct WithDtor { - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_WithDtor() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Union { - pub d: __BindgenUnionField, - pub i: __BindgenUnionField<::std::os::raw::c_int>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_Union() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for Union { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct WithUnion { - pub data: Union, -} -#[test] -fn bindgen_test_layout_WithUnion() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for WithUnion { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct RealAbstractionWithTonsOfMethods { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_RealAbstractionWithTonsOfMethods() { - assert_eq!(::std::mem::size_of::() , - 1usize); - assert_eq!(::std::mem::align_of::() , - 1usize); -} -extern "C" { - #[link_name = "_ZNK32RealAbstractionWithTonsOfMethods3barEv"] - pub fn RealAbstractionWithTonsOfMethods_bar(this: - *const RealAbstractionWithTonsOfMethods); -} -extern "C" { - #[link_name = "_ZN32RealAbstractionWithTonsOfMethods3barEv"] - pub fn RealAbstractionWithTonsOfMethods_bar1(this: - *mut RealAbstractionWithTonsOfMethods); -} -extern "C" { - #[link_name = "_ZN32RealAbstractionWithTonsOfMethods3barEi"] - pub fn RealAbstractionWithTonsOfMethods_bar2(this: - *mut RealAbstractionWithTonsOfMethods, - foo: ::std::os::raw::c_int); -} -extern "C" { - #[link_name = "_ZN32RealAbstractionWithTonsOfMethods3staEv"] - pub fn RealAbstractionWithTonsOfMethods_sta(); -} -impl Clone for RealAbstractionWithTonsOfMethods { - fn clone(&self) -> Self { *self } -} -impl RealAbstractionWithTonsOfMethods { - #[inline] - pub unsafe fn bar(&self) { RealAbstractionWithTonsOfMethods_bar(&*self) } - #[inline] - pub unsafe fn bar1(&mut self) { - RealAbstractionWithTonsOfMethods_bar1(&mut *self) - } - #[inline] - pub unsafe fn bar2(&mut self, foo: ::std::os::raw::c_int) { - RealAbstractionWithTonsOfMethods_bar2(&mut *self, foo) - } - #[inline] - pub unsafe fn sta() { RealAbstractionWithTonsOfMethods_sta() } -} diff --git a/tests/expectations/tests/class_nested.rs b/tests/expectations/tests/class_nested.rs deleted file mode 100644 index 593e156d..00000000 --- a/tests/expectations/tests/class_nested.rs +++ /dev/null @@ -1,59 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct A { - pub member_a: ::std::os::raw::c_int, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct A_B { - pub member_b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_A_B() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for A_B { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_A() { - assert_eq!(::std::mem::size_of::
() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for A { - fn clone(&self) -> Self { *self } -} -extern "C" { - #[link_name = "var"] - pub static mut var: A_B; -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct D { - pub member: A_B, -} -#[test] -fn bindgen_test_layout_D() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for D { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Templated { - pub member: T, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Templated_Templated_inner { - pub member_ptr: *mut T, -} diff --git a/tests/expectations/tests/class_no_members.rs b/tests/expectations/tests/class_no_members.rs deleted file mode 100644 index 017f7c22..00000000 --- a/tests/expectations/tests/class_no_members.rs +++ /dev/null @@ -1,45 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct whatever { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_whatever() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for whatever { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct whatever_child { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_whatever_child() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for whatever_child { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct whatever_child_with_member { - pub m_member: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_whatever_child_with_member() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for whatever_child_with_member { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/class_static.rs b/tests/expectations/tests/class_static.rs deleted file mode 100644 index 8108be2d..00000000 --- a/tests/expectations/tests/class_static.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct MyClass { - pub _address: u8, -} -extern "C" { - #[link_name = "_ZN7MyClass7exampleE"] - pub static mut MyClass_example: *const ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "_ZN7MyClass26example_check_no_collisionE"] - 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::() , 1usize); - assert_eq!(::std::mem::align_of::() , 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/tests/class_static_const.rs b/tests/expectations/tests/class_static_const.rs deleted file mode 100644 index eed6590c..00000000 --- a/tests/expectations/tests/class_static_const.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct A { - pub _address: u8, -} -pub const A_a: ::std::os::raw::c_int = 0; -pub const A_b: i32 = 63; -pub const A_c: u32 = 255; -#[test] -fn bindgen_test_layout_A() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for A { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/class_use_as.rs b/tests/expectations/tests/class_use_as.rs deleted file mode 100644 index c3843b31..00000000 --- a/tests/expectations/tests/class_use_as.rs +++ /dev/null @@ -1,35 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -/** - *
- */ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct whatever { - pub replacement: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_whatever() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for whatever { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct container { - pub c: whatever, -} -#[test] -fn bindgen_test_layout_container() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for container { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/class_with_dtor.rs b/tests/expectations/tests/class_with_dtor.rs deleted file mode 100644 index 8ed1ddf9..00000000 --- a/tests/expectations/tests/class_with_dtor.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug)] -pub struct HandleWithDtor { - pub ptr: *mut T, -} -pub type HandleValue = HandleWithDtor<::std::os::raw::c_int>; -#[repr(C)] -#[derive(Debug)] -pub struct WithoutDtor { - pub shouldBeWithDtor: HandleValue, -} -#[test] -fn bindgen_test_layout_WithoutDtor() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} diff --git a/tests/expectations/tests/class_with_inner_struct.rs b/tests/expectations/tests/class_with_inner_struct.rs deleted file mode 100644 index ab51396d..00000000 --- a/tests/expectations/tests/class_with_inner_struct.rs +++ /dev/null @@ -1,195 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct A { - pub c: ::std::os::raw::c_uint, - pub named_union: A__bindgen_ty_1, - pub __bindgen_anon_1: A__bindgen_ty_2, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct A_Segment { - pub begin: ::std::os::raw::c_int, - pub end: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_A_Segment() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for A_Segment { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct A__bindgen_ty_1 { - pub f: __BindgenUnionField<::std::os::raw::c_int>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_A__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for A__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct A__bindgen_ty_2 { - pub d: __BindgenUnionField<::std::os::raw::c_int>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_A__bindgen_ty_2() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for A__bindgen_ty_2 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_A() { - assert_eq!(::std::mem::size_of::
() , 12usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for A { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct B { - pub d: ::std::os::raw::c_uint, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct B_Segment { - pub begin: ::std::os::raw::c_int, - pub end: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_B_Segment() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for B_Segment { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_B() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for B { - fn clone(&self) -> Self { *self } -} -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum StepSyntax { - Keyword = 0, - FunctionalWithoutKeyword = 1, - FunctionalWithStartKeyword = 2, - FunctionalWithEndKeyword = 3, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C { - pub d: ::std::os::raw::c_uint, - pub __bindgen_anon_1: C__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C__bindgen_ty_1 { - pub mFunc: __BindgenUnionField, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: [u32; 4usize], -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C__bindgen_ty_1_1 { - pub mX1: f32, - pub mY1: f32, - pub mX2: f32, - pub mY2: f32, -} -#[test] -fn bindgen_test_layout_C__bindgen_ty_1_1() { - assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for C__bindgen_ty_1_1 { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C__bindgen_ty_1_2 { - pub mStepSyntax: StepSyntax, - pub mSteps: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_C__bindgen_ty_1_2() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for C__bindgen_ty_1_2 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_C__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for C__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C_Segment { - pub begin: ::std::os::raw::c_int, - pub end: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_C_Segment() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for C_Segment { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!(::std::mem::size_of::() , 20usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for C { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/class_with_typedef.rs b/tests/expectations/tests/class_with_typedef.rs deleted file mode 100644 index bc19f2bd..00000000 --- a/tests/expectations/tests/class_with_typedef.rs +++ /dev/null @@ -1,72 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub type AnotherInt = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C { - pub c: C_MyInt, - pub ptr: *mut C_MyInt, - pub arr: [C_MyInt; 10usize], - pub d: AnotherInt, - pub other_ptr: *mut AnotherInt, -} -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::() , 72usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -extern "C" { - #[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: C_MyInt) { C_method(&mut *self, c) } - #[inline] - pub unsafe fn methodRef(&mut self, c: *mut C_MyInt) { - C_methodRef(&mut *self, c) - } - #[inline] - pub unsafe fn complexMethodRef(&mut self, c: *mut C_Lookup) { - C_complexMethodRef(&mut *self, c) - } - #[inline] - pub unsafe fn anotherMethod(&mut self, c: AnotherInt) { - C_anotherMethod(&mut *self, c) - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct D { - pub _base: C, - pub ptr: *mut C_MyInt, -} -#[test] -fn bindgen_test_layout_D() { - assert_eq!(::std::mem::size_of::() , 80usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for D { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/complex.rs b/tests/expectations/tests/complex.rs deleted file mode 100644 index f2a97952..00000000 --- a/tests/expectations/tests/complex.rs +++ /dev/null @@ -1,64 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] -#[repr(C)] -pub struct __BindgenComplex { - pub re: T, - pub im: T, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct TestDouble { - pub mMember: __BindgenComplex, -} -#[test] -fn bindgen_test_layout_TestDouble() { - assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for TestDouble { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct TestDoublePtr { - pub mMember: *mut __BindgenComplex, -} -#[test] -fn bindgen_test_layout_TestDoublePtr() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for TestDoublePtr { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct TestFloat { - pub mMember: __BindgenComplex, -} -#[test] -fn bindgen_test_layout_TestFloat() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for TestFloat { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct TestFloatPtr { - pub mMember: *mut __BindgenComplex, -} -#[test] -fn bindgen_test_layout_TestFloatPtr() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for TestFloatPtr { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/complex_global.rs b/tests/expectations/tests/complex_global.rs deleted file mode 100644 index badc4d1f..00000000 --- a/tests/expectations/tests/complex_global.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] -#[repr(C)] -pub struct __BindgenComplex { - pub re: T, - pub im: T, -} -extern "C" { - #[link_name = "globalValueFloat"] - pub static mut globalValueFloat: __BindgenComplex; -} -extern "C" { - #[link_name = "globalValueDouble"] - pub static mut globalValueDouble: __BindgenComplex; -} -extern "C" { - #[link_name = "globalValueLongDouble"] - pub static mut globalValueLongDouble: __BindgenComplex; -} diff --git a/tests/expectations/tests/const_enum_unnamed.rs b/tests/expectations/tests/const_enum_unnamed.rs deleted file mode 100644 index 0bd3987a..00000000 --- a/tests/expectations/tests/const_enum_unnamed.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub const FOO_BAR: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAR; -pub const FOO_BAZ: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAZ; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { FOO_BAR = 0, FOO_BAZ = 1, } -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Foo { - pub _address: u8, -} -pub const Foo_FOO_BAR: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::FOO_BAR; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo__bindgen_ty_1 { FOO_BAR = 10, } -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for Foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/const_ptr.rs b/tests/expectations/tests/const_ptr.rs deleted file mode 100644 index 89400df1..00000000 --- a/tests/expectations/tests/const_ptr.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* 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/tests/const_resolved_ty.rs b/tests/expectations/tests/const_resolved_ty.rs deleted file mode 100644 index 77d8f438..00000000 --- a/tests/expectations/tests/const_resolved_ty.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -extern "C" { - pub fn foo(foo: *const u8); -} diff --git a/tests/expectations/tests/const_tparam.rs b/tests/expectations/tests/const_tparam.rs deleted file mode 100644 index 3ed10d28..00000000 --- a/tests/expectations/tests/const_tparam.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct C { - pub foo: *const T, - pub bar: *mut T, -} diff --git a/tests/expectations/tests/convert-floats.rs b/tests/expectations/tests/convert-floats.rs deleted file mode 100644 index 5cd38c13..00000000 --- a/tests/expectations/tests/convert-floats.rs +++ /dev/null @@ -1,30 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] -#[repr(C)] -pub struct __BindgenComplex { - pub re: T, - pub im: T, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub bar: ::std::os::raw::c_float, - pub baz: ::std::os::raw::c_float, - pub bazz: ::std::os::raw::c_double, - pub bazzz: *mut ::std::os::raw::c_double, - pub complexFloat: __BindgenComplex<::std::os::raw::c_float>, - pub complexDouble: __BindgenComplex<::std::os::raw::c_double>, -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 48usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/crtp.rs b/tests/expectations/tests/crtp.rs deleted file mode 100644 index e4a86b24..00000000 --- a/tests/expectations/tests/crtp.rs +++ /dev/null @@ -1,43 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Base { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Derived { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Derived() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for Derived { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug)] -pub struct BaseWithDestructor { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug)] -pub struct DerivedFromBaseWithDestructor { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_DerivedFromBaseWithDestructor() { - assert_eq!(::std::mem::size_of::() , - 1usize); - assert_eq!(::std::mem::align_of::() , - 1usize); -} diff --git a/tests/expectations/tests/decl_extern_int_twice.rs b/tests/expectations/tests/decl_extern_int_twice.rs deleted file mode 100644 index 603a51b1..00000000 --- a/tests/expectations/tests/decl_extern_int_twice.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -extern "C" { - #[link_name = "foo"] - pub static mut foo: ::std::os::raw::c_int; -} diff --git a/tests/expectations/tests/decl_ptr_to_array.rs b/tests/expectations/tests/decl_ptr_to_array.rs deleted file mode 100644 index b8abedb5..00000000 --- a/tests/expectations/tests/decl_ptr_to_array.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -extern "C" { - #[link_name = "foo"] - pub static mut foo: *mut [::std::os::raw::c_int; 1usize]; -} diff --git a/tests/expectations/tests/duplicated_constants_in_ns.rs b/tests/expectations/tests/duplicated_constants_in_ns.rs deleted file mode 100644 index cb69890c..00000000 --- a/tests/expectations/tests/duplicated_constants_in_ns.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![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/tests/elaborated.rs b/tests/expectations/tests/elaborated.rs deleted file mode 100644 index db373d41..00000000 --- a/tests/expectations/tests/elaborated.rs +++ /dev/null @@ -1,11 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub type whatever_t = ::std::os::raw::c_int; -extern "C" { - #[link_name = "_Z9somethingPKi"] - pub fn something(wat: *const whatever_t); -} diff --git a/tests/expectations/tests/empty_template_param_name.rs b/tests/expectations/tests/empty_template_param_name.rs deleted file mode 100644 index e10b56db..00000000 --- a/tests/expectations/tests/empty_template_param_name.rs +++ /dev/null @@ -1,13 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub type __void_t = ::std::os::raw::c_void; -#[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/tests/enum.rs b/tests/expectations/tests/enum.rs deleted file mode 100644 index 8138d697..00000000 --- a/tests/expectations/tests/enum.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { Bar = 0, Qux = 1, } -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Neg { MinusOne = -1, One = 1, } diff --git a/tests/expectations/tests/enum_alias.rs b/tests/expectations/tests/enum_alias.rs deleted file mode 100644 index 7ea85598..00000000 --- a/tests/expectations/tests/enum_alias.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* 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/tests/enum_and_vtable_mangling.rs b/tests/expectations/tests/enum_and_vtable_mangling.rs deleted file mode 100644 index a55c344e..00000000 --- a/tests/expectations/tests/enum_and_vtable_mangling.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub const match_: _bindgen_ty_1 = _bindgen_ty_1::match_; -pub const whatever_else: _bindgen_ty_1 = _bindgen_ty_1::whatever_else; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum _bindgen_ty_1 { match_ = 0, whatever_else = 1, } -#[repr(C)] -pub struct C__bindgen_vtable { -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C { - pub vtable_: *const C__bindgen_vtable, - pub i: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for C { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/enum_dupe.rs b/tests/expectations/tests/enum_dupe.rs deleted file mode 100644 index 322b89fc..00000000 --- a/tests/expectations/tests/enum_dupe.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub const Foo_Dupe: Foo = Foo::Bar; -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { Bar = 1, } diff --git a/tests/expectations/tests/enum_explicit_type.rs b/tests/expectations/tests/enum_explicit_type.rs deleted file mode 100644 index 4e555d3a..00000000 --- a/tests/expectations/tests/enum_explicit_type.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { Bar = 0, Qux = 1, } -#[repr(i8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Neg { MinusOne = -1, One = 1, } -#[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Bigger { Much = 255, Larger = 256, } -#[repr(i64)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum MuchLong { MuchLow = -4294967296, } -#[repr(i64)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum MuchLongLong { I64_MIN = -9223372036854775808, } -#[repr(u64)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum MuchULongLong { MuchHigh = 4294967296, } diff --git a/tests/expectations/tests/enum_negative.rs b/tests/expectations/tests/enum_negative.rs deleted file mode 100644 index 74cf4f16..00000000 --- a/tests/expectations/tests/enum_negative.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { Bar = -2, Qux = 1, } diff --git a/tests/expectations/tests/enum_packed.rs b/tests/expectations/tests/enum_packed.rs deleted file mode 100644 index 963763e1..00000000 --- a/tests/expectations/tests/enum_packed.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Foo { Bar = 0, Qux = 1, } -#[repr(i8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Neg { MinusOne = -1, One = 1, } -#[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Bigger { Much = 255, Larger = 256, } diff --git a/tests/expectations/tests/extern.rs b/tests/expectations/tests/extern.rs deleted file mode 100644 index e7ac7504..00000000 --- a/tests/expectations/tests/extern.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub type foo = - ::std::option::Option ::std::os::raw::c_int>; diff --git a/tests/expectations/tests/float128.rs b/tests/expectations/tests/float128.rs deleted file mode 100644 index b4b7b2bc..00000000 --- a/tests/expectations/tests/float128.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - - diff --git a/tests/expectations/tests/forward-inherit-struct-with-fields.rs b/tests/expectations/tests/forward-inherit-struct-with-fields.rs deleted file mode 100644 index 84104971..00000000 --- a/tests/expectations/tests/forward-inherit-struct-with-fields.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub _base: RootedBase, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct RootedBase { - pub foo: *mut T, - pub next: *mut Rooted, -} diff --git a/tests/expectations/tests/forward-inherit-struct.rs b/tests/expectations/tests/forward-inherit-struct.rs deleted file mode 100644 index e053adcd..00000000 --- a/tests/expectations/tests/forward-inherit-struct.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct RootedBase { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} diff --git a/tests/expectations/tests/forward_declared_struct.rs b/tests/expectations/tests/forward_declared_struct.rs deleted file mode 100644 index 5c2764e1..00000000 --- a/tests/expectations/tests/forward_declared_struct.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct a { - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_a() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for a { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct c { - pub d: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_c() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for c { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/func_proto.rs b/tests/expectations/tests/func_proto.rs deleted file mode 100644 index e7ac7504..00000000 --- a/tests/expectations/tests/func_proto.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub type foo = - ::std::option::Option ::std::os::raw::c_int>; diff --git a/tests/expectations/tests/func_ptr.rs b/tests/expectations/tests/func_ptr.rs deleted file mode 100644 index 87ec3e3d..00000000 --- a/tests/expectations/tests/func_ptr.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -extern "C" { - #[link_name = "foo"] - pub static mut foo: - ::std::option::Option ::std::os::raw::c_int>; -} diff --git a/tests/expectations/tests/func_ptr_in_struct.rs b/tests/expectations/tests/func_ptr_in_struct.rs deleted file mode 100644 index dcae771b..00000000 --- a/tests/expectations/tests/func_ptr_in_struct.rs +++ /dev/null @@ -1,25 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum baz { } -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Foo { - pub bar: ::std::option::Option baz>, -} -#[test] -fn bindgen_test_layout_Foo() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for Foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/func_with_array_arg.rs b/tests/expectations/tests/func_with_array_arg.rs deleted file mode 100644 index 1528e0ba..00000000 --- a/tests/expectations/tests/func_with_array_arg.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -extern "C" { - pub fn f(x: *mut ::std::os::raw::c_int); -} diff --git a/tests/expectations/tests/func_with_func_ptr_arg.rs b/tests/expectations/tests/func_with_func_ptr_arg.rs deleted file mode 100644 index 4ac25286..00000000 --- a/tests/expectations/tests/func_with_func_ptr_arg.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -extern "C" { - pub fn foo(bar: ::std::option::Option); -} diff --git a/tests/expectations/tests/in_class_typedef.rs b/tests/expectations/tests/in_class_typedef.rs deleted file mode 100644 index 4e95ca8c..00000000 --- a/tests/expectations/tests/in_class_typedef.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Foo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} -pub type Foo_elem_type = T; -pub type Foo_ptr_type = *mut T; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Foo_Bar { - pub x: ::std::os::raw::c_int, - pub y: ::std::os::raw::c_int, - pub _phantom_0: ::std::marker::PhantomData, -} diff --git a/tests/expectations/tests/inherit-namespaced.rs b/tests/expectations/tests/inherit-namespaced.rs deleted file mode 100644 index a58058b0..00000000 --- a/tests/expectations/tests/inherit-namespaced.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct RootedBase { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} diff --git a/tests/expectations/tests/inherit_named.rs b/tests/expectations/tests/inherit_named.rs deleted file mode 100644 index 8081c649..00000000 --- a/tests/expectations/tests/inherit_named.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Wohoo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Weeee { - pub _base: T, -} diff --git a/tests/expectations/tests/inherit_typedef.rs b/tests/expectations/tests/inherit_typedef.rs deleted file mode 100644 index ca9041e2..00000000 --- a/tests/expectations/tests/inherit_typedef.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* 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::() , 1usize); - assert_eq!(::std::mem::align_of::() , 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::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for Bar { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/inner_const.rs b/tests/expectations/tests/inner_const.rs deleted file mode 100644 index 666b8ce2..00000000 --- a/tests/expectations/tests/inner_const.rs +++ /dev/null @@ -1,27 +0,0 @@ -/* 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::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for Foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/inner_template_self.rs b/tests/expectations/tests/inner_template_self.rs deleted file mode 100644 index b965b92d..00000000 --- a/tests/expectations/tests/inner_template_self.rs +++ /dev/null @@ -1,25 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct LinkedList { - pub next: *mut LinkedList, - pub prev: *mut LinkedList, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct InstantiateIt { - pub m_list: LinkedList<::std::os::raw::c_int>, -} -#[test] -fn bindgen_test_layout_InstantiateIt() { - assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for InstantiateIt { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/int128_t.rs b/tests/expectations/tests/int128_t.rs deleted file mode 100644 index b4b7b2bc..00000000 --- a/tests/expectations/tests/int128_t.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - - diff --git a/tests/expectations/tests/jsval_layout_opaque.rs b/tests/expectations/tests/jsval_layout_opaque.rs deleted file mode 100644 index 91f898af..00000000 --- a/tests/expectations/tests/jsval_layout_opaque.rs +++ /dev/null @@ -1,200 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -pub const JSVAL_TAG_SHIFT: ::std::os::raw::c_uint = 47; -pub const JSVAL_PAYLOAD_MASK: ::std::os::raw::c_ulonglong = 140737488355327; -pub const JSVAL_TAG_MASK: ::std::os::raw::c_longlong = -140737488355328; -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSValueType { - JSVAL_TYPE_DOUBLE = 0, - JSVAL_TYPE_INT32 = 1, - JSVAL_TYPE_UNDEFINED = 2, - JSVAL_TYPE_BOOLEAN = 3, - JSVAL_TYPE_MAGIC = 4, - JSVAL_TYPE_STRING = 5, - JSVAL_TYPE_SYMBOL = 6, - JSVAL_TYPE_NULL = 7, - JSVAL_TYPE_OBJECT = 8, - JSVAL_TYPE_UNKNOWN = 32, - JSVAL_TYPE_MISSING = 33, -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSValueTag { - JSVAL_TAG_MAX_DOUBLE = 131056, - JSVAL_TAG_INT32 = 131057, - JSVAL_TAG_UNDEFINED = 131058, - JSVAL_TAG_STRING = 131061, - JSVAL_TAG_SYMBOL = 131062, - JSVAL_TAG_BOOLEAN = 131059, - JSVAL_TAG_MAGIC = 131060, - JSVAL_TAG_NULL = 131063, - JSVAL_TAG_OBJECT = 131064, -} -#[repr(u64)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSValueShiftedTag { - JSVAL_SHIFTED_TAG_MAX_DOUBLE = 18444492278190833663, - JSVAL_SHIFTED_TAG_INT32 = 18444633011384221696, - JSVAL_SHIFTED_TAG_UNDEFINED = 18444773748872577024, - JSVAL_SHIFTED_TAG_STRING = 18445195961337643008, - JSVAL_SHIFTED_TAG_SYMBOL = 18445336698825998336, - JSVAL_SHIFTED_TAG_BOOLEAN = 18444914486360932352, - JSVAL_SHIFTED_TAG_MAGIC = 18445055223849287680, - JSVAL_SHIFTED_TAG_NULL = 18445477436314353664, - JSVAL_SHIFTED_TAG_OBJECT = 18445618173802708992, -} -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum JSWhyMagic { - JS_ELEMENTS_HOLE = 0, - JS_NO_ITER_VALUE = 1, - JS_GENERATOR_CLOSING = 2, - JS_NO_CONSTANT = 3, - JS_THIS_POISON = 4, - JS_ARG_POISON = 5, - JS_SERIALIZE_NO_NODE = 6, - JS_LAZY_ARGUMENTS = 7, - JS_OPTIMIZED_ARGUMENTS = 8, - JS_IS_CONSTRUCTING = 9, - JS_OVERWRITTEN_CALLEE = 10, - JS_BLOCK_NEEDS_CLONE = 11, - JS_HASH_KEY_EMPTY = 12, - JS_ION_ERROR = 13, - JS_ION_BAILOUT = 14, - JS_OPTIMIZED_OUT = 15, - JS_UNINITIALIZED_LEXICAL = 16, - JS_GENERIC_MAGIC = 17, - JS_WHY_MAGIC_COUNT = 18, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct jsval_layout { - pub asBits: __BindgenUnionField, - pub debugView: __BindgenUnionField, - pub s: __BindgenUnionField, - pub asDouble: __BindgenUnionField, - pub asPtr: __BindgenUnionField<*mut ::std::os::raw::c_void>, - pub asWord: __BindgenUnionField, - pub asUIntPtr: __BindgenUnionField, - pub bindgen_union_field: u64, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct jsval_layout__bindgen_ty_1 { - pub _bitfield_1: u64, -} -#[test] -fn bindgen_test_layout_jsval_layout__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for jsval_layout__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -impl jsval_layout__bindgen_ty_1 { - #[inline] - pub fn payload47(&self) -> u64 { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & - (140737488355327usize as u64)) >> - 0u32) as u64) - } - } - #[inline] - pub fn set_payload47(&mut self, val: u64) { - self._bitfield_1 &= !(140737488355327usize as u64); - self._bitfield_1 |= - ((val as u64 as u64) << 0u32) & (140737488355327usize as u64); - } - #[inline] - 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: JSValueTag) { - self._bitfield_1 &= !(18446603336221196288usize as u64); - self._bitfield_1 |= - ((val as u32 as u64) << 47u32) & - (18446603336221196288usize as u64); - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct jsval_layout__bindgen_ty_2 { - pub payload: jsval_layout__bindgen_ty_2_1, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct jsval_layout__bindgen_ty_2_1 { - pub i32: __BindgenUnionField, - pub u32: __BindgenUnionField, - pub why: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_jsval_layout__bindgen_ty_2_1() { - assert_eq!(::std::mem::size_of::() , - 4usize); - assert_eq!(::std::mem::align_of::() , - 4usize); -} -impl Clone for jsval_layout__bindgen_ty_2_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_jsval_layout__bindgen_ty_2() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for jsval_layout__bindgen_ty_2 { - 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, -} -#[test] -fn bindgen_test_layout_Value() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for Value { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/keywords.rs b/tests/expectations/tests/keywords.rs deleted file mode 100644 index 5b75389e..00000000 --- a/tests/expectations/tests/keywords.rs +++ /dev/null @@ -1,202 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -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/tests/macro-expr-basic.rs b/tests/expectations/tests/macro-expr-basic.rs deleted file mode 100644 index 355294e7..00000000 --- a/tests/expectations/tests/macro-expr-basic.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub const FOO: ::std::os::raw::c_uint = 1; -pub const BAR: ::std::os::raw::c_uint = 4; -pub const BAZ: ::std::os::raw::c_uint = 5; -pub const MIN: ::std::os::raw::c_longlong = -9223372036854775808; -pub const BARR: ::std::os::raw::c_uint = 1; -pub const BAZZ: ::std::os::raw::c_uint = 7; -pub const I_RAN_OUT_OF_DUMB_NAMES: ::std::os::raw::c_uint = 7; -pub const HAZ_A_COMMENT: ::std::os::raw::c_uint = 1; -pub const HAZ_A_COMMENT_INSIDE: ::std::os::raw::c_uint = 2; diff --git a/tests/expectations/tests/macro-redef.rs b/tests/expectations/tests/macro-redef.rs deleted file mode 100644 index 881a44ae..00000000 --- a/tests/expectations/tests/macro-redef.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub const FOO: ::std::os::raw::c_uint = 4; -pub const BAR: ::std::os::raw::c_uint = 5; -pub const BAZ: ::std::os::raw::c_uint = 6; diff --git a/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs b/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs deleted file mode 100644 index 5e9cf522..00000000 --- a/tests/expectations/tests/multiple-inherit-empty-correct-layout.rs +++ /dev/null @@ -1,45 +0,0 @@ -/* 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::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for Foo { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Bar { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Bar() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for Bar { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Baz { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Baz() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for Baz { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/mutable.rs b/tests/expectations/tests/mutable.rs deleted file mode 100644 index 0d0d6ea3..00000000 --- a/tests/expectations/tests/mutable.rs +++ /dev/null @@ -1,42 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C { - pub m_member: ::std::os::raw::c_int, - pub m_other: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for C { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug)] -pub struct NonCopiable { - pub m_member: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_NonCopiable() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -#[repr(C)] -#[derive(Debug)] -pub struct NonCopiableWithNonCopiableMutableMember { - pub m_member: NonCopiable, -} -#[test] -fn bindgen_test_layout_NonCopiableWithNonCopiableMutableMember() { - assert_eq!(::std::mem::size_of::() - , 4usize); - assert_eq!(::std::mem::align_of::() - , 4usize); -} diff --git a/tests/expectations/tests/namespace.rs b/tests/expectations/tests/namespace.rs deleted file mode 100644 index bc8bae68..00000000 --- a/tests/expectations/tests/namespace.rs +++ /dev/null @@ -1,85 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub mod root { - use root; - extern "C" { - #[link_name = "_Z9top_levelv"] - pub fn top_level(); - } - pub mod whatever { - use root; - pub type whatever_int_t = ::std::os::raw::c_int; - extern "C" { - #[link_name = "_ZN8whatever11in_whateverEv"] - pub fn in_whatever(); - } - } - pub mod _bindgen_mod_id_13 { - 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 A { - pub b: root::whatever::whatever_int_t, - } - #[test] - fn bindgen_test_layout_A() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); - } - impl Clone for A { - fn clone(&self) -> Self { *self } - } - } - #[repr(C)] - #[derive(Debug)] - pub struct C { - pub _base: root::_bindgen_mod_id_13::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 D { - pub m_c: root::C, - } - extern "C" { - #[link_name = "_ZN1w3hehEv"] - pub fn heh() -> root::w::whatever_int_t; - } - extern "C" { - #[link_name = "_ZN1w3fooEv"] - pub fn foo() -> root::C<::std::os::raw::c_int>; - } - extern "C" { - #[link_name = "_ZN1w4barrEv"] - pub fn barr() -> root::C; - } - } -} -extern "C" { - #[link_name = "_Z9top_levelv"] - pub fn top_level(); -} -#[repr(C)] -#[derive(Debug)] -pub struct C { - pub _base: root::_bindgen_mod_id_13::A, - pub m_c: T, - pub m_c_ptr: *mut T, - pub m_c_arr: [T; 10usize], -} diff --git a/tests/expectations/tests/nested.rs b/tests/expectations/tests/nested.rs deleted file mode 100644 index fdd435aa..00000000 --- a/tests/expectations/tests/nested.rs +++ /dev/null @@ -1,59 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Calc { - pub w: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_Calc() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for Calc { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Test { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Test_Size { - pub mWidth: Test_Size_Dimension, - pub mHeight: Test_Size_Dimension, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Test_Size_Dimension { - pub _base: Calc, -} -#[test] -fn bindgen_test_layout_Test_Size_Dimension() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for Test_Size_Dimension { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_Test_Size() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for Test_Size { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_Test() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for Test { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/nested_vtable.rs b/tests/expectations/tests/nested_vtable.rs deleted file mode 100644 index d74ad55f..00000000 --- a/tests/expectations/tests/nested_vtable.rs +++ /dev/null @@ -1,48 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct nsISupports__bindgen_vtable { -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct nsISupports { - pub vtable_: *const nsISupports__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_nsISupports() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 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::() , 8usize); - assert_eq!(::std::mem::align_of::() , 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::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for Runnable { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/no-std.rs b/tests/expectations/tests/no-std.rs deleted file mode 100644 index f50a889d..00000000 --- a/tests/expectations/tests/no-std.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - -#![no_std] -mod libc { pub type c_int = i32; pub enum c_void {} } - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub a: libc::c_int, - pub b: libc::c_int, - pub bar: *mut libc::c_void, -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::core::mem::size_of::() , 16usize); - assert_eq!(::core::mem::align_of::() , 8usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/no_copy.rs b/tests/expectations/tests/no_copy.rs deleted file mode 100644 index 53ab9677..00000000 --- a/tests/expectations/tests/no_copy.rs +++ /dev/null @@ -1,13 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -/**
*/ -#[repr(C)] -#[derive(Debug)] -pub struct CopiableButWait { - pub whatever: ::std::os::raw::c_int, - pub _phantom_0: ::std::marker::PhantomData, -} diff --git a/tests/expectations/tests/nsStyleAutoArray.rs b/tests/expectations/tests/nsStyleAutoArray.rs deleted file mode 100644 index c150ec46..00000000 --- a/tests/expectations/tests/nsStyleAutoArray.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsTArray { - pub mBuff: *mut T, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct nsStyleAutoArray { - pub mFirstElement: T, - pub mOtherElements: nsTArray, -} -#[repr(i32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum nsStyleAutoArray_WithSingleInitialElement { - WITH_SINGLE_INITIAL_ELEMENT = 0, -} diff --git a/tests/expectations/tests/only_bitfields.rs b/tests/expectations/tests/only_bitfields.rs deleted file mode 100644 index 68968826..00000000 --- a/tests/expectations/tests/only_bitfields.rs +++ /dev/null @@ -1,45 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C { - pub _bitfield_1: u8, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for C { - fn clone(&self) -> Self { *self } -} -impl C { - #[inline] - 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 as u8) << 0u32) & (1usize as u8); - } - #[inline] - pub fn b(&self) -> bool { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & (254usize as u8)) >> - 1u32) as u8) - } - } - #[inline] - 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); - } -} diff --git a/tests/expectations/tests/opaque_in_struct.rs b/tests/expectations/tests/opaque_in_struct.rs deleted file mode 100644 index d537f5c7..00000000 --- a/tests/expectations/tests/opaque_in_struct.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -/**
*/ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct opaque { - pub _bindgen_opaque_blob: u32, -} -#[test] -fn bindgen_test_layout_opaque() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for opaque { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct container { - pub contained: u32, -} -#[test] -fn bindgen_test_layout_container() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for container { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/opaque_pointer.rs b/tests/expectations/tests/opaque_pointer.rs deleted file mode 100644 index 067f55bd..00000000 --- a/tests/expectations/tests/opaque_pointer.rs +++ /dev/null @@ -1,45 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -/** - *
- */ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct OtherOpaque { - pub _bindgen_opaque_blob: u32, -} -#[test] -fn bindgen_test_layout_OtherOpaque() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for OtherOpaque { - fn clone(&self) -> Self { *self } -} -/** - *
- */ -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Opaque { - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[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_WithOpaquePtr() { - assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for WithOpaquePtr { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/opaque_typedef.rs b/tests/expectations/tests/opaque_typedef.rs deleted file mode 100644 index c45cbc6f..00000000 --- a/tests/expectations/tests/opaque_typedef.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct RandomTemplate { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} -/**
*/ -pub type ShouldBeOpaque = [u8; 0usize]; -pub type ShouldNotBeOpaque = RandomTemplate; diff --git a/tests/expectations/tests/overflowed_enum.rs b/tests/expectations/tests/overflowed_enum.rs deleted file mode 100644 index 9e1f8a7f..00000000 --- a/tests/expectations/tests/overflowed_enum.rs +++ /dev/null @@ -1,16 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(u32)] -#[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, PartialEq, Eq, Hash)] -pub enum Bar { One = 1, Big = 2, } diff --git a/tests/expectations/tests/overloading.rs b/tests/expectations/tests/overloading.rs deleted file mode 100644 index 4e138e7d..00000000 --- a/tests/expectations/tests/overloading.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -extern "C" { - #[link_name = "_Z8Evaluatec"] - pub fn Evaluate(r: ::std::os::raw::c_char) -> bool; -} -extern "C" { - #[link_name = "_Z8Evaluateii"] - pub fn Evaluate1(x: ::std::os::raw::c_int, y: ::std::os::raw::c_int) - -> bool; -} -extern "C" { - #[link_name = "_ZN3foo10MyFunctionEv"] - pub fn MyFunction(); -} -extern "C" { - #[link_name = "_ZN3bar10MyFunctionEv"] - pub fn MyFunction1(); -} diff --git a/tests/expectations/tests/private.rs b/tests/expectations/tests/private.rs deleted file mode 100644 index c4ac37d1..00000000 --- a/tests/expectations/tests/private.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct HasPrivate { - pub mNotPrivate: ::std::os::raw::c_int, - /**
*/ - mIsPrivate: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_HasPrivate() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for HasPrivate { - fn clone(&self) -> Self { *self } -} -/**
*/ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct VeryPrivate { - mIsPrivate: ::std::os::raw::c_int, - mIsAlsoPrivate: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_VeryPrivate() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for VeryPrivate { - fn clone(&self) -> Self { *self } -} -/**
*/ -#[repr(C)] -#[derive(Debug, Copy)] -pub struct ContradictPrivate { - /**
*/ - pub mNotPrivate: ::std::os::raw::c_int, - mIsPrivate: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_ContradictPrivate() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for ContradictPrivate { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/redeclaration.rs b/tests/expectations/tests/redeclaration.rs deleted file mode 100644 index 0d7e585c..00000000 --- a/tests/expectations/tests/redeclaration.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -extern "C" { - pub fn foo(); -} diff --git a/tests/expectations/tests/ref_argument_array.rs b/tests/expectations/tests/ref_argument_array.rs deleted file mode 100644 index c88492d7..00000000 --- a/tests/expectations/tests/ref_argument_array.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub const NSID_LENGTH: ::std::os::raw::c_uint = 10; -#[repr(C)] -pub struct nsID__bindgen_vtable { -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct nsID { - pub vtable_: *const nsID__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_nsID() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for nsID { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/replace_template_alias.rs b/tests/expectations/tests/replace_template_alias.rs deleted file mode 100644 index 61a2fbcc..00000000 --- a/tests/expectations/tests/replace_template_alias.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub ptr: MaybeWrapped, -} -/// But the replacement type does use T! -/// -///
-pub type MaybeWrapped = T; diff --git a/tests/expectations/tests/replaces_double.rs b/tests/expectations/tests/replaces_double.rs deleted file mode 100644 index 50dafd42..00000000 --- a/tests/expectations/tests/replaces_double.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub ptr: Rooted_MaybeWrapped, -} -/** - *
- */ -pub type Rooted_MaybeWrapped = T; diff --git a/tests/expectations/tests/size_t_template.rs b/tests/expectations/tests/size_t_template.rs deleted file mode 100644 index 78351ecc..00000000 --- a/tests/expectations/tests/size_t_template.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C { - pub arr: [u32; 3usize], -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!(::std::mem::size_of::() , 12usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for C { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_containing_forward_declared_struct.rs b/tests/expectations/tests/struct_containing_forward_declared_struct.rs deleted file mode 100644 index 388cc595..00000000 --- a/tests/expectations/tests/struct_containing_forward_declared_struct.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct a { - pub val_a: *mut a_b, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct a_b { - pub val_b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_a_b() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for a_b { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_a() { - assert_eq!(::std::mem::size_of::
() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for a { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_with_anon_struct.rs b/tests/expectations/tests/struct_with_anon_struct.rs deleted file mode 100644 index 1c49675d..00000000 --- a/tests/expectations/tests/struct_with_anon_struct.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub bar: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_with_anon_struct_array.rs b/tests/expectations/tests/struct_with_anon_struct_array.rs deleted file mode 100644 index 6e1c0315..00000000 --- a/tests/expectations/tests/struct_with_anon_struct_array.rs +++ /dev/null @@ -1,48 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub bar: [foo__bindgen_ty_1; 2usize], - pub baz: [[[foo__bindgen_ty_2; 4usize]; 3usize]; 2usize], -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_2 { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_2() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_2 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 208usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_with_anon_struct_pointer.rs b/tests/expectations/tests/struct_with_anon_struct_pointer.rs deleted file mode 100644 index aa77d4b6..00000000 --- a/tests/expectations/tests/struct_with_anon_struct_pointer.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub bar: *mut foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_with_anon_union.rs b/tests/expectations/tests/struct_with_anon_union.rs deleted file mode 100644 index 0d2e937a..00000000 --- a/tests/expectations/tests/struct_with_anon_union.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub bar: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub a: __BindgenUnionField<::std::os::raw::c_uint>, - pub b: __BindgenUnionField<::std::os::raw::c_ushort>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_with_anon_unnamed_struct.rs b/tests/expectations/tests/struct_with_anon_unnamed_struct.rs deleted file mode 100644 index 1b77fccc..00000000 --- a/tests/expectations/tests/struct_with_anon_unnamed_struct.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub __bindgen_anon_1: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_uint, - pub b: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_with_anon_unnamed_union.rs b/tests/expectations/tests/struct_with_anon_unnamed_union.rs deleted file mode 100644 index 2914eb41..00000000 --- a/tests/expectations/tests/struct_with_anon_unnamed_union.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub __bindgen_anon_1: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub a: __BindgenUnionField<::std::os::raw::c_uint>, - pub b: __BindgenUnionField<::std::os::raw::c_ushort>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_with_bitfields.rs b/tests/expectations/tests/struct_with_bitfields.rs deleted file mode 100644 index 3fb83a47..00000000 --- a/tests/expectations/tests/struct_with_bitfields.rs +++ /dev/null @@ -1,122 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct bitfield { - pub _bitfield_1: u8, - pub e: ::std::os::raw::c_int, - pub _bitfield_2: u8, - pub _bitfield_3: u32, -} -#[test] -fn bindgen_test_layout_bitfield() { - assert_eq!(::std::mem::size_of::() , 16usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for bitfield { - fn clone(&self) -> Self { *self } -} -impl bitfield { - #[inline] - pub fn a(&self) -> ::std::os::raw::c_ushort { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & (1usize as u8)) >> - 0u32) as u16) - } - } - #[inline] - 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 { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & (2usize as u8)) >> - 1u32) as u16) - } - } - #[inline] - 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 { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & (4usize as u8)) >> - 2u32) as u16) - } - } - #[inline] - 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 { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & (8usize as u8)) >> - 3u32) as u16) - } - } - #[inline] - 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 { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & (48usize as u8)) >> - 4u32) as u16) - } - } - #[inline] - 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 { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & (192usize as u8)) >> - 6u32) as u16) - } - } - #[inline] - 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 { - unsafe { - ::std::mem::transmute(((self._bitfield_2 & (3usize as u8)) >> - 0u32) as u32) - } - } - #[inline] - 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 { - unsafe { - ::std::mem::transmute(((self._bitfield_3 & - (4294967295usize as u32)) >> 0u32) as - u32) - } - } - #[inline] - pub fn set_g(&mut self, val: ::std::os::raw::c_uint) { - self._bitfield_3 &= !(4294967295usize as u32); - self._bitfield_3 |= - ((val as u32 as u32) << 0u32) & (4294967295usize as u32); - } -} diff --git a/tests/expectations/tests/struct_with_derive_debug.rs b/tests/expectations/tests/struct_with_derive_debug.rs deleted file mode 100644 index 52906a81..00000000 --- a/tests/expectations/tests/struct_with_derive_debug.rs +++ /dev/null @@ -1,50 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct LittleArray { - pub a: [::std::os::raw::c_int; 32usize], -} -#[test] -fn bindgen_test_layout_LittleArray() { - assert_eq!(::std::mem::size_of::() , 128usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for LittleArray { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -pub struct BigArray { - pub a: [::std::os::raw::c_int; 33usize], -} -#[test] -fn bindgen_test_layout_BigArray() { - assert_eq!(::std::mem::size_of::() , 132usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct WithLittleArray { - pub a: LittleArray, -} -#[test] -fn bindgen_test_layout_WithLittleArray() { - assert_eq!(::std::mem::size_of::() , 128usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for WithLittleArray { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -pub struct WithBigArray { - pub a: BigArray, -} -#[test] -fn bindgen_test_layout_WithBigArray() { - assert_eq!(::std::mem::size_of::() , 132usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} diff --git a/tests/expectations/tests/struct_with_nesting.rs b/tests/expectations/tests/struct_with_nesting.rs deleted file mode 100644 index 97a0949e..00000000 --- a/tests/expectations/tests/struct_with_nesting.rs +++ /dev/null @@ -1,90 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub a: ::std::os::raw::c_uint, - pub __bindgen_anon_1: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub b: __BindgenUnionField<::std::os::raw::c_uint>, - pub __bindgen_anon_1: __BindgenUnionField, - pub __bindgen_anon_2: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1_1 { - pub c1: ::std::os::raw::c_ushort, - pub c2: ::std::os::raw::c_ushort, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1_1() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 2usize); -} -impl Clone for foo__bindgen_ty_1_1 { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1_2 { - 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, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1_2() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for foo__bindgen_ty_1_2 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_with_packing.rs b/tests/expectations/tests/struct_with_packing.rs deleted file mode 100644 index 93fc3f11..00000000 --- a/tests/expectations/tests/struct_with_packing.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C, packed)] -#[derive(Debug, Copy)] -pub struct a { - pub b: ::std::os::raw::c_char, - pub c: ::std::os::raw::c_short, -} -#[test] -fn bindgen_test_layout_a() { - assert_eq!(::std::mem::size_of::() , 3usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for a { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_with_struct.rs b/tests/expectations/tests/struct_with_struct.rs deleted file mode 100644 index c8cdc927..00000000 --- a/tests/expectations/tests/struct_with_struct.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub bar: foo__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub x: ::std::os::raw::c_uint, - pub y: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/struct_with_typedef_template_arg.rs b/tests/expectations/tests/struct_with_typedef_template_arg.rs deleted file mode 100644 index 6f8d71f1..00000000 --- a/tests/expectations/tests/struct_with_typedef_template_arg.rs +++ /dev/null @@ -1,15 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Proxy { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - pub _phantom_1: ::std::marker::PhantomData, -} -pub type Proxy_foo = - ::std::option::Option; diff --git a/tests/expectations/tests/template.rs b/tests/expectations/tests/template.rs deleted file mode 100644 index 76afc879..00000000 --- a/tests/expectations/tests/template.rs +++ /dev/null @@ -1,170 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug)] -pub struct Foo { - pub m_member: T, - pub m_member_ptr: *mut T, - pub m_member_arr: [T; 1usize], - pub _phantom_1: ::std::marker::PhantomData, -} -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 D { - pub m_foo: D_MyFoo, - pub _phantom_0: ::std::marker::PhantomData, -} -pub type D_MyFoo = Foo<::std::os::raw::c_int, ::std::os::raw::c_int>; -#[repr(C)] -#[derive(Debug)] -pub struct D_U { - pub m_nested_foo: D_MyFoo, - pub m_baz: Z, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub prev: *mut T, - pub next: *mut Rooted<*mut ::std::os::raw::c_void>, - pub ptr: T, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct RootedContainer { - pub root: Rooted<*mut ::std::os::raw::c_void>, -} -#[test] -fn bindgen_test_layout_RootedContainer() { - assert_eq!(::std::mem::size_of::() , 24usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for RootedContainer { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug)] -pub struct WithDtor { - pub member: T, -} -pub type WithDtorIntFwd = WithDtor<::std::os::raw::c_int>; -#[repr(C)] -#[derive(Debug)] -pub struct PODButContainsDtor { - pub member: WithDtorIntFwd, -} -#[test] -fn bindgen_test_layout_PODButContainsDtor() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -/**
*/ -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Opaque { - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct POD { - pub opaque_member: u32, -} -#[test] -fn bindgen_test_layout_POD() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for POD { - fn clone(&self) -> Self { *self } -} -/** - *
- */ -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct NestedReplaced { - pub buff: *mut T, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct NestedBase { - pub buff: *mut T, - pub _phantom_1: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Incomplete { - pub d: T, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct NestedContainer { - pub c: T, - pub nested: NestedReplaced, - pub inc: Incomplete, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Untemplated { - pub _address: u8, -} -#[test] -fn bindgen_test_layout_Untemplated() { - assert_eq!(::std::mem::size_of::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for Untemplated { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Templated { - pub m_untemplated: Untemplated, - pub _phantom_0: ::std::marker::PhantomData, -} -/** - * 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. - * - *
- */ -#[repr(C)] -#[derive(Debug)] -pub struct ReplacedWithoutDestructor { - pub buff: *mut T, -} -#[repr(C)] -#[derive(Debug)] -pub struct ShouldNotBeCopiable { - pub m_member: ReplacedWithoutDestructor, -} -#[repr(C)] -#[derive(Debug)] -pub struct ShouldNotBeCopiableAsWell { - pub m_member: ReplacedWithoutDestructorFwd, -} -/** - * 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. - * - *
- */ -#[repr(C)] -#[derive(Debug)] -pub struct ReplacedWithoutDestructorFwd { - pub buff: *mut T, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct TemplateWithVar { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} diff --git a/tests/expectations/tests/template_alias.rs b/tests/expectations/tests/template_alias.rs deleted file mode 100644 index 6457381f..00000000 --- a/tests/expectations/tests/template_alias.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub type Wrapped = T; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub ptr: Wrapped, -} diff --git a/tests/expectations/tests/template_alias_basic.rs b/tests/expectations/tests/template_alias_basic.rs deleted file mode 100644 index 656fff33..00000000 --- a/tests/expectations/tests/template_alias_basic.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub type Wrapped = T; diff --git a/tests/expectations/tests/template_alias_namespace.rs b/tests/expectations/tests/template_alias_namespace.rs deleted file mode 100644 index 475c2b05..00000000 --- a/tests/expectations/tests/template_alias_namespace.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub mod root { - use root; - pub mod JS { - use root; - pub mod detail { - use root; - pub type Wrapped = T; - } - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct Rooted { - pub ptr: root::JS::detail::Wrapped, - } - } -} diff --git a/tests/expectations/tests/template_typedef_transitive_param.rs b/tests/expectations/tests/template_typedef_transitive_param.rs deleted file mode 100644 index 166ddc3c..00000000 --- a/tests/expectations/tests/template_typedef_transitive_param.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Wrapper { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Wrapper_Wrapped { - pub t: T, -} -pub type Wrapper_Type = Wrapper_Wrapped; diff --git a/tests/expectations/tests/template_typedefs.rs b/tests/expectations/tests/template_typedefs.rs deleted file mode 100644 index 5f0d80b9..00000000 --- a/tests/expectations/tests/template_typedefs.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub type foo = - ::std::option::Option; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Foo { - pub _address: u8, - pub _phantom_0: ::std::marker::PhantomData, - pub _phantom_1: ::std::marker::PhantomData, -} -pub type Foo_Char = T; -pub type Foo_FooPtrTypedef = *mut Foo_Char; -pub type Foo_nsCOMArrayEnumFunc = - ::std::option::Option bool>; diff --git a/tests/expectations/tests/type_alias_empty.rs b/tests/expectations/tests/type_alias_empty.rs deleted file mode 100644 index 47e36006..00000000 --- a/tests/expectations/tests/type_alias_empty.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub type bool_constant = (); diff --git a/tests/expectations/tests/typeref.rs b/tests/expectations/tests/typeref.rs deleted file mode 100644 index da944146..00000000 --- a/tests/expectations/tests/typeref.rs +++ /dev/null @@ -1,96 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[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::() , 8usize); - assert_eq!(::std::mem::align_of::() , 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::() , 1usize); - assert_eq!(::std::mem::align_of::() , 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::() , 1usize); - assert_eq!(::std::mem::align_of::() , 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::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for Bar { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct StyleShapeSource { - pub __bindgen_anon_1: StyleShapeSource__bindgen_ty_1, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct StyleShapeSource__bindgen_ty_1 { - pub mPosition: __BindgenUnionField<*mut Position>, - pub mFragmentOrURL: __BindgenUnionField<*mut FragmentOrURL>, - pub bindgen_union_field: u64, - pub _phantom_0: ::std::marker::PhantomData, -} diff --git a/tests/expectations/tests/union_dtor.rs b/tests/expectations/tests/union_dtor.rs deleted file mode 100644 index 9be626ff..00000000 --- a/tests/expectations/tests/union_dtor.rs +++ /dev/null @@ -1,42 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug)] -pub struct UnionWithDtor { - pub mFoo: __BindgenUnionField<::std::os::raw::c_int>, - pub mBar: __BindgenUnionField<*mut ::std::os::raw::c_void>, - pub bindgen_union_field: u64, -} -#[test] -fn bindgen_test_layout_UnionWithDtor() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} diff --git a/tests/expectations/tests/union_fields.rs b/tests/expectations/tests/union_fields.rs deleted file mode 100644 index 495e80f9..00000000 --- a/tests/expectations/tests/union_fields.rs +++ /dev/null @@ -1,47 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct _bindgen_ty_1 { - pub mInt: __BindgenUnionField<::std::os::raw::c_int>, - pub mFloat: __BindgenUnionField, - pub mPointer: __BindgenUnionField<*mut ::std::os::raw::c_void>, - pub bindgen_union_field: u64, -} -#[test] -fn bindgen_test_layout__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::<_bindgen_ty_1>() , 8usize); - assert_eq!(::std::mem::align_of::<_bindgen_ty_1>() , 8usize); -} -impl Clone for _bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -pub type nsStyleUnion = _bindgen_ty_1; diff --git a/tests/expectations/tests/union_template.rs b/tests/expectations/tests/union_template.rs deleted file mode 100644 index fc92afb8..00000000 --- a/tests/expectations/tests/union_template.rs +++ /dev/null @@ -1,62 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct NastyStruct { - pub mIsSome: bool, - pub mStorage: NastyStruct__bindgen_ty_1, - pub __bindgen_anon_1: NastyStruct__bindgen_ty_2, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct NastyStruct__bindgen_ty_1 { - pub mFoo: __BindgenUnionField<*mut ::std::os::raw::c_void>, - pub mDummy: __BindgenUnionField<::std::os::raw::c_ulong>, - pub bindgen_union_field: u64, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct NastyStruct__bindgen_ty_2 { - pub wat: __BindgenUnionField<::std::os::raw::c_short>, - pub wut: __BindgenUnionField<*mut ::std::os::raw::c_int>, - pub bindgen_union_field: u64, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Whatever { - pub mTPtr: __BindgenUnionField<*mut ::std::os::raw::c_void>, - pub mInt: __BindgenUnionField<::std::os::raw::c_int>, - pub bindgen_union_field: u64, - pub _phantom_0: ::std::marker::PhantomData, -} diff --git a/tests/expectations/tests/union_with_anon_struct.rs b/tests/expectations/tests/union_with_anon_struct.rs deleted file mode 100644 index f0a21512..00000000 --- a/tests/expectations/tests/union_with_anon_struct.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub bar: __BindgenUnionField, - pub bindgen_union_field: [u32; 2usize], -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub a: ::std::os::raw::c_uint, - pub b: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/union_with_anon_struct_bitfield.rs b/tests/expectations/tests/union_with_anon_struct_bitfield.rs deleted file mode 100644 index 548b0dc4..00000000 --- a/tests/expectations/tests/union_with_anon_struct_bitfield.rs +++ /dev/null @@ -1,86 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub a: __BindgenUnionField<::std::os::raw::c_int>, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub _bitfield_1: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -impl foo__bindgen_ty_1 { - #[inline] - pub fn b(&self) -> ::std::os::raw::c_int { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & (127usize as u32)) >> - 0u32) as u32) - } - } - #[inline] - 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 { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & - (4294967168usize as u32)) >> 7u32) as - u32) - } - } - #[inline] - pub fn set_c(&mut self, val: ::std::os::raw::c_int) { - self._bitfield_1 &= !(4294967168usize as u32); - self._bitfield_1 |= - ((val as u32 as u32) << 7u32) & (4294967168usize as u32); - } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/union_with_anon_union.rs b/tests/expectations/tests/union_with_anon_union.rs deleted file mode 100644 index 95278556..00000000 --- a/tests/expectations/tests/union_with_anon_union.rs +++ /dev/null @@ -1,59 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub bar: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub a: __BindgenUnionField<::std::os::raw::c_uint>, - pub b: __BindgenUnionField<::std::os::raw::c_ushort>, - pub bindgen_union_field: u32, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/union_with_anon_unnamed_struct.rs b/tests/expectations/tests/union_with_anon_unnamed_struct.rs deleted file mode 100644 index 2d6fab97..00000000 --- a/tests/expectations/tests/union_with_anon_unnamed_struct.rs +++ /dev/null @@ -1,61 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct pixel { - pub rgba: __BindgenUnionField<::std::os::raw::c_uint>, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct pixel__bindgen_ty_1 { - 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, -} -#[test] -fn bindgen_test_layout_pixel__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for pixel__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_pixel() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for pixel { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/union_with_anon_unnamed_union.rs b/tests/expectations/tests/union_with_anon_unnamed_union.rs deleted file mode 100644 index eb214017..00000000 --- a/tests/expectations/tests/union_with_anon_unnamed_union.rs +++ /dev/null @@ -1,60 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub a: __BindgenUnionField<::std::os::raw::c_uint>, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub b: __BindgenUnionField<::std::os::raw::c_ushort>, - pub c: __BindgenUnionField<::std::os::raw::c_uchar>, - pub bindgen_union_field: u16, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 2usize); - assert_eq!(::std::mem::align_of::() , 2usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/union_with_big_member.rs b/tests/expectations/tests/union_with_big_member.rs deleted file mode 100644 index b921f33c..00000000 --- a/tests/expectations/tests/union_with_big_member.rs +++ /dev/null @@ -1,75 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Copy)] -pub struct WithBigArray { - pub a: __BindgenUnionField<::std::os::raw::c_int>, - pub b: __BindgenUnionField<[::std::os::raw::c_int; 33usize]>, - pub bindgen_union_field: [u32; 33usize], -} -#[test] -fn bindgen_test_layout_WithBigArray() { - assert_eq!(::std::mem::size_of::() , 132usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for WithBigArray { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct WithBigArray2 { - pub a: __BindgenUnionField<::std::os::raw::c_int>, - pub b: __BindgenUnionField<[::std::os::raw::c_char; 33usize]>, - pub bindgen_union_field: [u32; 9usize], -} -#[test] -fn bindgen_test_layout_WithBigArray2() { - assert_eq!(::std::mem::size_of::() , 36usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for WithBigArray2 { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Copy)] -pub struct WithBigMember { - pub a: __BindgenUnionField<::std::os::raw::c_int>, - pub b: __BindgenUnionField, - pub bindgen_union_field: [u32; 33usize], -} -#[test] -fn bindgen_test_layout_WithBigMember() { - assert_eq!(::std::mem::size_of::() , 132usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for WithBigMember { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/union_with_nesting.rs b/tests/expectations/tests/union_with_nesting.rs deleted file mode 100644 index 61c08a2a..00000000 --- a/tests/expectations/tests/union_with_nesting.rs +++ /dev/null @@ -1,89 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct __BindgenUnionField(::std::marker::PhantomData); -impl __BindgenUnionField { - #[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 ::std::default::Default for __BindgenUnionField { - #[inline] - fn default() -> Self { Self::new() } -} -impl ::std::clone::Clone for __BindgenUnionField { - #[inline] - fn clone(&self) -> Self { Self::new() } -} -impl ::std::marker::Copy for __BindgenUnionField { } -impl ::std::fmt::Debug for __BindgenUnionField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__BindgenUnionField") - } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub a: __BindgenUnionField<::std::os::raw::c_uint>, - pub __bindgen_anon_1: __BindgenUnionField, - pub bindgen_union_field: u32, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1 { - pub __bindgen_anon_1: foo__bindgen_ty_1_1, - pub __bindgen_anon_2: foo__bindgen_ty_1_2, -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1_1 { - pub b1: __BindgenUnionField<::std::os::raw::c_ushort>, - pub b2: __BindgenUnionField<::std::os::raw::c_ushort>, - pub bindgen_union_field: u16, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1_1() { - assert_eq!(::std::mem::size_of::() , 2usize); - assert_eq!(::std::mem::align_of::() , 2usize); -} -impl Clone for foo__bindgen_ty_1_1 { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo__bindgen_ty_1_2 { - pub c1: __BindgenUnionField<::std::os::raw::c_ushort>, - pub c2: __BindgenUnionField<::std::os::raw::c_ushort>, - pub bindgen_union_field: u16, -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1_2() { - assert_eq!(::std::mem::size_of::() , 2usize); - assert_eq!(::std::mem::align_of::() , 2usize); -} -impl Clone for foo__bindgen_ty_1_2 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo__bindgen_ty_1() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 2usize); -} -impl Clone for foo__bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 4usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/unknown_attr.rs b/tests/expectations/tests/unknown_attr.rs deleted file mode 100644 index fd9cce45..00000000 --- a/tests/expectations/tests/unknown_attr.rs +++ /dev/null @@ -1,16 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct _bindgen_ty_1 { - pub __clang_max_align_nonce1: ::std::os::raw::c_longlong, - pub __clang_max_align_nonce2: f64, -} -impl Clone for _bindgen_ty_1 { - fn clone(&self) -> Self { *self } -} -pub type max_align_t = _bindgen_ty_1; diff --git a/tests/expectations/tests/use-core.rs b/tests/expectations/tests/use-core.rs deleted file mode 100644 index b0900f5f..00000000 --- a/tests/expectations/tests/use-core.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - -extern crate core; - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub a: ::std::os::raw::c_int, - pub b: ::std::os::raw::c_int, - pub bar: *mut ::std::os::raw::c_void, -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::core::mem::size_of::() , 16usize); - assert_eq!(::core::mem::align_of::() , 8usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} -pub type fooFunction = - ::core::option::Option; diff --git a/tests/expectations/tests/using.rs b/tests/expectations/tests/using.rs deleted file mode 100644 index dbb6c84f..00000000 --- a/tests/expectations/tests/using.rs +++ /dev/null @@ -1,14 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Point { - pub x: T, - pub y: T, -} -pub type IntPoint2D = Point<::std::os::raw::c_int>; -pub type IntVec2D = Point<::std::os::raw::c_int>; diff --git a/tests/expectations/tests/vector.rs b/tests/expectations/tests/vector.rs deleted file mode 100644 index b8ca5735..00000000 --- a/tests/expectations/tests/vector.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct foo { - pub mMember: [::std::os::raw::c_longlong; 1usize], -} -#[test] -fn bindgen_test_layout_foo() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for foo { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/virtual_dtor.rs b/tests/expectations/tests/virtual_dtor.rs deleted file mode 100644 index 9571f084..00000000 --- a/tests/expectations/tests/virtual_dtor.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct nsSlots__bindgen_vtable { -} -#[repr(C)] -#[derive(Debug)] -pub struct nsSlots { - pub vtable_: *const nsSlots__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_nsSlots() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} diff --git a/tests/expectations/tests/virtual_overloaded.rs b/tests/expectations/tests/virtual_overloaded.rs deleted file mode 100644 index 7833cdbf..00000000 --- a/tests/expectations/tests/virtual_overloaded.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -pub struct C__bindgen_vtable { -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct C { - pub vtable_: *const C__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_C() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for C { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/vtable_recursive_sig.rs b/tests/expectations/tests/vtable_recursive_sig.rs deleted file mode 100644 index ce62eeb0..00000000 --- a/tests/expectations/tests/vtable_recursive_sig.rs +++ /dev/null @@ -1,35 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Derived { - pub _base: Base, -} -#[test] -fn bindgen_test_layout_Derived() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for Derived { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -pub struct Base__bindgen_vtable { -} -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Base { - pub vtable_: *const Base__bindgen_vtable, -} -#[test] -fn bindgen_test_layout_Base() { - assert_eq!(::std::mem::size_of::() , 8usize); - assert_eq!(::std::mem::align_of::() , 8usize); -} -impl Clone for Base { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/weird_bitfields.rs b/tests/expectations/tests/weird_bitfields.rs deleted file mode 100644 index 56ee76a5..00000000 --- a/tests/expectations/tests/weird_bitfields.rs +++ /dev/null @@ -1,128 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(u32)] -#[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 Weird { - pub mStrokeDasharrayLength: ::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, - pub mFillRule: ::std::os::raw::c_uchar, - pub mImageRendering: ::std::os::raw::c_uchar, - pub mPaintOrder: ::std::os::raw::c_uchar, - pub mShapeRendering: ::std::os::raw::c_uchar, - pub mStrokeLinecap: ::std::os::raw::c_uchar, - pub mStrokeLinejoin: ::std::os::raw::c_uchar, - pub mTextAnchor: ::std::os::raw::c_uchar, - pub mTextRendering: ::std::os::raw::c_uchar, - pub _bitfield_2: u16, -} -#[test] -fn bindgen_test_layout_Weird() { - assert_eq!(::std::mem::size_of::() , 24usize); - assert_eq!(::std::mem::align_of::() , 4usize); -} -impl Clone for Weird { - fn clone(&self) -> Self { *self } -} -impl Weird { - #[inline] - pub fn bitTest(&self) -> ::std::os::raw::c_uint { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & (65535usize as u32)) >> - 0u32) as u32) - } - } - #[inline] - pub fn set_bitTest(&mut self, val: ::std::os::raw::c_uint) { - self._bitfield_1 &= !(65535usize as u32); - self._bitfield_1 |= - ((val as u32 as u32) << 0u32) & (65535usize as u32); - } - #[inline] - pub fn bitTest2(&self) -> ::std::os::raw::c_uint { - unsafe { - ::std::mem::transmute(((self._bitfield_1 & - (2147418112usize as u32)) >> 16u32) as - u32) - } - } - #[inline] - pub fn set_bitTest2(&mut self, val: ::std::os::raw::c_uint) { - self._bitfield_1 &= !(2147418112usize as u32); - self._bitfield_1 |= - ((val as u32 as u32) << 16u32) & (2147418112usize as u32); - } - #[inline] - 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: nsStyleSVGOpacitySource) { - self._bitfield_2 &= !(7usize as u16); - self._bitfield_2 |= ((val as u32 as u16) << 0u32) & (7usize as u16); - } - #[inline] - 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: nsStyleSVGOpacitySource) { - self._bitfield_2 &= !(56usize as u16); - self._bitfield_2 |= ((val as u32 as u16) << 3u32) & (56usize as u16); - } - #[inline] - 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 u16); - self._bitfield_2 |= ((val as u8 as u16) << 6u32) & (64usize as u16); - } - #[inline] - 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 u16); - self._bitfield_2 |= ((val as u8 as u16) << 7u32) & (128usize as u16); - } - #[inline] - 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 u16); - self._bitfield_2 |= ((val as u8 as u16) << 8u32) & (256usize as u16); - } -} diff --git a/tests/expectations/tests/what_is_going_on.rs b/tests/expectations/tests/what_is_going_on.rs deleted file mode 100644 index 6f1998d1..00000000 --- a/tests/expectations/tests/what_is_going_on.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* 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::() , 1usize); - assert_eq!(::std::mem::align_of::() , 1usize); -} -impl Clone for UnknownUnits { - fn clone(&self) -> Self { *self } -} -pub type Float = f32; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct PointTyped { - pub x: F, - pub y: F, - pub _phantom_0: ::std::marker::PhantomData, -} -pub type IntPoint = PointTyped; diff --git a/tests/expectations/tests/whitelist_basic.rs b/tests/expectations/tests/whitelist_basic.rs deleted file mode 100644 index 0104f049..00000000 --- a/tests/expectations/tests/whitelist_basic.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct WhitelistMe { - pub foo: ::std::os::raw::c_int, - pub bar: WhitelistMe_Inner, - pub _phantom_0: ::std::marker::PhantomData, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct WhitelistMe_Inner { - pub bar: T, -} diff --git a/tests/expectations/tests/whitelist_vars.rs b/tests/expectations/tests/whitelist_vars.rs deleted file mode 100644 index f7af24b2..00000000 --- a/tests/expectations/tests/whitelist_vars.rs +++ /dev/null @@ -1,10 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(non_snake_case)] - - -pub const NONE: ::std::os::raw::c_uint = 0; -pub const FOO: ::std::os::raw::c_uint = 5; -pub const FOOB: ::std::os::raw::c_int = -2; -pub const FOOBAR: ::std::os::raw::c_int = -10; diff --git a/tests/headers/accessors.hpp b/tests/headers/accessors.hpp deleted file mode 100644 index 4c23e35d..00000000 --- a/tests/headers/accessors.hpp +++ /dev/null @@ -1,46 +0,0 @@ -struct SomeAccessors { - int mNoAccessor; - /**
*/ - int mBothAccessors; - /**
*/ - int mUnsafeAccessors; - /**
*/ - int mImmutableAccessor; -}; - -/**
*/ -struct AllAccessors { - int mBothAccessors; - int mAlsoBothAccessors; -}; - -/**
*/ -struct AllUnsafeAccessors { - int mBothAccessors; - int mAlsoBothAccessors; -}; - -/**
*/ -struct ContradictAccessors { - int mBothAccessors; - /**
*/ - int mNoAccessors; - /**
*/ - int mUnsafeAccessors; - /**
*/ - int mImmutableAccessor; -}; - -/**
*/ -struct Replacing { - int mAccessor; -}; - -struct Replaced { - int noOp; -}; - -/**
*/ -struct Wrapper { - Replaced mReplaced; -}; diff --git a/tests/headers/annotation_hide.hpp b/tests/headers/annotation_hide.hpp deleted file mode 100644 index 3c82c9a2..00000000 --- a/tests/headers/annotation_hide.hpp +++ /dev/null @@ -1,16 +0,0 @@ - -/** - *
- */ -struct C; - -/** - *
- */ -struct D { - int a; -}; - -struct NotAnnotated { - int f; -}; diff --git a/tests/headers/anon_enum.hpp b/tests/headers/anon_enum.hpp deleted file mode 100644 index c7405202..00000000 --- a/tests/headers/anon_enum.hpp +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index 15cda6b1..00000000 --- a/tests/headers/anon_enum_whitelist.h +++ /dev/null @@ -1,6 +0,0 @@ -// 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 deleted file mode 100644 index 126f6a6e..00000000 --- a/tests/headers/anon_union.hpp +++ /dev/null @@ -1,20 +0,0 @@ -template -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 { -}; diff --git a/tests/headers/arg_keyword.hpp b/tests/headers/arg_keyword.hpp deleted file mode 100644 index 9f0af850..00000000 --- a/tests/headers/arg_keyword.hpp +++ /dev/null @@ -1 +0,0 @@ -void foo(const char* type); diff --git a/tests/headers/base-to-derived.hpp b/tests/headers/base-to-derived.hpp deleted file mode 100644 index ea31e0f2..00000000 --- a/tests/headers/base-to-derived.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// bindgen-flags: -- -std=c++11 - -struct false_type {}; - -template -struct __is_base_to_derived_ref; - -template -struct __is_base_to_derived_ref<_From, _To, true> -{ - typedef _To type; - - static constexpr bool value = type::value; -}; - -template -struct __is_base_to_derived_ref<_From, _To, false> -: public false_type -{ }; diff --git a/tests/headers/bitfield-enum-basic.h b/tests/headers/bitfield-enum-basic.h deleted file mode 100644 index 364bebf2..00000000 --- a/tests/headers/bitfield-enum-basic.h +++ /dev/null @@ -1,27 +0,0 @@ -// bindgen-flags: --bitfield-enum "Foo|Buz|NS_.*|DUMMY_.*" -- -std=c++11 - -enum Foo { - Bar = 1 << 1, - Baz = 1 << 2, - Duplicated = 1 << 2, - Negative = -3, -}; - -enum class Buz : signed char { - Bar = 1 << 1, - Baz = 1 << 2, - Duplicated = 1 << 2, - Negative = -3, -}; - -enum { - NS_FOO = 1 << 0, - NS_BAR = 1 << 1, -}; - -class Dummy { - enum { - DUMMY_FOO = 1 << 0, - DUMMY_BAR = 1 << 1, - }; -}; diff --git a/tests/headers/blocks.h b/tests/headers/blocks.h deleted file mode 100644 index 80420e6e..00000000 --- a/tests/headers/blocks.h +++ /dev/null @@ -1,3 +0,0 @@ -// bindgen-flags: -- -fblocks - -void atexit_b(void (^)(void)); diff --git a/tests/headers/class.hpp b/tests/headers/class.hpp deleted file mode 100644 index e753f186..00000000 --- a/tests/headers/class.hpp +++ /dev/null @@ -1,29 +0,0 @@ -class C { - int a; - // More than rust limits (32) - char big_array[33]; -}; - -class WithDtor { - int b; - - ~WithDtor() {} -}; - -union Union { - float d; - int i; -}; - -class WithUnion { - Union data; -}; - -class RealAbstractionWithTonsOfMethods { - void foo(); -public: - void bar() const; - void bar(); - void bar(int foo); - static void sta(); -}; diff --git a/tests/headers/class_nested.hpp b/tests/headers/class_nested.hpp deleted file mode 100644 index ab38d500..00000000 --- a/tests/headers/class_nested.hpp +++ /dev/null @@ -1,24 +0,0 @@ -class A { -public: - int member_a; - class B { - int member_b; - }; -}; - -A::B var; - -class D { - A::B member; -}; - -template -class Templated { - T member; - - class Templated_inner { - public: - T* member_ptr; - void get() {} - }; -}; diff --git a/tests/headers/class_no_members.hpp b/tests/headers/class_no_members.hpp deleted file mode 100644 index a4483558..00000000 --- a/tests/headers/class_no_members.hpp +++ /dev/null @@ -1,16 +0,0 @@ -// bindgen-flags: -- -std=c++11 - -class whatever { -}; - -class whatever_child: public whatever { -}; - -class whatever_child_with_member: public whatever { -public: - int m_member; -}; - -static_assert(sizeof(whatever) == 1, "Testing!"); -static_assert(sizeof(whatever_child) == 1, "Testing!"); -static_assert(sizeof(whatever_child_with_member) == 4, "Testing!"); diff --git a/tests/headers/class_static.hpp b/tests/headers/class_static.hpp deleted file mode 100644 index 21ab2321..00000000 --- a/tests/headers/class_static.hpp +++ /dev/null @@ -1,7 +0,0 @@ -class MyClass { -public: - static const int* example; - static const int* example_check_no_collision; -}; - -static const int* example_check_no_collision; diff --git a/tests/headers/class_static_const.hpp b/tests/headers/class_static_const.hpp deleted file mode 100644 index 150afe8b..00000000 --- a/tests/headers/class_static_const.hpp +++ /dev/null @@ -1,8 +0,0 @@ -using int32_t = int; -typedef unsigned int uint32_t; - -class A { - static const int a = 0; - static const int32_t b = 077; - static const uint32_t c = 0xff; -}; diff --git a/tests/headers/class_use_as.hpp b/tests/headers/class_use_as.hpp deleted file mode 100644 index a4e36ded..00000000 --- a/tests/headers/class_use_as.hpp +++ /dev/null @@ -1,15 +0,0 @@ - -/** - *
- */ -struct whatever_replacement { - int replacement; -}; - -struct whatever { - int b; -}; - -struct container { - whatever c; -}; diff --git a/tests/headers/class_with_dtor.hpp b/tests/headers/class_with_dtor.hpp deleted file mode 100644 index b9bf74e1..00000000 --- a/tests/headers/class_with_dtor.hpp +++ /dev/null @@ -1,13 +0,0 @@ - - -template -class HandleWithDtor { - T* ptr; - ~HandleWithDtor() {} -}; - -typedef HandleWithDtor HandleValue; - -class WithoutDtor { - HandleValue shouldBeWithDtor; -}; diff --git a/tests/headers/class_with_inner_struct.hpp b/tests/headers/class_with_inner_struct.hpp deleted file mode 100644 index ec729fe6..00000000 --- a/tests/headers/class_with_inner_struct.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// bindgen-flags: -- -std=c++11 - -class A { - unsigned c; - struct Segment { int begin, end; }; - union { - int f; - } named_union; - union { - int d; - }; -}; - -class B { - unsigned d; - struct Segment { int begin, end; }; -}; - - -enum class StepSyntax { - Keyword, // step-start and step-end - FunctionalWithoutKeyword, // steps(...) - FunctionalWithStartKeyword, // steps(..., start) - FunctionalWithEndKeyword, // steps(..., end) -}; - -class C { - unsigned d; - union { - struct { - float mX1; - float mY1; - float mX2; - float mY2; - } mFunc; - struct { - StepSyntax mStepSyntax; - unsigned int mSteps; - }; - }; - // To ensure it doesn't collide - struct Segment { int begin, end; }; -}; diff --git a/tests/headers/class_with_typedef.hpp b/tests/headers/class_with_typedef.hpp deleted file mode 100644 index 8707cffe..00000000 --- a/tests/headers/class_with_typedef.hpp +++ /dev/null @@ -1,22 +0,0 @@ -typedef int AnotherInt; - -class C { -public: - typedef int MyInt; - typedef const char* Lookup; - MyInt c; - MyInt* ptr; - MyInt arr[10]; - AnotherInt d; - AnotherInt* other_ptr; - - void method(MyInt c); - void methodRef(MyInt& c); - void complexMethodRef(Lookup& c); - void anotherMethod(AnotherInt c); -}; - -class D: public C { -public: - MyInt* ptr; -}; diff --git a/tests/headers/complex.h b/tests/headers/complex.h deleted file mode 100644 index 04877a4e..00000000 --- a/tests/headers/complex.h +++ /dev/null @@ -1,16 +0,0 @@ - -#define COMPLEX_TEST(ty_, name_) \ - struct Test##name_ { \ - ty_ _Complex mMember; \ - \ - }; \ - struct Test##name_##Ptr { \ - ty_ _Complex* mMember; \ - }; - -COMPLEX_TEST(double, Double) -COMPLEX_TEST(float, Float) - -// FIXME: 128-byte-aligned in some machines -// which we can't support right now in Rust. -// COMPLEX_TEST(long double, LongDouble) diff --git a/tests/headers/complex_global.h b/tests/headers/complex_global.h deleted file mode 100644 index d9f9fb01..00000000 --- a/tests/headers/complex_global.h +++ /dev/null @@ -1,3 +0,0 @@ -float _Complex globalValueFloat; -double _Complex globalValueDouble; -long double _Complex globalValueLongDouble; diff --git a/tests/headers/const_enum_unnamed.hpp b/tests/headers/const_enum_unnamed.hpp deleted file mode 100644 index eb139434..00000000 --- a/tests/headers/const_enum_unnamed.hpp +++ /dev/null @@ -1,9 +0,0 @@ - -enum { - FOO_BAR, - FOO_BAZ, -}; - -class Foo { - enum { FOO_BAR = 10 }; -}; diff --git a/tests/headers/const_ptr.hpp b/tests/headers/const_ptr.hpp deleted file mode 100644 index 66744f8b..00000000 --- a/tests/headers/const_ptr.hpp +++ /dev/null @@ -1,3 +0,0 @@ -extern "C" { - void foo(const void* bar); -} diff --git a/tests/headers/const_resolved_ty.h b/tests/headers/const_resolved_ty.h deleted file mode 100644 index 2521e61c..00000000 --- a/tests/headers/const_resolved_ty.h +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 05f26e4a..00000000 --- a/tests/headers/const_tparam.hpp +++ /dev/null @@ -1,5 +0,0 @@ -template -class C { - const T* const foo; - const T* bar; -}; diff --git a/tests/headers/convert-floats.h b/tests/headers/convert-floats.h deleted file mode 100644 index 08d9fe0b..00000000 --- a/tests/headers/convert-floats.h +++ /dev/null @@ -1,9 +0,0 @@ -// bindgen-flags: --no-convert-floats - -struct foo { - float bar, baz; - double bazz; - long double* bazzz; - float _Complex complexFloat; - double _Complex complexDouble; -}; diff --git a/tests/headers/crtp.hpp b/tests/headers/crtp.hpp deleted file mode 100644 index a5477c54..00000000 --- a/tests/headers/crtp.hpp +++ /dev/null @@ -1,12 +0,0 @@ -template -class Base {}; - -class Derived : public Base {}; - -template -class BaseWithDestructor { - ~BaseWithDestructor(); -}; - -class DerivedFromBaseWithDestructor : - public BaseWithDestructor {}; diff --git a/tests/headers/decl_extern_int_twice.h b/tests/headers/decl_extern_int_twice.h deleted file mode 100644 index 06f80e87..00000000 --- a/tests/headers/decl_extern_int_twice.h +++ /dev/null @@ -1,2 +0,0 @@ -extern int foo; -extern int foo; diff --git a/tests/headers/decl_ptr_to_array.h b/tests/headers/decl_ptr_to_array.h deleted file mode 100644 index 3222cbd4..00000000 --- a/tests/headers/decl_ptr_to_array.h +++ /dev/null @@ -1 +0,0 @@ -int (*foo)[1]; diff --git a/tests/headers/duplicated_constants_in_ns.hpp b/tests/headers/duplicated_constants_in_ns.hpp deleted file mode 100644 index bb343641..00000000 --- a/tests/headers/duplicated_constants_in_ns.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces -namespace foo { - const int FOO = 4; -} -namespace bar { - const int FOO = 5; -} diff --git a/tests/headers/elaborated.hpp b/tests/headers/elaborated.hpp deleted file mode 100644 index 4bfbff23..00000000 --- a/tests/headers/elaborated.hpp +++ /dev/null @@ -1,5 +0,0 @@ -namespace whatever { - typedef int whatever_t; -} - -void something(const whatever::whatever_t *wat); diff --git a/tests/headers/empty_template_param_name.hpp b/tests/headers/empty_template_param_name.hpp deleted file mode 100644 index b3360bc9..00000000 --- a/tests/headers/empty_template_param_name.hpp +++ /dev/null @@ -1,4 +0,0 @@ -template using __void_t = void; - -template> - struct __iterator_traits { }; diff --git a/tests/headers/enum.h b/tests/headers/enum.h deleted file mode 100644 index f2d301e7..00000000 --- a/tests/headers/enum.h +++ /dev/null @@ -1,9 +0,0 @@ -enum Foo { - Bar = 0, - Qux -}; - -enum Neg { - MinusOne = -1, - One = 1, -}; diff --git a/tests/headers/enum_alias.hpp b/tests/headers/enum_alias.hpp deleted file mode 100644 index 658f8fde..00000000 --- a/tests/headers/enum_alias.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// bindgen-flags: -- -std=c++11 - -typedef unsigned char uint8_t; - -enum Bar : uint8_t { - VAL -}; diff --git a/tests/headers/enum_and_vtable_mangling.hpp b/tests/headers/enum_and_vtable_mangling.hpp deleted file mode 100644 index 3abd6a29..00000000 --- a/tests/headers/enum_and_vtable_mangling.hpp +++ /dev/null @@ -1,11 +0,0 @@ - -enum { - match, - whatever_else, -}; - -class C { - int i; -public: - virtual void match() { }; -}; diff --git a/tests/headers/enum_dupe.h b/tests/headers/enum_dupe.h deleted file mode 100644 index 6d3591d5..00000000 --- a/tests/headers/enum_dupe.h +++ /dev/null @@ -1,4 +0,0 @@ -enum Foo { - Bar = 1, - Dupe = 1 -}; diff --git a/tests/headers/enum_explicit_type.hpp b/tests/headers/enum_explicit_type.hpp deleted file mode 100644 index 78eadd40..00000000 --- a/tests/headers/enum_explicit_type.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// bindgen-flags: -- -std=c++11 - -enum Foo: unsigned char { - Bar = 0, - Qux -}; - -enum Neg: char { - MinusOne = -1, - One = 1, -}; - -enum Bigger: unsigned short { - Much = 255, - Larger -}; - -enum MuchLong: long { - MuchLow = -4294967296, -}; - -enum MuchLongLong: long long { - I64_MIN = 1ll << 63, -}; - -enum MuchULongLong: unsigned long long { - MuchHigh = 4294967296, -}; diff --git a/tests/headers/enum_negative.h b/tests/headers/enum_negative.h deleted file mode 100644 index 6cbdfe04..00000000 --- a/tests/headers/enum_negative.h +++ /dev/null @@ -1,4 +0,0 @@ -enum Foo { - Bar = -2, - Qux = 1, -}; diff --git a/tests/headers/enum_packed.h b/tests/headers/enum_packed.h deleted file mode 100644 index 8654d110..00000000 --- a/tests/headers/enum_packed.h +++ /dev/null @@ -1,14 +0,0 @@ -enum __attribute__((packed)) Foo { - Bar = 0, - Qux -}; - -enum __attribute__((packed)) Neg { - MinusOne = -1, - One = 1, -}; - -enum __attribute__((packed)) Bigger { - Much = 255, - Larger -}; diff --git a/tests/headers/extern.hpp b/tests/headers/extern.hpp deleted file mode 100644 index 0779e038..00000000 --- a/tests/headers/extern.hpp +++ /dev/null @@ -1,3 +0,0 @@ -extern "C" { -#include "func_proto.h" -} diff --git a/tests/headers/float128.hpp b/tests/headers/float128.hpp deleted file mode 100644 index f554e88e..00000000 --- a/tests/headers/float128.hpp +++ /dev/null @@ -1,13 +0,0 @@ -// FIXME: libclang < 3.9 does not expose `__float128` in its interface, so this -// test will fail. Once we remove support for `--features llvm_stable` and -// require libclang >= 3.9, we can reenable this test. -// -// static __float128 global = 1.0; - -// FIXME: We have no way to get 128 bit aligned structs in Rust at the moment, -// and therefore the generated layout tests for this struct will fail. When we -// can enforce 128 bit alignment, we can re-enable this test. -// -// struct A { -// __float128 f; -// }; diff --git a/tests/headers/forward-inherit-struct-with-fields.hpp b/tests/headers/forward-inherit-struct-with-fields.hpp deleted file mode 100644 index 437fff5d..00000000 --- a/tests/headers/forward-inherit-struct-with-fields.hpp +++ /dev/null @@ -1,8 +0,0 @@ -template class Rooted; -namespace js { - template class RootedBase { - T* foo; - Rooted* next; - }; -} -template class Rooted : js::RootedBase {}; diff --git a/tests/headers/forward-inherit-struct.hpp b/tests/headers/forward-inherit-struct.hpp deleted file mode 100644 index ac7aef5e..00000000 --- a/tests/headers/forward-inherit-struct.hpp +++ /dev/null @@ -1,5 +0,0 @@ -template class Rooted; -namespace js { - template class RootedBase {}; -} -template class Rooted : js::RootedBase {}; diff --git a/tests/headers/forward_declared_struct.h b/tests/headers/forward_declared_struct.h deleted file mode 100644 index 2a69450c..00000000 --- a/tests/headers/forward_declared_struct.h +++ /dev/null @@ -1,11 +0,0 @@ -struct a; - -struct a { - int b; -}; - -struct c { - int d; -}; - -struct c; \ No newline at end of file diff --git a/tests/headers/func_proto.h b/tests/headers/func_proto.h deleted file mode 100644 index 51139ca9..00000000 --- a/tests/headers/func_proto.h +++ /dev/null @@ -1 +0,0 @@ -typedef int foo(int bar); diff --git a/tests/headers/func_ptr.h b/tests/headers/func_ptr.h deleted file mode 100644 index a4662f3d..00000000 --- a/tests/headers/func_ptr.h +++ /dev/null @@ -1 +0,0 @@ -int (*foo) (int x, int y); diff --git a/tests/headers/func_ptr_in_struct.h b/tests/headers/func_ptr_in_struct.h deleted file mode 100644 index 988db5b3..00000000 --- a/tests/headers/func_ptr_in_struct.h +++ /dev/null @@ -1,6 +0,0 @@ - -enum baz; - -struct Foo { - enum baz (*bar) (int x, int y); -}; diff --git a/tests/headers/func_with_array_arg.h b/tests/headers/func_with_array_arg.h deleted file mode 100644 index 1b81702b..00000000 --- a/tests/headers/func_with_array_arg.h +++ /dev/null @@ -1 +0,0 @@ -void f(int x[2]); diff --git a/tests/headers/func_with_func_ptr_arg.h b/tests/headers/func_with_func_ptr_arg.h deleted file mode 100644 index 629c84ab..00000000 --- a/tests/headers/func_with_func_ptr_arg.h +++ /dev/null @@ -1 +0,0 @@ -void foo(void (*bar)()); diff --git a/tests/headers/in_class_typedef.hpp b/tests/headers/in_class_typedef.hpp deleted file mode 100644 index dda7472d..00000000 --- a/tests/headers/in_class_typedef.hpp +++ /dev/null @@ -1,10 +0,0 @@ - -template -class Foo { - typedef T elem_type; - typedef T* ptr_type; - - typedef struct Bar { - int x, y; - } Bar; -}; diff --git a/tests/headers/inherit-namespaced.hpp b/tests/headers/inherit-namespaced.hpp deleted file mode 100644 index 61eafd5a..00000000 --- a/tests/headers/inherit-namespaced.hpp +++ /dev/null @@ -1,4 +0,0 @@ -namespace js { - template class RootedBase {}; -} -template class Rooted : js::RootedBase {}; diff --git a/tests/headers/inherit_named.hpp b/tests/headers/inherit_named.hpp deleted file mode 100644 index 9881d1b6..00000000 --- a/tests/headers/inherit_named.hpp +++ /dev/null @@ -1,5 +0,0 @@ -template -class Wohoo {}; - -template -class Weeee : public T {}; diff --git a/tests/headers/inherit_typedef.hpp b/tests/headers/inherit_typedef.hpp deleted file mode 100644 index 8d699e82..00000000 --- a/tests/headers/inherit_typedef.hpp +++ /dev/null @@ -1,5 +0,0 @@ -struct Foo {}; - -typedef Foo TypedefedFoo; - -struct Bar: public TypedefedFoo {}; diff --git a/tests/headers/inner_const.hpp b/tests/headers/inner_const.hpp deleted file mode 100644 index 25c2e603..00000000 --- a/tests/headers/inner_const.hpp +++ /dev/null @@ -1,6 +0,0 @@ - -class Foo { - static int BOO; - static Foo whatever; - int bar; -}; diff --git a/tests/headers/inner_template_self.hpp b/tests/headers/inner_template_self.hpp deleted file mode 100644 index 1ae5af06..00000000 --- a/tests/headers/inner_template_self.hpp +++ /dev/null @@ -1,10 +0,0 @@ - -template -class LinkedList { - LinkedList* next; - LinkedList* prev; -}; - -class InstantiateIt { - LinkedList m_list; -}; diff --git a/tests/headers/int128_t.h b/tests/headers/int128_t.h deleted file mode 100644 index eece252c..00000000 --- a/tests/headers/int128_t.h +++ /dev/null @@ -1,7 +0,0 @@ -/** - * FIXME: Uncomment this once we can generate the proper alignment for the type, - * i.e., when we use u128/i128. -struct Foo { - __int128 foo; -}; - */ diff --git a/tests/headers/jsval_layout_opaque.hpp b/tests/headers/jsval_layout_opaque.hpp deleted file mode 100644 index 85c5be63..00000000 --- a/tests/headers/jsval_layout_opaque.hpp +++ /dev/null @@ -1,424 +0,0 @@ -// 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; - - -#define JS_PUNBOX64 -#define IS_LITTLE_ENDIAN - -/* - * Try to get jsvals 64-bit aligned. We could almost assert that all values are - * aligned, but MSVC and GCC occasionally break alignment. - */ -#if defined(__GNUC__) || defined(__xlc__) || defined(__xlC__) -# define JSVAL_ALIGNMENT __attribute__((aligned (8))) -#elif defined(_MSC_VER) - /* - * Structs can be aligned with MSVC, but not if they are used as parameters, - * so we just don't try to align. - */ -# define JSVAL_ALIGNMENT -#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) -# define JSVAL_ALIGNMENT -#elif defined(__HP_cc) || defined(__HP_aCC) -# define JSVAL_ALIGNMENT -#endif - -#if defined(JS_PUNBOX64) -# define JSVAL_TAG_SHIFT 47 -#endif - -/* - * We try to use enums so that printing a jsval_layout in the debugger shows - * nice symbolic type tags, however we can only do this when we can force the - * underlying type of the enum to be the desired size. - */ -#if !defined(__SUNPRO_CC) && !defined(__xlC__) - -#if defined(_MSC_VER) -# define JS_ENUM_HEADER(id, type) enum id : type -# define JS_ENUM_FOOTER(id) -#else -# define JS_ENUM_HEADER(id, type) enum id -# define JS_ENUM_FOOTER(id) __attribute__((packed)) -#endif - -/* Remember to propagate changes to the C defines below. */ -JS_ENUM_HEADER(JSValueType, uint8_t) -{ - JSVAL_TYPE_DOUBLE = 0x00, - JSVAL_TYPE_INT32 = 0x01, - JSVAL_TYPE_UNDEFINED = 0x02, - JSVAL_TYPE_BOOLEAN = 0x03, - JSVAL_TYPE_MAGIC = 0x04, - JSVAL_TYPE_STRING = 0x05, - JSVAL_TYPE_SYMBOL = 0x06, - JSVAL_TYPE_NULL = 0x07, - JSVAL_TYPE_OBJECT = 0x08, - - /* These never appear in a jsval; they are only provided as an out-of-band value. */ - JSVAL_TYPE_UNKNOWN = 0x20, - JSVAL_TYPE_MISSING = 0x21 -} JS_ENUM_FOOTER(JSValueType); - -static_assert(sizeof(JSValueType) == 1, - "compiler typed enum support is apparently buggy"); - -#if defined(JS_NUNBOX32) - -/* Remember to propagate changes to the C defines below. */ -JS_ENUM_HEADER(JSValueTag, uint32_t) -{ - JSVAL_TAG_CLEAR = 0xFFFFFF80, - JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32, - JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED, - JSVAL_TAG_STRING = JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING, - JSVAL_TAG_SYMBOL = JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL, - JSVAL_TAG_BOOLEAN = JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN, - JSVAL_TAG_MAGIC = JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC, - JSVAL_TAG_NULL = JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL, - JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT -} JS_ENUM_FOOTER(JSValueTag); - -static_assert(sizeof(JSValueTag) == sizeof(uint32_t), - "compiler typed enum support is apparently buggy"); - -#elif defined(JS_PUNBOX64) - -/* Remember to propagate changes to the C defines below. */ -JS_ENUM_HEADER(JSValueTag, uint32_t) -{ - JSVAL_TAG_MAX_DOUBLE = 0x1FFF0, - JSVAL_TAG_INT32 = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32, - JSVAL_TAG_UNDEFINED = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED, - JSVAL_TAG_STRING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING, - JSVAL_TAG_SYMBOL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL, - JSVAL_TAG_BOOLEAN = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN, - JSVAL_TAG_MAGIC = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC, - JSVAL_TAG_NULL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL, - JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT -} JS_ENUM_FOOTER(JSValueTag); - -static_assert(sizeof(JSValueTag) == sizeof(uint32_t), - "compiler typed enum support is apparently buggy"); - -JS_ENUM_HEADER(JSValueShiftedTag, uint64_t) -{ - JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF), - JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_SYMBOL = (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT), - JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT) -} JS_ENUM_FOOTER(JSValueShiftedTag); - -static_assert(sizeof(JSValueShiftedTag) == sizeof(uint64_t), - "compiler typed enum support is apparently buggy"); - -#endif - -/* - * All our supported compilers implement C++11 |enum Foo : T| syntax, so don't - * expose these macros. (This macro exists *only* because gcc bug 51242 - * makes bit-fields of - * typed enums trigger a warning that can't be turned off. Don't expose it - * beyond this file!) - */ -#undef JS_ENUM_HEADER -#undef JS_ENUM_FOOTER - -#else /* !defined(__SUNPRO_CC) && !defined(__xlC__) */ - -typedef uint8_t JSValueType; -#define JSVAL_TYPE_DOUBLE ((uint8_t)0x00) -#define JSVAL_TYPE_INT32 ((uint8_t)0x01) -#define JSVAL_TYPE_UNDEFINED ((uint8_t)0x02) -#define JSVAL_TYPE_BOOLEAN ((uint8_t)0x03) -#define JSVAL_TYPE_MAGIC ((uint8_t)0x04) -#define JSVAL_TYPE_STRING ((uint8_t)0x05) -#define JSVAL_TYPE_SYMBOL ((uint8_t)0x06) -#define JSVAL_TYPE_NULL ((uint8_t)0x07) -#define JSVAL_TYPE_OBJECT ((uint8_t)0x08) -#define JSVAL_TYPE_UNKNOWN ((uint8_t)0x20) - -#if defined(JS_NUNBOX32) - -typedef uint32_t JSValueTag; -#define JSVAL_TAG_CLEAR ((uint32_t)(0xFFFFFF80)) -#define JSVAL_TAG_INT32 ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32)) -#define JSVAL_TAG_UNDEFINED ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED)) -#define JSVAL_TAG_STRING ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING)) -#define JSVAL_TAG_SYMBOL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL)) -#define JSVAL_TAG_BOOLEAN ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN)) -#define JSVAL_TAG_MAGIC ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC)) -#define JSVAL_TAG_NULL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL)) -#define JSVAL_TAG_OBJECT ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT)) - -#elif defined(JS_PUNBOX64) - -typedef uint32_t JSValueTag; -#define JSVAL_TAG_MAX_DOUBLE ((uint32_t)(0x1FFF0)) -#define JSVAL_TAG_INT32 (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32) -#define JSVAL_TAG_UNDEFINED (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED) -#define JSVAL_TAG_STRING (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING) -#define JSVAL_TAG_SYMBOL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL) -#define JSVAL_TAG_BOOLEAN (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN) -#define JSVAL_TAG_MAGIC (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC) -#define JSVAL_TAG_NULL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL) -#define JSVAL_TAG_OBJECT (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT) - -typedef uint64_t JSValueShiftedTag; -#define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF) -#define JSVAL_SHIFTED_TAG_INT32 (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_STRING (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_SYMBOL (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_MAGIC (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_NULL (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT) -#define JSVAL_SHIFTED_TAG_OBJECT (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT) - -#endif /* JS_PUNBOX64 */ -#endif /* !defined(__SUNPRO_CC) && !defined(__xlC__) */ - -#if defined(JS_NUNBOX32) - -#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type))) - -#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL -#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT -#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32 -#define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING - -#elif defined(JS_PUNBOX64) - -#define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL -#define JSVAL_TAG_MASK 0xFFFF800000000000LL -#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type))) -#define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64_t)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT) - -#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL -#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT -#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32 -#define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING - -#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET JSVAL_SHIFTED_TAG_NULL -#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET JSVAL_SHIFTED_TAG_OBJECT -#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET JSVAL_SHIFTED_TAG_UNDEFINED -#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET JSVAL_SHIFTED_TAG_STRING - -#endif /* JS_PUNBOX64 */ - -typedef enum JSWhyMagic -{ - /** a hole in a native object's elements */ - JS_ELEMENTS_HOLE, - - /** there is not a pending iterator value */ - JS_NO_ITER_VALUE, - - /** exception value thrown when closing a generator */ - JS_GENERATOR_CLOSING, - - /** compiler sentinel value */ - JS_NO_CONSTANT, - - /** used in debug builds to catch tracing errors */ - JS_THIS_POISON, - - /** used in debug builds to catch tracing errors */ - JS_ARG_POISON, - - /** an empty subnode in the AST serializer */ - JS_SERIALIZE_NO_NODE, - - /** lazy arguments value on the stack */ - JS_LAZY_ARGUMENTS, - - /** optimized-away 'arguments' value */ - JS_OPTIMIZED_ARGUMENTS, - - /** magic value passed to natives to indicate construction */ - JS_IS_CONSTRUCTING, - - /** arguments.callee has been overwritten */ - JS_OVERWRITTEN_CALLEE, - - /** value of static block object slot */ - JS_BLOCK_NEEDS_CLONE, - - /** see class js::HashableValue */ - JS_HASH_KEY_EMPTY, - - /** error while running Ion code */ - JS_ION_ERROR, - - /** missing recover instruction result */ - JS_ION_BAILOUT, - - /** optimized out slot */ - JS_OPTIMIZED_OUT, - - /** uninitialized lexical bindings that produce ReferenceError on touch. */ - JS_UNINITIALIZED_LEXICAL, - - /** for local use */ - JS_GENERIC_MAGIC, - - JS_WHY_MAGIC_COUNT -} JSWhyMagic; - -#if defined(IS_LITTLE_ENDIAN) -# if defined(JS_NUNBOX32) -typedef union jsval_layout -{ - uint64_t asBits; - struct { - union { - int32_t i32; - uint32_t u32; - uint32_t boo; // Don't use |bool| -- it must be four bytes. - JSString* str; - JS::Symbol* sym; - JSObject* obj; - js::gc::Cell* cell; - void* ptr; - JSWhyMagic why; - size_t word; - uintptr_t uintptr; - } payload; - JSValueTag tag; - } s; - double asDouble; - void* asPtr; -} JSVAL_ALIGNMENT jsval_layout; -# elif defined(JS_PUNBOX64) -typedef union jsval_layout -{ - uint64_t asBits; -#if !defined(_WIN64) - /* MSVC does not pack these correctly :-( */ - struct { - uint64_t payload47 : 47; - JSValueTag tag : 17; - } debugView; -#endif - struct { - union { - int32_t i32; - uint32_t u32; - JSWhyMagic why; - } payload; - } s; - double asDouble; - void* asPtr; - size_t asWord; - uintptr_t asUIntPtr; -} JSVAL_ALIGNMENT jsval_layout; -# endif /* JS_PUNBOX64 */ -#else /* defined(IS_LITTLE_ENDIAN) */ -# if defined(JS_NUNBOX32) -typedef union jsval_layout -{ - uint64_t asBits; - struct { - JSValueTag tag; - union { - int32_t i32; - uint32_t u32; - uint32_t boo; // Don't use |bool| -- it must be four bytes. - JSString* str; - JS::Symbol* sym; - JSObject* obj; - js::gc::Cell* cell; - void* ptr; - JSWhyMagic why; - size_t word; - uintptr_t uintptr; - } payload; - } s; - double asDouble; - void* asPtr; -} JSVAL_ALIGNMENT jsval_layout; -# elif defined(JS_PUNBOX64) -typedef union jsval_layout -{ - uint64_t asBits; - struct { - JSValueTag tag : 17; - uint64_t payload47 : 47; - } debugView; - struct { - uint32_t padding; - union { - int32_t i32; - uint32_t u32; - JSWhyMagic why; - } payload; - } s; - double asDouble; - void* asPtr; - size_t asWord; - uintptr_t asUIntPtr; -} JSVAL_ALIGNMENT jsval_layout; -# endif /* JS_PUNBOX64 */ -#endif /* defined(IS_LITTLE_ENDIAN) */ - -/* - * For codesize purposes on some platforms, it's important that the - * compiler know that JS::Values constructed from constant values can be - * folded to constant bit patterns at compile time, rather than - * constructed at runtime. Doing this requires a fair amount of C++11 - * features, which are not supported on all of our compilers. Set up - * some defines and helper macros in an attempt to confine the ugliness - * here, rather than scattering it all about the file. The important - * features are: - * - * - constexpr; - * - defaulted functions; - * - C99-style designated initializers. - */ -#if defined(__clang__) -# if __has_feature(cxx_constexpr) && __has_feature(cxx_defaulted_functions) -# define JS_VALUE_IS_CONSTEXPR -# endif -#elif defined(__GNUC__) -/* - * We need 4.5 for defaulted functions, 4.6 for constexpr, 4.7 because 4.6 - * doesn't understand |(X) { .field = ... }| syntax, and 4.7.3 because - * versions prior to that have bugs in the C++ front-end that cause crashes. - */ -# if MOZ_GCC_VERSION_AT_LEAST(4, 7, 3) -# define JS_VALUE_IS_CONSTEXPR -# endif -#endif - -#if defined(JS_VALUE_IS_CONSTEXPR) -# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \ - return (jsval_layout) { .asBits = (BITS) } -# define JS_VALUE_CONSTEXPR MOZ_CONSTEXPR -# define JS_VALUE_CONSTEXPR_VAR MOZ_CONSTEXPR_VAR -#else -# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \ - jsval_layout l; \ - l.asBits = (BITS); \ - return l; -# define JS_VALUE_CONSTEXPR -# define JS_VALUE_CONSTEXPR_VAR const -#endif - -struct Value { - jsval_layout data; -}; diff --git a/tests/headers/keywords.h b/tests/headers/keywords.h deleted file mode 100644 index 8699ce5f..00000000 --- a/tests/headers/keywords.h +++ /dev/null @@ -1,49 +0,0 @@ -int u8; -int u16; -int u32; -int u64; -int i8; -int i16; -int i32; -int i64; -int f32; -int f64; -int usize; -int isize; -int as; -int box; -int crate; -int false; -int fn; -int impl; -int in; -int let; -int loop; -int match; -int mod; -int move; -int mut; -int pub; -int ref; -int self; -int Self; -int super; -int trait; -int true; -int type; -int unsafe; -int use; -int where; -int abstract; -int alignof; -int become; -int final; -int macro; -int offsetof; -int override; -int priv; -int proc; -int pure; -int unsized; -int virtual; -int yield; diff --git a/tests/headers/macro-expr-basic.h b/tests/headers/macro-expr-basic.h deleted file mode 100644 index d2de7fdf..00000000 --- a/tests/headers/macro-expr-basic.h +++ /dev/null @@ -1,14 +0,0 @@ -#define FOO 1 -#define BAR 4 -#define BAZ (FOO + BAR) - -#define MIN (1 << 63) - -#define BARR (1 << 0) -#define BAZZ ((1 << 1) + BAZ) -#define I_RAN_OUT_OF_DUMB_NAMES (BARR | BAZZ) - -/* I haz a comment */ -#define HAZ_A_COMMENT BARR - -#define HAZ_A_COMMENT_INSIDE (/* comment for real */ BARR + FOO) diff --git a/tests/headers/macro-redef.h b/tests/headers/macro-redef.h deleted file mode 100644 index 0180d2ab..00000000 --- a/tests/headers/macro-redef.h +++ /dev/null @@ -1,5 +0,0 @@ -#define FOO 4 -#define BAR (1 + FOO) -#undef FOO -#define FOO 5 -#define BAZ (1 + FOO) diff --git a/tests/headers/multiple-inherit-empty-correct-layout.hpp b/tests/headers/multiple-inherit-empty-correct-layout.hpp deleted file mode 100644 index 1e2b133a..00000000 --- a/tests/headers/multiple-inherit-empty-correct-layout.hpp +++ /dev/null @@ -1,3 +0,0 @@ -struct Foo {}; -struct Bar {}; -struct Baz : public Foo, public Bar {}; diff --git a/tests/headers/mutable.hpp b/tests/headers/mutable.hpp deleted file mode 100644 index b61a1031..00000000 --- a/tests/headers/mutable.hpp +++ /dev/null @@ -1,14 +0,0 @@ -class C { - mutable int m_member; - int m_other; -}; - -class NonCopiable { - mutable int m_member; - - ~NonCopiable() {}; -}; - -class NonCopiableWithNonCopiableMutableMember { - mutable NonCopiable m_member; -}; diff --git a/tests/headers/namespace.hpp b/tests/headers/namespace.hpp deleted file mode 100644 index 65788539..00000000 --- a/tests/headers/namespace.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces - -void top_level(); - -namespace whatever { - typedef int whatever_int_t; - - void in_whatever(); -} - -namespace { - namespace empty {} - - void foo(); - struct A { - whatever::whatever_int_t b; - public: - int lets_hope_this_works(); - }; -} - -template -class C: public A { - T m_c; - T* m_c_ptr; - T m_c_arr[10]; -}; - - -template<> -class C; - - -namespace w { - typedef unsigned int whatever_int_t; - - template - class D { - C m_c; - }; - - whatever_int_t heh(); // this should return w::whatever_int_t, and not whatever::whatever_int_t - - C foo(); - - C barr(); // <- This is the problematic one -} diff --git a/tests/headers/nested.hpp b/tests/headers/nested.hpp deleted file mode 100644 index 299e1768..00000000 --- a/tests/headers/nested.hpp +++ /dev/null @@ -1,15 +0,0 @@ - -class Calc { - int w; -}; - -class Test { -public: - struct Size; - friend struct Size; - struct Size { - struct Dimension : public Calc { - }; - Dimension mWidth, mHeight; - }; -}; diff --git a/tests/headers/nested_vtable.hpp b/tests/headers/nested_vtable.hpp deleted file mode 100644 index 87d6ce1f..00000000 --- a/tests/headers/nested_vtable.hpp +++ /dev/null @@ -1,8 +0,0 @@ -class nsISupports { -public: - virtual nsISupports* QueryInterface(); -}; - -class nsIRunnable : public nsISupports {}; - -class Runnable : public nsIRunnable {}; diff --git a/tests/headers/no-std.h b/tests/headers/no-std.h deleted file mode 100644 index 7bee9657..00000000 --- a/tests/headers/no-std.h +++ /dev/null @@ -1,5 +0,0 @@ -// bindgen-flags: --ctypes-prefix "libc" --use-core --raw-line "#![no_std]" --raw-line "mod libc { pub type c_int = i32; pub enum c_void {} }" -struct foo { - int a, b; - void* bar; -}; diff --git a/tests/headers/no_copy.hpp b/tests/headers/no_copy.hpp deleted file mode 100644 index 349e428e..00000000 --- a/tests/headers/no_copy.hpp +++ /dev/null @@ -1,6 +0,0 @@ - -/**
*/ -template -class CopiableButWait { - int whatever; -}; diff --git a/tests/headers/nsStyleAutoArray.hpp b/tests/headers/nsStyleAutoArray.hpp deleted file mode 100644 index 950152c0..00000000 --- a/tests/headers/nsStyleAutoArray.hpp +++ /dev/null @@ -1,57 +0,0 @@ - -template -class nsTArray { - T* mBuff; -}; - -template -class nsStyleAutoArray -{ -public: - // This constructor places a single element in mFirstElement. - enum WithSingleInitialElement { WITH_SINGLE_INITIAL_ELEMENT }; - explicit nsStyleAutoArray(WithSingleInitialElement) {} - nsStyleAutoArray(const nsStyleAutoArray& aOther) { *this = aOther; } - nsStyleAutoArray& operator=(const nsStyleAutoArray& aOther) { - mFirstElement = aOther.mFirstElement; - mOtherElements = aOther.mOtherElements; - return *this; - } - - bool operator==(const nsStyleAutoArray& aOther) const { - return Length() == aOther.Length() && - mFirstElement == aOther.mFirstElement && - mOtherElements == aOther.mOtherElements; - } - bool operator!=(const nsStyleAutoArray& aOther) const { - return !(*this == aOther); - } - - unsigned long Length() const { - return mOtherElements.Length() + 1; - } - const T& operator[](unsigned long aIndex) const { - return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1]; - } - T& operator[](unsigned long aIndex) { - return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1]; - } - - void EnsureLengthAtLeast(unsigned long aMinLen) { - if (aMinLen > 0) { - mOtherElements.EnsureLengthAtLeast(aMinLen - 1); - } - } - - void SetLengthNonZero(unsigned long aNewLen) { - mOtherElements.SetLength(aNewLen - 1); - } - - void TruncateLengthNonZero(unsigned long aNewLen) { - mOtherElements.TruncateLength(aNewLen - 1); - } - -private: - T mFirstElement; - nsTArray mOtherElements; -}; diff --git a/tests/headers/only_bitfields.hpp b/tests/headers/only_bitfields.hpp deleted file mode 100644 index 84db0586..00000000 --- a/tests/headers/only_bitfields.hpp +++ /dev/null @@ -1,5 +0,0 @@ -// bindgen-flags: --no-unstable-rust -class C { - bool a: 1; - bool b: 7; -}; diff --git a/tests/headers/opaque_in_struct.hpp b/tests/headers/opaque_in_struct.hpp deleted file mode 100644 index 3cffeb20..00000000 --- a/tests/headers/opaque_in_struct.hpp +++ /dev/null @@ -1,10 +0,0 @@ - - -/**
*/ -typedef struct opaque { - int waht; -} opaque; - -struct container { - opaque contained; -}; diff --git a/tests/headers/opaque_pointer.hpp b/tests/headers/opaque_pointer.hpp deleted file mode 100644 index 53f8ce1f..00000000 --- a/tests/headers/opaque_pointer.hpp +++ /dev/null @@ -1,22 +0,0 @@ - -/** - *
- */ -struct OtherOpaque { - int c; -}; - -/** - *
- */ -template -struct Opaque { - T whatever; -}; - -struct WithOpaquePtr { - Opaque* whatever; - Opaque other; - OtherOpaque t; -}; - diff --git a/tests/headers/opaque_typedef.hpp b/tests/headers/opaque_typedef.hpp deleted file mode 100644 index 25640738..00000000 --- a/tests/headers/opaque_typedef.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// bindgen-flags: -- -std=c++11 -template -class RandomTemplate; - -template -class Wat; - -template -class Wat3; - -template<> -class Wat3<3>; - -/**
*/ -typedef RandomTemplate ShouldBeOpaque; - -typedef RandomTemplate ShouldNotBeOpaque; diff --git a/tests/headers/overflowed_enum.hpp b/tests/headers/overflowed_enum.hpp deleted file mode 100644 index 1f2075a5..00000000 --- a/tests/headers/overflowed_enum.hpp +++ /dev/null @@ -1,12 +0,0 @@ -// bindgen-flags: -- -std=c++11 -Wno-narrowing - -enum Foo { - BAP_ARM = 0x93fcb9, - BAP_X86 = 0xb67eed, - BAP_X86_64 = 0xba7b274f, -}; - -enum Bar: unsigned short { - One = 1, - Big = 65538, -}; diff --git a/tests/headers/overloading.hpp b/tests/headers/overloading.hpp deleted file mode 100644 index 3c2b0487..00000000 --- a/tests/headers/overloading.hpp +++ /dev/null @@ -1,9 +0,0 @@ -extern bool Evaluate(char r); -extern bool Evaluate(int x, int y); - -namespace foo { - extern void MyFunction(); -} -namespace bar { - extern void MyFunction(); -} diff --git a/tests/headers/private.hpp b/tests/headers/private.hpp deleted file mode 100644 index c0f3ce7f..00000000 --- a/tests/headers/private.hpp +++ /dev/null @@ -1,21 +0,0 @@ - -struct HasPrivate { - int mNotPrivate; - /**
*/ - int mIsPrivate; -}; - - -/**
*/ -struct VeryPrivate { - int mIsPrivate; - int mIsAlsoPrivate; -}; - - -/**
*/ -struct ContradictPrivate { - /**
*/ - int mNotPrivate; - int mIsPrivate; -}; diff --git a/tests/headers/redeclaration.hpp b/tests/headers/redeclaration.hpp deleted file mode 100644 index d536b158..00000000 --- a/tests/headers/redeclaration.hpp +++ /dev/null @@ -1,7 +0,0 @@ -extern "C" { - void foo(); -} - -extern "C" { - void foo(); -} diff --git a/tests/headers/ref_argument_array.hpp b/tests/headers/ref_argument_array.hpp deleted file mode 100644 index dc73fd62..00000000 --- a/tests/headers/ref_argument_array.hpp +++ /dev/null @@ -1,6 +0,0 @@ - -#define NSID_LENGTH 10 -class nsID { -public: - virtual void ToProvidedString(char (&aDest)[NSID_LENGTH]) = 0; -}; diff --git a/tests/headers/replace_template_alias.hpp b/tests/headers/replace_template_alias.hpp deleted file mode 100644 index 6ceae4e5..00000000 --- a/tests/headers/replace_template_alias.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// bindgen-flags: -- --std=c++14 - -namespace JS { -namespace detail { - -/// Notice how this doesn't use T. -template -using MaybeWrapped = int; - -} - -template -class Rooted { - detail::MaybeWrapped ptr; -}; - -} - -/// But the replacement type does use T! -/// -///
-template -using replaces_MaybeWrapped = T; diff --git a/tests/headers/replaces_double.hpp b/tests/headers/replaces_double.hpp deleted file mode 100644 index 1a78b0d9..00000000 --- a/tests/headers/replaces_double.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// bindgen-flags: --blacklist-type Wrapper -- --std=c++11 - -template -struct Wrapper { - struct Wrapped { - T t; - }; - using Type = Wrapped; -}; - -template -class Rooted { - using MaybeWrapped = typename Wrapper::Type; - MaybeWrapped ptr; - - /** - *
- */ - using MaybeWrapped_simple = T; -}; diff --git a/tests/headers/size_t_template.hpp b/tests/headers/size_t_template.hpp deleted file mode 100644 index 6045c698..00000000 --- a/tests/headers/size_t_template.hpp +++ /dev/null @@ -1,8 +0,0 @@ -template -class Array { - T inner[N]; -}; - -class C { - Array arr; -}; diff --git a/tests/headers/struct_containing_forward_declared_struct.h b/tests/headers/struct_containing_forward_declared_struct.h deleted file mode 100644 index d38aca2f..00000000 --- a/tests/headers/struct_containing_forward_declared_struct.h +++ /dev/null @@ -1,7 +0,0 @@ -struct a { - struct b* val_a; -}; - -struct b { - int val_b; -}; diff --git a/tests/headers/struct_with_anon_struct.h b/tests/headers/struct_with_anon_struct.h deleted file mode 100644 index 1617d7a8..00000000 --- a/tests/headers/struct_with_anon_struct.h +++ /dev/null @@ -1,6 +0,0 @@ -struct foo { - struct { - int a; - int b; - } bar; -}; diff --git a/tests/headers/struct_with_anon_struct_array.h b/tests/headers/struct_with_anon_struct_array.h deleted file mode 100644 index 9ea977e8..00000000 --- a/tests/headers/struct_with_anon_struct_array.h +++ /dev/null @@ -1,10 +0,0 @@ -struct foo { - struct { - int a; - int b; - } bar[2]; - struct { - int a; - int b; - } baz[2][3][4]; -}; diff --git a/tests/headers/struct_with_anon_struct_pointer.h b/tests/headers/struct_with_anon_struct_pointer.h deleted file mode 100644 index 0c486d84..00000000 --- a/tests/headers/struct_with_anon_struct_pointer.h +++ /dev/null @@ -1,6 +0,0 @@ -struct foo { - struct { - int a; - int b; - } *bar; -}; diff --git a/tests/headers/struct_with_anon_union.h b/tests/headers/struct_with_anon_union.h deleted file mode 100644 index 3a92b940..00000000 --- a/tests/headers/struct_with_anon_union.h +++ /dev/null @@ -1,6 +0,0 @@ -struct foo { - union { - unsigned int a; - unsigned short b; - } bar; -}; diff --git a/tests/headers/struct_with_anon_unnamed_struct.h b/tests/headers/struct_with_anon_unnamed_struct.h deleted file mode 100644 index f8ac4225..00000000 --- a/tests/headers/struct_with_anon_unnamed_struct.h +++ /dev/null @@ -1,6 +0,0 @@ -struct foo { - struct { - unsigned int a; - unsigned int b; - }; -}; diff --git a/tests/headers/struct_with_anon_unnamed_union.h b/tests/headers/struct_with_anon_unnamed_union.h deleted file mode 100644 index 7158e727..00000000 --- a/tests/headers/struct_with_anon_unnamed_union.h +++ /dev/null @@ -1,6 +0,0 @@ -struct foo { - union { - unsigned int a; - unsigned short b; - }; -}; diff --git a/tests/headers/struct_with_bitfields.h b/tests/headers/struct_with_bitfields.h deleted file mode 100644 index 107fb136..00000000 --- a/tests/headers/struct_with_bitfields.h +++ /dev/null @@ -1,13 +0,0 @@ -// bindgen-flags: --no-unstable-rust -struct bitfield { - unsigned short - a :1, - b :1, - c :1, - :1, - :2, - d :2; - int e; - unsigned int f : 2; - unsigned int g : 32; -}; diff --git a/tests/headers/struct_with_derive_debug.h b/tests/headers/struct_with_derive_debug.h deleted file mode 100644 index 98ba1b3d..00000000 --- a/tests/headers/struct_with_derive_debug.h +++ /dev/null @@ -1,15 +0,0 @@ -struct LittleArray { - int a[32]; -}; - -struct BigArray{ - int a[33]; -}; - -struct WithLittleArray { - struct LittleArray a; -}; - -struct WithBigArray { - struct BigArray a; -}; diff --git a/tests/headers/struct_with_nesting.h b/tests/headers/struct_with_nesting.h deleted file mode 100644 index 9d7fa176..00000000 --- a/tests/headers/struct_with_nesting.h +++ /dev/null @@ -1,17 +0,0 @@ -struct foo { - unsigned int a; - union { - unsigned int b; - struct { - unsigned short c1; - unsigned short c2; - }; - - struct { - unsigned char d1; - unsigned char d2; - unsigned char d3; - unsigned char d4; - }; - }; -}; diff --git a/tests/headers/struct_with_packing.h b/tests/headers/struct_with_packing.h deleted file mode 100644 index 1b9fe131..00000000 --- a/tests/headers/struct_with_packing.h +++ /dev/null @@ -1,4 +0,0 @@ -struct a { - char b; - short c; -} __attribute__((packed)); diff --git a/tests/headers/struct_with_struct.h b/tests/headers/struct_with_struct.h deleted file mode 100644 index 78b1cc81..00000000 --- a/tests/headers/struct_with_struct.h +++ /dev/null @@ -1,6 +0,0 @@ -struct foo { - struct { - unsigned int x; - unsigned int y; - } bar; -}; diff --git a/tests/headers/struct_with_typedef_template_arg.hpp b/tests/headers/struct_with_typedef_template_arg.hpp deleted file mode 100644 index 7fed21ab..00000000 --- a/tests/headers/struct_with_typedef_template_arg.hpp +++ /dev/null @@ -1,4 +0,0 @@ -template -struct Proxy { - typedef void (*foo)(T* bar); -}; diff --git a/tests/headers/template.hpp b/tests/headers/template.hpp deleted file mode 100644 index c13643c3..00000000 --- a/tests/headers/template.hpp +++ /dev/null @@ -1,144 +0,0 @@ -template class Foo { - T m_member; - T* m_member_ptr; - T m_member_arr[1]; -}; - -void bar(Foo foo); - -template -class D { - typedef Foo MyFoo; - - MyFoo m_foo; - - template - class U { - MyFoo m_nested_foo; - Z m_baz; - }; -}; - -template -class Rooted { - T* prev; - Rooted* next; - T ptr; -}; - -class RootedContainer { - Rooted root; -}; - -template -class WithDtor; - -typedef WithDtor WithDtorIntFwd; - -template -class WithDtor { - T member; - ~WithDtor() {} -}; - -class PODButContainsDtor { - WithDtorIntFwd member; -}; - - -/**
*/ -template -class Opaque { - T member; -}; - -class POD { - Opaque opaque_member; -}; - -/** - *
- */ -template -class Nested { - T* buff; -}; - -template -class NestedBase { - T* buff; -}; - -template -class NestedReplaced: public NestedBase { -}; - -template -class Incomplete; - -template -class NestedContainer { - T c; -private: - NestedReplaced nested; - Incomplete inc; -}; - -template -class Incomplete { - T d; -}; - -class Untemplated {}; - -template -class Templated { - Untemplated m_untemplated; -}; - -/** - * 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. - * - *
- */ -template -class ReplacedWithDestructor { - T* buff; - ~ReplacedWithDestructor() {}; -}; - -template -class ReplacedWithoutDestructor { - T* buff; -}; - -template -class ReplacedWithoutDestructorFwd; - -template -class ShouldNotBeCopiable { - ReplacedWithoutDestructor m_member; -}; - -template -class ShouldNotBeCopiableAsWell { - ReplacedWithoutDestructorFwd m_member; -}; - -/** - * 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. - * - *
- */ -template -class ReplacedWithDestructorDeclaredAfter { - T* buff; - ~ReplacedWithDestructorDeclaredAfter() {}; -}; - -template -class TemplateWithVar { - static T var = 0; -}; diff --git a/tests/headers/template_alias.hpp b/tests/headers/template_alias.hpp deleted file mode 100644 index 646d9f40..00000000 --- a/tests/headers/template_alias.hpp +++ /dev/null @@ -1,13 +0,0 @@ -// bindgen-flags: -- -std=c++14 - -namespace JS { -namespace detail { - template - using Wrapped = T; -} - -template -struct Rooted { - detail::Wrapped ptr; -}; -} diff --git a/tests/headers/template_alias_basic.hpp b/tests/headers/template_alias_basic.hpp deleted file mode 100644 index 964f6e27..00000000 --- a/tests/headers/template_alias_basic.hpp +++ /dev/null @@ -1,4 +0,0 @@ -// bindgen-flags: -- -std=c++11 - -template -using Wrapped = T; diff --git a/tests/headers/template_alias_namespace.hpp b/tests/headers/template_alias_namespace.hpp deleted file mode 100644 index bd637166..00000000 --- a/tests/headers/template_alias_namespace.hpp +++ /dev/null @@ -1,13 +0,0 @@ -// bindgen-flags: --enable-cxx-namespaces -- -std=c++14 - -namespace JS { -namespace detail { - template - using Wrapped = T; -} - -template -struct Rooted { - detail::Wrapped ptr; -}; -} diff --git a/tests/headers/template_typedef_transitive_param.hpp b/tests/headers/template_typedef_transitive_param.hpp deleted file mode 100644 index 2269ac36..00000000 --- a/tests/headers/template_typedef_transitive_param.hpp +++ /dev/null @@ -1,7 +0,0 @@ -template -struct Wrapper { - struct Wrapped { - T t; - }; - using Type = Wrapped; -}; diff --git a/tests/headers/template_typedefs.hpp b/tests/headers/template_typedefs.hpp deleted file mode 100644 index 5e13dcd8..00000000 --- a/tests/headers/template_typedefs.hpp +++ /dev/null @@ -1,8 +0,0 @@ -typedef void (*foo)(int); - -template -class Foo { - typedef T Char; - typedef Char* FooPtrTypedef; - typedef bool (*nsCOMArrayEnumFunc)(T* aElement, void* aData); -}; diff --git a/tests/headers/type_alias_empty.hpp b/tests/headers/type_alias_empty.hpp deleted file mode 100644 index f0760c8f..00000000 --- a/tests/headers/type_alias_empty.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// bindgen-flags: --whitelist-type bool_constant -- -std=c++11 - -// NB: The --whitelist-type is done to trigger the traversal of the types on -// codegen in order to trigger #67. - -template -struct integral_constant {}; - -template -using bool_constant = integral_constant; diff --git a/tests/headers/typeref.hpp b/tests/headers/typeref.hpp deleted file mode 100644 index b94c98ef..00000000 --- a/tests/headers/typeref.hpp +++ /dev/null @@ -1,28 +0,0 @@ -struct nsFoo; - -namespace mozilla { - -struct FragmentOrURL { bool mIsLocalRef; }; -struct Position { }; - -} // namespace mozilla - -class Bar { - nsFoo* mFoo; -}; - -namespace mozilla { - -template -struct StyleShapeSource { - union { - Position* mPosition; - FragmentOrURL* mFragmentOrURL; - }; -}; - -} // namespace mozilla - -struct nsFoo { - mozilla::StyleShapeSource mBar; -}; diff --git a/tests/headers/union_dtor.hpp b/tests/headers/union_dtor.hpp deleted file mode 100644 index 399dc89d..00000000 --- a/tests/headers/union_dtor.hpp +++ /dev/null @@ -1,5 +0,0 @@ -union UnionWithDtor { - ~UnionWithDtor(); - int mFoo; - void* mBar; -}; diff --git a/tests/headers/union_fields.hpp b/tests/headers/union_fields.hpp deleted file mode 100644 index aec3a7fd..00000000 --- a/tests/headers/union_fields.hpp +++ /dev/null @@ -1,5 +0,0 @@ -typedef union { - int mInt; - float mFloat; - void* mPointer; -} nsStyleUnion; diff --git a/tests/headers/union_template.hpp b/tests/headers/union_template.hpp deleted file mode 100644 index 0d0a9bb3..00000000 --- a/tests/headers/union_template.hpp +++ /dev/null @@ -1,19 +0,0 @@ -template -struct NastyStruct { - bool mIsSome; - union { - void* mFoo; - unsigned long mDummy; - } mStorage; - - union { - short wat; - int* wut; - }; -}; - -template -union Whatever { - void* mTPtr; - int mInt; -}; diff --git a/tests/headers/union_with_anon_struct.h b/tests/headers/union_with_anon_struct.h deleted file mode 100644 index 7f8dec95..00000000 --- a/tests/headers/union_with_anon_struct.h +++ /dev/null @@ -1,6 +0,0 @@ -union foo { - struct { - unsigned int a; - unsigned int b; - } bar; -}; diff --git a/tests/headers/union_with_anon_struct_bitfield.h b/tests/headers/union_with_anon_struct_bitfield.h deleted file mode 100644 index 24c7dce8..00000000 --- a/tests/headers/union_with_anon_struct_bitfield.h +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --no-unstable-rust -union foo { - int a; - struct { - int b : 7; - int c : 25; - }; -}; diff --git a/tests/headers/union_with_anon_union.h b/tests/headers/union_with_anon_union.h deleted file mode 100644 index 212431b8..00000000 --- a/tests/headers/union_with_anon_union.h +++ /dev/null @@ -1,6 +0,0 @@ -union foo { - union { - unsigned int a; - unsigned short b; - } bar; -}; diff --git a/tests/headers/union_with_anon_unnamed_struct.h b/tests/headers/union_with_anon_unnamed_struct.h deleted file mode 100644 index 79558049..00000000 --- a/tests/headers/union_with_anon_unnamed_struct.h +++ /dev/null @@ -1,9 +0,0 @@ -union pixel { - unsigned int rgba; - struct { - unsigned char r; - unsigned char g; - unsigned char b; - unsigned char a; - }; -}; diff --git a/tests/headers/union_with_anon_unnamed_union.h b/tests/headers/union_with_anon_unnamed_union.h deleted file mode 100644 index 7580771a..00000000 --- a/tests/headers/union_with_anon_unnamed_union.h +++ /dev/null @@ -1,7 +0,0 @@ -union foo { - unsigned int a; - union { - unsigned short b; - unsigned char c; - }; -}; diff --git a/tests/headers/union_with_big_member.h b/tests/headers/union_with_big_member.h deleted file mode 100644 index 6347d6ca..00000000 --- a/tests/headers/union_with_big_member.h +++ /dev/null @@ -1,14 +0,0 @@ -union WithBigArray { - int a; - int b[33]; -}; - -union WithBigArray2 { - int a; - char b[33]; -}; - -union WithBigMember { - int a; - union WithBigArray b; -}; diff --git a/tests/headers/union_with_nesting.h b/tests/headers/union_with_nesting.h deleted file mode 100644 index cd907d57..00000000 --- a/tests/headers/union_with_nesting.h +++ /dev/null @@ -1,14 +0,0 @@ -union foo { - unsigned int a; - struct { - union { - unsigned short b1; - unsigned short b2; - }; - - union { - unsigned short c1; - unsigned short c2; - }; - }; -}; diff --git a/tests/headers/unknown_attr.h b/tests/headers/unknown_attr.h deleted file mode 100644 index f87e9f0b..00000000 --- a/tests/headers/unknown_attr.h +++ /dev/null @@ -1,6 +0,0 @@ -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/use-core.h b/tests/headers/use-core.h deleted file mode 100644 index 42bb10d9..00000000 --- a/tests/headers/use-core.h +++ /dev/null @@ -1,8 +0,0 @@ -// bindgen-flags: --use-core --raw-line "extern crate core;" - -struct foo { - int a, b; - void* bar; -}; - -typedef void (*fooFunction)(int bar); diff --git a/tests/headers/using.hpp b/tests/headers/using.hpp deleted file mode 100644 index ba07b9c8..00000000 --- a/tests/headers/using.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: -- -std=c++11 - -template -class Point { - T x; - T y; -}; - -typedef Point IntPoint2D; - -using IntVec2D = Point; diff --git a/tests/headers/vector.hpp b/tests/headers/vector.hpp deleted file mode 100644 index 4707f77f..00000000 --- a/tests/headers/vector.hpp +++ /dev/null @@ -1,3 +0,0 @@ -struct foo { - __attribute__((__vector_size__(1 * sizeof(long long)))) long long mMember; -}; diff --git a/tests/headers/virtual_dtor.hpp b/tests/headers/virtual_dtor.hpp deleted file mode 100644 index c35dcab1..00000000 --- a/tests/headers/virtual_dtor.hpp +++ /dev/null @@ -1,3 +0,0 @@ -struct nsSlots { - virtual ~nsSlots(); -}; diff --git a/tests/headers/virtual_overloaded.hpp b/tests/headers/virtual_overloaded.hpp deleted file mode 100644 index 8aea8a19..00000000 --- a/tests/headers/virtual_overloaded.hpp +++ /dev/null @@ -1,5 +0,0 @@ -class C { -public: - virtual void do_thing(char) { }; - virtual void do_thing(int) { }; -}; diff --git a/tests/headers/vtable_recursive_sig.hpp b/tests/headers/vtable_recursive_sig.hpp deleted file mode 100644 index 8729be00..00000000 --- a/tests/headers/vtable_recursive_sig.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// bindgen-flags: -- -std=c++11 - -class Derived; -class Base { -public: - virtual Derived* AsDerived() { return nullptr; } -}; - -class Derived final : public Base { - virtual Derived* AsDerived() override { return this; } -}; diff --git a/tests/headers/weird_bitfields.hpp b/tests/headers/weird_bitfields.hpp deleted file mode 100644 index 755681c1..00000000 --- a/tests/headers/weird_bitfields.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// bindgen-flags: --no-unstable-rust -// You can guess where this is taken from... -enum nsStyleSVGOpacitySource { - eStyleSVGOpacitySource_Normal, - eStyleSVGOpacitySource_ContextFillOpacity, - eStyleSVGOpacitySource_ContextStrokeOpacity -}; - -class Weird { - unsigned int mStrokeDasharrayLength; - unsigned int bitTest: 16; - unsigned int bitTest2: 15; - unsigned char mClipRule; // [inherited] - unsigned char mColorInterpolation; // [inherited] see nsStyleConsts.h - unsigned char mColorInterpolationFilters; // [inherited] see nsStyleConsts.h - unsigned char mFillRule; // [inherited] see nsStyleConsts.h - unsigned char mImageRendering; // [inherited] see nsStyleConsts.h - unsigned char mPaintOrder; // [inherited] see nsStyleConsts.h - unsigned char mShapeRendering; // [inherited] see nsStyleConsts.h - unsigned char mStrokeLinecap; // [inherited] see nsStyleConsts.h - unsigned char mStrokeLinejoin; // [inherited] see nsStyleConsts.h - unsigned char mTextAnchor; // [inherited] see nsStyleConsts.h - unsigned char mTextRendering; // [inherited] see nsStyleConsts.h - - // In SVG glyphs, whether we inherit fill or stroke opacity from the outer - // text object. - // Use 3 bits to avoid signedness problems in MSVC. - nsStyleSVGOpacitySource mFillOpacitySource : 3; - nsStyleSVGOpacitySource mStrokeOpacitySource : 3; - - // SVG glyph outer object inheritance for other properties - bool mStrokeDasharrayFromObject : 1; - bool mStrokeDashoffsetFromObject : 1; - bool mStrokeWidthFromObject : 1; -}; diff --git a/tests/headers/what_is_going_on.hpp b/tests/headers/what_is_going_on.hpp deleted file mode 100644 index 078c1ad5..00000000 --- a/tests/headers/what_is_going_on.hpp +++ /dev/null @@ -1,19 +0,0 @@ - -struct UnknownUnits {}; -typedef float Float; - -template -struct PointTyped { - F x; - F y; - - static PointTyped FromUnknownPoint(const PointTyped& aPoint) { - return PointTyped(aPoint.x, aPoint.y); - } - - PointTyped ToUnknownPoint() const { - return PointTyped(this->x, this->y); - } -}; - -typedef PointTyped IntPoint; diff --git a/tests/headers/whitelist_basic.hpp b/tests/headers/whitelist_basic.hpp deleted file mode 100644 index 8424f75a..00000000 --- a/tests/headers/whitelist_basic.hpp +++ /dev/null @@ -1,16 +0,0 @@ -// bindgen-flags: --whitelist-type WhitelistMe - -template -class WhitelistMe { - class Inner { - T bar; - }; - - int foo; - Inner bar; -}; - -struct DontWhitelistMe { - void* foo; - double _Complex noComplexGenerated; -}; diff --git a/tests/headers/whitelist_vars.h b/tests/headers/whitelist_vars.h deleted file mode 100644 index 07fa2815..00000000 --- a/tests/headers/whitelist_vars.h +++ /dev/null @@ -1,4 +0,0 @@ -#define NONE 0 -#define FOO 5 -#define FOOB -2 -#define FOOBAR (-10) diff --git a/tests/tests.rs b/tests/tests.rs deleted file mode 100644 index 1f72fccf..00000000 --- a/tests/tests.rs +++ /dev/null @@ -1,171 +0,0 @@ -// We add this `extern crate` here to ensure that bindgen is up-to-date and -// rebuilt, even though we aren't using any of its types or functions here, only -// indirectly calling the executable. -#[allow(dead_code)] -extern crate bindgen; - -use std::env; -use std::fs; -use std::io::Read; -use std::path::{Path, PathBuf}; -use std::process; - -const TEST_BATCH_DEFAULT_SIZE: usize = 16; - -fn spawn_run_bindgen(run_bindgen: P, - bindgen: Q, - header: R) - -> process::Child - where P: AsRef, - Q: AsRef, - R: AsRef, -{ - let run_bindgen = run_bindgen.as_ref(); - let bindgen = bindgen.as_ref(); - let header = header.as_ref(); - - // Convert from "tests/headers/foo.hpp" to "tests/expectations/tests/foo.rs" by - // saving the filename, popping off "headers/foo.hpp", pushing - // "expectations/tests", pushing the saved filename, and finally modifying the - // extension. - - let mut expected = PathBuf::from(header); - let file_name = expected.file_name() - .expect("Should have filename") - .to_os_string(); - expected.pop(); - expected.pop(); - expected.push("expectations"); - expected.push("tests"); - expected.push(file_name); - expected.set_extension("rs"); - - // And the same style conversion as above, but for the dummy uses. We assume - // that .hpp means we should generate a .cpp uses file, and .h means we - // should generate a .c file. - - let mut dummy_uses = PathBuf::from(header); - let file_name = dummy_uses.file_name() - .expect("Should still have filename") - .to_os_string(); - dummy_uses.pop(); - dummy_uses.pop(); - dummy_uses.push("uses"); - dummy_uses.push(file_name); - dummy_uses.set_extension(if header.extension().and_then(|s| s.to_str()) == - Some("hpp") { - "cpp" - } else { - "c" - }); - - process::Command::new(run_bindgen) - .stdout(process::Stdio::piped()) - .stderr(process::Stdio::piped()) - .arg(bindgen) - .arg(header) - .arg(expected) - .arg("--dummy-uses") - .arg(dummy_uses) - .spawn() - .expect("Should be able to spawn run-bindgen.py child process") -} - -#[test] -fn run_bindgen_tests() { - let crate_root = env::var("CARGO_MANIFEST_DIR") - .expect("should have CARGO_MANIFEST_DIR environment variable"); - - let mut run_bindgen = PathBuf::from(&crate_root); - run_bindgen.push("tests"); - run_bindgen.push("tools"); - run_bindgen.push("run-bindgen.py"); - - let mut bindgen = PathBuf::from(&crate_root); - bindgen.push("target"); - if cfg!(debug_assertions) { - bindgen.push("debug"); - } else { - bindgen.push("release"); - } - bindgen.push("bindgen"); - if !bindgen.is_file() { - panic!("{} is not a file! Build bindgen before running tests.", - bindgen.display()); - } - - let mut headers_dir = PathBuf::from(&crate_root); - headers_dir.push("tests"); - headers_dir.push("headers"); - - let entries = fs::read_dir(&headers_dir) - .expect("Should read directory") - .map(|result| result.expect("Should read directory entry")); - - let tests = entries.filter(|entry| { - match entry.path().extension().and_then(|s| s.to_str()) { - Some("h") | Some("hpp") => true, - _ => false, - } - }) - .collect::>(); - - let batch_size = env::var("BINDGEN_TEST_BATCH_SIZE") - .ok() - .and_then(|x| x.parse::().ok()) - .unwrap_or(TEST_BATCH_DEFAULT_SIZE); - - // Spawn `batch_size` children to run in parallel and wait on all of them - // before processing the next batch. This puts a limit on the resources - // consumed when testing, so that we don't overload the system. - - let children = tests.chunks(batch_size).map(|x| { - x.iter() - .map(|entry| { - let child = spawn_run_bindgen(run_bindgen.clone(), - bindgen.clone(), - entry.path()); - (entry.path(), child) - }) - .collect::>() - }); - - let failures: Vec<_> = children.flat_map(|x| { - x.into_iter().filter_map(|(path, mut child)| { - let passed = child.wait() - .expect("Should wait on child process") - .success(); - - if passed { None } else { Some((path, child)) } - }) - }) - .collect(); - - let num_failures = failures.len(); - - for (path, child) in failures { - println!("FAIL: {}", path.display()); - - let mut buf = String::new(); - - child.stdout - .expect("should have stdout piped") - .read_to_string(&mut buf) - .expect("should read child's stdout"); - for line in buf.lines() { - println!("child stdout> {}", line); - } - - child.stderr - .expect("should have stderr piped") - .read_to_string(&mut buf) - .expect("should read child's stderr"); - for line in buf.lines() { - println!("child stderr> {}", line); - } - } - - if num_failures > 0 { - panic!("{} test failures!", num_failures); - } -} diff --git a/tests/tools/run-bindgen.py b/tests/tools/run-bindgen.py deleted file mode 100755 index 519e6891..00000000 --- a/tests/tools/run-bindgen.py +++ /dev/null @@ -1,175 +0,0 @@ -#!/usr/bin/env python - -from __future__ import print_function - -import argparse -import difflib -import os -import sys -import subprocess -import tempfile -import shlex - -BINDGEN_FLAGS_PREFIX = "// bindgen-flags: " - -COMMON_PRELUDE = """ -#![allow(non_snake_case)] -""" - -DESCRIPTION = """ -Run bindgen on a test header and check the generated bindings against expected -output. -""" - -def make_parser(): - """Make the commandline parser""" - parser = argparse.ArgumentParser(description=DESCRIPTION) - parser.add_argument("bindgen", - metavar="BINDGEN", - help="The path to the bindgen executable") - parser.add_argument("header", - metavar="HEADER", - help="The path to the input header") - parser.add_argument("rust_bindings", - metavar="RUST_BINDINGS", - help="The path to the generated rust output. If a file \ - at this path already exists, the newly generated \ - bindings will be checked against those extant \ - expected bindings.") - parser.add_argument("--feature", - dest="features", - action="append", - nargs=1, - help="Run tests that depend on bindgen being built with \ - the given feature.") - parser.add_argument("--dummy-uses", - dest="dummy_uses", - help="The path to generate dummy C/C++ uses of the \ - whitelisted types from the input header at.") - return parser - -def usage_and_exit(*args): - """Print the program usage and exit. If args are given, print them first""" - if len(args) > 0: - print(*args) - make_parser().print_help() - sys.exit(1) - -def parse_args(): - """Get, parse, and validate commandline arguments.""" - parser = make_parser() - args = parser.parse_args() - - if args.features is None: - args.features = [] - - if not os.path.isfile(args.bindgen): - usage_and_exit("error: bindgen is not a file:", args.bindgen) - - if not os.path.isfile(args.header): - usage_and_exit("error: header is not a file:", args.header) - - return args - -def make_bindgen_env(): - """Build the environment to run bindgen in.""" - env = os.environ.copy() - env["RUST_BACKTRACE"] = "1" - - # El Capitan likes to unset dyld variables - # https://forums.developer.apple.com/thread/9233 - if "DYLD_LIBRARY_PATH" not in env and "LIBCLANG_PATH" in env: - env["DYLD_LIBRARY_PATH"] = env["LIBCLANG_PATH"] - - return env - -def get_bindgen_flags(header_path): - """ - Return the bindgen flags required for this header - """ - flags = ["--no-unstable-rust"] - for line in COMMON_PRELUDE.split("\n"): - flags.append("--raw-line") - flags.append(line) - - with open(header_path) as f: - for line in f: - if line.startswith(BINDGEN_FLAGS_PREFIX): - flags.extend(shlex.split(line.strip().split(BINDGEN_FLAGS_PREFIX)[1])) - break - - return flags - -def get_expected_bindings(rust_bindings_path): - """ - Get the expected, generated rust bindings output, or None if there is no - expected output yet. - """ - expected_bindings = None - if os.path.isfile(rust_bindings_path): - with open(rust_bindings_path) as f: - expected_bindings = f.read() - return expected_bindings - -def get_actual_bindings(rust_bindings_path): - """Get the actual generated rust bindings output.""" - assert os.path.isfile(rust_bindings_path) - with open(rust_bindings_path) as f: - return f.read() - -def run_cmd(command, **kwargs): - """Run the given command, passing through **kwargs to subprocess.check_call""" - print("run-bindgen.py: running", command) - subprocess.check_call(command, **kwargs) - -def generate_bindings(bindgen, dummy_uses, flags, header, output): - """Generate the rust bindings.""" - command = [bindgen, "-o", output] - if dummy_uses: - command.extend(["--dummy-uses", dummy_uses]) - command.extend(flags) - command.append(header) - run_cmd(command, cwd=os.getcwd(), env=make_bindgen_env()) - -def check_actual_vs_expected(expected_bindings, rust_bindings_path): - """ - Check the actual generated rust bindings versus our expected generated rust - bindings. If they don't match up, print a diff between them and exit with a - failure. - """ - if expected_bindings is None: - return - - actual_bindings = get_actual_bindings(rust_bindings_path) - if actual_bindings == expected_bindings: - return - - print("error: actual generated bindings do not match expected generated bindings!") - - def to_diffable(s): - return map(lambda l: l + "\n", s.split("\n")) - - diff = difflib.unified_diff(to_diffable(expected_bindings), - to_diffable(actual_bindings), - fromfile="expected_bindings.rs", - tofile="actual_bindings.rs") - sys.stderr.writelines(diff) - sys.stderr.write("\n") - - sys.exit(1) - -def main(): - args = parse_args() - - test_flags = get_bindgen_flags(args.header) - expected_bindings = get_expected_bindings(args.rust_bindings) - generate_bindings(args.bindgen, - args.dummy_uses, - test_flags, - args.header, - args.rust_bindings) - check_actual_vs_expected(expected_bindings, args.rust_bindings) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/tests/uses/.gitignore b/tests/uses/.gitignore deleted file mode 100644 index 40d7cb4c..00000000 --- a/tests/uses/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.c -*.cpp -- cgit v1.2.3