Skip to content

Commit 12dfbc7

Browse files
Ruafw-immunant
authored andcommitted
transpile: Use literal directly when taking address of string literal
1 parent df75627 commit 12dfbc7

File tree

2 files changed

+51
-8
lines changed

2 files changed

+51
-8
lines changed

c2rust-transpile/src/translator/operators.rs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -938,10 +938,10 @@ impl<'c> Translation<'c> {
938938
// In this translation, there are only pointers to functions and
939939
// & becomes a no-op when applied to a function.
940940

941-
let arg = self.convert_expr(ctx.used().set_needs_address(true), arg, None)?;
941+
let val = self.convert_expr(ctx.used().set_needs_address(true), arg, None)?;
942942

943943
if self.ast_context.is_function_pointer(ctype) {
944-
Ok(arg.map(|x| mk().call_expr(mk().ident_expr("Some"), vec![x])))
944+
Ok(val.map(|x| mk().call_expr(mk().ident_expr("Some"), vec![x])))
945945
} else {
946946
let pointee_ty =
947947
self.ast_context
@@ -950,13 +950,57 @@ impl<'c> Translation<'c> {
950950
TranslationError::generic("Address-of should return a pointer")
951951
})?;
952952

953+
let expr_kind = &self.ast_context.index(arg).kind;
954+
let translate_as_macro = self
955+
.convert_const_macro_expansion(ctx, arg, None)
956+
.ok()
957+
.flatten()
958+
.is_some();
959+
960+
// String literals are translated with a transmute, which produces a temporary.
961+
// Taking the address of a temporary leaves a dangling pointer. So instead,
962+
// cast the string literal directly so that its 'static lifetime is preserved.
963+
if let (
964+
&CExprKind::Literal(
965+
literal_cqual_type,
966+
CLiteral::String(ref bytes, element_size @ 1),
967+
),
968+
false,
969+
) = (expr_kind, translate_as_macro)
970+
{
971+
let num_elems =
972+
match self.ast_context.resolve_type(literal_cqual_type.ctype).kind {
973+
CTypeKind::ConstantArray(_, num_elems) => num_elems,
974+
ref kind => {
975+
panic!(
976+
"String literal with unknown size: {bytes:?}, kind = {kind:?}"
977+
)
978+
}
979+
};
980+
981+
// Match the literal size to the expected size padding with zeros as needed
982+
let size = num_elems * (element_size as usize);
983+
let mut bytes_padded = Vec::with_capacity(size);
984+
bytes_padded.extend(bytes);
985+
bytes_padded.resize(size, 0);
986+
987+
let array_ty = mk().array_ty(
988+
mk().ident_ty("u8"),
989+
mk().lit_expr(bytes_padded.len() as u128),
990+
);
991+
let bytes_literal = mk().lit_expr(bytes_padded);
992+
let val = mk().cast_expr(bytes_literal, mk().ptr_ty(array_ty));
993+
let val = mk().cast_expr(val, ty);
994+
return Ok(WithStmts::new_val(val));
995+
}
996+
953997
let mutbl = if pointee_ty.qualifiers.is_const {
954998
Mutability::Immutable
955999
} else {
9561000
Mutability::Mutable
9571001
};
9581002

959-
arg.result_map(|a| {
1003+
val.result_map(|a| {
9601004
let mut addr_of_arg: Box<Expr>;
9611005

9621006
if ctx.is_static {

c2rust-transpile/tests/snapshots/[email protected]

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,12 @@ pub unsafe extern "C" fn entry() {
8686
let mut const_char_lit_ptr: *const ::core::ffi::c_char =
8787
b"abc\0" as *const u8 as *const ::core::ffi::c_char;
8888
let mut const_char_lit_array_ptr: *const [::core::ffi::c_char; 4] =
89-
&::core::mem::transmute::<[u8; 4], [::core::ffi::c_char; 4]>(*b"abc\0")
90-
as *const [::core::ffi::c_char; 4];
89+
b"abc\0" as *const [u8; 4] as *const [::core::ffi::c_char; 4];
9190
let mut char_lit_ptr: *mut ::core::ffi::c_char =
9291
b"abc\0" as *const u8 as *const ::core::ffi::c_char as *mut ::core::ffi::c_char;
93-
let mut char_lit_array_ptr: *mut [::core::ffi::c_char; 4] =
94-
&::core::mem::transmute::<[u8; 4], [::core::ffi::c_char; 4]>(*b"abc\0")
95-
as *const [::core::ffi::c_char; 4] as *mut [::core::ffi::c_char; 4];
92+
let mut char_lit_array_ptr: *mut [::core::ffi::c_char; 4] = b"abc\0" as *const [u8; 4]
93+
as *const [::core::ffi::c_char; 4]
94+
as *mut [::core::ffi::c_char; 4];
9695
let mut past_end: *mut ::core::ffi::c_char = &mut *simple
9796
.as_mut_ptr()
9897
.offset(::core::mem::size_of::<[::core::ffi::c_char; 9]>() as isize)

0 commit comments

Comments
 (0)