diff --git a/c2rust-ast-builder/src/builder.rs b/c2rust-ast-builder/src/builder.rs index 89bc092b2c..98c270ebd9 100644 --- a/c2rust-ast-builder/src/builder.rs +++ b/c2rust-ast-builder/src/builder.rs @@ -17,7 +17,7 @@ pub mod properties { fn to_token(&self) -> Option; } - #[derive(Debug, Copy, Clone)] + #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Mutability { Mutable, Immutable, diff --git a/c2rust-transpile/src/c_ast/mod.rs b/c2rust-transpile/src/c_ast/mod.rs index 0cbfdca7bd..b348d98e0f 100644 --- a/c2rust-transpile/src/c_ast/mod.rs +++ b/c2rust-transpile/src/c_ast/mod.rs @@ -3186,6 +3186,25 @@ impl CTypeKind { }; Some(ty) } + + /// Return the element type of a pointer or array + pub(crate) fn array_element_type(&self) -> Option { + Some(match *self { + Self::ConstantArray(ty, _) => ty, + Self::IncompleteArray(ty) => ty, + Self::VariableArray(ty, _) => ty, + _ => return None, + }) + } + + pub(crate) fn array_element_type_mut(&mut self) -> Option<&mut CTypeId> { + Some(match self { + Self::ConstantArray(ty, _) => ty, + Self::IncompleteArray(ty) => ty, + Self::VariableArray(ty, _) => ty, + _ => return None, + }) + } } impl Display for CTypeKind { diff --git a/c2rust-transpile/src/translator/functions.rs b/c2rust-transpile/src/translator/functions.rs index e423e49610..c507a2181e 100644 --- a/c2rust-transpile/src/translator/functions.rs +++ b/c2rust-transpile/src/translator/functions.rs @@ -356,7 +356,7 @@ impl<'c> Translation<'c> { pub fn convert_function_call( &self, - mut ctx: ExprContext, + ctx: ExprContext, func: CExprId, args: &[CExprId], call_expr_ty: CQualTypeId, @@ -447,9 +447,6 @@ impl<'c> Translation<'c> { }; let call = func.and_then_try(|func| { - // We want to decay refs only when function is variadic - ctx.decay_ref = DecayRef::from(is_variadic); - let args = self.convert_call_args(ctx.used(), args, arg_tys.as_deref(), is_variadic)?; let call_expr = args.map(|args| mk().call_expr(func, args)); diff --git a/c2rust-transpile/src/translator/literals.rs b/c2rust-transpile/src/translator/literals.rs index 7483a053dd..0a4eaf7539 100644 --- a/c2rust-transpile/src/translator/literals.rs +++ b/c2rust-transpile/src/translator/literals.rs @@ -194,9 +194,13 @@ impl<'c> Translation<'c> { val: CExprId, override_ty: Option, ) -> TranslationResult>> { + if !qty.qualifiers.is_const && ctx.expanding_macro.is_some() { + return Err("mutable lvalues are not supported inside macros".into()); + } + // C compound literals are lvalues, but equivalent Rust expressions generally are not. // So if an address is needed, store it in an intermediate variable first. - if !ctx.needs_address || !ctx.is_used() || ctx.expanding_macro.is_some() { + if !ctx.needs_address || !ctx.is_used() { return self.convert_expr(ctx.not_needs_address(), val, override_ty); } diff --git a/c2rust-transpile/src/translator/mod.rs b/c2rust-transpile/src/translator/mod.rs index 8fb6f5b95c..80ca5e9e3e 100644 --- a/c2rust-transpile/src/translator/mod.rs +++ b/c2rust-transpile/src/translator/mod.rs @@ -74,45 +74,6 @@ struct Import { ident_name: String, } -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum DecayRef { - Yes, - Default, - No, -} - -impl DecayRef { - // Here we give intrinsic meaning to default to equate to yes/true - // when actually evaluated - pub fn is_yes(&self) -> bool { - match self { - DecayRef::Yes => true, - DecayRef::Default => true, - DecayRef::No => false, - } - } - - #[inline] - pub fn is_no(&self) -> bool { - !self.is_yes() - } - - pub fn set_default_to_no(&mut self) { - if *self == DecayRef::Default { - *self = DecayRef::No; - } - } -} - -impl From for DecayRef { - fn from(b: bool) -> Self { - match b { - true => DecayRef::Yes, - false => DecayRef::No, - } - } -} - #[derive(Debug, Copy, Clone)] pub enum ReplaceMode { None, @@ -158,7 +119,6 @@ pub struct ExprContext { #[allow(dead_code)] is_static: bool, - decay_ref: DecayRef, is_bitfield_write: bool, /// We will be referring to the expression by address. In this context we @@ -187,12 +147,6 @@ impl ExprContext { self.is_used } - pub fn decay_ref(self) -> Self { - ExprContext { - decay_ref: DecayRef::Yes, - ..self - } - } pub fn const_(self) -> Self { ExprContext { is_const: true, @@ -900,7 +854,6 @@ pub fn translate( is_const: false, is_pattern: false, is_static: false, - decay_ref: DecayRef::Default, is_bitfield_write: false, needs_address: false, expanding_macro: None, @@ -1755,7 +1708,7 @@ impl<'c> Translation<'c> { pub fn use_feature(&self, feature: &'static str) { if matches!( feature, - "asm" | "inline_const" | "label_break_value" | "raw_ref_op" + "asm" | "inline_const" | "label_break_value" | "ptr_from_ref" | "raw_ref_op" ) && self.tcfg.edition >= Edition2024 { return; @@ -2497,25 +2450,25 @@ impl<'c> Translation<'c> { CExprKind::Binary(_, CBinOp::EqualEqual, null_expr, ptr, _, _) if self.ast_context.is_null_expr(null_expr) => { - return self.convert_pointer_is_null(ctx.decay_ref(), ptr, target); + return self.convert_pointer_is_null(ctx, ptr, target); } CExprKind::Binary(_, CBinOp::EqualEqual, ptr, null_expr, _, _) if self.ast_context.is_null_expr(null_expr) => { - return self.convert_pointer_is_null(ctx.decay_ref(), ptr, target); + return self.convert_pointer_is_null(ctx, ptr, target); } CExprKind::Binary(_, CBinOp::NotEqual, null_expr, ptr, _, _) if self.ast_context.is_null_expr(null_expr) => { - return self.convert_pointer_is_null(ctx.decay_ref(), ptr, !target); + return self.convert_pointer_is_null(ctx, ptr, !target); } CExprKind::Binary(_, CBinOp::NotEqual, ptr, null_expr, _, _) if self.ast_context.is_null_expr(null_expr) => { - return self.convert_pointer_is_null(ctx.decay_ref(), ptr, !target); + return self.convert_pointer_is_null(ctx, ptr, !target); } CExprKind::Literal(_, ref literal @ CLiteral::Integer(0 | 1, _)) @@ -2546,11 +2499,7 @@ impl<'c> Translation<'c> { return self.convert_pointer_is_null(ctx, expr, !target); } - // DecayRef could (and probably should) be Default instead of Yes here; however, as noted - // in https://github.com/rust-lang/rust/issues/53772, you cant compare a reference (lhs) to - // a ptr (rhs) (even though the reverse works!). We could also be smarter here and just - // specify Yes for that particular case, given enough analysis. - let expr_rs = self.convert_expr(ctx.decay_ref(), expr, None)?; + let expr_rs = self.convert_expr(ctx, expr, None)?; Ok(expr_rs.map(|mut expr_rs| { if expr_type_kind.is_bool() { @@ -3067,7 +3016,6 @@ impl<'c> Translation<'c> { } } - // ref decayed ptrs generally need a type annotation if let Some(CExprKind::Unary(_, CUnOp::AddressOf, _, _)) = initializer_kind { return true; @@ -3646,8 +3594,8 @@ impl<'c> Translation<'c> { matches!(expr_kind, CExprKind::ExplicitCast(..)), ), - Unary(result_type_id, op, arg, _lrvalue) => { - self.convert_unary_operator(ctx, override_ty, result_type_id, op, arg) + Unary(result_type_id, op, arg, lrvalue) => { + self.convert_unary_operator(ctx, override_ty, result_type_id, op, arg, lrvalue) } Conditional(ty, cond, lhs, rhs) => { @@ -3743,8 +3691,8 @@ impl<'c> Translation<'c> { ) .map_err(|e| e.add_loc(self.ast_context.display_loc(src_loc))), - ArraySubscript(_, lhs, rhs, lrvalue) => self - .convert_array_subscript(ctx, override_ty, lhs, rhs, lrvalue, true) + ArraySubscript(result_type_id, lhs, rhs, lrvalue) => self + .convert_array_subscript(ctx, override_ty, result_type_id, lhs, rhs, lrvalue, true) .map_err(|e| e.add_loc(self.ast_context.display_loc(src_loc))), Call(call_expr_ty, func, ref args) => { @@ -3865,6 +3813,8 @@ impl<'c> Translation<'c> { .get_decl(&decl_id) .ok_or_else(|| format_err!("Missing declref {:?}", decl_id))? .kind; + + #[allow(unreachable_code)] // TODO temporary (see below). if ctx.expanding_macro.is_some() { // TODO Determining which declarations have been declared within the scope of the const macro expr // vs. which are out-of-scope of the const macro is non-trivial, @@ -3874,7 +3824,10 @@ impl<'c> Translation<'c> { "Cannot yet refer to declarations in a const expr", )); - #[allow(unreachable_code)] // TODO temporary (see above). + if matches!(lrvalue, LRValue::LValue) && !result_type_id.qualifiers.is_const { + return Err("mutable lvalues are not supported inside macros".into()); + } + if let CDeclKind::Variable { has_static_duration: true, .. @@ -4206,11 +4159,6 @@ impl<'c> Translation<'c> { } match kind { - // A reference must be decayed if a bitcast is required. Const casts in - // LLVM 8 are now NoOp casts, so we need to include it as well. - CastKind::BitCast | CastKind::PointerToIntegral | CastKind::NoOp => { - ctx.decay_ref = DecayRef::Yes - } CastKind::ArrayToPointerDecay | CastKind::FunctionToPointerDecay | CastKind::BuiltinFnToFnPtr => { @@ -4487,7 +4435,7 @@ impl<'c> Translation<'c> { } CastKind::ArrayToPointerDecay => { - self.convert_array_to_pointer_decay(ctx, source_cty, target_cty, val, expr) + self.make_address_of(ctx, target_cty, source_cty, expr, val, true) } CastKind::NullToPointer => { diff --git a/c2rust-transpile/src/translator/operators.rs b/c2rust-transpile/src/translator/operators.rs index 3c9dfccbf7..4ca3d2d84a 100644 --- a/c2rust-transpile/src/translator/operators.rs +++ b/c2rust-transpile/src/translator/operators.rs @@ -5,7 +5,7 @@ use super::*; impl<'c> Translation<'c> { pub fn convert_binary_expr( &self, - mut ctx: ExprContext, + ctx: ExprContext, expected_type_id: Option, result_type_id: CQualTypeId, op: CBinOp, @@ -53,14 +53,6 @@ impl<'c> Translation<'c> { ), _ => { - // Comparing references to pointers isn't consistently supported by rust - // and so we need to decay references to pointers to do so. See - // https://github.com/rust-lang/rust/issues/53772. This might be removable - // once the above issue is resolved. - if op == CBinOp::EqualEqual || op == CBinOp::NotEqual { - ctx = ctx.decay_ref(); - } - let lhs_kind = &self.ast_context.index_unwrap_parens(lhs).kind; let mut lhs_type_id = lhs_kind.get_qual_type().ok_or_else(|| { format_translation_err!( @@ -119,26 +111,13 @@ impl<'c> Translation<'c> { .and_then_try(|_| self.convert_expr(ctx, rhs, Some(rhs_type_id)))? .map(|_| self.panic_or_err("Binary expression is not supposed to be used"))) } else { - let rhs_ctx = ctx; - - // When we use methods on pointers (ie wrapping_offset_from or offset) - // we must ensure we have an explicit raw ptr for the self param, as - // self references do not decay - if op.is_pointer_arithmetic() { - let ty_kind = &self.ast_context.resolve_type(lhs_type_id.ctype).kind; - - if let CTypeKind::Pointer(_) = ty_kind { - ctx = ctx.decay_ref(); - } - } - // Using `.is_none()` and `.is_some()` for null comparison means we don't // have to rely on `trait PartialEq` as much and it is also more idiomatic. if matches!(op, CBinOp::EqualEqual | CBinOp::NotEqual) { let is_null = op == CBinOp::EqualEqual; if self.ast_context.is_null_expr(lhs) { - let val = self.convert_pointer_is_null(rhs_ctx, rhs, is_null)?; + let val = self.convert_pointer_is_null(ctx, rhs, is_null)?; return Ok(val.map(bool_to_int)); } else if self.ast_context.is_null_expr(rhs) { let val = self.convert_pointer_is_null(ctx, lhs, is_null)?; @@ -147,7 +126,7 @@ impl<'c> Translation<'c> { } let lhs_val = self.convert_expr(ctx, lhs, Some(lhs_type_id))?; - let rhs_val = self.convert_expr(rhs_ctx, rhs, Some(rhs_type_id))?; + let rhs_val = self.convert_expr(ctx, rhs, Some(rhs_type_id))?; lhs_val.zip(rhs_val).and_then_try(|(lhs_val, rhs_val)| { self.convert_binary_operator( @@ -557,6 +536,7 @@ impl<'c> Translation<'c> { result_type_id: CQualTypeId, op: CUnOp, arg: CExprId, + lrvalue: LRValue, ) -> TranslationResult>> { let expr_type_id = expected_type_id.unwrap_or(result_type_id); match op { @@ -569,7 +549,7 @@ impl<'c> Translation<'c> { self.convert_indecrement_operator(ctx, expected_type_id, result_type_id, op, arg) } - CUnOp::Deref => self.convert_deref(ctx, expr_type_id, arg), + CUnOp::Deref => self.convert_deref(ctx, expr_type_id, arg, lrvalue), CUnOp::Plus => self.convert_expr(ctx, arg, expected_type_id), // promotion is explicit in the clang AST CUnOp::Negate => self.convert_negate_operator(ctx, expr_type_id, arg), diff --git a/c2rust-transpile/src/translator/pointers.rs b/c2rust-transpile/src/translator/pointers.rs index 08c5e17ae0..ec2a016ed7 100644 --- a/c2rust-transpile/src/translator/pointers.rs +++ b/c2rust-transpile/src/translator/pointers.rs @@ -1,10 +1,12 @@ +use std::borrow::Cow; + use c2rust_ast_builder::{mk, properties::Mutability}; use c2rust_ast_exporter::clang_ast::LRValue; use c2rust_rust_tools::RustEdition; use failure::{err_msg, format_err}; use syn::{BinOp, Expr, Type, UnOp}; -use crate::c_ast::CUnOp; +use crate::c_ast::{CUnOp, TypedAstContext}; use crate::translator::IdOrExpr; use crate::{ diagnostics::{TranslationError, TranslationErrorKind, TranslationResult}, @@ -19,7 +21,7 @@ use crate::{ impl<'c> Translation<'c> { pub fn convert_address_of( &self, - mut ctx: ExprContext, + ctx: ExprContext, cqual_type: CQualTypeId, arg: CExprId, ) -> TranslationResult>> { @@ -31,73 +33,61 @@ impl<'c> Translation<'c> { return self.convert_expr(ctx, *target, None) } // Array subscript functions as a deref too. - &CExprKind::ArraySubscript(_, lhs, rhs, _) => { + &CExprKind::ArraySubscript(result_type_id, lhs, rhs, _) => { return self.convert_array_subscript( ctx.needs_address(), Some(cqual_type), + result_type_id, lhs, rhs, LRValue::RValue, // if we bypass the deref, we stay an RValue false, // don't deref, keep as pointer ); } - // An AddrOf DeclRef/Member is safe to not decay - // if the translator isn't already giving a hard yes to decaying (ie, BitCasts). - // So we only convert default to no decay. - CExprKind::DeclRef(..) | CExprKind::Member(..) => ctx.decay_ref.set_default_to_no(), _ => (), } let val = self.convert_expr(ctx.needs_address(), arg, None)?; - // & becomes a no-op when applied to a function. - if self.ast_context.is_function_pointer(cqual_type.ctype) { - return Ok(val.map(|x| mk().call_expr(mk().ident_expr("Some"), vec![x]))); - } - let arg_cty = arg_kind .get_qual_type() .ok_or_else(|| format_err!("bad source type"))?; - self.convert_address_of_common(ctx, Some(arg), arg_cty, cqual_type, val, false) + self.make_address_of(ctx, cqual_type, arg_cty, Some(arg), val, false) } - pub fn convert_array_to_pointer_decay( + pub(crate) fn make_address_of( &self, ctx: ExprContext, - source_cty: CQualTypeId, - target_cty: CQualTypeId, - val: WithStmts>, - expr: Option, + pointer_cty: CQualTypeId, + arg_cty: CQualTypeId, + arg: Option, + mut val: WithStmts>, + is_array_decay: bool, ) -> TranslationResult>> { - // Because va_list is sometimes defined as a single-element - // array in order for it to allocate memory as a local variable - // and to be a pointer as a function argument we would get - // spurious casts when trying to treat it like a VaList which - // has reference semantics. - if self.ast_context.is_va_list(target_cty.ctype) { - return Ok(val); - } + if is_array_decay { + // Because va_list is sometimes defined as a single-element + // array in order for it to allocate memory as a local variable + // and to be a pointer as a function argument we would get + // spurious casts when trying to treat it like a VaList which + // has reference semantics. + if self.ast_context.is_va_list(pointer_cty.ctype) { + return Ok(val); + } - let source_ty_kind = &self.ast_context.resolve_type(source_cty.ctype).kind; + let source_ty_kind = &self.ast_context.resolve_type(arg_cty.ctype).kind; - // Variable length arrays are already represented as pointers. - if let CTypeKind::VariableArray(..) = source_ty_kind { - return Ok(val); + // Variable length arrays are already represented as pointers. + if let CTypeKind::VariableArray(..) = source_ty_kind { + return Ok(val); + } + } else { + // & becomes a no-op when applied to a function. + if self.ast_context.is_function_pointer(pointer_cty.ctype) { + return Ok(val.map(|x| mk().call_expr(mk().ident_expr("Some"), vec![x]))); + } } - self.convert_address_of_common(ctx, expr, source_cty, target_cty, val, true) - } - - fn convert_address_of_common( - &self, - ctx: ExprContext, - arg: Option, - arg_cty: CQualTypeId, - pointer_cty: CQualTypeId, - mut val: WithStmts>, - is_array_decay: bool, - ) -> TranslationResult>> { let arg_expr_kind = arg.map(|arg| { let arg = self.ast_context.unwrap_predefined_ident(arg); &self.ast_context.index_unwrap_parens(arg).kind @@ -108,81 +98,83 @@ impl<'c> Translation<'c> { .ok_or_else(|| TranslationError::generic("Address-of should return a pointer"))?; let arg_is_macro = arg.map_or(false, |arg| self.expr_is_expanded_macro(ctx, arg, None)); - let mut needs_cast = false; - let mut ref_cast_pointee_ty = None; - let mutbl = if ctx.is_const && !pointee_cty.qualifiers.is_const { + let mutbl = if self.tcfg.edition < RustEdition::Edition2024 + && ctx.is_const + && !pointee_cty.qualifiers.is_const + { // const contexts aren't able to use &mut, so we work around that // by using & and an extra cast through & to *const to *mut // TODO: Rust 1.83: Allowed, so this can be removed. - needs_cast = true; Mutability::Immutable } else { pointee_cty.mutability() }; - // Narrow string literals are translated directly as `[u8; N]` literals when their address - // is taken, without the transmute. String/byte literals are already references in Rust. - if let ( - Some(&CExprKind::Literal(literal_cty, CLiteral::String(_, element_size @ 1))), - false, - ) = (arg_expr_kind, arg_is_macro) - { - if is_array_decay { - val = val.map(|val| mk().method_call_expr(val, "as_ptr", vec![])); - } else { - let size = self.ast_context.array_len(literal_cty.ctype) * element_size as usize; - ref_cast_pointee_ty = - Some(mk().array_ty(mk().ident_ty("u8"), mk().lit_expr(size as u128))); - } - needs_cast = true; - } + let mut cast_source_type_kind = + Cow::Borrowed(&self.ast_context.resolve_type(arg_cty.ctype).kind); + // 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 || matches!(arg_expr_kind, Some(CExprKind::Literal(..))) { - let arg_cty_kind = &self.ast_context.resolve_type(arg_cty.ctype).kind; + if arg_is_macro || matches!(arg_expr_kind, Some(CExprKind::Literal(..))) { + if !pointee_cty.qualifiers.is_const { + return Err("taking mutable address of string literal or macro".into()); + } + + // Narrow string literals are translated directly as `[u8; N]` literals + // when their address is taken, without the transmute. + // String/byte literals are already references in Rust. + let is_byte_string_literal = matches!( + arg_expr_kind, + Some(&CExprKind::Literal(_, CLiteral::String(_, 1))) + ) && !arg_is_macro; if is_array_decay { - let method = match mutbl { - Mutability::Mutable => "as_mut_ptr", - Mutability::Immutable => "as_ptr", - }; - val = val.map(|val| mk().method_call_expr(val, method, vec![])); - - // If the target pointee type is different from the source element type, - // then we need to cast the ptr type as well. - if arg_cty_kind.element_ty().map_or(false, |arg_element_cty| { - arg_element_cty != pointee_cty.ctype - }) { - needs_cast = true; + if is_byte_string_literal { + cast_source_type_kind = Cow::Borrowed(&CTypeKind::UInt8); + } else { + let Some(element_type_id) = cast_source_type_kind.array_element_type() else { + return Err(TranslationError::generic( + "Argument of array decay should have array type" + )); + }; + cast_source_type_kind = + Cow::Borrowed(&self.ast_context.resolve_type(element_type_id).kind); } - } else { - 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. - if ctx.decay_ref.is_yes() || needs_cast { - ref_cast_pointee_ty = Some(self.convert_pointee_type(arg_cty.ctype)?); + val = val.map(|val| mk().method_call_expr(val, "as_ptr", vec![])); + } else { + if is_byte_string_literal { + let Some(element_type_id) = + cast_source_type_kind.to_mut().array_element_type_mut() + else { + return Err(TranslationError::generic( + "String literal should have array type", + )); + }; + *element_type_id = self.ast_context.type_for_kind(&CTypeKind::UInt8); + } else { + val = val.map(|val| mk().borrow_expr(val)); } + + self.use_feature("ptr_from_ref"); + let func = mk().abs_path_expr(vec!["core", "ptr", "from_ref"]); + val = val.map(|val| mk().call_expr(func, vec![val])); } } 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. - // TODO: Rust 1.76: Use `ptr::from_ref`. - if let Some(pointee_ty) = ref_cast_pointee_ty { - val = val.map(|val| mk().cast_expr(val, mk().set_mutbl(mutbl).ptr_ty(pointee_ty))); - } + let pointee_type_kind = &self.ast_context.resolve_type(pointee_cty.ctype).kind; - // Perform a final cast to the target type if needed. - if needs_cast { + // If the target pointee type is different from the source type, + // then we need to cast the pointer type. + if !self.ast_context.type_kinds_eq( + pointee_type_kind, + &cast_source_type_kind, + &TypedAstContext::resolve_type_id, + ) || pointee_cty.mutability() != mutbl + { let pointer_ty = self.convert_type(pointer_cty.ctype)?; val = val.map(|val| mk().cast_expr(val, pointer_ty)); } @@ -195,7 +187,15 @@ impl<'c> Translation<'c> { ctx: ExprContext, cqual_type: CQualTypeId, arg: CExprId, + lrvalue: LRValue, ) -> TranslationResult>> { + if matches!(lrvalue, LRValue::LValue) + && !cqual_type.qualifiers.is_const + && ctx.expanding_macro.is_some() + { + return Err("mutable lvalues are not supported inside macros".into()); + } + let arg_expr_kind = &self.ast_context.index_unwrap_parens(arg).kind; if let &CExprKind::Unary(_, CUnOp::AddressOf, arg, _) = arg_expr_kind { @@ -220,11 +220,19 @@ impl<'c> Translation<'c> { &self, ctx: ExprContext, expected_type_id: Option, + result_type_id: CQualTypeId, lhs: CExprId, rhs: CExprId, lrvalue: LRValue, deref: bool, ) -> TranslationResult>> { + if matches!(lrvalue, LRValue::LValue) + && !result_type_id.qualifiers.is_const + && ctx.expanding_macro.is_some() + { + return Err("mutable lvalues are not supported inside macros".into()); + } + let (pointer_id, offset_id) = if self.ast_context.expr_is_indexable(lhs) { (lhs, rhs) } else { @@ -332,8 +340,7 @@ impl<'c> Translation<'c> { }; // LHS must be ref decayed for the offset method call's self param - let pointer_rs = - self.convert_expr(ctx.not_needs_address().decay_ref(), pointer_id, None)?; + let pointer_rs = self.convert_expr(ctx.not_needs_address(), pointer_id, None)?; let target_type_id = self.ast_context.type_for_kind(&CTypeKind::SSize); let offset_rs = self.convert_expr_with_cast( ctx.not_needs_address(), @@ -692,7 +699,7 @@ impl<'c> Translation<'c> { let expr_type_id = expr .type_id(&self.ast_context) .ok_or_else(|| format_err!("Invalid expression type"))?; - let expr_rs = self.convert_expr(ctx.decay_ref(), expr, None)?; + let expr_rs = self.convert_expr(ctx, expr, None)?; if self.ast_context.is_function_pointer(expr_type_id.ctype) { let method = if is_null { "is_none" } else { "is_some" }; diff --git a/c2rust-transpile/src/translator/structs_unions.rs b/c2rust-transpile/src/translator/structs_unions.rs index a92444787a..429d8de224 100644 --- a/c2rust-transpile/src/translator/structs_unions.rs +++ b/c2rust-transpile/src/translator/structs_unions.rs @@ -1053,6 +1053,13 @@ impl<'a> Translation<'a> { lrvalue: LRValue, override_ty: Option, ) -> TranslationResult>> { + if matches!(lrvalue, LRValue::LValue) + && !qual_ty.qualifiers.is_const + && ctx.expanding_macro.is_some() + { + return Err("mutable lvalues are not supported inside macros".into()); + } + if !ctx.is_used() { return self.convert_expr(ctx, expr, None); } diff --git a/c2rust-transpile/tests/snapshots/macros.c b/c2rust-transpile/tests/snapshots/macros.c index 6183cd2d71..9299dd4649 100644 --- a/c2rust-transpile/tests/snapshots/macros.c +++ b/c2rust-transpile/tests/snapshots/macros.c @@ -12,7 +12,8 @@ struct S { #define LITERAL_CHAR 'x' #define LITERAL_STR "hello" #define LITERAL_ARRAY {1, 2, 3} -#define LITERAL_STRUCT ((struct S){.i = 5}) +#define LITERAL_STRUCT ((const struct S){.i = 5}) +#define LITERAL_STRUCT_MUT ((struct S){.i = 5}) #define NESTED_INT LITERAL_INT #define NESTED_BOOL LITERAL_BOOL @@ -35,8 +36,10 @@ struct S { #define BUILTIN __builtin_clz(LITERAL_INT) #define REF_MACRO &INDEXING #define REF_LITERAL &LITERAL_STRUCT +#define REF_LITERAL_MUT &LITERAL_STRUCT_MUT #define TERNARY LITERAL_BOOL ? 1 : 2 #define MEMBER LITERAL_STRUCT.i +#define MEMBER_MUT LITERAL_STRUCT_MUT.i #define STMT_EXPR \ ({ \ @@ -49,123 +52,6 @@ struct S { mixed; \ }) -void local_muts() { - int literal_int = LITERAL_INT; - bool literal_bool = LITERAL_BOOL; - float literal_float = LITERAL_FLOAT; - char literal_char = LITERAL_CHAR; - const char *literal_str_ptr = LITERAL_STR; - char literal_str[] = LITERAL_STR; - int literal_array[] = LITERAL_ARRAY; - struct S literal_struct = LITERAL_STRUCT; - - int nested_int = NESTED_INT; - bool nested_bool = NESTED_BOOL; - float nested_float = NESTED_FLOAT; - char nested_char = NESTED_CHAR; - const char *nested_str_ptr = NESTED_STR; - char nested_str[] = NESTED_STR; - int nested_array[] = NESTED_ARRAY; - struct S nested_struct = NESTED_STRUCT; - - int negative_int = NEGATIVE_INT; - int int_arithmetic = INT_ARITHMETIC; - float mixed_arithmetic = MIXED_ARITHMETIC; - int parens = PARENS; - const char *ptr_arithmetic = PTR_ARITHMETIC; - unsigned long long widening_cast = WIDENING_CAST; - char narrowing_cast = NARROWING_CAST; - double conversion_cast = CONVERSION_CAST; - char indexing = INDEXING; - const char *str_concatenation_ptr = STR_CONCATENATION; - char str_concatenation[] = STR_CONCATENATION; - int builtin = BUILTIN; - const char *ref_indexing = REF_MACRO; - const struct S *ref_struct = REF_LITERAL; - int ternary = TERNARY; - int member = MEMBER; - float stmt_expr = STMT_EXPR; -} - -void local_consts() { - const int literal_int = LITERAL_INT; - const bool literal_bool = LITERAL_BOOL; - const float literal_float = LITERAL_FLOAT; - const char literal_char = LITERAL_CHAR; - const char *const literal_str_ptr = LITERAL_STR; - const char literal_str[] = LITERAL_STR; - const int literal_array[] = LITERAL_ARRAY; - const struct S literal_struct = LITERAL_STRUCT; - - const int nested_int = NESTED_INT; - const bool nested_bool = NESTED_BOOL; - const float nested_float = NESTED_FLOAT; - const char nested_char = NESTED_CHAR; - const char *const nested_str_ptr = NESTED_STR; - const char nested_str[] = NESTED_STR; - const int nested_array[] = NESTED_ARRAY; - const struct S nested_struct = NESTED_STRUCT; - - const int negative_int = NEGATIVE_INT; - const int int_arithmetic = INT_ARITHMETIC; - const float mixed_arithmetic = MIXED_ARITHMETIC; - const int parens = PARENS; - const char *const ptr_arithmetic = PTR_ARITHMETIC; - const unsigned long long widening_cast = WIDENING_CAST; - const char narrowing_cast = NARROWING_CAST; - const double conversion_cast = CONVERSION_CAST; - const char indexing = INDEXING; - const char *const str_concatenation_ptr = STR_CONCATENATION; - const char str_concatenation[] = STR_CONCATENATION; - const int builtin = BUILTIN; - const char *const ref_indexing = REF_MACRO; - const struct S *const ref_struct = REF_LITERAL; - const int ternary = TERNARY; - const int member = MEMBER; - const float stmt_expr = STMT_EXPR; -} - -// TODO These are declared in the global scope and thus clash, -// which is an error for statics. -#if 0 -void local_static_consts() { - static const int literal_int = LITERAL_INT; - static const bool literal_bool = LITERAL_BOOL; - static const float literal_float = LITERAL_FLOAT; - static const char literal_char = LITERAL_CHAR; - static const char *const literal_str_ptr = LITERAL_STR; - static const char literal_str[] = LITERAL_STR; - static const int literal_array[] = LITERAL_ARRAY; - static const struct S literal_struct = LITERAL_STRUCT; - - static const int nested_int = NESTED_INT; - static const bool nested_bool = NESTED_BOOL; - static const float nested_float = NESTED_FLOAT; - static const char nested_char = NESTED_CHAR; - static const char *const nested_str_ptr = NESTED_STR; - static const char nested_str[] = NESTED_STR; - static const int nested_array[] = NESTED_ARRAY; - static const struct S nested_struct = NESTED_STRUCT; - - static const int int_arithmetic = INT_ARITHMETIC; - static const float mixed_arithmetic = MIXED_ARITHMETIC; - static const int parens = PARENS; - static const char *const ptr_arithmetic = PTR_ARITHMETIC; - static const unsigned long long widening_cast = WIDENING_CAST; - static const char narrowing_cast = NARROWING_CAST; - static const double conversion_cast = CONVERSION_CAST; - static const char indexing = INDEXING; - static const char *const str_concatenation_ptr = STR_CONCATENATION; - static const char str_concatenation[] = STR_CONCATENATION; - static const int builtin = BUILTIN; - static const char *const ref_indexing = REF_MACRO; - static const struct S *const ref_struct = REF_LITERAL; - static const int ternary = TERNARY; - static const int member = MEMBER; - static const float stmt_expr = STMT_EXPR; -} -#endif - // global static consts static const int global_static_const_literal_int = LITERAL_INT; @@ -176,6 +62,7 @@ static const char *const global_static_const_literal_str_ptr = LITERAL_STR; static const char global_static_const_literal_str[] = LITERAL_STR; static const int global_static_const_literal_array[] = LITERAL_ARRAY; static const struct S global_static_const_literal_struct = LITERAL_STRUCT; +static const struct S global_static_const_literal_struct_mut = LITERAL_STRUCT_MUT; static const int global_static_const_nested_int = NESTED_INT; static const bool global_static_const_nested_bool = NESTED_BOOL; @@ -202,8 +89,10 @@ static const char global_static_const_str_concatenation[] = STR_CONCATENATION; static const int global_static_const_builtin = BUILTIN; static const char *const global_static_const_ref_indexing = REF_MACRO; static const struct S *const global_static_const_ref_struct = REF_LITERAL; +static struct S *const global_static_const_ref_struct_mut = REF_LITERAL_MUT; static const int global_static_const_ternary = TERNARY; static const int global_static_const_member = MEMBER; +static const int global_static_const_member_mut = MEMBER_MUT; // static const float global_static_const_stmt_expr = STMT_EXPR; // Statement expression not allowed at file scope. void global_static_consts() { @@ -216,6 +105,7 @@ void global_static_consts() { (void)global_static_const_literal_str; (void)global_static_const_literal_array; (void)global_static_const_literal_struct; + (void)global_static_const_literal_struct_mut; (void)global_static_const_nested_int; (void)global_static_const_nested_bool; @@ -240,8 +130,10 @@ void global_static_consts() { (void)global_static_const_builtin; (void)global_static_const_ref_indexing; (void)global_static_const_ref_struct; + (void)global_static_const_ref_struct_mut; (void)global_static_const_ternary; (void)global_static_const_member; + (void)global_static_const_member_mut; // (void)global_static_const_stmt_expr; } @@ -255,6 +147,7 @@ const char *const global_const_literal_str_ptr = LITERAL_STR; const char global_const_literal_str[] = LITERAL_STR; const int global_const_literal_array[] = LITERAL_ARRAY; const struct S global_const_literal_struct = LITERAL_STRUCT; +const struct S global_const_literal_struct_mut = LITERAL_STRUCT_MUT; const int global_const_nested_int = NESTED_INT; const bool global_const_nested_bool = NESTED_BOOL; @@ -279,10 +172,137 @@ const char global_const_str_concatenation[] = STR_CONCATENATION; const int global_const_builtin = BUILTIN; const char *const global_const_ref_indexing = REF_MACRO; const struct S *const global_const_ref_struct = REF_LITERAL; +struct S *const global_const_ref_struct_mut = REF_LITERAL_MUT; const int global_const_ternary = TERNARY; const int global_const_member = MEMBER; +const int global_const_member_mut = MEMBER_MUT; // const float global_const_stmt_expr = STMT_EXPR; // Statement expression not allowed at file scope. +void local_muts() { + int literal_int = LITERAL_INT; + bool literal_bool = LITERAL_BOOL; + float literal_float = LITERAL_FLOAT; + char literal_char = LITERAL_CHAR; + const char *literal_str_ptr = LITERAL_STR; + char literal_str[] = LITERAL_STR; + int literal_array[] = LITERAL_ARRAY; + struct S literal_struct = LITERAL_STRUCT; + struct S literal_struct_mut = LITERAL_STRUCT_MUT; + + int nested_int = NESTED_INT; + bool nested_bool = NESTED_BOOL; + float nested_float = NESTED_FLOAT; + char nested_char = NESTED_CHAR; + const char *nested_str_ptr = NESTED_STR; + char nested_str[] = NESTED_STR; + int nested_array[] = NESTED_ARRAY; + struct S nested_struct = NESTED_STRUCT; + + int negative_int = NEGATIVE_INT; + int int_arithmetic = INT_ARITHMETIC; + float mixed_arithmetic = MIXED_ARITHMETIC; + int parens = PARENS; + const char *ptr_arithmetic = PTR_ARITHMETIC; + unsigned long long widening_cast = WIDENING_CAST; + char narrowing_cast = NARROWING_CAST; + double conversion_cast = CONVERSION_CAST; + char indexing = INDEXING; + const char *str_concatenation_ptr = STR_CONCATENATION; + char str_concatenation[] = STR_CONCATENATION; + int builtin = BUILTIN; + const char *ref_indexing = REF_MACRO; + const struct S *ref_struct = REF_LITERAL; + struct S *ref_struct_mut = REF_LITERAL_MUT; + int ternary = TERNARY; + int member = MEMBER; + int member_mut = MEMBER_MUT; + float stmt_expr = STMT_EXPR; +} + +void local_consts() { + const int literal_int = LITERAL_INT; + const bool literal_bool = LITERAL_BOOL; + const float literal_float = LITERAL_FLOAT; + const char literal_char = LITERAL_CHAR; + const char *const literal_str_ptr = LITERAL_STR; + const char literal_str[] = LITERAL_STR; + const int literal_array[] = LITERAL_ARRAY; + const struct S literal_struct = LITERAL_STRUCT; + const struct S literal_struct_mut = LITERAL_STRUCT_MUT; + + const int nested_int = NESTED_INT; + const bool nested_bool = NESTED_BOOL; + const float nested_float = NESTED_FLOAT; + const char nested_char = NESTED_CHAR; + const char *const nested_str_ptr = NESTED_STR; + const char nested_str[] = NESTED_STR; + const int nested_array[] = NESTED_ARRAY; + const struct S nested_struct = NESTED_STRUCT; + + const int negative_int = NEGATIVE_INT; + const int int_arithmetic = INT_ARITHMETIC; + const float mixed_arithmetic = MIXED_ARITHMETIC; + const int parens = PARENS; + const char *const ptr_arithmetic = PTR_ARITHMETIC; + const unsigned long long widening_cast = WIDENING_CAST; + const char narrowing_cast = NARROWING_CAST; + const double conversion_cast = CONVERSION_CAST; + const char indexing = INDEXING; + const char *const str_concatenation_ptr = STR_CONCATENATION; + const char str_concatenation[] = STR_CONCATENATION; + const int builtin = BUILTIN; + const char *const ref_indexing = REF_MACRO; + const struct S *const ref_struct = REF_LITERAL; + struct S *const ref_struct_mut = REF_LITERAL_MUT; + const int ternary = TERNARY; + const int member = MEMBER; + const int member_mut = MEMBER_MUT; + const float stmt_expr = STMT_EXPR; +} + +// TODO These are declared in the global scope and thus clash, +// which is an error for statics. +#if 0 +void local_static_consts() { + static const int literal_int = LITERAL_INT; + static const bool literal_bool = LITERAL_BOOL; + static const float literal_float = LITERAL_FLOAT; + static const char literal_char = LITERAL_CHAR; + static const char *const literal_str_ptr = LITERAL_STR; + static const char literal_str[] = LITERAL_STR; + static const int literal_array[] = LITERAL_ARRAY; + static const struct S literal_struct = LITERAL_STRUCT; + static const struct S literal_struct_mut = LITERAL_STRUCT_MUT; + + static const int nested_int = NESTED_INT; + static const bool nested_bool = NESTED_BOOL; + static const float nested_float = NESTED_FLOAT; + static const char nested_char = NESTED_CHAR; + static const char *const nested_str_ptr = NESTED_STR; + static const char nested_str[] = NESTED_STR; + static const int nested_array[] = NESTED_ARRAY; + static const struct S nested_struct = NESTED_STRUCT; + + static const int int_arithmetic = INT_ARITHMETIC; + static const float mixed_arithmetic = MIXED_ARITHMETIC; + static const int parens = PARENS; + static const char *const ptr_arithmetic = PTR_ARITHMETIC; + static const unsigned long long widening_cast = WIDENING_CAST; + static const char narrowing_cast = NARROWING_CAST; + static const double conversion_cast = CONVERSION_CAST; + static const char indexing = INDEXING; + static const char *const str_concatenation_ptr = STR_CONCATENATION; + static const char str_concatenation[] = STR_CONCATENATION; + static const int builtin = BUILTIN; + static const char *const ref_indexing = REF_MACRO; + static const struct S *const ref_struct = REF_LITERAL; + static struct S *const ref_struct_mut = REF_LITERAL_MUT; + static const int ternary = TERNARY; + static const int member = MEMBER; + static const float stmt_expr = STMT_EXPR; +} +#endif + typedef unsigned long long U64; #define TEST_FN_MACRO(x) ((x) * (x)) diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.2021.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.2021.clang15.snap index d9b2bce721..a827a5af78 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.2021.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.2021.clang15.snap @@ -11,7 +11,7 @@ expression: cat tests/snapshots/arrays.2021.clang15.rs unused_assignments, unused_mut )] -#![feature(raw_ref_op)] +#![feature(ptr_from_ref, raw_ref_op)] extern "C" { static mut my_array: [::core::ffi::c_int; 1]; static mut my_indexes: [::core::ffi::c_int; 1]; @@ -100,10 +100,10 @@ pub unsafe extern "C" fn entry() { let mut const_char_lit_ptr: *const ::core::ffi::c_char = b"abc\0".as_ptr() as *const ::core::ffi::c_char; let mut const_char_lit_array_ptr: *const [::core::ffi::c_char; 4] = - b"abc\0" as *const [u8; 4] as *const [::core::ffi::c_char; 4]; + ::core::ptr::from_ref(b"abc\0") as *const [::core::ffi::c_char; 4]; let mut char_lit_ptr: *mut ::core::ffi::c_char = b"abc\0".as_ptr() as *const ::core::ffi::c_char as *mut ::core::ffi::c_char; - let mut char_lit_array_ptr: *mut [::core::ffi::c_char; 4] = b"abc\0" as *const [u8; 4] + let mut char_lit_array_ptr: *mut [::core::ffi::c_char; 4] = ::core::ptr::from_ref(b"abc\0") as *const [::core::ffi::c_char; 4] as *mut [::core::ffi::c_char; 4]; let mut past_end: *mut ::core::ffi::c_char = (&raw mut static_char_array diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.2024.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.2024.clang15.snap index 640c1c76dc..311b073f8a 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.2024.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@arrays.c.2024.clang15.snap @@ -52,7 +52,7 @@ pub static mut static_char_ptr: *mut ::core::ffi::c_char = b"mystring\0".as_ptr() as *const ::core::ffi::c_char as *mut ::core::ffi::c_char; #[unsafe(no_mangle)] pub static mut static_void_ptr: *mut ::core::ffi::c_void = - &raw const static_char_array as *mut ::core::ffi::c_char as *mut ::core::ffi::c_void; + &raw mut static_char_array as *mut ::core::ffi::c_char as *mut ::core::ffi::c_void; #[unsafe(no_mangle)] pub unsafe extern "C" fn entry() { let mut int_2d: [[::core::ffi::c_int; 1]; 1] = [[1 as ::core::ffi::c_int]]; @@ -100,10 +100,10 @@ pub unsafe extern "C" fn entry() { let mut const_char_lit_ptr: *const ::core::ffi::c_char = b"abc\0".as_ptr() as *const ::core::ffi::c_char; let mut const_char_lit_array_ptr: *const [::core::ffi::c_char; 4] = - b"abc\0" as *const [u8; 4] as *const [::core::ffi::c_char; 4]; + ::core::ptr::from_ref(b"abc\0") as *const [::core::ffi::c_char; 4]; let mut char_lit_ptr: *mut ::core::ffi::c_char = b"abc\0".as_ptr() as *const ::core::ffi::c_char as *mut ::core::ffi::c_char; - let mut char_lit_array_ptr: *mut [::core::ffi::c_char; 4] = b"abc\0" as *const [u8; 4] + let mut char_lit_array_ptr: *mut [::core::ffi::c_char; 4] = ::core::ptr::from_ref(b"abc\0") as *const [::core::ffi::c_char; 4] as *mut [::core::ffi::c_char; 4]; let mut past_end: *mut ::core::ffi::c_char = (&raw mut static_char_array diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2021.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2021.clang15.snap index 846ac42353..2b56db2955 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2021.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2021.clang15.snap @@ -11,7 +11,7 @@ expression: cat tests/snapshots/bool.2021.clang15.rs unused_assignments, unused_mut )] -#![feature(inline_const)] +#![feature(inline_const, ptr_from_ref)] pub const r#true: ::core::ffi::c_int = 1 as ::core::ffi::c_int; pub const r#false: ::core::ffi::c_int = 0 as ::core::ffi::c_int; pub const MACRO_INT0: ::core::ffi::c_int = 0 as ::core::ffi::c_int; @@ -64,44 +64,59 @@ pub const WSTR: [::core::ffi::c_int; 3] = unsafe { }; #[no_mangle] pub unsafe extern "C" fn test_ptr(mut arg: ::core::ffi::c_int) { - let mut not_wstr: ::core::ffi::c_int = (&const { - unsafe { - ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0") - } - } as *const [::core::ffi::c_int; 3]) - .is_null() as ::core::ffi::c_int; - let mut conditional_wstr: ::core::ffi::c_int = if !(&const { - unsafe { - ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0") - } - } as *const [::core::ffi::c_int; 3]) - .is_null() + let mut not_wstr: ::core::ffi::c_int = ::core::ptr::from_ref( + &const { + unsafe { + ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>( + *b"a\0\0\0b\0\0\0\0\0\0\0", + ) + } + }, + ) + .is_null() as ::core::ffi::c_int; + let mut conditional_wstr: ::core::ffi::c_int = if !::core::ptr::from_ref( + &const { + unsafe { + ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>( + *b"a\0\0\0b\0\0\0\0\0\0\0", + ) + } + }, + ) + .is_null() { 1 as ::core::ffi::c_int } else { 2 as ::core::ffi::c_int }; - let mut and_wstr: ::core::ffi::c_int = (!(&const { - unsafe { - ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0") - } - } as *const [::core::ffi::c_int; 3]) - .is_null() + let mut and_wstr: ::core::ffi::c_int = (!::core::ptr::from_ref( + &const { + unsafe { + ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>( + *b"a\0\0\0b\0\0\0\0\0\0\0", + ) + } + }, + ) + .is_null() && arg != 0) as ::core::ffi::c_int; - let mut cast_wstr: ::core::ffi::c_int = !(&const { - unsafe { - ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0") - } - } as *const [::core::ffi::c_int; 3]) - .is_null() as ::core::ffi::c_int; + let mut cast_wstr: ::core::ffi::c_int = !::core::ptr::from_ref( + &const { + unsafe { + ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>( + *b"a\0\0\0b\0\0\0\0\0\0\0", + ) + } + }, + ) + .is_null() as ::core::ffi::c_int; let mut not_macro_str: ::core::ffi::c_int = - (&STR as *const [::core::ffi::c_char; 3]).is_null() as ::core::ffi::c_int; + ::core::ptr::from_ref(&STR).is_null() as ::core::ffi::c_int; let mut not_macro_wstr: ::core::ffi::c_int = - (&WSTR as *const [::core::ffi::c_int; 3]).is_null() as ::core::ffi::c_int; - let mut conditional_macro_str: ::core::ffi::c_int = - if !(&STR as *const [::core::ffi::c_char; 3]).is_null() { - 1 as ::core::ffi::c_int - } else { - 2 as ::core::ffi::c_int - }; + ::core::ptr::from_ref(&WSTR).is_null() as ::core::ffi::c_int; + let mut conditional_macro_str: ::core::ffi::c_int = if !::core::ptr::from_ref(&STR).is_null() { + 1 as ::core::ffi::c_int + } else { + 2 as ::core::ffi::c_int + }; } diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2024.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2024.clang15.snap index fc01d45a80..d211c7c7d7 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2024.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2024.clang15.snap @@ -64,44 +64,59 @@ pub const WSTR: [::core::ffi::c_int; 3] = unsafe { }; #[unsafe(no_mangle)] pub unsafe extern "C" fn test_ptr(mut arg: ::core::ffi::c_int) { - let mut not_wstr: ::core::ffi::c_int = (&const { - unsafe { - ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0") - } - } as *const [::core::ffi::c_int; 3]) - .is_null() as ::core::ffi::c_int; - let mut conditional_wstr: ::core::ffi::c_int = if !(&const { - unsafe { - ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0") - } - } as *const [::core::ffi::c_int; 3]) - .is_null() + let mut not_wstr: ::core::ffi::c_int = ::core::ptr::from_ref( + &const { + unsafe { + ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>( + *b"a\0\0\0b\0\0\0\0\0\0\0", + ) + } + }, + ) + .is_null() as ::core::ffi::c_int; + let mut conditional_wstr: ::core::ffi::c_int = if !::core::ptr::from_ref( + &const { + unsafe { + ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>( + *b"a\0\0\0b\0\0\0\0\0\0\0", + ) + } + }, + ) + .is_null() { 1 as ::core::ffi::c_int } else { 2 as ::core::ffi::c_int }; - let mut and_wstr: ::core::ffi::c_int = (!(&const { - unsafe { - ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0") - } - } as *const [::core::ffi::c_int; 3]) - .is_null() + let mut and_wstr: ::core::ffi::c_int = (!::core::ptr::from_ref( + &const { + unsafe { + ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>( + *b"a\0\0\0b\0\0\0\0\0\0\0", + ) + } + }, + ) + .is_null() && arg != 0) as ::core::ffi::c_int; - let mut cast_wstr: ::core::ffi::c_int = !(&const { - unsafe { - ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0") - } - } as *const [::core::ffi::c_int; 3]) - .is_null() as ::core::ffi::c_int; + let mut cast_wstr: ::core::ffi::c_int = !::core::ptr::from_ref( + &const { + unsafe { + ::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>( + *b"a\0\0\0b\0\0\0\0\0\0\0", + ) + } + }, + ) + .is_null() as ::core::ffi::c_int; let mut not_macro_str: ::core::ffi::c_int = - (&STR as *const [::core::ffi::c_char; 3]).is_null() as ::core::ffi::c_int; + ::core::ptr::from_ref(&STR).is_null() as ::core::ffi::c_int; let mut not_macro_wstr: ::core::ffi::c_int = - (&WSTR as *const [::core::ffi::c_int; 3]).is_null() as ::core::ffi::c_int; - let mut conditional_macro_str: ::core::ffi::c_int = - if !(&STR as *const [::core::ffi::c_char; 3]).is_null() { - 1 as ::core::ffi::c_int - } else { - 2 as ::core::ffi::c_int - }; + ::core::ptr::from_ref(&WSTR).is_null() as ::core::ffi::c_int; + let mut conditional_macro_str: ::core::ffi::c_int = if !::core::ptr::from_ref(&STR).is_null() { + 1 as ::core::ffi::c_int + } else { + 2 as ::core::ffi::c_int + }; } diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.2021.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.2021.clang15.snap index f9a7cb7388..5578f4336b 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.2021.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.2021.clang15.snap @@ -40,11 +40,6 @@ static mut c2rust_lvalue_4: [::core::ffi::c_char; 6] = #[no_mangle] pub static mut static_char_array_ptr: *mut [::core::ffi::c_char; 6] = unsafe { &raw const c2rust_lvalue_4 as *mut [::core::ffi::c_char; 6] }; -pub const SINGLE_INT: ::core::ffi::c_int = 42 as ::core::ffi::c_int; -pub const INT_ARRAY: [::core::ffi::c_int; 2] = - [42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int]; -pub const CHAR_ARRAY: [::core::ffi::c_char; 6] = - unsafe { ::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0") }; #[no_mangle] pub unsafe extern "C" fn local_compound_literals() { let mut single_int: ::core::ffi::c_int = 42 as ::core::ffi::c_int; @@ -64,15 +59,23 @@ pub unsafe extern "C" fn local_compound_literals() { let mut c2rust_lvalue_9: [::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] = &raw mut c2rust_lvalue_9; - 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; - let mut macro_int_ptr_to_array: *mut ::core::ffi::c_int = INT_ARRAY.as_mut_ptr(); - let mut macro_char_ptr_to_array: *mut ::core::ffi::c_char = CHAR_ARRAY.as_mut_ptr(); - let mut macro_int_array_ptr: *mut [::core::ffi::c_int; 2] = - &mut INT_ARRAY as *mut [::core::ffi::c_int; 2]; - let mut macro_char_array_ptr: *mut [::core::ffi::c_char; 6] = - &mut CHAR_ARRAY as *mut [::core::ffi::c_char; 6]; + let mut macro_single_int: ::core::ffi::c_int = 42 as ::core::ffi::c_int; + let mut c2rust_lvalue_10: ::core::ffi::c_int = 42 as ::core::ffi::c_int; + let mut macro_single_int_ptr: *mut ::core::ffi::c_int = &raw mut c2rust_lvalue_10; + let mut c2rust_lvalue_11: [::core::ffi::c_int; 2] = + [42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int]; + let mut macro_int_ptr_to_array: *mut ::core::ffi::c_int = + &raw mut c2rust_lvalue_11 as *mut ::core::ffi::c_int; + let mut c2rust_lvalue_12: [::core::ffi::c_char; 6] = + ::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0"); + let mut macro_char_ptr_to_array: *mut ::core::ffi::c_char = + &raw mut c2rust_lvalue_12 as *mut ::core::ffi::c_char; + let mut c2rust_lvalue_13: [::core::ffi::c_int; 2] = + [42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int]; + let mut macro_int_array_ptr: *mut [::core::ffi::c_int; 2] = &raw mut c2rust_lvalue_13; + let mut c2rust_lvalue_14: [::core::ffi::c_char; 6] = + ::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0"); + let mut macro_char_array_ptr: *mut [::core::ffi::c_char; 6] = &raw mut c2rust_lvalue_14; } #[no_mangle] pub unsafe extern "C" fn deref_addrof() { diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.2024.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.2024.clang15.snap index c005935de1..10eb302bbe 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.2024.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@compound_literals.c.2024.clang15.snap @@ -16,35 +16,27 @@ expression: cat tests/snapshots/compound_literals.2024.clang15.rs pub static mut static_single_int: ::core::ffi::c_int = 42; static mut c2rust_lvalue: ::core::ffi::c_int = 42; #[unsafe(no_mangle)] -pub static mut static_single_int_ptr: *mut ::core::ffi::c_int = - &raw const c2rust_lvalue as *mut ::core::ffi::c_int; +pub static mut static_single_int_ptr: *mut ::core::ffi::c_int = &raw mut c2rust_lvalue; static mut c2rust_lvalue_0: [::core::ffi::c_int; 2] = [42, 9001]; #[unsafe(no_mangle)] pub static mut static_int_ptr_to_array: *mut ::core::ffi::c_int = - &raw const c2rust_lvalue_0 as *mut ::core::ffi::c_int; + &raw mut c2rust_lvalue_0 as *mut ::core::ffi::c_int; static mut c2rust_lvalue_1: [::core::ffi::c_int; 2] = [42, 9001]; #[unsafe(no_mangle)] pub static mut static_volatile_int_ptr_to_array: *mut ::core::ffi::c_int = - &raw const c2rust_lvalue_1 as *mut ::core::ffi::c_int as *mut ::core::ffi::c_int; + &raw mut c2rust_lvalue_1 as *mut ::core::ffi::c_int as *mut ::core::ffi::c_int; static mut c2rust_lvalue_2: [::core::ffi::c_int; 2] = [42, 9001]; #[unsafe(no_mangle)] -pub static mut static_int_array_ptr: *mut [::core::ffi::c_int; 2] = - &raw const c2rust_lvalue_2 as *mut [::core::ffi::c_int; 2]; +pub static mut static_int_array_ptr: *mut [::core::ffi::c_int; 2] = &raw mut c2rust_lvalue_2; static mut c2rust_lvalue_3: [::core::ffi::c_char; 6] = unsafe { ::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0") }; #[unsafe(no_mangle)] pub static mut static_char_ptr_to_array: *mut ::core::ffi::c_char = - &raw const c2rust_lvalue_3 as *mut ::core::ffi::c_char; + &raw mut c2rust_lvalue_3 as *mut ::core::ffi::c_char; static mut c2rust_lvalue_4: [::core::ffi::c_char; 6] = unsafe { ::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0") }; #[unsafe(no_mangle)] -pub static mut static_char_array_ptr: *mut [::core::ffi::c_char; 6] = - &raw const c2rust_lvalue_4 as *mut [::core::ffi::c_char; 6]; -pub const SINGLE_INT: ::core::ffi::c_int = 42 as ::core::ffi::c_int; -pub const INT_ARRAY: [::core::ffi::c_int; 2] = - [42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int]; -pub const CHAR_ARRAY: [::core::ffi::c_char; 6] = - unsafe { ::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0") }; +pub static mut static_char_array_ptr: *mut [::core::ffi::c_char; 6] = &raw mut c2rust_lvalue_4; #[unsafe(no_mangle)] pub unsafe extern "C" fn local_compound_literals() { let mut single_int: ::core::ffi::c_int = 42 as ::core::ffi::c_int; @@ -64,15 +56,23 @@ pub unsafe extern "C" fn local_compound_literals() { let mut c2rust_lvalue_9: [::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] = &raw mut c2rust_lvalue_9; - 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; - let mut macro_int_ptr_to_array: *mut ::core::ffi::c_int = INT_ARRAY.as_mut_ptr(); - let mut macro_char_ptr_to_array: *mut ::core::ffi::c_char = CHAR_ARRAY.as_mut_ptr(); - let mut macro_int_array_ptr: *mut [::core::ffi::c_int; 2] = - &mut INT_ARRAY as *mut [::core::ffi::c_int; 2]; - let mut macro_char_array_ptr: *mut [::core::ffi::c_char; 6] = - &mut CHAR_ARRAY as *mut [::core::ffi::c_char; 6]; + let mut macro_single_int: ::core::ffi::c_int = 42 as ::core::ffi::c_int; + let mut c2rust_lvalue_10: ::core::ffi::c_int = 42 as ::core::ffi::c_int; + let mut macro_single_int_ptr: *mut ::core::ffi::c_int = &raw mut c2rust_lvalue_10; + let mut c2rust_lvalue_11: [::core::ffi::c_int; 2] = + [42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int]; + let mut macro_int_ptr_to_array: *mut ::core::ffi::c_int = + &raw mut c2rust_lvalue_11 as *mut ::core::ffi::c_int; + let mut c2rust_lvalue_12: [::core::ffi::c_char; 6] = + ::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0"); + let mut macro_char_ptr_to_array: *mut ::core::ffi::c_char = + &raw mut c2rust_lvalue_12 as *mut ::core::ffi::c_char; + let mut c2rust_lvalue_13: [::core::ffi::c_int; 2] = + [42 as ::core::ffi::c_int, 9001 as ::core::ffi::c_int]; + let mut macro_int_array_ptr: *mut [::core::ffi::c_int; 2] = &raw mut c2rust_lvalue_13; + let mut c2rust_lvalue_14: [::core::ffi::c_char; 6] = + ::core::mem::transmute::<[u8; 6], [::core::ffi::c_char; 6]>(*b"hello\0"); + let mut macro_char_array_ptr: *mut [::core::ffi::c_char; 6] = &raw mut c2rust_lvalue_14; } #[unsafe(no_mangle)] pub unsafe extern "C" fn deref_addrof() { diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@empty_init.c.2024.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@empty_init.c.2024.clang15.snap index 4c884273fa..529682bbed 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@empty_init.c.2024.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@empty_init.c.2024.clang15.snap @@ -27,7 +27,7 @@ static mut c2rust_lvalue: Scope = Scope { next: ::core::ptr::null_mut::(), }; #[unsafe(no_mangle)] -pub static mut scope: *mut Scope = &raw const c2rust_lvalue as *mut Scope; +pub static mut scope: *mut Scope = &raw mut c2rust_lvalue; #[unsafe(no_mangle)] pub unsafe extern "C" fn foo() { let mut f: Foo_t = Foo_t { x: 0 }; diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2024.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2024.clang15.snap index 1efb461b0c..44bb7d57e8 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2024.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2024.clang15.snap @@ -115,4 +115,4 @@ pub unsafe extern "C" fn mut_to_const_ptr_cast( #[unsafe(no_mangle)] pub static mut global: ::core::ffi::c_int = 0; #[unsafe(no_mangle)] -pub static mut global_ptr: *const ::core::ffi::c_int = &raw const global as *mut ::core::ffi::c_int; +pub static mut global_ptr: *const ::core::ffi::c_int = &raw mut global; diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.2021.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.2021.clang15.snap index 8a46d85bb8..ca9db11936 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.2021.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.2021.clang15.snap @@ -11,7 +11,7 @@ expression: cat tests/snapshots/macros.2021.clang15.rs unused_assignments, unused_mut )] -#![feature(raw_ref_op)] +#![feature(ptr_from_ref, raw_ref_op)] extern "C" { fn extern_fn() -> ::core::ffi::c_int; } @@ -48,9 +48,7 @@ pub const LITERAL_ARRAY: [::core::ffi::c_int; 3] = [ 2 as ::core::ffi::c_int, 3 as ::core::ffi::c_int, ]; -pub const LITERAL_STRUCT: S = S { - i: 5 as ::core::ffi::c_int, -}; +pub const LITERAL_STRUCT: S = S { i: 5 }; pub const NESTED_INT: ::core::ffi::c_int = LITERAL_INT; pub const NESTED_BOOL: ::core::ffi::c_int = LITERAL_BOOL; pub const NESTED_FLOAT: ::core::ffi::c_double = LITERAL_FLOAT; @@ -82,108 +80,13 @@ pub const REF_MACRO: *const ::core::ffi::c_char = unsafe { .as_ptr() .offset(LITERAL_FLOAT as ::core::ffi::c_int as isize) }; -pub const REF_LITERAL: *mut S = &LITERAL_STRUCT as *const S as *mut S; +pub const REF_LITERAL: *const S = ::core::ptr::from_ref(&LITERAL_STRUCT); pub const TERNARY: ::core::ffi::c_int = if LITERAL_BOOL != 0 { 1 as ::core::ffi::c_int } else { 2 as ::core::ffi::c_int }; pub const MEMBER: ::core::ffi::c_int = LITERAL_STRUCT.i; -#[no_mangle] -pub unsafe extern "C" fn local_muts() { - let mut literal_int: ::core::ffi::c_int = LITERAL_INT; - let mut literal_bool: bool = LITERAL_BOOL != 0; - let mut literal_float: ::core::ffi::c_float = LITERAL_FLOAT as ::core::ffi::c_float; - let mut literal_char: ::core::ffi::c_char = LITERAL_CHAR as ::core::ffi::c_char; - let mut literal_str_ptr: *const ::core::ffi::c_char = LITERAL_STR.as_ptr(); - let mut literal_str: [::core::ffi::c_char; 6] = LITERAL_STR; - let mut literal_array: [::core::ffi::c_int; 3] = LITERAL_ARRAY; - let mut literal_struct: S = LITERAL_STRUCT; - let mut nested_int: ::core::ffi::c_int = NESTED_INT; - let mut nested_bool: bool = NESTED_BOOL != 0; - let mut nested_float: ::core::ffi::c_float = NESTED_FLOAT as ::core::ffi::c_float; - let mut nested_char: ::core::ffi::c_char = NESTED_CHAR as ::core::ffi::c_char; - let mut nested_str_ptr: *const ::core::ffi::c_char = NESTED_STR.as_ptr(); - let mut nested_str: [::core::ffi::c_char; 6] = NESTED_STR; - let mut nested_array: [::core::ffi::c_int; 3] = NESTED_ARRAY; - let mut nested_struct: S = NESTED_STRUCT; - let mut negative_int: ::core::ffi::c_int = NEGATIVE_INT; - let mut int_arithmetic: ::core::ffi::c_int = INT_ARITHMETIC; - let mut mixed_arithmetic: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; - let mut parens: ::core::ffi::c_int = PARENS; - let mut ptr_arithmetic: *const ::core::ffi::c_char = PTR_ARITHMETIC; - let mut widening_cast: ::core::ffi::c_ulonglong = WIDENING_CAST; - let mut narrowing_cast: ::core::ffi::c_char = NARROWING_CAST; - let mut conversion_cast: ::core::ffi::c_double = CONVERSION_CAST; - let mut indexing: ::core::ffi::c_char = INDEXING; - let mut str_concatenation_ptr: *const ::core::ffi::c_char = STR_CONCATENATION.as_ptr(); - let mut str_concatenation: [::core::ffi::c_char; 18] = STR_CONCATENATION; - let mut builtin: ::core::ffi::c_int = - (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; - let mut ref_indexing: *const ::core::ffi::c_char = REF_MACRO; - let mut ref_struct: *const S = REF_LITERAL; - let mut ternary: ::core::ffi::c_int = TERNARY; - let mut member: ::core::ffi::c_int = MEMBER; - let mut stmt_expr: ::core::ffi::c_float = ({ - let mut builtin_0: ::core::ffi::c_int = - (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; - let mut indexing_0: ::core::ffi::c_char = INDEXING; - let mut mixed: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; - let mut i: ::core::ffi::c_int = 0 as ::core::ffi::c_int; - while i < builtin_0 { - mixed += indexing_0 as ::core::ffi::c_float; - i += 1; - } - mixed - }); -} -#[no_mangle] -pub unsafe extern "C" fn local_consts() { - let literal_int: ::core::ffi::c_int = LITERAL_INT; - let literal_bool: bool = LITERAL_BOOL != 0; - let literal_float: ::core::ffi::c_float = LITERAL_FLOAT as ::core::ffi::c_float; - let literal_char: ::core::ffi::c_char = LITERAL_CHAR as ::core::ffi::c_char; - let literal_str_ptr: *const ::core::ffi::c_char = LITERAL_STR.as_ptr(); - let literal_str: [::core::ffi::c_char; 6] = LITERAL_STR; - let literal_array: [::core::ffi::c_int; 3] = LITERAL_ARRAY; - let literal_struct: S = LITERAL_STRUCT; - let nested_int: ::core::ffi::c_int = NESTED_INT; - let nested_bool: bool = NESTED_BOOL != 0; - let nested_float: ::core::ffi::c_float = NESTED_FLOAT as ::core::ffi::c_float; - let nested_char: ::core::ffi::c_char = NESTED_CHAR as ::core::ffi::c_char; - let nested_str_ptr: *const ::core::ffi::c_char = NESTED_STR.as_ptr(); - let nested_str: [::core::ffi::c_char; 6] = NESTED_STR; - let nested_array: [::core::ffi::c_int; 3] = NESTED_ARRAY; - let nested_struct: S = NESTED_STRUCT; - let negative_int: ::core::ffi::c_int = NEGATIVE_INT; - let int_arithmetic: ::core::ffi::c_int = INT_ARITHMETIC; - let mixed_arithmetic: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; - let parens: ::core::ffi::c_int = PARENS; - let ptr_arithmetic: *const ::core::ffi::c_char = PTR_ARITHMETIC; - let widening_cast: ::core::ffi::c_ulonglong = WIDENING_CAST; - let narrowing_cast: ::core::ffi::c_char = NARROWING_CAST; - let conversion_cast: ::core::ffi::c_double = CONVERSION_CAST; - let indexing: ::core::ffi::c_char = INDEXING; - let str_concatenation_ptr: *const ::core::ffi::c_char = STR_CONCATENATION.as_ptr(); - let str_concatenation: [::core::ffi::c_char; 18] = STR_CONCATENATION; - let builtin: ::core::ffi::c_int = (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; - let ref_indexing: *const ::core::ffi::c_char = REF_MACRO; - let ref_struct: *const S = REF_LITERAL; - let ternary: ::core::ffi::c_int = TERNARY; - let member: ::core::ffi::c_int = MEMBER; - let stmt_expr: ::core::ffi::c_float = ({ - let mut builtin_0: ::core::ffi::c_int = - (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; - let mut indexing_0: ::core::ffi::c_char = INDEXING; - let mut mixed: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; - let mut i: ::core::ffi::c_int = 0 as ::core::ffi::c_int; - while i < builtin_0 { - mixed += indexing_0 as ::core::ffi::c_float; - i += 1; - } - mixed - }); -} static mut global_static_const_literal_int: ::core::ffi::c_int = LITERAL_INT; static mut global_static_const_literal_bool: bool = LITERAL_BOOL != 0; static mut global_static_const_literal_float: ::core::ffi::c_float = @@ -194,6 +97,7 @@ static mut global_static_const_literal_str_ptr: *const ::core::ffi::c_char = LIT static mut global_static_const_literal_str: [::core::ffi::c_char; 6] = LITERAL_STR; static mut global_static_const_literal_array: [::core::ffi::c_int; 3] = LITERAL_ARRAY; static mut global_static_const_literal_struct: S = LITERAL_STRUCT; +static mut global_static_const_literal_struct_mut: S = S { i: 5 }; static mut global_static_const_nested_int: ::core::ffi::c_int = NESTED_INT; static mut global_static_const_nested_bool: bool = NESTED_BOOL != 0; static mut global_static_const_nested_float: ::core::ffi::c_float = @@ -223,8 +127,12 @@ static mut global_static_const_builtin: ::core::ffi::c_int = static mut global_static_const_ref_indexing: *const ::core::ffi::c_char = ::core::ptr::null::<::core::ffi::c_char>(); static mut global_static_const_ref_struct: *const S = REF_LITERAL; +static mut c2rust_lvalue: S = S { i: 5 }; +static mut global_static_const_ref_struct_mut: *mut S = + unsafe { &raw const c2rust_lvalue as *mut S }; static mut global_static_const_ternary: ::core::ffi::c_int = 0; static mut global_static_const_member: ::core::ffi::c_int = 0; +static mut global_static_const_member_mut: ::core::ffi::c_int = 0; #[no_mangle] pub unsafe extern "C" fn global_static_consts() {} #[no_mangle] @@ -245,6 +153,8 @@ pub static mut global_const_literal_array: [::core::ffi::c_int; 3] = LITERAL_ARR #[no_mangle] pub static mut global_const_literal_struct: S = LITERAL_STRUCT; #[no_mangle] +pub static mut global_const_literal_struct_mut: S = S { i: 5 }; +#[no_mangle] pub static mut global_const_nested_int: ::core::ffi::c_int = NESTED_INT; #[no_mangle] pub static mut global_const_nested_bool: bool = NESTED_BOOL != 0; @@ -294,11 +204,134 @@ pub static mut global_const_ref_indexing: *const ::core::ffi::c_char = ::core::ptr::null::<::core::ffi::c_char>(); #[no_mangle] pub static mut global_const_ref_struct: *const S = REF_LITERAL; +static mut c2rust_lvalue_0: S = S { i: 5 }; +#[no_mangle] +pub static mut global_const_ref_struct_mut: *mut S = + unsafe { &raw const c2rust_lvalue_0 as *mut S }; #[no_mangle] pub static mut global_const_ternary: ::core::ffi::c_int = 0; #[no_mangle] pub static mut global_const_member: ::core::ffi::c_int = 0; #[no_mangle] +pub static mut global_const_member_mut: ::core::ffi::c_int = 0; +#[no_mangle] +pub unsafe extern "C" fn local_muts() { + let mut literal_int: ::core::ffi::c_int = LITERAL_INT; + let mut literal_bool: bool = LITERAL_BOOL != 0; + let mut literal_float: ::core::ffi::c_float = LITERAL_FLOAT as ::core::ffi::c_float; + let mut literal_char: ::core::ffi::c_char = LITERAL_CHAR as ::core::ffi::c_char; + let mut literal_str_ptr: *const ::core::ffi::c_char = LITERAL_STR.as_ptr(); + let mut literal_str: [::core::ffi::c_char; 6] = LITERAL_STR; + let mut literal_array: [::core::ffi::c_int; 3] = LITERAL_ARRAY; + let mut literal_struct: S = LITERAL_STRUCT; + let mut literal_struct_mut: S = S { + i: 5 as ::core::ffi::c_int, + }; + let mut nested_int: ::core::ffi::c_int = NESTED_INT; + let mut nested_bool: bool = NESTED_BOOL != 0; + let mut nested_float: ::core::ffi::c_float = NESTED_FLOAT as ::core::ffi::c_float; + let mut nested_char: ::core::ffi::c_char = NESTED_CHAR as ::core::ffi::c_char; + let mut nested_str_ptr: *const ::core::ffi::c_char = NESTED_STR.as_ptr(); + let mut nested_str: [::core::ffi::c_char; 6] = NESTED_STR; + let mut nested_array: [::core::ffi::c_int; 3] = NESTED_ARRAY; + let mut nested_struct: S = NESTED_STRUCT; + let mut negative_int: ::core::ffi::c_int = NEGATIVE_INT; + let mut int_arithmetic: ::core::ffi::c_int = INT_ARITHMETIC; + let mut mixed_arithmetic: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; + let mut parens: ::core::ffi::c_int = PARENS; + let mut ptr_arithmetic: *const ::core::ffi::c_char = PTR_ARITHMETIC; + let mut widening_cast: ::core::ffi::c_ulonglong = WIDENING_CAST; + let mut narrowing_cast: ::core::ffi::c_char = NARROWING_CAST; + let mut conversion_cast: ::core::ffi::c_double = CONVERSION_CAST; + let mut indexing: ::core::ffi::c_char = INDEXING; + let mut str_concatenation_ptr: *const ::core::ffi::c_char = STR_CONCATENATION.as_ptr(); + let mut str_concatenation: [::core::ffi::c_char; 18] = STR_CONCATENATION; + let mut builtin: ::core::ffi::c_int = + (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; + let mut ref_indexing: *const ::core::ffi::c_char = REF_MACRO; + let mut ref_struct: *const S = REF_LITERAL; + let mut c2rust_lvalue_1: S = S { + i: 5 as ::core::ffi::c_int, + }; + let mut ref_struct_mut: *mut S = &raw mut c2rust_lvalue_1; + let mut ternary: ::core::ffi::c_int = TERNARY; + let mut member: ::core::ffi::c_int = MEMBER; + let mut member_mut: ::core::ffi::c_int = S { + i: 5 as ::core::ffi::c_int, + } + .i; + let mut stmt_expr: ::core::ffi::c_float = ({ + let mut builtin_0: ::core::ffi::c_int = + (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; + let mut indexing_0: ::core::ffi::c_char = INDEXING; + let mut mixed: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; + let mut i: ::core::ffi::c_int = 0 as ::core::ffi::c_int; + while i < builtin_0 { + mixed += indexing_0 as ::core::ffi::c_float; + i += 1; + } + mixed + }); +} +#[no_mangle] +pub unsafe extern "C" fn local_consts() { + let literal_int: ::core::ffi::c_int = LITERAL_INT; + let literal_bool: bool = LITERAL_BOOL != 0; + let literal_float: ::core::ffi::c_float = LITERAL_FLOAT as ::core::ffi::c_float; + let literal_char: ::core::ffi::c_char = LITERAL_CHAR as ::core::ffi::c_char; + let literal_str_ptr: *const ::core::ffi::c_char = LITERAL_STR.as_ptr(); + let literal_str: [::core::ffi::c_char; 6] = LITERAL_STR; + let literal_array: [::core::ffi::c_int; 3] = LITERAL_ARRAY; + let literal_struct: S = LITERAL_STRUCT; + let literal_struct_mut: S = S { + i: 5 as ::core::ffi::c_int, + }; + let nested_int: ::core::ffi::c_int = NESTED_INT; + let nested_bool: bool = NESTED_BOOL != 0; + let nested_float: ::core::ffi::c_float = NESTED_FLOAT as ::core::ffi::c_float; + let nested_char: ::core::ffi::c_char = NESTED_CHAR as ::core::ffi::c_char; + let nested_str_ptr: *const ::core::ffi::c_char = NESTED_STR.as_ptr(); + let nested_str: [::core::ffi::c_char; 6] = NESTED_STR; + let nested_array: [::core::ffi::c_int; 3] = NESTED_ARRAY; + let nested_struct: S = NESTED_STRUCT; + let negative_int: ::core::ffi::c_int = NEGATIVE_INT; + let int_arithmetic: ::core::ffi::c_int = INT_ARITHMETIC; + let mixed_arithmetic: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; + let parens: ::core::ffi::c_int = PARENS; + let ptr_arithmetic: *const ::core::ffi::c_char = PTR_ARITHMETIC; + let widening_cast: ::core::ffi::c_ulonglong = WIDENING_CAST; + let narrowing_cast: ::core::ffi::c_char = NARROWING_CAST; + let conversion_cast: ::core::ffi::c_double = CONVERSION_CAST; + let indexing: ::core::ffi::c_char = INDEXING; + let str_concatenation_ptr: *const ::core::ffi::c_char = STR_CONCATENATION.as_ptr(); + let str_concatenation: [::core::ffi::c_char; 18] = STR_CONCATENATION; + let builtin: ::core::ffi::c_int = (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; + let ref_indexing: *const ::core::ffi::c_char = REF_MACRO; + let ref_struct: *const S = REF_LITERAL; + let mut c2rust_lvalue_1: S = S { + i: 5 as ::core::ffi::c_int, + }; + let ref_struct_mut: *mut S = &raw mut c2rust_lvalue_1; + let ternary: ::core::ffi::c_int = TERNARY; + let member: ::core::ffi::c_int = MEMBER; + let member_mut: ::core::ffi::c_int = S { + i: 5 as ::core::ffi::c_int, + } + .i; + let stmt_expr: ::core::ffi::c_float = ({ + let mut builtin_0: ::core::ffi::c_int = + (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; + let mut indexing_0: ::core::ffi::c_char = INDEXING; + let mut mixed: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; + let mut i: ::core::ffi::c_int = 0 as ::core::ffi::c_int; + while i < builtin_0 { + mixed += indexing_0 as ::core::ffi::c_float; + i += 1; + } + mixed + }); +} +#[no_mangle] pub unsafe extern "C" fn test_fn_macro(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { return x * x; } @@ -402,11 +435,13 @@ unsafe extern "C" fn c2rust_run_static_initializers() { global_static_const_ref_indexing = REF_MACRO; global_static_const_ternary = TERNARY; global_static_const_member = MEMBER; + global_static_const_member_mut = S { i: 5 }.i; global_const_ptr_arithmetic = PTR_ARITHMETIC; global_const_indexing = INDEXING; global_const_ref_indexing = REF_MACRO; global_const_ternary = TERNARY; global_const_member = MEMBER; + global_const_member_mut = S { i: 5 }.i; } #[used] #[cfg_attr(target_os = "linux", link_section = ".init_array")] diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.2024.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.2024.clang15.snap index 28aee86cb5..a3d4197c5f 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.2024.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.2024.clang15.snap @@ -48,9 +48,7 @@ pub const LITERAL_ARRAY: [::core::ffi::c_int; 3] = [ 2 as ::core::ffi::c_int, 3 as ::core::ffi::c_int, ]; -pub const LITERAL_STRUCT: S = S { - i: 5 as ::core::ffi::c_int, -}; +pub const LITERAL_STRUCT: S = S { i: 5 }; pub const NESTED_INT: ::core::ffi::c_int = LITERAL_INT; pub const NESTED_BOOL: ::core::ffi::c_int = LITERAL_BOOL; pub const NESTED_FLOAT: ::core::ffi::c_double = LITERAL_FLOAT; @@ -82,108 +80,13 @@ pub const REF_MACRO: *const ::core::ffi::c_char = unsafe { .as_ptr() .offset(LITERAL_FLOAT as ::core::ffi::c_int as isize) }; -pub const REF_LITERAL: *mut S = &LITERAL_STRUCT as *const S as *mut S; +pub const REF_LITERAL: *const S = ::core::ptr::from_ref(&LITERAL_STRUCT); pub const TERNARY: ::core::ffi::c_int = if LITERAL_BOOL != 0 { 1 as ::core::ffi::c_int } else { 2 as ::core::ffi::c_int }; pub const MEMBER: ::core::ffi::c_int = LITERAL_STRUCT.i; -#[unsafe(no_mangle)] -pub unsafe extern "C" fn local_muts() { - let mut literal_int: ::core::ffi::c_int = LITERAL_INT; - let mut literal_bool: bool = LITERAL_BOOL != 0; - let mut literal_float: ::core::ffi::c_float = LITERAL_FLOAT as ::core::ffi::c_float; - let mut literal_char: ::core::ffi::c_char = LITERAL_CHAR as ::core::ffi::c_char; - let mut literal_str_ptr: *const ::core::ffi::c_char = LITERAL_STR.as_ptr(); - let mut literal_str: [::core::ffi::c_char; 6] = LITERAL_STR; - let mut literal_array: [::core::ffi::c_int; 3] = LITERAL_ARRAY; - let mut literal_struct: S = LITERAL_STRUCT; - let mut nested_int: ::core::ffi::c_int = NESTED_INT; - let mut nested_bool: bool = NESTED_BOOL != 0; - let mut nested_float: ::core::ffi::c_float = NESTED_FLOAT as ::core::ffi::c_float; - let mut nested_char: ::core::ffi::c_char = NESTED_CHAR as ::core::ffi::c_char; - let mut nested_str_ptr: *const ::core::ffi::c_char = NESTED_STR.as_ptr(); - let mut nested_str: [::core::ffi::c_char; 6] = NESTED_STR; - let mut nested_array: [::core::ffi::c_int; 3] = NESTED_ARRAY; - let mut nested_struct: S = NESTED_STRUCT; - let mut negative_int: ::core::ffi::c_int = NEGATIVE_INT; - let mut int_arithmetic: ::core::ffi::c_int = INT_ARITHMETIC; - let mut mixed_arithmetic: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; - let mut parens: ::core::ffi::c_int = PARENS; - let mut ptr_arithmetic: *const ::core::ffi::c_char = PTR_ARITHMETIC; - let mut widening_cast: ::core::ffi::c_ulonglong = WIDENING_CAST; - let mut narrowing_cast: ::core::ffi::c_char = NARROWING_CAST; - let mut conversion_cast: ::core::ffi::c_double = CONVERSION_CAST; - let mut indexing: ::core::ffi::c_char = INDEXING; - let mut str_concatenation_ptr: *const ::core::ffi::c_char = STR_CONCATENATION.as_ptr(); - let mut str_concatenation: [::core::ffi::c_char; 18] = STR_CONCATENATION; - let mut builtin: ::core::ffi::c_int = - (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; - let mut ref_indexing: *const ::core::ffi::c_char = REF_MACRO; - let mut ref_struct: *const S = REF_LITERAL; - let mut ternary: ::core::ffi::c_int = TERNARY; - let mut member: ::core::ffi::c_int = MEMBER; - let mut stmt_expr: ::core::ffi::c_float = ({ - let mut builtin_0: ::core::ffi::c_int = - (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; - let mut indexing_0: ::core::ffi::c_char = INDEXING; - let mut mixed: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; - let mut i: ::core::ffi::c_int = 0 as ::core::ffi::c_int; - while i < builtin_0 { - mixed += indexing_0 as ::core::ffi::c_float; - i += 1; - } - mixed - }); -} -#[unsafe(no_mangle)] -pub unsafe extern "C" fn local_consts() { - let literal_int: ::core::ffi::c_int = LITERAL_INT; - let literal_bool: bool = LITERAL_BOOL != 0; - let literal_float: ::core::ffi::c_float = LITERAL_FLOAT as ::core::ffi::c_float; - let literal_char: ::core::ffi::c_char = LITERAL_CHAR as ::core::ffi::c_char; - let literal_str_ptr: *const ::core::ffi::c_char = LITERAL_STR.as_ptr(); - let literal_str: [::core::ffi::c_char; 6] = LITERAL_STR; - let literal_array: [::core::ffi::c_int; 3] = LITERAL_ARRAY; - let literal_struct: S = LITERAL_STRUCT; - let nested_int: ::core::ffi::c_int = NESTED_INT; - let nested_bool: bool = NESTED_BOOL != 0; - let nested_float: ::core::ffi::c_float = NESTED_FLOAT as ::core::ffi::c_float; - let nested_char: ::core::ffi::c_char = NESTED_CHAR as ::core::ffi::c_char; - let nested_str_ptr: *const ::core::ffi::c_char = NESTED_STR.as_ptr(); - let nested_str: [::core::ffi::c_char; 6] = NESTED_STR; - let nested_array: [::core::ffi::c_int; 3] = NESTED_ARRAY; - let nested_struct: S = NESTED_STRUCT; - let negative_int: ::core::ffi::c_int = NEGATIVE_INT; - let int_arithmetic: ::core::ffi::c_int = INT_ARITHMETIC; - let mixed_arithmetic: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; - let parens: ::core::ffi::c_int = PARENS; - let ptr_arithmetic: *const ::core::ffi::c_char = PTR_ARITHMETIC; - let widening_cast: ::core::ffi::c_ulonglong = WIDENING_CAST; - let narrowing_cast: ::core::ffi::c_char = NARROWING_CAST; - let conversion_cast: ::core::ffi::c_double = CONVERSION_CAST; - let indexing: ::core::ffi::c_char = INDEXING; - let str_concatenation_ptr: *const ::core::ffi::c_char = STR_CONCATENATION.as_ptr(); - let str_concatenation: [::core::ffi::c_char; 18] = STR_CONCATENATION; - let builtin: ::core::ffi::c_int = (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; - let ref_indexing: *const ::core::ffi::c_char = REF_MACRO; - let ref_struct: *const S = REF_LITERAL; - let ternary: ::core::ffi::c_int = TERNARY; - let member: ::core::ffi::c_int = MEMBER; - let stmt_expr: ::core::ffi::c_float = ({ - let mut builtin_0: ::core::ffi::c_int = - (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; - let mut indexing_0: ::core::ffi::c_char = INDEXING; - let mut mixed: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; - let mut i: ::core::ffi::c_int = 0 as ::core::ffi::c_int; - while i < builtin_0 { - mixed += indexing_0 as ::core::ffi::c_float; - i += 1; - } - mixed - }); -} static mut global_static_const_literal_int: ::core::ffi::c_int = LITERAL_INT; static mut global_static_const_literal_bool: bool = LITERAL_BOOL != 0; static mut global_static_const_literal_float: ::core::ffi::c_float = @@ -194,6 +97,7 @@ static mut global_static_const_literal_str_ptr: *const ::core::ffi::c_char = LIT static mut global_static_const_literal_str: [::core::ffi::c_char; 6] = LITERAL_STR; static mut global_static_const_literal_array: [::core::ffi::c_int; 3] = LITERAL_ARRAY; static mut global_static_const_literal_struct: S = LITERAL_STRUCT; +static mut global_static_const_literal_struct_mut: S = S { i: 5 }; static mut global_static_const_nested_int: ::core::ffi::c_int = NESTED_INT; static mut global_static_const_nested_bool: bool = NESTED_BOOL != 0; static mut global_static_const_nested_float: ::core::ffi::c_float = @@ -223,8 +127,11 @@ static mut global_static_const_builtin: ::core::ffi::c_int = static mut global_static_const_ref_indexing: *const ::core::ffi::c_char = ::core::ptr::null::<::core::ffi::c_char>(); static mut global_static_const_ref_struct: *const S = REF_LITERAL; +static mut c2rust_lvalue: S = S { i: 5 }; +static mut global_static_const_ref_struct_mut: *mut S = &raw mut c2rust_lvalue; static mut global_static_const_ternary: ::core::ffi::c_int = 0; static mut global_static_const_member: ::core::ffi::c_int = 0; +static mut global_static_const_member_mut: ::core::ffi::c_int = 0; #[unsafe(no_mangle)] pub unsafe extern "C" fn global_static_consts() {} #[unsafe(no_mangle)] @@ -245,6 +152,8 @@ pub static mut global_const_literal_array: [::core::ffi::c_int; 3] = LITERAL_ARR #[unsafe(no_mangle)] pub static mut global_const_literal_struct: S = LITERAL_STRUCT; #[unsafe(no_mangle)] +pub static mut global_const_literal_struct_mut: S = S { i: 5 }; +#[unsafe(no_mangle)] pub static mut global_const_nested_int: ::core::ffi::c_int = NESTED_INT; #[unsafe(no_mangle)] pub static mut global_const_nested_bool: bool = NESTED_BOOL != 0; @@ -294,11 +203,133 @@ pub static mut global_const_ref_indexing: *const ::core::ffi::c_char = ::core::ptr::null::<::core::ffi::c_char>(); #[unsafe(no_mangle)] pub static mut global_const_ref_struct: *const S = REF_LITERAL; +static mut c2rust_lvalue_0: S = S { i: 5 }; +#[unsafe(no_mangle)] +pub static mut global_const_ref_struct_mut: *mut S = &raw mut c2rust_lvalue_0; #[unsafe(no_mangle)] pub static mut global_const_ternary: ::core::ffi::c_int = 0; #[unsafe(no_mangle)] pub static mut global_const_member: ::core::ffi::c_int = 0; #[unsafe(no_mangle)] +pub static mut global_const_member_mut: ::core::ffi::c_int = 0; +#[unsafe(no_mangle)] +pub unsafe extern "C" fn local_muts() { + let mut literal_int: ::core::ffi::c_int = LITERAL_INT; + let mut literal_bool: bool = LITERAL_BOOL != 0; + let mut literal_float: ::core::ffi::c_float = LITERAL_FLOAT as ::core::ffi::c_float; + let mut literal_char: ::core::ffi::c_char = LITERAL_CHAR as ::core::ffi::c_char; + let mut literal_str_ptr: *const ::core::ffi::c_char = LITERAL_STR.as_ptr(); + let mut literal_str: [::core::ffi::c_char; 6] = LITERAL_STR; + let mut literal_array: [::core::ffi::c_int; 3] = LITERAL_ARRAY; + let mut literal_struct: S = LITERAL_STRUCT; + let mut literal_struct_mut: S = S { + i: 5 as ::core::ffi::c_int, + }; + let mut nested_int: ::core::ffi::c_int = NESTED_INT; + let mut nested_bool: bool = NESTED_BOOL != 0; + let mut nested_float: ::core::ffi::c_float = NESTED_FLOAT as ::core::ffi::c_float; + let mut nested_char: ::core::ffi::c_char = NESTED_CHAR as ::core::ffi::c_char; + let mut nested_str_ptr: *const ::core::ffi::c_char = NESTED_STR.as_ptr(); + let mut nested_str: [::core::ffi::c_char; 6] = NESTED_STR; + let mut nested_array: [::core::ffi::c_int; 3] = NESTED_ARRAY; + let mut nested_struct: S = NESTED_STRUCT; + let mut negative_int: ::core::ffi::c_int = NEGATIVE_INT; + let mut int_arithmetic: ::core::ffi::c_int = INT_ARITHMETIC; + let mut mixed_arithmetic: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; + let mut parens: ::core::ffi::c_int = PARENS; + let mut ptr_arithmetic: *const ::core::ffi::c_char = PTR_ARITHMETIC; + let mut widening_cast: ::core::ffi::c_ulonglong = WIDENING_CAST; + let mut narrowing_cast: ::core::ffi::c_char = NARROWING_CAST; + let mut conversion_cast: ::core::ffi::c_double = CONVERSION_CAST; + let mut indexing: ::core::ffi::c_char = INDEXING; + let mut str_concatenation_ptr: *const ::core::ffi::c_char = STR_CONCATENATION.as_ptr(); + let mut str_concatenation: [::core::ffi::c_char; 18] = STR_CONCATENATION; + let mut builtin: ::core::ffi::c_int = + (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; + let mut ref_indexing: *const ::core::ffi::c_char = REF_MACRO; + let mut ref_struct: *const S = REF_LITERAL; + let mut c2rust_lvalue_1: S = S { + i: 5 as ::core::ffi::c_int, + }; + let mut ref_struct_mut: *mut S = &raw mut c2rust_lvalue_1; + let mut ternary: ::core::ffi::c_int = TERNARY; + let mut member: ::core::ffi::c_int = MEMBER; + let mut member_mut: ::core::ffi::c_int = S { + i: 5 as ::core::ffi::c_int, + } + .i; + let mut stmt_expr: ::core::ffi::c_float = ({ + let mut builtin_0: ::core::ffi::c_int = + (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; + let mut indexing_0: ::core::ffi::c_char = INDEXING; + let mut mixed: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; + let mut i: ::core::ffi::c_int = 0 as ::core::ffi::c_int; + while i < builtin_0 { + mixed += indexing_0 as ::core::ffi::c_float; + i += 1; + } + mixed + }); +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn local_consts() { + let literal_int: ::core::ffi::c_int = LITERAL_INT; + let literal_bool: bool = LITERAL_BOOL != 0; + let literal_float: ::core::ffi::c_float = LITERAL_FLOAT as ::core::ffi::c_float; + let literal_char: ::core::ffi::c_char = LITERAL_CHAR as ::core::ffi::c_char; + let literal_str_ptr: *const ::core::ffi::c_char = LITERAL_STR.as_ptr(); + let literal_str: [::core::ffi::c_char; 6] = LITERAL_STR; + let literal_array: [::core::ffi::c_int; 3] = LITERAL_ARRAY; + let literal_struct: S = LITERAL_STRUCT; + let literal_struct_mut: S = S { + i: 5 as ::core::ffi::c_int, + }; + let nested_int: ::core::ffi::c_int = NESTED_INT; + let nested_bool: bool = NESTED_BOOL != 0; + let nested_float: ::core::ffi::c_float = NESTED_FLOAT as ::core::ffi::c_float; + let nested_char: ::core::ffi::c_char = NESTED_CHAR as ::core::ffi::c_char; + let nested_str_ptr: *const ::core::ffi::c_char = NESTED_STR.as_ptr(); + let nested_str: [::core::ffi::c_char; 6] = NESTED_STR; + let nested_array: [::core::ffi::c_int; 3] = NESTED_ARRAY; + let nested_struct: S = NESTED_STRUCT; + let negative_int: ::core::ffi::c_int = NEGATIVE_INT; + let int_arithmetic: ::core::ffi::c_int = INT_ARITHMETIC; + let mixed_arithmetic: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; + let parens: ::core::ffi::c_int = PARENS; + let ptr_arithmetic: *const ::core::ffi::c_char = PTR_ARITHMETIC; + let widening_cast: ::core::ffi::c_ulonglong = WIDENING_CAST; + let narrowing_cast: ::core::ffi::c_char = NARROWING_CAST; + let conversion_cast: ::core::ffi::c_double = CONVERSION_CAST; + let indexing: ::core::ffi::c_char = INDEXING; + let str_concatenation_ptr: *const ::core::ffi::c_char = STR_CONCATENATION.as_ptr(); + let str_concatenation: [::core::ffi::c_char; 18] = STR_CONCATENATION; + let builtin: ::core::ffi::c_int = (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; + let ref_indexing: *const ::core::ffi::c_char = REF_MACRO; + let ref_struct: *const S = REF_LITERAL; + let mut c2rust_lvalue_1: S = S { + i: 5 as ::core::ffi::c_int, + }; + let ref_struct_mut: *mut S = &raw mut c2rust_lvalue_1; + let ternary: ::core::ffi::c_int = TERNARY; + let member: ::core::ffi::c_int = MEMBER; + let member_mut: ::core::ffi::c_int = S { + i: 5 as ::core::ffi::c_int, + } + .i; + let stmt_expr: ::core::ffi::c_float = ({ + let mut builtin_0: ::core::ffi::c_int = + (LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32; + let mut indexing_0: ::core::ffi::c_char = INDEXING; + let mut mixed: ::core::ffi::c_float = MIXED_ARITHMETIC as ::core::ffi::c_float; + let mut i: ::core::ffi::c_int = 0 as ::core::ffi::c_int; + while i < builtin_0 { + mixed += indexing_0 as ::core::ffi::c_float; + i += 1; + } + mixed + }); +} +#[unsafe(no_mangle)] pub unsafe extern "C" fn test_fn_macro(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { return x * x; } @@ -402,11 +433,13 @@ unsafe extern "C" fn c2rust_run_static_initializers() { global_static_const_ref_indexing = REF_MACRO; global_static_const_ternary = TERNARY; global_static_const_member = MEMBER; + global_static_const_member_mut = S { i: 5 }.i; global_const_ptr_arithmetic = PTR_ARITHMETIC; global_const_indexing = INDEXING; global_const_ref_indexing = REF_MACRO; global_const_ternary = TERNARY; global_const_member = MEMBER; + global_const_member_mut = S { i: 5 }.i; } #[used] #[cfg_attr(target_os = "linux", unsafe(link_section = ".init_array"))] diff --git a/docs/source_walkthrough.md b/docs/source_walkthrough.md index 9b07d228fa..9eae39d6d4 100644 --- a/docs/source_walkthrough.md +++ b/docs/source_walkthrough.md @@ -218,11 +218,6 @@ This allows emitting different code in such situations, to account for the different lifetimes of compound literals for example. `is_static` usually implies `is_const`, but not always. -The `decay_ref` attribute keeps track of whether or not -we're in a context in which Rust will infer that a reference can decay in to a pointer. -This can happen at method calls, variable initializers, and possibly more locations. -This allows the translation to omit some otherwise superfluous casts. - The `va_decl` attribute indicates which, if any, declaration corresponds to the variable-argument list for the current variadic function. This enables us to drop the associated declaration,