Skip to content
Merged
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
17 changes: 15 additions & 2 deletions c2rust-transpile/src/translator/literals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,29 @@ impl<'c> Translation<'c> {

if ctx.needs_address && element_size == 1 {
// Unlike in C, Rust string literals are already references by default.
// So if the address needs to be taken, just make a bare literal.
// So if the address needs to be taken, just make a bare literal and let
// `convert_address_of_common` cast it to the appropriate type.
// Strings with element_size > 1 cannot be cast from a byte literal for
// alignment reasons, and need a transmute.
Ok(WithStmts::new_val(val))
} else {
// std::mem::transmute::<[u8; size], ctype>(*b"xxxx")
let array_ty = mk().array_ty(mk().ident_ty("u8"), mk().lit_expr(len as u128));
let val = transmute_expr(
let mut val = transmute_expr(
array_ty,
self.convert_type(ty.ctype)?,
mk().unary_expr(UnOp::Deref(Default::default()), val),
);

// A transmute creates a temporary, which cannot have its address taken without
// creating dangling pointers. Wrap it inside an inline `const` block, so that
// it will be const-promoted to 'static.
if ctx.needs_address {
self.use_feature("inline_const");
let stmts = vec![mk().expr_stmt(val)];
val = mk().const_block_expr(mk().const_block(stmts));
}

Ok(WithStmts::new_unsafe_val(val))
}
}
Expand Down
6 changes: 4 additions & 2 deletions c2rust-transpile/src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1580,8 +1580,10 @@ impl<'c> Translation<'c> {

/// Called when translation makes use of a language feature that will require a feature-gate.
pub fn use_feature(&self, feature: &'static str) {
if matches!(feature, "asm" | "label_break_value" | "raw_ref_op")
&& self.tcfg.edition >= Edition2024
if matches!(
feature,
"asm" | "inline_const" | "label_break_value" | "raw_ref_op"
) && self.tcfg.edition >= Edition2024
{
return;
}
Expand Down
12 changes: 4 additions & 8 deletions c2rust-transpile/src/translator/pointers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,11 @@ impl<'c> Translation<'c> {
}
needs_cast = true;
}
// Values that translate into temporaries can't be raw-borrowed in Rust,
// and must be regular-borrowed first.
// Borrowing in a const context will extend the lifetime to static.
// Values that translate into const temporaries can't be raw-borrowed in Rust.
// They must be regular-borrowed first, which will extend the lifetime to static.
else if arg_is_macro
|| ctx.is_const
&& matches!(
arg_expr_kind,
Some(CExprKind::Literal(..) | CExprKind::CompoundLiteral(..))
)
|| matches!(arg_expr_kind, Some(CExprKind::Literal(..)))
|| ctx.is_const && matches!(arg_expr_kind, Some(CExprKind::CompoundLiteral(..)))
{
let arg_cty_kind = &self.ast_context.resolve_type(arg_cty.ctype).kind;

Expand Down
7 changes: 2 additions & 5 deletions c2rust-transpile/tests/snapshots/os-specific/wide_strings.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@
wchar_t static_array[] = L"x";
wchar_t static_array_longer[3] = L"x";
wchar_t static_array_shorter[1] = L"xy";
// Currently broken, see #1571
// const wchar_t *static_ptr = L"x";
const wchar_t *static_ptr = L"x";

void func() {
wchar_t array[] = L"x";
wchar_t array_longer[3] = L"x";
wchar_t array_shorter[1] = L"xy";

// Currently broken, see #1571
// const wchar_t *ptr = L"x";
const wchar_t *ptr = L"x";

size_t len = wcslen(array);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ expression: cat tests/snapshots/os-specific/wide_strings.2021.linux.rs
unused_assignments,
unused_mut
)]
#![feature(raw_ref_op)]
#![feature(inline_const, raw_ref_op)]
extern "C" {
fn wcslen(__s: *const wchar_t) -> ::core::ffi::c_ulong;
}
Expand All @@ -26,12 +26,20 @@ pub static mut static_array_longer: [wchar_t; 3] =
pub static mut static_array_shorter: [wchar_t; 1] =
unsafe { ::core::mem::transmute::<[u8; 4], [wchar_t; 1]>(*b"x\0\0\0") };
#[no_mangle]
pub static mut static_ptr: *const wchar_t = unsafe {
const { ::core::mem::transmute::<[u8; 8], [::core::ffi::c_int; 2]>(*b"x\0\0\0\0\0\0\0") }
Comment thread
kkysen marked this conversation as resolved.
.as_ptr() as *const wchar_t
};
#[no_mangle]
pub unsafe extern "C" fn func() {
let mut array: [wchar_t; 2] =
::core::mem::transmute::<[u8; 8], [wchar_t; 2]>(*b"x\0\0\0\0\0\0\0");
let mut array_longer: [wchar_t; 3] =
::core::mem::transmute::<[u8; 12], [wchar_t; 3]>(*b"x\0\0\0\0\0\0\0\0\0\0\0");
let mut array_shorter: [wchar_t; 1] =
::core::mem::transmute::<[u8; 4], [wchar_t; 1]>(*b"x\0\0\0");
let mut ptr: *const wchar_t =
const { ::core::mem::transmute::<[u8; 8], [::core::ffi::c_int; 2]>(*b"x\0\0\0\0\0\0\0") }
.as_ptr() as *const wchar_t;
let mut len: size_t = wcslen(&raw mut array as *mut wchar_t) as size_t;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ expression: cat tests/snapshots/os-specific/wide_strings.2021.macos.rs
unused_assignments,
unused_mut
)]
#![feature(raw_ref_op)]
#![feature(inline_const, raw_ref_op)]
extern "C" {
fn wcslen(_: *const wchar_t) -> ::core::ffi::c_ulong;
}
Expand All @@ -28,12 +28,20 @@ pub static mut static_array_longer: [wchar_t; 3] =
pub static mut static_array_shorter: [wchar_t; 1] =
unsafe { ::core::mem::transmute::<[u8; 4], [wchar_t; 1]>(*b"x\0\0\0") };
#[no_mangle]
pub static mut static_ptr: *const wchar_t = unsafe {
const { ::core::mem::transmute::<[u8; 8], [::core::ffi::c_int; 2]>(*b"x\0\0\0\0\0\0\0") }
.as_ptr() as *const wchar_t
};
#[no_mangle]
pub unsafe extern "C" fn func() {
let mut array: [wchar_t; 2] =
::core::mem::transmute::<[u8; 8], [wchar_t; 2]>(*b"x\0\0\0\0\0\0\0");
let mut array_longer: [wchar_t; 3] =
::core::mem::transmute::<[u8; 12], [wchar_t; 3]>(*b"x\0\0\0\0\0\0\0\0\0\0\0");
let mut array_shorter: [wchar_t; 1] =
::core::mem::transmute::<[u8; 4], [wchar_t; 1]>(*b"x\0\0\0");
let mut ptr: *const wchar_t =
const { ::core::mem::transmute::<[u8; 8], [::core::ffi::c_int; 2]>(*b"x\0\0\0\0\0\0\0") }
.as_ptr() as *const wchar_t;
let mut len: size_t = wcslen(&raw mut array as *mut wchar_t) as size_t;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,20 @@ pub static mut static_array_longer: [wchar_t; 3] =
pub static mut static_array_shorter: [wchar_t; 1] =
unsafe { ::core::mem::transmute::<[u8; 4], [wchar_t; 1]>(*b"x\0\0\0") };
#[unsafe(no_mangle)]
pub static mut static_ptr: *const wchar_t = unsafe {
const { ::core::mem::transmute::<[u8; 8], [::core::ffi::c_int; 2]>(*b"x\0\0\0\0\0\0\0") }
.as_ptr() as *const wchar_t
};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn func() {
let mut array: [wchar_t; 2] =
::core::mem::transmute::<[u8; 8], [wchar_t; 2]>(*b"x\0\0\0\0\0\0\0");
let mut array_longer: [wchar_t; 3] =
::core::mem::transmute::<[u8; 12], [wchar_t; 3]>(*b"x\0\0\0\0\0\0\0\0\0\0\0");
let mut array_shorter: [wchar_t; 1] =
::core::mem::transmute::<[u8; 4], [wchar_t; 1]>(*b"x\0\0\0");
let mut ptr: *const wchar_t =
const { ::core::mem::transmute::<[u8; 8], [::core::ffi::c_int; 2]>(*b"x\0\0\0\0\0\0\0") }
.as_ptr() as *const wchar_t;
let mut len: size_t = wcslen(&raw mut array as *mut wchar_t) as size_t;
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,20 @@ pub static mut static_array_longer: [wchar_t; 3] =
pub static mut static_array_shorter: [wchar_t; 1] =
unsafe { ::core::mem::transmute::<[u8; 4], [wchar_t; 1]>(*b"x\0\0\0") };
#[unsafe(no_mangle)]
pub static mut static_ptr: *const wchar_t = unsafe {
const { ::core::mem::transmute::<[u8; 8], [::core::ffi::c_int; 2]>(*b"x\0\0\0\0\0\0\0") }
.as_ptr() as *const wchar_t
};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn func() {
let mut array: [wchar_t; 2] =
::core::mem::transmute::<[u8; 8], [wchar_t; 2]>(*b"x\0\0\0\0\0\0\0");
let mut array_longer: [wchar_t; 3] =
::core::mem::transmute::<[u8; 12], [wchar_t; 3]>(*b"x\0\0\0\0\0\0\0\0\0\0\0");
let mut array_shorter: [wchar_t; 1] =
::core::mem::transmute::<[u8; 4], [wchar_t; 1]>(*b"x\0\0\0");
let mut ptr: *const wchar_t =
const { ::core::mem::transmute::<[u8; 8], [::core::ffi::c_int; 2]>(*b"x\0\0\0\0\0\0\0") }
.as_ptr() as *const wchar_t;
let mut len: size_t = wcslen(&raw mut array as *mut wchar_t) as size_t;
}
Loading