Skip to content

Commit 2be8ad5

Browse files
committed
transpile: Properly handle address-of static compound literals
1 parent b5ef9d3 commit 2be8ad5

7 files changed

Lines changed: 81 additions & 52 deletions

c2rust-transpile/src/translator/literals.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,12 @@ impl<'c> Translation<'c> {
147147
val: CExprId,
148148
override_ty: Option<CQualTypeId>,
149149
) -> TranslationResult<WithStmts<Box<Expr>>> {
150-
if !ctx.needs_address() || ctx.is_const {
151-
// consts have their intermediates' lifetimes extended.
150+
// C compound literals are lvalues, but equivalent Rust expressions generally are not.
151+
// So if an address is needed, store it in an intermediate variable first.
152+
if !ctx.needs_address() || ctx.expanding_macro.is_some() {
152153
return self.convert_expr(ctx, val, override_ty);
153154
}
154155

155-
// C compound literals are lvalues, but equivalent Rust expressions generally are not.
156-
// So if an address is needed, store it in an intermediate variable first.
157156
let fresh_name = self.renamer.borrow_mut().fresh();
158157
let fresh_ty = self.convert_type(override_ty.unwrap_or(qty).ctype)?;
159158

@@ -162,25 +161,39 @@ impl<'c> Translation<'c> {
162161
let val = self.convert_expr(ctx.set_needs_address(false), val, override_ty)?;
163162

164163
val.and_then(|val| {
165-
let fresh_stmt = {
164+
// If we are translating a static variable,
165+
// then the fresh variable should also be static.
166+
if ctx.is_static {
167+
let item = mk().mutbl().static_item(&fresh_name, fresh_ty, val);
168+
let fresh_stmt = mk().item_stmt(item);
169+
let mut val = WithStmts::new(vec![fresh_stmt], mk().ident_expr(fresh_name));
170+
171+
// Accessing a static variable is unsafe.
172+
// In the current nightly, this applies also to taking a raw pointer,
173+
// but this requirement was removed in later versions of the
174+
// `raw_ref_op` feature.
175+
if self.tcfg.edition < Edition2024 {
176+
val.set_unsafe();
177+
}
178+
179+
Ok(val)
180+
} else {
166181
let mutbl = if qty.qualifiers.is_const {
167182
Mutability::Immutable
168183
} else {
169184
Mutability::Mutable
170185
};
171-
172186
let local = mk().local(
173187
mk().set_mutbl(mutbl).ident_pat(&fresh_name),
174188
Some(fresh_ty),
175189
Some(val),
176190
);
177-
mk().local_stmt(Box::new(local))
178-
};
179-
180-
Ok(WithStmts::new(
181-
vec![fresh_stmt],
182-
mk().ident_expr(fresh_name),
183-
))
191+
let fresh_stmt = mk().local_stmt(Box::new(local));
192+
Ok(WithStmts::new(
193+
vec![fresh_stmt],
194+
mk().ident_expr(fresh_name),
195+
))
196+
}
184197
})
185198
}
186199

c2rust-transpile/src/translator/pointers.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,7 @@ impl<'c> Translation<'c> {
144144
// and must be regular-borrowed first.
145145
// Borrowing in a const context will extend the lifetime to static.
146146
else if arg_is_macro
147-
|| ctx.is_const
148-
&& matches!(
149-
arg_expr_kind,
150-
Some(CExprKind::Literal(..) | CExprKind::CompoundLiteral(..))
151-
)
147+
|| ctx.is_const && matches!(arg_expr_kind, Some(CExprKind::Literal(..)))
152148
{
153149
let arg_cty_kind = &self.ast_context.resolve_type(arg_cty.ctype).kind;
154150

c2rust-transpile/src/with_stmts.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ impl<T> WithStmts<T> {
1717
is_unsafe: false,
1818
}
1919
}
20+
21+
pub fn new_unsafe(stmts: Vec<Stmt>, val: T) -> Self {
22+
WithStmts {
23+
stmts,
24+
val,
25+
is_unsafe: true,
26+
}
27+
}
28+
2029
pub fn new_val(val: T) -> Self {
2130
WithStmts {
2231
stmts: vec![],

c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.2021.snap

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,22 @@ expression: cat tests/snapshots/compound_literals.2021.rs
1414
#![feature(raw_ref_op)]
1515
#[no_mangle]
1616
pub static mut static_single_int: ::core::ffi::c_int = 42;
17+
static mut c2rust_fresh0: ::core::ffi::c_int = 42;
1718
#[no_mangle]
1819
pub static mut static_single_int_ptr: *mut ::core::ffi::c_int =
19-
&42 as *const ::core::ffi::c_int as *mut ::core::ffi::c_int;
20+
unsafe { &raw const c2rust_fresh0 as *mut ::core::ffi::c_int };
21+
static mut c2rust_fresh1: [::core::ffi::c_int; 2] = [42, 9001];
2022
#[no_mangle]
2123
pub static mut static_int_ptr_to_array: *mut ::core::ffi::c_int =
22-
[42, 9001].as_ptr() as *mut ::core::ffi::c_int;
24+
unsafe { &raw const c2rust_fresh1 as *mut ::core::ffi::c_int };
25+
static mut c2rust_fresh2: [::core::ffi::c_int; 2] = [42, 9001];
2326
#[no_mangle]
2427
pub static mut static_volatile_int_ptr_to_array: *mut ::core::ffi::c_int =
25-
[42, 9001].as_ptr() as *mut ::core::ffi::c_int as *mut ::core::ffi::c_int;
28+
unsafe { &raw const c2rust_fresh2 as *mut ::core::ffi::c_int as *mut ::core::ffi::c_int };
29+
static mut c2rust_fresh3: [::core::ffi::c_int; 2] = [42, 9001];
2630
#[no_mangle]
2731
pub static mut static_int_array_ptr: *mut [::core::ffi::c_int; 2] =
28-
&[42, 9001] as *const [::core::ffi::c_int; 2] as *mut [::core::ffi::c_int; 2];
32+
unsafe { &raw const c2rust_fresh3 as *mut [::core::ffi::c_int; 2] };
2933
pub const SINGLE_INT: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
3034
pub const INT_ARRAY: [::core::ffi::c_int; 2] =
3135
[42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int];
@@ -35,22 +39,22 @@ pub const CHAR_ARRAY: [::core::ffi::c_char; 6] =
3539
pub unsafe extern "C" fn local_compound_literals() {
3640
unsafe {
3741
let mut single_int: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
38-
let mut c2rust_fresh0: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
39-
let mut single_int_ptr: *mut ::core::ffi::c_int = &raw mut c2rust_fresh0;
40-
let mut c2rust_fresh1: [::core::ffi::c_int; 2] =
42+
let mut c2rust_fresh4: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
43+
let mut single_int_ptr: *mut ::core::ffi::c_int = &raw mut c2rust_fresh4;
44+
let mut c2rust_fresh5: [::core::ffi::c_int; 2] =
4145
[42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int];
4246
let mut int_ptr_to_array: *mut ::core::ffi::c_int =
43-
&raw mut c2rust_fresh1 as *mut ::core::ffi::c_int;
44-
let mut c2rust_fresh2: [::core::ffi::c_char; 6] =
47+
&raw mut c2rust_fresh5 as *mut ::core::ffi::c_int;
48+
let mut c2rust_fresh6: [::core::ffi::c_char; 6] =
4549
::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0");
4650
let mut char_ptr_to_array: *mut ::core::ffi::c_char =
47-
&raw mut c2rust_fresh2 as *mut ::core::ffi::c_char;
48-
let mut c2rust_fresh3: [::core::ffi::c_int; 2] =
51+
&raw mut c2rust_fresh6 as *mut ::core::ffi::c_char;
52+
let mut c2rust_fresh7: [::core::ffi::c_int; 2] =
4953
[42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int];
50-
let mut int_array_ptr: *mut [::core::ffi::c_int; 2] = &raw mut c2rust_fresh3;
51-
let mut c2rust_fresh4: [::core::ffi::c_char; 6] =
54+
let mut int_array_ptr: *mut [::core::ffi::c_int; 2] = &raw mut c2rust_fresh7;
55+
let mut c2rust_fresh8: [::core::ffi::c_char; 6] =
5256
::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0");
53-
let mut char_array_ptr: *mut [::core::ffi::c_char; 6] = &raw mut c2rust_fresh4;
57+
let mut char_array_ptr: *mut [::core::ffi::c_char; 6] = &raw mut c2rust_fresh8;
5458
let mut macro_single_int: ::core::ffi::c_int = SINGLE_INT;
5559
let mut macro_single_int_ptr: *mut ::core::ffi::c_int =
5660
&mut SINGLE_INT as *mut ::core::ffi::c_int;

c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.2024.snap

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,22 @@ expression: cat tests/snapshots/compound_literals.2024.rs
1313
#![deny(unsafe_op_in_unsafe_fn)]
1414
#[unsafe(no_mangle)]
1515
pub static mut static_single_int: ::core::ffi::c_int = 42;
16+
static mut c2rust_fresh0: ::core::ffi::c_int = 42;
1617
#[unsafe(no_mangle)]
1718
pub static mut static_single_int_ptr: *mut ::core::ffi::c_int =
18-
&42 as *const ::core::ffi::c_int as *mut ::core::ffi::c_int;
19+
&raw const c2rust_fresh0 as *mut ::core::ffi::c_int ;
20+
static mut c2rust_fresh1: [::core::ffi::c_int; 2] = [42, 9001];
1921
#[unsafe(no_mangle)]
2022
pub static mut static_int_ptr_to_array: *mut ::core::ffi::c_int =
21-
[42, 9001].as_ptr() as *mut ::core::ffi::c_int;
23+
&raw const c2rust_fresh1 as *mut ::core::ffi::c_int;
24+
static mut c2rust_fresh2: [::core::ffi::c_int; 2] = [42, 9001];
2225
#[unsafe(no_mangle)]
2326
pub static mut static_volatile_int_ptr_to_array: *mut ::core::ffi::c_int =
24-
[42, 9001].as_ptr() as *mut ::core::ffi::c_int as *mut ::core::ffi::c_int;
27+
&raw const c2rust_fresh2 as *mut ::core::ffi::c_int as *mut ::core::ffi::c_int;
28+
static mut c2rust_fresh3: [::core::ffi::c_int; 2] = [42, 9001];
2529
#[unsafe(no_mangle)]
2630
pub static mut static_int_array_ptr: *mut [::core::ffi::c_int; 2] =
27-
&[42, 9001] as *const [::core::ffi::c_int; 2] as *mut [::core::ffi::c_int; 2];
31+
&raw const c2rust_fresh3 as *mut [::core::ffi::c_int; 2];
2832
pub const SINGLE_INT: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
2933
pub const INT_ARRAY: [::core::ffi::c_int; 2] =
3034
[42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int];
@@ -34,22 +38,22 @@ pub const CHAR_ARRAY: [::core::ffi::c_char; 6] =
3438
pub unsafe extern "C" fn local_compound_literals() {
3539
unsafe {
3640
let mut single_int: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
37-
let mut c2rust_fresh0: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
38-
let mut single_int_ptr: *mut ::core::ffi::c_int = &raw mut c2rust_fresh0;
39-
let mut c2rust_fresh1: [::core::ffi::c_int; 2] =
41+
let mut c2rust_fresh4: ::core::ffi::c_int = 42 as ::core::ffi::c_int;
42+
let mut single_int_ptr: *mut ::core::ffi::c_int = &raw mut c2rust_fresh4;
43+
let mut c2rust_fresh5: [::core::ffi::c_int; 2] =
4044
[42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int];
4145
let mut int_ptr_to_array: *mut ::core::ffi::c_int =
42-
&raw mut c2rust_fresh1 as *mut ::core::ffi::c_int;
43-
let mut c2rust_fresh2: [::core::ffi::c_char; 6] =
46+
&raw mut c2rust_fresh5 as *mut ::core::ffi::c_int;
47+
let mut c2rust_fresh6: [::core::ffi::c_char; 6] =
4448
::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0");
4549
let mut char_ptr_to_array: *mut ::core::ffi::c_char =
46-
&raw mut c2rust_fresh2 as *mut ::core::ffi::c_char;
47-
let mut c2rust_fresh3: [::core::ffi::c_int; 2] =
50+
&raw mut c2rust_fresh6 as *mut ::core::ffi::c_char;
51+
let mut c2rust_fresh7: [::core::ffi::c_int; 2] =
4852
[42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int];
49-
let mut int_array_ptr: *mut [::core::ffi::c_int; 2] = &raw mut c2rust_fresh3;
50-
let mut c2rust_fresh4: [::core::ffi::c_char; 6] =
53+
let mut int_array_ptr: *mut [::core::ffi::c_int; 2] = &raw mut c2rust_fresh7;
54+
let mut c2rust_fresh8: [::core::ffi::c_char; 6] =
5155
::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0");
52-
let mut char_array_ptr: *mut [::core::ffi::c_char; 6] = &raw mut c2rust_fresh4;
56+
let mut char_array_ptr: *mut [::core::ffi::c_char; 6] = &raw mut c2rust_fresh8;
5357
let mut macro_single_int: ::core::ffi::c_int = SINGLE_INT;
5458
let mut macro_single_int_ptr: *mut ::core::ffi::c_int =
5559
&mut SINGLE_INT as *mut ::core::ffi::c_int;

c2rust-transpile/tests/snapshots/snapshots__transpile@empty_init.c.2021.snap

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ expression: cat tests/snapshots/empty_init.2021.rs
1111
unused_mut
1212
)]
1313
#![deny(unsafe_op_in_unsafe_fn)]
14+
#![feature(raw_ref_op)]
1415
#[derive(Copy, Clone)]
1516
#[repr(C)]
1617
pub struct Scope {
1718
pub next: *mut Scope,
1819
}
19-
#[no_mangle]
20-
pub static mut scope: *mut Scope = &Scope {
20+
static mut c2rust_fresh0: Scope = Scope {
2121
next: ::core::ptr::null::<Scope>() as *mut Scope,
22-
} as *const Scope as *mut Scope;
22+
};
23+
#[no_mangle]
24+
pub static mut scope: *mut Scope = unsafe { &raw const c2rust_fresh0 as *mut Scope };

c2rust-transpile/tests/snapshots/snapshots__transpile@empty_init.c.2024.snap

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ expression: cat tests/snapshots/empty_init.2024.rs
1616
pub struct Scope {
1717
pub next: *mut Scope,
1818
}
19-
#[unsafe(no_mangle)]
20-
pub static mut scope: *mut Scope = &Scope {
19+
static mut c2rust_fresh0: Scope = Scope {
2120
next: ::core::ptr::null::<Scope>() as *mut Scope,
22-
} as *const Scope as *mut Scope;
21+
};
22+
#[unsafe(no_mangle)]
23+
pub static mut scope: *mut Scope = &raw const c2rust_fresh0 as *mut Scope;

0 commit comments

Comments
 (0)