diff --git a/c2rust-ast-builder/src/builder.rs b/c2rust-ast-builder/src/builder.rs index 80fe27608d..6e0df772aa 100644 --- a/c2rust-ast-builder/src/builder.rs +++ b/c2rust-ast-builder/src/builder.rs @@ -10,7 +10,7 @@ use syn::{__private::ToTokens, punctuated::Punctuated, *}; pub mod properties { use proc_macro2::Span; - use syn::{StaticMutability, Token}; + use syn::{PointerMutability, StaticMutability, Token}; pub trait ToToken { type Token; @@ -34,6 +34,13 @@ pub mod properties { } impl Mutability { + pub fn to_pointer_mutability(&self, span: Span) -> PointerMutability { + match self { + Mutability::Mutable => PointerMutability::Mut(Token![mut](span)), + Mutability::Immutable => PointerMutability::Const(Token![const](span)), + } + } + pub fn to_static_mutability(&self, span: Span) -> StaticMutability { match self { Mutability::Mutable => StaticMutability::Mut(Token![mut](span)), @@ -837,7 +844,7 @@ impl Builder { self.path_expr(vec![name]) } - pub fn addr_of_expr(self, e: Box) -> Box { + pub fn borrow_expr(self, e: Box) -> Box { Box::new(parenthesize_if_necessary(Expr::Reference(ExprReference { attrs: self.attrs, and_token: Token![&](self.span), @@ -846,6 +853,16 @@ impl Builder { }))) } + pub fn raw_borrow_expr(self, e: Box) -> Box { + Box::new(parenthesize_if_necessary(Expr::RawAddr(ExprRawAddr { + attrs: self.attrs, + and_token: Token![&](self.span), + raw: Token![raw](self.span), + mutability: self.mutbl.to_pointer_mutability(self.span), + expr: e, + }))) + } + pub fn mac_expr(self, mac: Macro) -> Box { Box::new(Expr::Macro(ExprMacro { attrs: self.attrs, diff --git a/c2rust-transpile/src/rust_ast/set_span.rs b/c2rust-transpile/src/rust_ast/set_span.rs index 8848e02070..2763865b0f 100644 --- a/c2rust-transpile/src/rust_ast/set_span.rs +++ b/c2rust-transpile/src/rust_ast/set_span.rs @@ -140,6 +140,7 @@ impl SetSpan for Expr { RangeLimits::Closed(mut r) => r.spans[0] = s, RangeLimits::HalfOpen(mut r) => r.spans[0] = s, }, + Expr::RawAddr(e) => e.and_token.span = s, Expr::Reference(e) => e.and_token.span = s, Expr::Return(e) => e.return_token.span = s, Expr::Try(e) => e.question_token.span = s, diff --git a/c2rust-transpile/src/translator/assembly.rs b/c2rust-transpile/src/translator/assembly.rs index c5a91a3a3e..35270421dc 100644 --- a/c2rust-transpile/src/translator/assembly.rs +++ b/c2rust-transpile/src/translator/assembly.rs @@ -883,7 +883,7 @@ impl<'c> Translation<'c> { // c2rust-ast-exporter added it (there's no gcc equivalent); // in this case, we need to do what clang does and pass in // the operand by-address instead of by-value - out_expr = mk().mutbl().addr_of_expr(out_expr); + out_expr = mk().mutbl().borrow_expr(out_expr); } if let Some(_tied_operand) = tied_operands.get(&(output_idx, true)) { @@ -900,7 +900,7 @@ impl<'c> Translation<'c> { let output_local = mk().local( mk().ident_pat(&output_name), None, - Some(mk().mutbl().addr_of_expr(out_expr)), + Some(mk().mutbl().borrow_expr(out_expr)), ); stmts.push(mk().local_stmt(Box::new(output_local))); @@ -924,7 +924,7 @@ impl<'c> Translation<'c> { let mut in_expr = in_expr.into_value(); if operand.mem_only { - in_expr = mk().addr_of_expr(in_expr); + in_expr = mk().borrow_expr(in_expr); } if let Some(tied_operand) = tied_operands.get(&(input_idx, false)) { self.use_crate(ExternCrate::C2RustAsmCasts); diff --git a/c2rust-transpile/src/translator/mod.rs b/c2rust-transpile/src/translator/mod.rs index 1123c08314..233664068e 100644 --- a/c2rust-transpile/src/translator/mod.rs +++ b/c2rust-transpile/src/translator/mod.rs @@ -3082,7 +3082,7 @@ impl<'c> Translation<'c> { } } _ => { - let addr_lhs = mk().set_mutbl(mutbl).addr_of_expr(lhs); + let addr_lhs = mk().set_mutbl(mutbl).borrow_expr(lhs); let lhs_type = self.convert_type(lhs_type.ctype)?; let ty = mk().set_mutbl(mutbl).ptr_ty(lhs_type); diff --git a/c2rust-transpile/src/translator/pointers.rs b/c2rust-transpile/src/translator/pointers.rs index 0cf669cdb9..87f6fca067 100644 --- a/c2rust-transpile/src/translator/pointers.rs +++ b/c2rust-transpile/src/translator/pointers.rs @@ -142,7 +142,17 @@ impl<'c> Translation<'c> { Some(mk().array_ty(mk().ident_ty("u8"), mk().lit_expr(len as u128))); } needs_cast = true; - } else { + } + // Values that translate into temporaries can't be raw-borrowed in Rust, + // and must be regular-borrowed first. + // Borrowing in a static/const context will extend the lifetime to static. + else if arg_is_macro + || ctx.is_static + && matches!( + arg_expr_kind, + Some(CExprKind::Literal(..) | CExprKind::CompoundLiteral(..)) + ) + { let arg_cty_kind = &self.ast_context.resolve_type(arg_cty.ctype).kind; if is_array_decay { @@ -160,7 +170,7 @@ impl<'c> Translation<'c> { needs_cast = true; } } else { - val = val.map(|val| mk().set_mutbl(mutbl).addr_of_expr(val)); + val = val.map(|val| mk().set_mutbl(mutbl).borrow_expr(val)); // Add an intermediate reference-to-pointer cast if the context needs // reference-to-pointer decay, or if another cast follows. @@ -168,6 +178,15 @@ impl<'c> Translation<'c> { ref_cast_pointee_ty = Some(self.convert_pointee_type(arg_cty.ctype)?); } } + } else { + self.use_feature("raw_ref_op"); + val = val.map(|val| mk().set_mutbl(mutbl).raw_borrow_expr(val)); + + if is_array_decay { + // TODO: Call `ptr::as_[mut]_ptr` instead once that is available. + // (`array_ptr_get` feature added to nightly in January 2024) + needs_cast = true; + } } // Perform an intermediate reference-to-pointer cast if needed. diff --git a/c2rust-transpile/tests/snapshots/ref_ub.c b/c2rust-transpile/tests/snapshots/ref_ub.c new file mode 100644 index 0000000000..33666dd80e --- /dev/null +++ b/c2rust-transpile/tests/snapshots/ref_ub.c @@ -0,0 +1,17 @@ +// From #301. + +typedef struct { + int len; +} Foo; + +void dec(Foo* f) { + f->len--; +} + +int main() { + Foo f = {5}; + Foo *fp = &f; + dec(fp); + f.len = 6; + dec(fp); +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@vm_x86.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@vm_x86.c.snap index 93ec6e4056..b0b1a88287 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@vm_x86.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@vm_x86.c.snap @@ -11,6 +11,7 @@ input_file: c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c unused_assignments, unused_mut )] +#![feature(raw_ref_op)] #[derive(Copy, Clone)] #[repr(C)] pub struct vm_t { @@ -52,8 +53,8 @@ pub unsafe extern "C" fn VM_CallCompiled( *(image.offset(programStack as isize) as *mut byte as *mut ::core::ffi::c_int) = -(1 as ::core::ffi::c_int); entryPoint = (*vm).codeBase.offset((*vm).entryOfs as isize); - opStack = - (stack.as_mut_ptr() as *mut ::core::ffi::c_int).offset(16 as ::core::ffi::c_int as isize); + opStack = (&raw mut stack as *mut byte as *mut ::core::ffi::c_int) + .offset(16 as ::core::ffi::c_int as isize); *opStack = 0 as ::core::ffi::c_int; opStackOfs = 0 as ::core::ffi::c_int; if opStackOfs != 1 as ::core::ffi::c_int diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64-linux@varargs.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64-linux@varargs.c.snap index 1daffe5f4d..389f3a6141 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64-linux@varargs.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64-linux@varargs.c.snap @@ -11,7 +11,7 @@ input_file: c2rust-transpile/tests/snapshots/arch-os-specific/varargs.c unused_assignments, unused_mut )] -#![feature(c_variadic)] +#![feature(c_variadic, raw_ref_op)] extern "C" { fn printf(__format: *const ::core::ffi::c_char, ...) -> ::core::ffi::c_int; fn vprintf( @@ -129,8 +129,8 @@ pub unsafe extern "C" fn valist_struct_pointer_member( let mut b: vastruct = vastruct { args: ::core::mem::MaybeUninit::uninit().assume_init(), }; - let mut p: *mut vastruct = &mut a; - let mut q: *mut vastruct = &mut b; + let mut p: *mut vastruct = &raw mut a; + let mut q: *mut vastruct = &raw mut b; (*p).args = args.clone(); (*q).args = (*p).args.clone(); vprintf(fmt, (*p).args.as_va_list()); @@ -156,7 +156,7 @@ pub unsafe extern "C" fn borrowed_valist(mut count: size_t, mut args: ...) { let mut ap: ::core::ffi::VaListImpl; ap = args.clone(); while count > 0 as size_t { - print_int(&mut ap); + print_int(&raw mut ap); count = count.wrapping_sub(1); } } diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@vm_x86.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@vm_x86.c.snap index 8ba9494b2b..b38469f35d 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@vm_x86.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@vm_x86.c.snap @@ -11,7 +11,7 @@ input_file: c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c unused_assignments, unused_mut )] -#![feature(asm)] +#![feature(asm, raw_ref_op)] use ::core::arch::asm; #[derive(Copy, Clone)] #[repr(C)] @@ -54,8 +54,8 @@ pub unsafe extern "C" fn VM_CallCompiled( *(image.offset(programStack as isize) as *mut byte as *mut ::core::ffi::c_int) = -(1 as ::core::ffi::c_int); entryPoint = (*vm).codeBase.offset((*vm).entryOfs as isize); - opStack = - (stack.as_mut_ptr() as *mut ::core::ffi::c_int).offset(16 as ::core::ffi::c_int as isize); + opStack = (&raw mut stack as *mut byte as *mut ::core::ffi::c_int) + .offset(16 as ::core::ffi::c_int as isize); *opStack = 0 as ::core::ffi::c_int; opStackOfs = 0 as ::core::ffi::c_int; asm!( diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.snap index 3aa753c54b..176bdb42fc 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.snap @@ -11,6 +11,7 @@ input_file: c2rust-transpile/tests/snapshots/arrays.c unused_assignments, unused_mut )] +#![feature(raw_ref_op)] #[derive(Copy, Clone)] #[repr(C)] pub struct C2RustUnnamed { @@ -42,7 +43,7 @@ pub static mut static_char_ptr: *mut ::core::ffi::c_char = b"mystring\0" as *const u8 as *const ::core::ffi::c_char as *mut ::core::ffi::c_char; #[no_mangle] pub static mut static_void_ptr: *mut ::core::ffi::c_void = - unsafe { static_char_array.as_ptr() as *mut ::core::ffi::c_char as *mut ::core::ffi::c_void }; + unsafe { &raw const static_char_array as *mut ::core::ffi::c_char as *mut ::core::ffi::c_void }; #[no_mangle] pub unsafe extern "C" fn entry() { let mut int_2d: [[::core::ffi::c_int; 1]; 1] = [[1 as ::core::ffi::c_int]]; @@ -84,10 +85,12 @@ pub unsafe extern "C" fn entry() { ::core::mem::transmute::<[u8; 20], [::core::ffi::c_char; 20]>( *b"abc\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", ); - let mut int_var_ptr: *mut ::core::ffi::c_int = int_empty_init.as_mut_ptr(); - let mut int_var_array_ptr: *mut [::core::ffi::c_int; 16] = &mut int_empty_init; - let mut char_var_ptr: *mut ::core::ffi::c_char = char_with_string.as_mut_ptr(); - let mut char_var_array_ptr: *mut [::core::ffi::c_char; 4] = &mut char_with_string; + let mut int_var_ptr: *mut ::core::ffi::c_int = + &raw mut int_empty_init as *mut ::core::ffi::c_int; + let mut int_var_array_ptr: *mut [::core::ffi::c_int; 16] = &raw mut int_empty_init; + let mut char_var_ptr: *mut ::core::ffi::c_char = + &raw mut char_with_string as *mut ::core::ffi::c_char; + let mut char_var_array_ptr: *mut [::core::ffi::c_char; 4] = &raw mut char_with_string; let mut const_char_lit_ptr: *const ::core::ffi::c_char = b"abc\0" as *const u8 as *const ::core::ffi::c_char; let mut const_char_lit_array_ptr: *const [::core::ffi::c_char; 4] = @@ -97,8 +100,8 @@ pub unsafe extern "C" fn entry() { let mut char_lit_array_ptr: *mut [::core::ffi::c_char; 4] = b"abc\0" as *const [u8; 4] as *const [::core::ffi::c_char; 4] as *mut [::core::ffi::c_char; 4]; - let mut past_end: *mut ::core::ffi::c_char = static_char_array - .as_mut_ptr() + let mut past_end: *mut ::core::ffi::c_char = (&raw mut static_char_array + as *mut ::core::ffi::c_char) .offset(::core::mem::size_of::<[::core::ffi::c_char; 9]>() as isize) as *mut ::core::ffi::c_char; past_end = static_char_ptr.offset(8 as ::core::ffi::c_int as isize) as *mut ::core::ffi::c_char; diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@atomics.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@atomics.c.snap index 55f16d88b9..7a9af1db0e 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@atomics.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@atomics.c.snap @@ -11,28 +11,29 @@ input_file: c2rust-transpile/tests/snapshots/atomics.c unused_assignments, unused_mut )] -#![feature(core_intrinsics)] +#![feature(core_intrinsics, raw_ref_op)] #[no_mangle] pub unsafe extern "C" fn c11_atomics(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { - *&mut x = 0 as ::core::ffi::c_int; - ::core::intrinsics::atomic_store_seqcst(&mut x, 1 as ::core::ffi::c_int); - ::core::intrinsics::atomic_load_seqcst(&mut x); - ::core::intrinsics::atomic_xadd_seqcst(&mut x, 2 as ::core::ffi::c_int); - ::core::intrinsics::atomic_xsub_seqcst(&mut x, 1 as ::core::ffi::c_int); - ::core::intrinsics::atomic_and_seqcst(&mut x, 0xf as ::core::ffi::c_int); - ::core::intrinsics::atomic_or_seqcst(&mut x, 0x10 as ::core::ffi::c_int); - ::core::intrinsics::atomic_nand_seqcst(&mut x, 0xff as ::core::ffi::c_int); - ::core::intrinsics::atomic_xchg_seqcst(&mut x, 42 as ::core::ffi::c_int); + *&raw mut x = 0 as ::core::ffi::c_int; + ::core::intrinsics::atomic_store_seqcst(&raw mut x, 1 as ::core::ffi::c_int); + ::core::intrinsics::atomic_load_seqcst(&raw mut x); + ::core::intrinsics::atomic_xadd_seqcst(&raw mut x, 2 as ::core::ffi::c_int); + ::core::intrinsics::atomic_xsub_seqcst(&raw mut x, 1 as ::core::ffi::c_int); + ::core::intrinsics::atomic_and_seqcst(&raw mut x, 0xf as ::core::ffi::c_int); + ::core::intrinsics::atomic_or_seqcst(&raw mut x, 0x10 as ::core::ffi::c_int); + ::core::intrinsics::atomic_nand_seqcst(&raw mut x, 0xff as ::core::ffi::c_int); + ::core::intrinsics::atomic_xchg_seqcst(&raw mut x, 42 as ::core::ffi::c_int); let mut expected: ::core::ffi::c_int = 42 as ::core::ffi::c_int; let mut desired: ::core::ffi::c_int = 100 as ::core::ffi::c_int; - let fresh0 = ::core::intrinsics::atomic_cxchg_seqcst_seqcst(&mut x, *&mut expected, desired); - *&mut expected = fresh0.0; + let fresh0 = + ::core::intrinsics::atomic_cxchg_seqcst_seqcst(&raw mut x, *&raw mut expected, desired); + *&raw mut expected = fresh0.0; fresh0.1; expected = 100 as ::core::ffi::c_int; desired = 200 as ::core::ffi::c_int; let fresh1 = - ::core::intrinsics::atomic_cxchgweak_seqcst_seqcst(&mut x, *&mut expected, desired); - *&mut expected = fresh1.0; + ::core::intrinsics::atomic_cxchgweak_seqcst_seqcst(&raw mut x, *&raw mut expected, desired); + *&raw mut expected = fresh1.0; fresh1.1; return x; } diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.snap index a6f885b418..e3e2dd2a7a 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.snap @@ -11,6 +11,7 @@ input_file: c2rust-transpile/tests/snapshots/compound_literals.c unused_assignments, unused_mut )] +#![feature(raw_ref_op)] #[no_mangle] pub static mut static_single_int: ::core::ffi::c_int = 42; #[no_mangle] @@ -34,21 +35,20 @@ pub const CHAR_ARRAY: [::core::ffi::c_char; 6] = pub unsafe extern "C" fn local_compound_literals() { let mut single_int: ::core::ffi::c_int = 42 as ::core::ffi::c_int; let mut fresh0: ::core::ffi::c_int = 42 as ::core::ffi::c_int; - let mut single_int_ptr: *mut ::core::ffi::c_int = &mut fresh0 as *mut ::core::ffi::c_int; + let mut single_int_ptr: *mut ::core::ffi::c_int = &raw mut fresh0; let mut fresh1: [::core::ffi::c_int; 2] = [42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int]; - let mut int_ptr_to_array: *mut ::core::ffi::c_int = fresh1.as_mut_ptr(); + let mut int_ptr_to_array: *mut ::core::ffi::c_int = &raw mut fresh1 as *mut ::core::ffi::c_int; let mut fresh2: [::core::ffi::c_char; 6] = ::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0"); - let mut char_ptr_to_array: *mut ::core::ffi::c_char = fresh2.as_mut_ptr(); + let mut char_ptr_to_array: *mut ::core::ffi::c_char = + &raw mut fresh2 as *mut ::core::ffi::c_char; let mut fresh3: [::core::ffi::c_int; 2] = [42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int]; - let mut int_array_ptr: *mut [::core::ffi::c_int; 2] = - &mut fresh3 as *mut [::core::ffi::c_int; 2]; + let mut int_array_ptr: *mut [::core::ffi::c_int; 2] = &raw mut fresh3; let mut fresh4: [::core::ffi::c_char; 6] = ::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0"); - let mut char_array_ptr: *mut [::core::ffi::c_char; 6] = - &mut fresh4 as *mut [::core::ffi::c_char; 6]; + let mut char_array_ptr: *mut [::core::ffi::c_char; 6] = &raw mut fresh4; let mut macro_single_int: ::core::ffi::c_int = SINGLE_INT; let mut macro_single_int_ptr: *mut ::core::ffi::c_int = &mut SINGLE_INT as *mut ::core::ffi::c_int; diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.snap index 5e2e44e91c..f12633c170 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.snap @@ -11,6 +11,7 @@ input_file: c2rust-transpile/tests/snapshots/exprs.c unused_assignments, unused_mut )] +#![feature(raw_ref_op)] extern "C" { fn puts(str: *const ::core::ffi::c_char) -> ::core::ffi::c_int; } @@ -29,7 +30,7 @@ pub unsafe extern "C" fn unary_without_side_effect() { i; !i; (i == 0) as ::core::ffi::c_int; - &mut i; + &raw mut i; i; i += 1; i -= 1; diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap index 65880ed297..7c053d88b6 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap @@ -11,6 +11,7 @@ input_file: c2rust-transpile/tests/snapshots/macros.c unused_assignments, unused_mut )] +#![feature(raw_ref_op)] extern "C" { fn extern_fn() -> ::core::ffi::c_int; } @@ -370,7 +371,7 @@ pub static mut fns: fn_ptrs = { init }; #[no_mangle] -pub static mut p: *const fn_ptrs = unsafe { &fns }; +pub static mut p: *const fn_ptrs = unsafe { &raw const fns }; pub const ZSTD_WINDOWLOG_MAX_32: ::core::ffi::c_int = 30 as ::core::ffi::c_int; pub const ZSTD_WINDOWLOG_MAX_64: ::core::ffi::c_int = 31 as ::core::ffi::c_int; #[no_mangle] @@ -384,7 +385,7 @@ pub unsafe extern "C" fn test_zstd() -> U64 { #[no_mangle] pub unsafe extern "C" fn stmt_expr_inc() -> ::core::ffi::c_int { let mut a: ::core::ffi::c_int = 0 as ::core::ffi::c_int; - let mut b: *mut ::core::ffi::c_int = &mut a; + let mut b: *mut ::core::ffi::c_int = &raw mut a; ({ *b += 1; *b; diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@ref_ub.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@ref_ub.c.snap new file mode 100644 index 0000000000..e35f8f0a5d --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@ref_ub.c.snap @@ -0,0 +1,39 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/ref_ub.rs +input_file: c2rust-transpile/tests/snapshots/ref_ub.c +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#![feature(raw_ref_op)] +#[derive(Copy, Clone)] +#[repr(C)] +pub struct Foo { + pub len: ::core::ffi::c_int, +} +#[no_mangle] +pub unsafe extern "C" fn dec(mut f: *mut Foo) { + (*f).len -= 1; +} +unsafe fn main_0() -> ::core::ffi::c_int { + let mut f: Foo = { + let mut init = Foo { + len: 5 as ::core::ffi::c_int, + }; + init + }; + let mut fp: *mut Foo = &raw mut f; + dec(fp); + f.len = 6 as ::core::ffi::c_int; + dec(fp); + return 0; +} +pub fn main() { + unsafe { ::std::process::exit(main_0() as i32) } +} diff --git a/tests/unit/arrays/src/test_arrays.rs b/tests/unit/arrays/src/test_arrays.rs index 82479cf867..e71b408651 100644 --- a/tests/unit/arrays/src/test_arrays.rs +++ b/tests/unit/arrays/src/test_arrays.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::arrays::rust_entry; use crate::incomplete_arrays::{rust_check_some_ints, rust_entry2, rust_test_sized_array}; use crate::variable_arrays::{rust_alloca_arrays, rust_variable_arrays}; diff --git a/tests/unit/builtins/src/test_builtins.rs b/tests/unit/builtins/src/test_builtins.rs index de82132ba6..b552f86309 100644 --- a/tests/unit/builtins/src/test_builtins.rs +++ b/tests/unit/builtins/src/test_builtins.rs @@ -1,4 +1,4 @@ -//! feature_core_intrinsics +//! feature_core_intrinsics, feature_raw_ref_op use crate::alloca::rust_alloca_hello; use crate::atomics::{rust_atomics_entry, rust_new_atomics}; diff --git a/tests/unit/casts/src/test_casts.rs b/tests/unit/casts/src/test_casts.rs index bad9ccd9dc..1d13d37c97 100644 --- a/tests/unit/casts/src/test_casts.rs +++ b/tests/unit/casts/src/test_casts.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::cast_funptr::{rust_entry, rust_get_identity, rust_identity}; use crate::casts::rust_cast_stuff; diff --git a/tests/unit/conditionals/src/test_conditionals.rs b/tests/unit/conditionals/src/test_conditionals.rs index 2353217677..d18af7666e 100644 --- a/tests/unit/conditionals/src/test_conditionals.rs +++ b/tests/unit/conditionals/src/test_conditionals.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::binary_conditional::rust_entry3; use crate::conditional::rust_entry; use crate::conditionals::{rust_entry2, rust_ternaries}; diff --git a/tests/unit/ints/src/test_arithmetic.rs b/tests/unit/ints/src/test_arithmetic.rs index dc3397271a..2cb0a61bd7 100644 --- a/tests/unit/ints/src/test_arithmetic.rs +++ b/tests/unit/ints/src/test_arithmetic.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::arithmetic::rust_entry2; use std::ffi::{c_int, c_uint}; diff --git a/tests/unit/items/src/test_varargs.rs b/tests/unit/items/src/test_varargs.rs index d373bb9127..ddcc8fdbb8 100644 --- a/tests/unit/items/src/test_varargs.rs +++ b/tests/unit/items/src/test_varargs.rs @@ -1,4 +1,4 @@ -//! feature_c_variadic, +//! feature_c_variadic, feature_raw_ref_op use crate::varargs::rust_call_printf; // See #1281. Varargs don't yet work on aarch64. diff --git a/tests/unit/macros/src/test_define.rs b/tests/unit/macros/src/test_define.rs index 9a38fd724a..39d37ae4cd 100644 --- a/tests/unit/macros/src/test_define.rs +++ b/tests/unit/macros/src/test_define.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::define::{rust_fns, rust_stmt_expr_inc}; use crate::define::{rust_reference_define, TEST_CONST1, TEST_CONST2, TEST_PARENS}; use crate::define::{rust_test_zstd, ZSTD_WINDOWLOG_MAX_32, ZSTD_WINDOWLOG_MAX_64}; diff --git a/tests/unit/misc/src/test_exprs.rs b/tests/unit/misc/src/test_exprs.rs index 04555acbda..32e66235d0 100644 --- a/tests/unit/misc/src/test_exprs.rs +++ b/tests/unit/misc/src/test_exprs.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::exprs::rust_exprs; use std::ffi::{c_int, c_uint}; diff --git a/tests/unit/misc/src/test_quicksort.rs b/tests/unit/misc/src/test_quicksort.rs index d5a09a0ecc..c06da72a8c 100644 --- a/tests/unit/misc/src/test_quicksort.rs +++ b/tests/unit/misc/src/test_quicksort.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::qsort::{rust_partition, rust_quickSort, rust_swap}; use std::ffi::c_int; diff --git a/tests/unit/misc/src/test_sizeofs.rs b/tests/unit/misc/src/test_sizeofs.rs index 262235100b..88840d15d3 100644 --- a/tests/unit/misc/src/test_sizeofs.rs +++ b/tests/unit/misc/src/test_sizeofs.rs @@ -1,4 +1,4 @@ -//! feature_core_intrinsics, feature_label_break_value +//! feature_core_intrinsics, feature_label_break_value, feature_raw_ref_op use crate::sizeofs::rust_sizeofs; use std::ffi::{c_int, c_uint}; diff --git a/tests/unit/misc/src/test_typedef.rs b/tests/unit/misc/src/test_typedef.rs index 812e209f4d..be9f5f2e3f 100644 --- a/tests/unit/misc/src/test_typedef.rs +++ b/tests/unit/misc/src/test_typedef.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::typedef::{int_ptr, my_int, rust_entry}; use std::ffi::c_int; diff --git a/tests/unit/misc/src/test_uninitialized.rs b/tests/unit/misc/src/test_uninitialized.rs index 005aac15ac..390ac74b95 100644 --- a/tests/unit/misc/src/test_uninitialized.rs +++ b/tests/unit/misc/src/test_uninitialized.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::uninitialized::{bar, baz, e, foo, rust_entry2, s, /*myint, myintp,*/ u}; use std::ffi::{c_int, c_uint}; diff --git a/tests/unit/pointers/src/test_pointers.rs b/tests/unit/pointers/src/test_pointers.rs index 7793e48477..6a95f04988 100644 --- a/tests/unit/pointers/src/test_pointers.rs +++ b/tests/unit/pointers/src/test_pointers.rs @@ -1,4 +1,4 @@ -//! feature_c_variadic +//! feature_c_variadic, feature_raw_ref_op use crate::function_pointers::rust_entry3; use crate::pointer_arith::rust_entry2; diff --git a/tests/unit/statics/src/test_sections.rs b/tests/unit/statics/src/test_sections.rs index f6f8860019..964183f83e 100644 --- a/tests/unit/statics/src/test_sections.rs +++ b/tests/unit/statics/src/test_sections.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + #[cfg(not(target_os = "macos"))] use crate::attributes::{rust_no_attrs, rust_used_static, rust_used_static2, rust_used_static3}; use crate::sections::*; diff --git a/tests/unit/structs/src/test_flex_array_members.rs b/tests/unit/structs/src/test_flex_array_members.rs index a679bd2dc4..ec28c5fa28 100644 --- a/tests/unit/structs/src/test_flex_array_members.rs +++ b/tests/unit/structs/src/test_flex_array_members.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::flex_array_members::rust_exercise_flex_arrays; use std::ffi::{c_int, c_uint}; diff --git a/tests/unit/structs/src/test_struct_with_exp.rs b/tests/unit/structs/src/test_struct_with_exp.rs index 18f8a47567..0d9ffb464b 100644 --- a/tests/unit/structs/src/test_struct_with_exp.rs +++ b/tests/unit/structs/src/test_struct_with_exp.rs @@ -1,3 +1,5 @@ +//! feature_raw_ref_op + use crate::struct_with_exp::rust_struct_with_exp; use std::ffi::{c_int, c_uint};