Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions hs-bindgen/fixtures/globals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/* automatically generated by rust-bindgen 0.71.1 */

unsafe extern "C" {
/// Global variables
pub static mut simpleGlobal: ::std::os::raw::c_int;
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct config {
pub x: ::std::os::raw::c_int,
pub y: ::std::os::raw::c_int,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of config"][::std::mem::size_of::<config>() - 8usize];
["Alignment of config"][::std::mem::align_of::<config>() - 4usize];
["Offset of field: config::x"][::std::mem::offset_of!(config, x) - 0usize];
["Offset of field: config::y"][::std::mem::offset_of!(config, y) - 4usize];
};
unsafe extern "C" {
pub static mut compoundGlobal1: config;
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct inline_struct {
pub x: ::std::os::raw::c_int,
pub y: ::std::os::raw::c_int,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of inline_struct"][::std::mem::size_of::<inline_struct>() - 8usize];
["Alignment of inline_struct"][::std::mem::align_of::<inline_struct>() - 4usize];
[
"Offset of field: inline_struct::x",
][::std::mem::offset_of!(inline_struct, x) - 0usize];
[
"Offset of field: inline_struct::y",
][::std::mem::offset_of!(inline_struct, y) - 4usize];
};
unsafe extern "C" {
pub static mut compoundGlobal2: inline_struct;
}
/** Non-extern non-static global variables

These kinds of variables need to be treated with care, to avoid duplicate
symbols, but do exist in the wild.

We test with various kinds of initializers as we must explicitly ignore them
in our parser. The list here roughly follows the definition of `CXCursor`
[1], starting at `CXCursor_IntegerLiteral`; see also definition of 'varDecl'
in `HsBindgen.Frontend.Pass.Parse.Decl`.

[1]: https://clang.llvm.org/doxygen/group__CINDEX.html#gaaccc432245b4cd9f2d470913f9ef0013*/
pub const nesInteger: ::std::os::raw::c_int = 1;
pub const nesFloating: f32 = 1.2000000476837158;
pub const nesString1: &[u8; 3] = b"hi\0";
pub const nesString2: &[u8; 3] = b"hi\0";
pub const nesCharacter: ::std::os::raw::c_char = 97;
pub const nesParen: ::std::os::raw::c_int = 1;
pub const nesUnary: ::std::os::raw::c_int = 5;
pub const nesBinary: ::std::os::raw::c_int = 3;
pub const nesConditional: ::std::os::raw::c_int = 2;
pub const nesCast: f32 = 1.0;
unsafe extern "C" {
pub static mut nesCompound: *mut ::std::os::raw::c_int;
}
unsafe extern "C" {
pub static mut nesInitList: [u8; 4usize];
}
pub const nesBool: bool = true;
unsafe extern "C" {
/** Additional examples of global variables, abstracted from real examples

The `streamBinary`/`streamBinary_len` example comes from [1], and is an
example of a non-extern non-static global (indeed, the header does not even
use @pragma once@ or similar).

[1]: https://github.com/analogdevicesinc/no-OS/blob/855c4b3c34f2297865e448661ba4fcc0931bf430/drivers/rf-transceiver/talise/firmware/talise_stream_binary.h#L322-L325*/
pub static mut streamBinary: [u8; 4096usize];
}
pub const streamBinary_len: u32 = 4096;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct version_t {
pub major: u8,
pub minor: u16,
pub patch: u8,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of version_t"][::std::mem::size_of::<version_t>() - 6usize];
["Alignment of version_t"][::std::mem::align_of::<version_t>() - 2usize];
[
"Offset of field: version_t::major",
][::std::mem::offset_of!(version_t, major) - 0usize];
[
"Offset of field: version_t::minor",
][::std::mem::offset_of!(version_t, minor) - 2usize];
[
"Offset of field: version_t::patch",
][::std::mem::offset_of!(version_t, patch) - 4usize];
};
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct struct1_t {
pub x: u16,
pub y: bool,
pub version: version_t,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of struct1_t"][::std::mem::size_of::<struct1_t>() - 10usize];
["Alignment of struct1_t"][::std::mem::align_of::<struct1_t>() - 2usize];
["Offset of field: struct1_t::x"][::std::mem::offset_of!(struct1_t, x) - 0usize];
["Offset of field: struct1_t::y"][::std::mem::offset_of!(struct1_t, y) - 2usize];
[
"Offset of field: struct1_t::version",
][::std::mem::offset_of!(struct1_t, version) - 4usize];
};
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct struct2_t {
pub field1: struct1_t,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of struct2_t"][::std::mem::size_of::<struct2_t>() - 10usize];
["Alignment of struct2_t"][::std::mem::align_of::<struct2_t>() - 2usize];
[
"Offset of field: struct2_t::field1",
][::std::mem::offset_of!(struct2_t, field1) - 0usize];
};
unsafe extern "C" {
pub static mut some_global_struct: struct2_t;
}
/** Error cases

NOTE: We test the error for thread_local separately (as it requires C23).*/
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _bindgen_ty_1 {
pub x: ::std::os::raw::c_int,
pub y: ::std::os::raw::c_int,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of _bindgen_ty_1"][::std::mem::size_of::<_bindgen_ty_1>() - 8usize];
["Alignment of _bindgen_ty_1"][::std::mem::align_of::<_bindgen_ty_1>() - 4usize];
[
"Offset of field: _bindgen_ty_1::x",
][::std::mem::offset_of!(_bindgen_ty_1, x) - 0usize];
[
"Offset of field: _bindgen_ty_1::y",
][::std::mem::offset_of!(_bindgen_ty_1, y) - 4usize];
};
unsafe extern "C" {
pub static mut unusableAnon: _bindgen_ty_1;
}
66 changes: 31 additions & 35 deletions hs-bindgen/test/hs-bindgen/Test/HsBindgen/Golden.hs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,37 @@ testCases = [
Just $ Expected ()
_otherwise ->
Nothing
, let declsWithWarnings :: [DeclId]
declsWithWarnings = [
-- non-extern non-static globals
"nesInteger"
, "nesFloating"
, "nesString1"
, "nesString2"
, "nesCharacter"
, "nesParen"
, "nesUnary"
, "nesBinary"
, "nesConditional"
, "nesCast"
, "nesCompound"
, "nesInitList"
, "nesBool"
, "streamBinary"
, "streamBinary_len"
, "some_global_struct"
-- Other warnings
, "unusableAnon"
]
in (defaultTest "globals") {
testTracePredicate = customTracePredicate' declsWithWarnings $ \case
TraceFrontend (FrontendParse (PotentialDuplicateGlobal info)) ->
Just $ Expected (C.declId info)
TraceFrontend (FrontendParse (UnexpectedAnonInExtern info)) ->
Just $ Expected (C.declId info)
_otherwise ->
Nothing
}
, testTraceCustom "skip_over_long_double" ["fun1", "struct1"] $ \case
TraceFrontend (FrontendParse (UnsupportedType info UnsupportedLongDouble)) ->
Just $ Expected $ C.declId info
Expand Down Expand Up @@ -243,41 +274,6 @@ testCases = [
Nothing
, testRustBindgen = RustBindgenFail
}
, let declsWithWarnings :: [DeclId]
declsWithWarnings = [
-- non-extern non-static globals
"nesInteger"
, "nesFloating"
, "nesString1"
, "nesString2"
, "nesCharacter"
, "nesParen"
, "nesUnary"
, "nesBinary"
, "nesConditional"
, "nesCast"
, "nesCompound"
, "nesInitList"
, "nesBool"
, "streamBinary"
, "streamBinary_len"
, "some_global_struct"
-- Other warnings
, "unusableAnon"
]
in (defaultTest "globals") {
-- Getting different output from (the same version of) rust-bindgen
-- for this test on CI than locally. Unsure why, compiled against
-- different llvm version? For now we just disable it.
testRustBindgen = RustBindgenIgnore
, testTracePredicate = customTracePredicate' declsWithWarnings $ \case
TraceFrontend (FrontendParse (PotentialDuplicateGlobal info)) ->
Just $ Expected (C.declId info)
TraceFrontend (FrontendParse (UnexpectedAnonInExtern info)) ->
Just $ Expected (C.declId info)
_otherwise ->
Nothing
}
, (defaultTest "macro_strings") {
testRustBindgen = RustBindgenFail
}
Expand Down
Loading