diff --git a/c2rust-ast-builder/src/builder.rs b/c2rust-ast-builder/src/builder.rs index 489194ebb0..15877b37e8 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)), @@ -826,7 +833,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), @@ -835,6 +842,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/convert_type.rs b/c2rust-transpile/src/convert_type.rs index ec11b14059..970e92ab42 100644 --- a/c2rust-transpile/src/convert_type.rs +++ b/c2rust-transpile/src/convert_type.rs @@ -268,44 +268,49 @@ impl TypeConverter { Ok(mk().unsafe_().extern_("C").barefn_ty(fn_ty)) } + /// Converts the qualified type of a pointer. pub fn convert_pointer( &mut self, ctxt: &TypedAstContext, qtype: CQualTypeId, ) -> TranslationResult> { - let mutbl = if qtype.qualifiers.is_const { - Mutability::Immutable + let pointee_ty = self.convert_pointee(ctxt, qtype.ctype)?; + + if let CTypeKind::Function(..) = ctxt.resolve_type(qtype.ctype).kind { + // Function pointers are translated to Option applied to the function type + // in order to support NULL function pointers natively + let param = mk().angle_bracketed_args(vec![pointee_ty]); + Ok(mk().path_ty(vec![mk().path_segment_with_args("Option", param)])) } else { - Mutability::Mutable - }; + let mutbl = if qtype.qualifiers.is_const { + Mutability::Immutable + } else { + Mutability::Mutable + }; - match ctxt.resolve_type(qtype.ctype).kind { + Ok(mk().set_mutbl(mutbl).ptr_ty(pointee_ty)) + } + } + + /// Converts the pointee type of a pointer. + pub fn convert_pointee( + &mut self, + ctxt: &TypedAstContext, + ctype: CTypeId, + ) -> TranslationResult> { + match ctxt.resolve_type(ctype).kind { // While void converts to () in function returns, it converts to c_void // in the case of pointers. - CTypeKind::Void => Ok(mk() - .set_mutbl(mutbl) - .ptr_ty(mk().abs_path_ty(vec!["core", "ffi", "c_void"]))), + CTypeKind::Void => Ok(mk().abs_path_ty(vec!["core", "ffi", "c_void"])), CTypeKind::VariableArray(mut elt, _len) => { while let CTypeKind::VariableArray(elt_, _) = ctxt.resolve_type(elt).kind { elt = elt_ } - let child_ty = self.convert(ctxt, elt)?; - Ok(mk().set_mutbl(mutbl).ptr_ty(child_ty)) - } - - // Function pointers are translated to Option applied to the function type - // in order to support NULL function pointers natively - CTypeKind::Function(..) => { - let fn_ty = self.convert(ctxt, qtype.ctype)?; - let param = mk().angle_bracketed_args(vec![fn_ty]); - Ok(mk().path_ty(vec![mk().path_segment_with_args("Option", param)])) + self.convert(ctxt, elt) } - _ => { - let child_ty = self.convert(ctxt, qtype.ctype)?; - Ok(mk().set_mutbl(mutbl).ptr_ty(child_ty)) - } + _ => self.convert(ctxt, ctype), } } 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/literals.rs b/c2rust-transpile/src/translator/literals.rs index 200b27bb66..cf82833c5c 100644 --- a/c2rust-transpile/src/translator/literals.rs +++ b/c2rust-transpile/src/translator/literals.rs @@ -151,31 +151,42 @@ impl<'c> Translation<'c> { Ok(WithStmts::new_val(val)) } - CLiteral::String(ref val, width) => { - let mut val = val.to_owned(); - let num_elems = match self.ast_context.resolve_type(ty.ctype).kind { - CTypeKind::ConstantArray(_elem_ty, num_elems) => num_elems, - ref kind => { - panic!("String literal with unknown size: {val:?}, kind = {kind:?}") - } - }; - - // Match the literal size to the expected size padding with zeros as needed - let size = num_elems * (width as usize); - val.resize(size, 0); + CLiteral::String(ref bytes, element_size) => { + let bytes_padded = self.string_literal_bytes(ty.ctype, bytes, element_size); // std::mem::transmute::<[u8; size], ctype>(*b"xxxx") - let u8_ty = mk().path_ty(vec!["u8"]); - let width_lit = mk().lit_expr(mk().int_unsuffixed_lit(val.len() as u128)); - Ok(WithStmts::new_unsafe_val(transmute_expr( - mk().array_ty(u8_ty, width_lit), + let array_ty = mk().array_ty( + mk().ident_ty("u8"), + mk().lit_expr(bytes_padded.len() as u128), + ); + let val = transmute_expr( + array_ty, self.convert_type(ty.ctype)?, - mk().unary_expr(UnOp::Deref(Default::default()), mk().lit_expr(val)), - ))) + mk().unary_expr(UnOp::Deref(Default::default()), mk().lit_expr(bytes_padded)), + ); + Ok(WithStmts::new_unsafe_val(val)) } } } + /// Returns the bytes of a string literal, including any additional zero bytes to pad the + /// literal to the expected size. + pub fn string_literal_bytes(&self, ctype: CTypeId, bytes: &[u8], element_size: u8) -> Vec { + let num_elems = match self.ast_context.resolve_type(ctype).kind { + CTypeKind::ConstantArray(_, num_elems) => num_elems, + ref kind => { + panic!("String literal with unknown size: {bytes:?}, kind = {kind:?}") + } + }; + + let size = num_elems * (element_size as usize); + let mut bytes_padded = Vec::with_capacity(size); + bytes_padded.extend(bytes); + bytes_padded.resize(size, 0); + + bytes_padded + } + /// Convert an initialization list into an expression. These initialization lists can be /// used as array literals, struct literals, and union literals in code. pub fn convert_init_list( diff --git a/c2rust-transpile/src/translator/mod.rs b/c2rust-transpile/src/translator/mod.rs index 1ffbb889ff..bb32d68827 100644 --- a/c2rust-transpile/src/translator/mod.rs +++ b/c2rust-transpile/src/translator/mod.rs @@ -3071,6 +3071,14 @@ impl<'c> Translation<'c> { .convert(&self.ast_context, type_id) } + fn convert_pointee_type(&self, type_id: CTypeId) -> TranslationResult> { + self.import_type(type_id); + + self.type_converter + .borrow_mut() + .convert_pointee(&self.ast_context, type_id) + } + /// Construct an expression for a NULL at any type, including forward declarations, /// function pointers, and normal pointers. fn null_ptr(&self, type_id: CTypeId, is_static: bool) -> TranslationResult> { @@ -3085,13 +3093,8 @@ impl<'c> Translation<'c> { let ty = self.convert_type(type_id)?; let mut zero = mk().lit_expr(mk().int_unsuffixed_lit(0)); if is_static && !pointee.qualifiers.is_const { - let mut qtype = pointee; - qtype.qualifiers.is_const = true; - let ty_ = self - .type_converter - .borrow_mut() - .convert_pointer(&self.ast_context, qtype)?; - zero = mk().cast_expr(zero, ty_); + let ty_ = self.convert_pointee_type(pointee.ctype)?; + zero = mk().cast_expr(zero, mk().ptr_ty(ty_)); } Ok(mk().cast_expr(zero, ty)) } @@ -3123,7 +3126,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); @@ -4705,80 +4708,12 @@ impl<'c> Translation<'c> { return Ok(val); } - let pointee = self - .ast_context - .get_pointee_qual_type(target_cty.ctype) - .unwrap_or_else(|| panic!("dereferencing a non-pointer")); - - let is_const = pointee.qualifiers.is_const; - - // Handle literals by looking at the next level of expr nesting. Avoid doing this - // for expressions that will be translated as const macros, because emitting the - // name of the const macro only occurs if we process the expr_id with a direct call - // to `convert_expr`. - let expr_kind = expr.map(|e| &self.ast_context.index(e).kind); - let translate_as_macro = expr - .map(|e| { - self.convert_const_macro_expansion(ctx, e, None) - .ok() - .flatten() - .is_some() - }) - .unwrap_or(false); - match expr_kind { - Some(&CExprKind::Literal(_, CLiteral::String(ref bytes, 1))) - if is_const && !translate_as_macro => - { - let target_ty = self.convert_type(target_cty.ctype)?; - - let mut bytes = bytes.to_owned(); - bytes.push(0); - let byte_literal = mk().lit_expr(bytes); - let val = - mk().cast_expr(byte_literal, mk().ptr_ty(mk().path_ty(vec!["u8"]))); - let val = mk().cast_expr(val, target_ty); - Ok(WithStmts::new_val(val)) - } - _ => { - // Variable length arrays are already represented as pointers. - if let CTypeKind::VariableArray(..) = source_ty_kind { - Ok(val) - } else { - let method = if is_const || ctx.is_static { - "as_ptr" - } else { - "as_mut_ptr" - }; - - let call = val.map(|x| mk().method_call_expr(x, method, vec![])); - - // If the target pointee type is different from the source element type, - // then we need to cast the ptr type as well. - let call = match source_ty_kind.element_ty() { - None => call, - Some(source_element_ty) if source_element_ty == pointee.ctype => { - call - } - Some(_) => { - let target_ty = self.convert_type(target_cty.ctype)?; - call.map(|ptr| mk().cast_expr(ptr, target_ty)) - } - }; - - // Static arrays can now use as_ptr. Can also cast that const ptr to a - // mutable pointer as we do here: - if ctx.is_static && !is_const { - return Ok(call.map(|val| { - let inferred_type = mk().infer_ty(); - let ptr_type = mk().mutbl().ptr_ty(inferred_type); - mk().cast_expr(val, ptr_type) - })); - } - - Ok(call) - } - } + // Variable length arrays are already represented as pointers. + if let CTypeKind::VariableArray(..) = source_ty_kind { + return Ok(val); } + + self.convert_address_of(ctx, expr, source_cty, target_cty, val, true) } CastKind::NullToPointer => { @@ -4938,6 +4873,126 @@ impl<'c> Translation<'c> { val.map(|x| mk().cast_expr(x, target_ty)) } + pub fn convert_address_of( + &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| &self.ast_context.index(arg).kind); + let pointee_cty = self + .ast_context + .get_pointee_qual_type(pointer_cty.ctype) + .ok_or_else(|| TranslationError::generic("Address-of should return a pointer"))?; + let arg_is_macro = arg.map_or(false, |arg| { + matches!( + self.convert_const_macro_expansion(ctx, arg, None), + Ok(Some(_)) + ) + }); + + let mut needs_cast = false; + let mut ref_cast_pointee_ty = None; + let mutbl = if pointee_cty.qualifiers.is_const { + Mutability::Immutable + } else if ctx.is_static { + // static variable initializers 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 { + Mutability::Mutable + }; + + // String literals are translated with a transmute, which produces a temporary. + // Taking the address of a temporary leaves a dangling pointer. So instead, + // cast the string literal directly so that its 'static lifetime is preserved. + if let ( + Some(&CExprKind::Literal(literal_cty, CLiteral::String(ref bytes, element_size @ 1))), + false, + ) = (arg_expr_kind, arg_is_macro) + { + let bytes_padded = self.string_literal_bytes(literal_cty.ctype, bytes, element_size); + let len = bytes_padded.len(); + val = WithStmts::new_val(mk().lit_expr(bytes_padded)); + + if is_array_decay { + ref_cast_pointee_ty = Some(mk().ident_ty("u8")); + } else { + ref_cast_pointee_ty = + Some(mk().array_ty(mk().ident_ty("u8"), mk().lit_expr(len as u128))); + } + needs_cast = true; + } + // 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 { + 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; + } + } 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.type_converter + .borrow_mut() + .convert_pointee(&self.ast_context, 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. + // 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))); + } + + // Perform a final cast to the target type if needed. + if needs_cast { + let pointer_ty = self.convert_type(pointer_cty.ctype)?; + val = val.map(|val| mk().cast_expr(val, pointer_ty)); + } + + Ok(val) + } + pub fn implicit_default_expr( &self, ty_id: CTypeId, diff --git a/c2rust-transpile/src/translator/operators.rs b/c2rust-transpile/src/translator/operators.rs index 180baf5017..62da81c9f1 100644 --- a/c2rust-transpile/src/translator/operators.rs +++ b/c2rust-transpile/src/translator/operators.rs @@ -915,7 +915,6 @@ impl<'c> Translation<'c> { lrvalue: LRValue, ) -> TranslationResult>> { let CQualTypeId { ctype, .. } = cqual_type; - let ty = self.convert_type(ctype)?; let resolved_ctype = self.ast_context.resolve_type(ctype); let mut unary = match name { @@ -927,109 +926,27 @@ impl<'c> Translation<'c> { CExprKind::Unary(_, c_ast::UnOp::Deref, target, _) => { return self.convert_expr(ctx, *target, None) } - // 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. + // 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() } _ => (), - }; - - // In this translation, there are only pointers to functions and - // & becomes a no-op when applied to a function. + } let val = self.convert_expr(ctx.used().set_needs_address(true), arg, None)?; - if self.ast_context.is_function_pointer(ctype) { - Ok(val.map(|x| mk().call_expr(mk().ident_expr("Some"), vec![x]))) - } else { - let pointee_ty = - self.ast_context - .get_pointee_qual_type(ctype) - .ok_or_else(|| { - TranslationError::generic("Address-of should return a pointer") - })?; - - let expr_kind = &self.ast_context.index(arg).kind; - let translate_as_macro = self - .convert_const_macro_expansion(ctx, arg, None) - .ok() - .flatten() - .is_some(); - - // String literals are translated with a transmute, which produces a temporary. - // Taking the address of a temporary leaves a dangling pointer. So instead, - // cast the string literal directly so that its 'static lifetime is preserved. - if let ( - &CExprKind::Literal( - literal_cqual_type, - CLiteral::String(ref bytes, element_size @ 1), - ), - false, - ) = (expr_kind, translate_as_macro) - { - let num_elems = - match self.ast_context.resolve_type(literal_cqual_type.ctype).kind { - CTypeKind::ConstantArray(_, num_elems) => num_elems, - ref kind => { - panic!( - "String literal with unknown size: {bytes:?}, kind = {kind:?}" - ) - } - }; - - // Match the literal size to the expected size padding with zeros as needed - let size = num_elems * (element_size as usize); - let mut bytes_padded = Vec::with_capacity(size); - bytes_padded.extend(bytes); - bytes_padded.resize(size, 0); - - let array_ty = mk().array_ty( - mk().ident_ty("u8"), - mk().lit_expr(bytes_padded.len() as u128), - ); - let bytes_literal = mk().lit_expr(bytes_padded); - let val = mk().cast_expr(bytes_literal, mk().ptr_ty(array_ty)); - let val = mk().cast_expr(val, ty); - return Ok(WithStmts::new_val(val)); - } - - let mutbl = if pointee_ty.qualifiers.is_const { - Mutability::Immutable - } else { - Mutability::Mutable - }; - - val.result_map(|a| { - let mut addr_of_arg: Box; - - if ctx.is_static { - // static variable initializers aren't able to use &mut, - // so we work around that by using & and an extra cast - // through & to *const to *mut - addr_of_arg = mk().addr_of_expr(a); - if let Mutability::Mutable = mutbl { - let mut qtype = pointee_ty; - qtype.qualifiers.is_const = true; - let ty_ = self - .type_converter - .borrow_mut() - .convert_pointer(&self.ast_context, qtype)?; - addr_of_arg = mk().cast_expr(addr_of_arg, ty_); - } - } else { - // Normal case is allowed to use &mut if needed - addr_of_arg = mk().set_mutbl(mutbl).addr_of_expr(a); + // & 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]))); + } - // Avoid unnecessary reference to pointer decay in fn call args: - if ctx.decay_ref.is_no() { - return Ok(addr_of_arg); - } - } + let arg_cty = arg_kind + .get_qual_type() + .ok_or_else(|| format_err!("bad source type"))?; - Ok(mk().cast_expr(addr_of_arg, ty)) - }) - } + self.convert_address_of(ctx, Some(arg), arg_cty, cqual_type, val, false) } c_ast::UnOp::PreIncrement => self.convert_pre_increment(ctx, cqual_type, true, arg), c_ast::UnOp::PreDecrement => self.convert_pre_increment(ctx, cqual_type, false, arg), diff --git a/c2rust-transpile/tests/snapshots/arrays.c b/c2rust-transpile/tests/snapshots/arrays.c index da524373cd..2b74929394 100644 --- a/c2rust-transpile/tests/snapshots/arrays.c +++ b/c2rust-transpile/tests/snapshots/arrays.c @@ -1,7 +1,8 @@ #include -static char simple[] = "mystring"; -static char *foo = "mystring"; +char static_char_array[] = "mystring"; +char *static_char_ptr = "mystring"; +void *static_void_ptr = (void*) static_char_array; void entry(void) { int int_2d[1][1] = { 1 }; @@ -27,7 +28,7 @@ void entry(void) { int *int_var_ptr = int_empty_init; int (*int_var_array_ptr)[16] = &int_empty_init; - char *char_var_ptr_var = char_with_string; + char *char_var_ptr = char_with_string; char (*char_var_array_ptr)[4] = &char_with_string; const char *const_char_lit_ptr = "abc"; const char (*const_char_lit_array_ptr)[4] = &"abc"; @@ -44,8 +45,8 @@ void entry(void) { #endif // Test that we can get the address of the element past the end of the array - char *past_end = &simple[sizeof(simple)]; - past_end = &foo[8]; + char *past_end = &static_char_array[sizeof(static_char_array)]; + past_end = &static_char_ptr[8]; } void short_initializer() { diff --git a/c2rust-transpile/tests/snapshots/compound_literals.c b/c2rust-transpile/tests/snapshots/compound_literals.c index df82aee4dc..840b7ad017 100644 --- a/c2rust-transpile/tests/snapshots/compound_literals.c +++ b/c2rust-transpile/tests/snapshots/compound_literals.c @@ -1,11 +1,12 @@ int static_single_int = (int) { 42 }; int *static_single_int_ptr = &((int) { 42 }); int *static_int_ptr_to_array = (int[]) { 42, 9001 }; +volatile int *static_volatile_int_ptr_to_array = (int[]) { 42, 9001 }; +int (*static_int_array_ptr)[2] = &(int[]) { 42, 9001 }; + // Currently generates broken Rust code, see // https://github.com/immunant/c2rust/issues/1410 //char *static_char_ptr_to_array = (char[]) { "hello" }; -int (*static_int_array_ptr)[2] = &(int[]) { 42, 9001 }; -// As above //char (*static_char_array_ptr)[6] = &(char[]) { "hello" }; #define SINGLE_INT ((int) { 42 }) 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 8e15e172ef..1149202b04 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 { @@ -42,18 +43,18 @@ pub unsafe extern "C" fn VM_CallCompiled( programStack -= 8 as ::core::ffi::c_int + 4 as ::core::ffi::c_int * MAX_VMMAIN_ARGS; arg = 0 as ::core::ffi::c_int; while arg < MAX_VMMAIN_ARGS { - *(&mut *image.offset( + *(&raw mut *image.offset( (programStack + 8 as ::core::ffi::c_int + arg * 4 as ::core::ffi::c_int) as isize, - ) as *mut byte as *mut ::core::ffi::c_int) = *args.offset(arg as isize); + ) as *mut ::core::ffi::c_int) = *args.offset(arg as isize); arg += 1; } - *(&mut *image.offset((programStack + 4 as ::core::ffi::c_int) as isize) as *mut byte + *(&raw mut *image.offset((programStack + 4 as ::core::ffi::c_int) as isize) as *mut ::core::ffi::c_int) = 0 as ::core::ffi::c_int; - *(&mut *image.offset(programStack as isize) as *mut byte as *mut ::core::ffi::c_int) = + *(&raw mut *image.offset(programStack as isize) 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@vm_x86.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@vm_x86.c.snap index 3893b0277f..25d8a8f17d 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)] @@ -44,18 +44,18 @@ pub unsafe extern "C" fn VM_CallCompiled( programStack -= 8 as ::core::ffi::c_int + 4 as ::core::ffi::c_int * MAX_VMMAIN_ARGS; arg = 0 as ::core::ffi::c_int; while arg < MAX_VMMAIN_ARGS { - *(&mut *image.offset( + *(&raw mut *image.offset( (programStack + 8 as ::core::ffi::c_int + arg * 4 as ::core::ffi::c_int) as isize, - ) as *mut byte as *mut ::core::ffi::c_int) = *args.offset(arg as isize); + ) as *mut ::core::ffi::c_int) = *args.offset(arg as isize); arg += 1; } - *(&mut *image.offset((programStack + 4 as ::core::ffi::c_int) as isize) as *mut byte + *(&raw mut *image.offset((programStack + 4 as ::core::ffi::c_int) as isize) as *mut ::core::ffi::c_int) = 0 as ::core::ffi::c_int; - *(&mut *image.offset(programStack as isize) as *mut byte as *mut ::core::ffi::c_int) = + *(&raw mut *image.offset(programStack as isize) 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 b8eb61d0cc..f3cd16b750 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 { @@ -34,11 +35,16 @@ pub struct C2RustUnnamed_2 { pub x: ::core::ffi::c_short, pub y: ::core::ffi::c_int, } -static mut simple: [::core::ffi::c_char; 9] = +#[no_mangle] +pub static mut static_char_array: [::core::ffi::c_char; 9] = unsafe { ::core::mem::transmute::<[u8; 9], [::core::ffi::c_char; 9]>(*b"mystring\0") }; -static mut foo: *mut ::core::ffi::c_char = +#[no_mangle] +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 { &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]]; int_2d[0 as ::core::ffi::c_int as usize][0 as ::core::ffi::c_int as usize] += @@ -79,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_var: *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] = @@ -92,11 +100,10 @@ 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 = &mut *simple - .as_mut_ptr() - .offset(::core::mem::size_of::<[::core::ffi::c_char; 9]>() as isize) - as *mut ::core::ffi::c_char; - past_end = &mut *foo.offset(8 as ::core::ffi::c_int as isize) as *mut ::core::ffi::c_char; + let mut past_end: *mut ::core::ffi::c_char = &raw mut *(&raw mut static_char_array + as *mut ::core::ffi::c_char) + .offset(::core::mem::size_of::<[::core::ffi::c_char; 9]>() as isize); + past_end = &raw mut *static_char_ptr.offset(8 as ::core::ffi::c_int as isize); } #[no_mangle] pub unsafe extern "C" fn short_initializer() { 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 b1329d0909..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,13 +11,18 @@ 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] pub static mut static_single_int_ptr: *mut ::core::ffi::c_int = &42 as *const ::core::ffi::c_int as *mut ::core::ffi::c_int; #[no_mangle] -pub static mut static_int_ptr_to_array: *mut ::core::ffi::c_int = [42, 9001].as_ptr() as *mut _; +pub static mut static_int_ptr_to_array: *mut ::core::ffi::c_int = + [42, 9001].as_ptr() as *mut ::core::ffi::c_int; +#[no_mangle] +pub static mut static_volatile_int_ptr_to_array: *mut ::core::ffi::c_int = + [42, 9001].as_ptr() as *mut ::core::ffi::c_int as *mut ::core::ffi::c_int; #[no_mangle] pub static mut static_int_array_ptr: *mut [::core::ffi::c_int; 2] = &[42, 9001] as *const [::core::ffi::c_int; 2] as *mut [::core::ffi::c_int; 2]; @@ -30,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 2125fc3142..950437f91c 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; @@ -43,10 +44,12 @@ pub unsafe extern "C" fn unary_with_side_effect() { side_effect(); !side_effect(); (side_effect() == 0) as ::core::ffi::c_int; - &*(b"\0" as *const u8 as *const ::core::ffi::c_char).offset(::core::mem::transmute::< - unsafe extern "C" fn() -> ::core::ffi::c_int, - unsafe extern "C" fn() -> ::core::ffi::c_int, - >(side_effect)() as isize) as *const ::core::ffi::c_char; + &raw const *(b"\0" as *const u8 as *const ::core::ffi::c_char).offset( + ::core::mem::transmute::< + unsafe extern "C" fn() -> ::core::ffi::c_int, + unsafe extern "C" fn() -> ::core::ffi::c_int, + >(side_effect)() as isize, + ); *arr[side_effect() as usize]; arr[side_effect() as usize] = arr[side_effect() as usize].offset(1); arr[side_effect() as usize] = arr[side_effect() as usize].offset(-1); diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap index fc5349c45b..9f0d0e6d38 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; } @@ -107,10 +108,9 @@ pub unsafe extern "C" fn local_muts() { ::core::mem::transmute::<[u8; 18], [::core::ffi::c_char; 18]>(*b"hello hello world\0"); 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 = &*NESTED_STR + let mut ref_indexing: *const ::core::ffi::c_char = &raw const *NESTED_STR .as_ptr() - .offset(LITERAL_FLOAT as ::core::ffi::c_int as isize) - as *const ::core::ffi::c_char; + .offset(LITERAL_FLOAT as ::core::ffi::c_int as isize); let mut ref_struct: *const S = &mut LITERAL_STRUCT as *mut S; let mut ternary: ::core::ffi::c_int = if LITERAL_BOOL != 0 { 1 as ::core::ffi::c_int @@ -177,10 +177,9 @@ pub unsafe extern "C" fn local_consts() { let str_concatenation: [::core::ffi::c_char; 18] = ::core::mem::transmute::<[u8; 18], [::core::ffi::c_char; 18]>(*b"hello hello world\0"); 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 = &*NESTED_STR + let ref_indexing: *const ::core::ffi::c_char = &raw const *NESTED_STR .as_ptr() - .offset(LITERAL_FLOAT as ::core::ffi::c_int as isize) - as *const ::core::ffi::c_char; + .offset(LITERAL_FLOAT as ::core::ffi::c_int as isize); let ref_struct: *const S = &mut LITERAL_STRUCT as *mut S; let ternary: ::core::ffi::c_int = if LITERAL_BOOL != 0 { 1 as ::core::ffi::c_int @@ -370,7 +369,7 @@ pub static mut fns: fn_ptrs = { init }; #[no_mangle] -pub static mut p: *const fn_ptrs = unsafe { &fns as *const fn_ptrs }; +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 +383,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; @@ -446,10 +445,9 @@ pub unsafe extern "C" fn late_init_var() -> ::core::ffi::c_int { unsafe extern "C" fn run_static_initializers() { global_static_const_ptr_arithmetic = PTR_ARITHMETIC; global_static_const_indexing = NESTED_STR[LITERAL_FLOAT as ::core::ffi::c_int as usize]; - global_static_const_ref_indexing = &*NESTED_STR + global_static_const_ref_indexing = &raw const *NESTED_STR .as_ptr() - .offset(LITERAL_FLOAT as ::core::ffi::c_int as isize) - as *const ::core::ffi::c_char; + .offset(LITERAL_FLOAT as ::core::ffi::c_int as isize); global_static_const_ternary = if LITERAL_BOOL != 0 { 1 as ::core::ffi::c_int } else { @@ -458,10 +456,9 @@ unsafe extern "C" fn run_static_initializers() { global_static_const_member = LITERAL_STRUCT.i; global_const_ptr_arithmetic = PTR_ARITHMETIC; global_const_indexing = NESTED_STR[LITERAL_FLOAT as ::core::ffi::c_int as usize]; - global_const_ref_indexing = &*NESTED_STR + global_const_ref_indexing = &raw const *NESTED_STR .as_ptr() - .offset(LITERAL_FLOAT as ::core::ffi::c_int as isize) - as *const ::core::ffi::c_char; + .offset(LITERAL_FLOAT as ::core::ffi::c_int as isize); global_const_ternary = if LITERAL_BOOL != 0 { 1 as ::core::ffi::c_int } else { diff --git a/tests/arrays/src/test_arrays.rs b/tests/arrays/src/test_arrays.rs index 82479cf867..e71b408651 100644 --- a/tests/arrays/src/test_arrays.rs +++ b/tests/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/builtins/src/test_builtins.rs b/tests/builtins/src/test_builtins.rs index de82132ba6..b552f86309 100644 --- a/tests/builtins/src/test_builtins.rs +++ b/tests/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/casts/src/test_casts.rs b/tests/casts/src/test_casts.rs index bad9ccd9dc..1d13d37c97 100644 --- a/tests/casts/src/test_casts.rs +++ b/tests/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/conditionals/src/test_conditionals.rs b/tests/conditionals/src/test_conditionals.rs index 2353217677..d18af7666e 100644 --- a/tests/conditionals/src/test_conditionals.rs +++ b/tests/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/ints/src/test_arithmetic.rs b/tests/ints/src/test_arithmetic.rs index dc3397271a..2cb0a61bd7 100644 --- a/tests/ints/src/test_arithmetic.rs +++ b/tests/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/items/src/test_varargs.rs b/tests/items/src/test_varargs.rs index 8c9d23469d..01422c6f05 100644 --- a/tests/items/src/test_varargs.rs +++ b/tests/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/macros/src/test_define.rs b/tests/macros/src/test_define.rs index 9a38fd724a..39d37ae4cd 100644 --- a/tests/macros/src/test_define.rs +++ b/tests/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/misc/src/test_exprs.rs b/tests/misc/src/test_exprs.rs index 04555acbda..32e66235d0 100644 --- a/tests/misc/src/test_exprs.rs +++ b/tests/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/misc/src/test_quicksort.rs b/tests/misc/src/test_quicksort.rs index d5a09a0ecc..c06da72a8c 100644 --- a/tests/misc/src/test_quicksort.rs +++ b/tests/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/misc/src/test_sizeofs.rs b/tests/misc/src/test_sizeofs.rs index 262235100b..88840d15d3 100644 --- a/tests/misc/src/test_sizeofs.rs +++ b/tests/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/misc/src/test_typedef.rs b/tests/misc/src/test_typedef.rs index 812e209f4d..be9f5f2e3f 100644 --- a/tests/misc/src/test_typedef.rs +++ b/tests/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/misc/src/test_uninitialized.rs b/tests/misc/src/test_uninitialized.rs index 005aac15ac..390ac74b95 100644 --- a/tests/misc/src/test_uninitialized.rs +++ b/tests/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/pointers/src/test_pointers.rs b/tests/pointers/src/test_pointers.rs index 7793e48477..6a95f04988 100644 --- a/tests/pointers/src/test_pointers.rs +++ b/tests/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/statics/src/test_sections.rs b/tests/statics/src/test_sections.rs index f6f8860019..964183f83e 100644 --- a/tests/statics/src/test_sections.rs +++ b/tests/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/structs/src/test_flex_array_members.rs b/tests/structs/src/test_flex_array_members.rs index a679bd2dc4..ec28c5fa28 100644 --- a/tests/structs/src/test_flex_array_members.rs +++ b/tests/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/structs/src/test_struct_with_exp.rs b/tests/structs/src/test_struct_with_exp.rs index 18f8a47567..0d9ffb464b 100644 --- a/tests/structs/src/test_struct_with_exp.rs +++ b/tests/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};