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
8 changes: 8 additions & 0 deletions c2rust-ast-builder/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2002,6 +2002,14 @@ impl Builder {
self.meta(Meta::Path(path))
}

pub fn abs_meta_path<Pa>(self, path: Pa) -> Meta
where
Pa: Make<Path>,
{
let path = mk().abs_path(path);
self.meta_path(path)
}

/// makes a meta item with the given path and some arguments
/// # Examples
///
Expand Down
14 changes: 5 additions & 9 deletions c2rust-transpile/src/translator/structs_unions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ impl<'a> Translation<'a> {

let mut derives = vec![];
if !contains_va_list {
derives.push("Copy");
derives.push("Clone");
derives.push(mk().meta_path("Copy"));
derives.push(mk().meta_path("Clone"));
};
let has_bitfields =
fields
Expand All @@ -82,7 +82,7 @@ impl<'a> Translation<'a> {
_ => unreachable!("Found non-field in record field list"),
});
if has_bitfields {
derives.push("BitfieldStruct");
derives.push(mk().abs_meta_path(vec!["c2rust_bitfields", "BitfieldStruct"]));
self.use_crate(ExternCrate::C2RustBitfields);
}

Expand Down Expand Up @@ -240,9 +240,7 @@ impl<'a> Translation<'a> {
/// Here we output a struct derive to generate bitfield data that looks like this:
///
/// ```no_run
/// # use c2rust_bitfields::BitfieldStruct;
/// #
/// #[derive(BitfieldStruct, Clone, Copy)]
/// #[derive(::c2rust_bitfields::BitfieldStruct, Clone, Copy)]
/// #[repr(C, align(2))]
/// struct Foo {
/// #[bitfield(name = "bf1", ty = "std::ffi::c_char", bits = "0..=9")]
Expand Down Expand Up @@ -341,9 +339,7 @@ impl<'a> Translation<'a> {
/// It looks like this in locals and (sectioned) statics:
///
/// ```no_run
/// # use c2rust_bitfields::BitfieldStruct;
/// #
/// # #[derive(BitfieldStruct, Clone, Copy)]
/// # #[derive(::c2rust_bitfields::BitfieldStruct, Clone, Copy)]
/// # #[repr(C, align(2))]
/// # struct Foo {
/// # #[bitfield(name = "bf1", ty = "std::ffi::c_char", bits = "0..=9")]
Expand Down
5 changes: 5 additions & 0 deletions c2rust-transpile/tests/snapshots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,11 @@ fn test_atomics() {
transpile("atomics.c").run();
}

#[test]
fn test_bitfields() {
transpile("bitfields.c").expect_compile_error(true).run();
}

#[test]
fn test_bool() {
transpile("bool.c").run();
Expand Down
16 changes: 16 additions & 0 deletions c2rust-transpile/tests/snapshots/bitfields.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
int printf(const char*, ...);

struct PacketHeader {
unsigned char version : 3;
unsigned char type : 2;
unsigned char flags : 3;
unsigned short sequence : 10;
unsigned short length : 6;
};

void test_bitfields(void) {
struct PacketHeader h = {0};
h.version = 5;
h.sequence = 513;
printf("version=%u sequence=%u\n", h.version, h.sequence);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
source: c2rust-transpile/tests/snapshots.rs
expression: cat tests/snapshots/bitfields.2021.rs
---
#![allow(
dead_code,
non_camel_case_types,
non_snake_case,
non_upper_case_globals,
unused_assignments,
unused_mut
)]
#![deny(unsafe_op_in_unsafe_fn)]
extern "C" {
fn printf(_: *const ::core::ffi::c_char, ...) -> ::core::ffi::c_int;
}
#[derive(Copy, Clone, ::c2rust_bitfields::BitfieldStruct)]
#[repr(C)]
pub struct PacketHeader {
#[bitfield(padding)]
pub c2rust_padding: [u8; 1],
#[bitfield(name = "version", ty = "::core::ffi::c_uchar", bits = "0..=2")]
#[bitfield(name = "type_0", ty = "::core::ffi::c_uchar", bits = "3..=4")]
#[bitfield(name = "flags", ty = "::core::ffi::c_uchar", bits = "5..=7")]
#[bitfield(name = "sequence", ty = "::core::ffi::c_ushort", bits = "16..=25")]
#[bitfield(name = "length", ty = "::core::ffi::c_ushort", bits = "26..=31")]
pub version_type_0_flags_sequence_length: [u8; 3],
}
#[no_mangle]
pub unsafe extern "C" fn test_bitfields() {
unsafe {
let mut h: PacketHeader = {
let mut init = PacketHeader {
c2rust_padding: [0; 1],
version_type_0_flags_sequence_length: [0; 3],
};
init.set_version(0 as ::core::ffi::c_uchar);
init.set_type_0(0);
init.set_flags(0);
init.set_sequence(0);
init.set_length(0);
init
};
h.set_version(5 as ::core::ffi::c_uchar as ::core::ffi::c_uchar);
h.set_sequence(513 as ::core::ffi::c_ushort as ::core::ffi::c_ushort);
printf(
b"version=%u sequence=%u\n\0".as_ptr() as *const ::core::ffi::c_char,
h.version() as ::core::ffi::c_int,
h.sequence() as ::core::ffi::c_int,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
source: c2rust-transpile/tests/snapshots.rs
expression: cat tests/snapshots/bitfields.2024.rs
---
#![allow(
dead_code,
non_camel_case_types,
non_snake_case,
non_upper_case_globals,
unused_assignments,
unused_mut
)]
#![deny(unsafe_op_in_unsafe_fn)]
unsafe extern "C" {
unsafe fn printf(_: *const ::core::ffi::c_char, ...) -> ::core::ffi::c_int;
}
#[derive(Copy, Clone, ::c2rust_bitfields::BitfieldStruct)]
#[repr(C)]
pub struct PacketHeader {
#[bitfield(padding)]
pub c2rust_padding: [u8; 1],
#[bitfield(name = "version", ty = "::core::ffi::c_uchar", bits = "0..=2")]
#[bitfield(name = "type_0", ty = "::core::ffi::c_uchar", bits = "3..=4")]
#[bitfield(name = "flags", ty = "::core::ffi::c_uchar", bits = "5..=7")]
#[bitfield(name = "sequence", ty = "::core::ffi::c_ushort", bits = "16..=25")]
#[bitfield(name = "length", ty = "::core::ffi::c_ushort", bits = "26..=31")]
pub version_type_0_flags_sequence_length: [u8; 3],
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn test_bitfields() {
unsafe {
let mut h: PacketHeader = {
let mut init = PacketHeader {
c2rust_padding: [0; 1],
version_type_0_flags_sequence_length: [0; 3],
};
init.set_version(0 as ::core::ffi::c_uchar);
init.set_type_0(0);
init.set_flags(0);
init.set_sequence(0);
init.set_length(0);
init
};
h.set_version(5 as ::core::ffi::c_uchar as ::core::ffi::c_uchar);
h.set_sequence(513 as ::core::ffi::c_ushort as ::core::ffi::c_ushort);
printf(
b"version=%u sequence=%u\n\0".as_ptr() as *const ::core::ffi::c_char,
h.version() as ::core::ffi::c_int,
h.sequence() as ::core::ffi::c_int,
);
}
}
Loading