@@ -4708,84 +4708,12 @@ impl<'c> Translation<'c> {
47084708 return Ok ( val) ;
47094709 }
47104710
4711- let pointee = self
4712- . ast_context
4713- . get_pointee_qual_type ( target_cty. ctype )
4714- . unwrap_or_else ( || panic ! ( "dereferencing a non-pointer" ) ) ;
4715-
4716- let is_const = pointee. qualifiers . is_const ;
4717-
4718- // Handle literals by looking at the next level of expr nesting. Avoid doing this
4719- // for expressions that will be translated as const macros, because emitting the
4720- // name of the const macro only occurs if we process the expr_id with a direct call
4721- // to `convert_expr`.
4722- let expr_kind = expr. map ( |e| & self . ast_context . index ( e) . kind ) ;
4723- let translate_as_macro = expr
4724- . map ( |e| {
4725- self . convert_const_macro_expansion ( ctx, e, None )
4726- . ok ( )
4727- . flatten ( )
4728- . is_some ( )
4729- } )
4730- . unwrap_or ( false ) ;
4731- match expr_kind {
4732- Some ( & CExprKind :: Literal (
4733- literal_cqual_type,
4734- CLiteral :: String ( ref bytes, element_size @ 1 ) ,
4735- ) ) if is_const && !translate_as_macro => {
4736- let target_ty = self . convert_type ( target_cty. ctype ) ?;
4737-
4738- let bytes_padded = self . string_literal_bytes (
4739- literal_cqual_type. ctype ,
4740- bytes,
4741- element_size,
4742- ) ;
4743- let element_ty = mk ( ) . ident_ty ( "u8" ) ;
4744- let bytes_literal = mk ( ) . lit_expr ( bytes_padded) ;
4745- let val = mk ( ) . cast_expr ( bytes_literal, mk ( ) . ptr_ty ( element_ty) ) ;
4746- let val = mk ( ) . cast_expr ( val, target_ty) ;
4747- Ok ( WithStmts :: new_val ( val) )
4748- }
4749- _ => {
4750- // Variable length arrays are already represented as pointers.
4751- if let CTypeKind :: VariableArray ( ..) = source_ty_kind {
4752- Ok ( val)
4753- } else {
4754- let method = if is_const || ctx. is_static {
4755- "as_ptr"
4756- } else {
4757- "as_mut_ptr"
4758- } ;
4759-
4760- let call = val. map ( |x| mk ( ) . method_call_expr ( x, method, vec ! [ ] ) ) ;
4761-
4762- // If the target pointee type is different from the source element type,
4763- // then we need to cast the ptr type as well.
4764- let call = match source_ty_kind. element_ty ( ) {
4765- None => call,
4766- Some ( source_element_ty) if source_element_ty == pointee. ctype => {
4767- call
4768- }
4769- Some ( _) => {
4770- let target_ty = self . convert_type ( target_cty. ctype ) ?;
4771- call. map ( |ptr| mk ( ) . cast_expr ( ptr, target_ty) )
4772- }
4773- } ;
4774-
4775- // Static arrays can now use as_ptr. Can also cast that const ptr to a
4776- // mutable pointer as we do here:
4777- if ctx. is_static && !is_const {
4778- return Ok ( call. map ( |val| {
4779- let inferred_type = mk ( ) . infer_ty ( ) ;
4780- let ptr_type = mk ( ) . mutbl ( ) . ptr_ty ( inferred_type) ;
4781- mk ( ) . cast_expr ( val, ptr_type)
4782- } ) ) ;
4783- }
4784-
4785- Ok ( call)
4786- }
4787- }
4711+ // Variable length arrays are already represented as pointers.
4712+ if let CTypeKind :: VariableArray ( ..) = source_ty_kind {
4713+ return Ok ( val) ;
47884714 }
4715+
4716+ self . convert_address_of ( ctx, expr, source_cty, target_cty, val, true )
47894717 }
47904718
47914719 CastKind :: NullToPointer => {
@@ -4945,6 +4873,107 @@ impl<'c> Translation<'c> {
49454873 val. map ( |x| mk ( ) . cast_expr ( x, target_ty) )
49464874 }
49474875
4876+ pub fn convert_address_of (
4877+ & self ,
4878+ ctx : ExprContext ,
4879+ arg : Option < CExprId > ,
4880+ arg_cty : CQualTypeId ,
4881+ pointer_cty : CQualTypeId ,
4882+ mut val : WithStmts < Box < Expr > > ,
4883+ is_array_decay : bool ,
4884+ ) -> TranslationResult < WithStmts < Box < Expr > > > {
4885+ let arg_expr_kind = arg. map ( |arg| & self . ast_context . index ( arg) . kind ) ;
4886+ let pointee_cty = self
4887+ . ast_context
4888+ . get_pointee_qual_type ( pointer_cty. ctype )
4889+ . ok_or_else ( || TranslationError :: generic ( "Address-of should return a pointer" ) ) ?;
4890+ let arg_is_macro = arg. map_or ( false , |arg| {
4891+ matches ! (
4892+ self . convert_const_macro_expansion( ctx, arg, None ) ,
4893+ Ok ( Some ( _) )
4894+ )
4895+ } ) ;
4896+
4897+ let mut needs_cast = false ;
4898+ let mut ref_cast_pointee_ty = None ;
4899+ let mutbl = if pointee_cty. qualifiers . is_const {
4900+ Mutability :: Immutable
4901+ } else if ctx. is_static {
4902+ // static variable initializers aren't able to use &mut, so we work around that
4903+ // by using & and an extra cast through & to *const to *mut
4904+ // TODO: Rust 1.83: Allowed, so this can be removed.
4905+ needs_cast = true ;
4906+ Mutability :: Immutable
4907+ } else {
4908+ Mutability :: Mutable
4909+ } ;
4910+
4911+ // String literals are translated with a transmute, which produces a temporary.
4912+ // Taking the address of a temporary leaves a dangling pointer. So instead,
4913+ // cast the string literal directly so that its 'static lifetime is preserved.
4914+ if let (
4915+ Some ( & CExprKind :: Literal ( literal_cty, CLiteral :: String ( ref bytes, element_size @ 1 ) ) ) ,
4916+ false ,
4917+ ) = ( arg_expr_kind, arg_is_macro)
4918+ {
4919+ let bytes_padded = self . string_literal_bytes ( literal_cty. ctype , bytes, element_size) ;
4920+ let len = bytes_padded. len ( ) ;
4921+ val = WithStmts :: new_val ( mk ( ) . lit_expr ( bytes_padded) ) ;
4922+
4923+ if is_array_decay {
4924+ ref_cast_pointee_ty = Some ( mk ( ) . ident_ty ( "u8" ) ) ;
4925+ } else {
4926+ ref_cast_pointee_ty =
4927+ Some ( mk ( ) . array_ty ( mk ( ) . ident_ty ( "u8" ) , mk ( ) . lit_expr ( len as u128 ) ) ) ;
4928+ }
4929+ needs_cast = true ;
4930+ } else {
4931+ let arg_cty_kind = & self . ast_context . resolve_type ( arg_cty. ctype ) . kind ;
4932+
4933+ if is_array_decay {
4934+ let method = match mutbl {
4935+ Mutability :: Mutable => "as_mut_ptr" ,
4936+ Mutability :: Immutable => "as_ptr" ,
4937+ } ;
4938+ val = val. map ( |val| mk ( ) . method_call_expr ( val, method, vec ! [ ] ) ) ;
4939+
4940+ // If the target pointee type is different from the source element type,
4941+ // then we need to cast the ptr type as well.
4942+ if arg_cty_kind. element_ty ( ) . map_or ( false , |arg_element_cty| {
4943+ arg_element_cty != pointee_cty. ctype
4944+ } ) {
4945+ needs_cast = true ;
4946+ }
4947+ } else {
4948+ val = val. map ( |val| mk ( ) . set_mutbl ( mutbl) . addr_of_expr ( val) ) ;
4949+
4950+ // Add an intermediate reference-to-pointer cast if the context needs
4951+ // reference-to-pointer decay, or if another cast follows.
4952+ if ctx. decay_ref . is_yes ( ) || needs_cast {
4953+ ref_cast_pointee_ty = Some (
4954+ self . type_converter
4955+ . borrow_mut ( )
4956+ . convert_pointee ( & self . ast_context , arg_cty. ctype ) ?,
4957+ ) ;
4958+ }
4959+ }
4960+ }
4961+
4962+ // Perform an intermediate reference-to-pointer cast if needed.
4963+ // TODO: Rust 1.76: Use `ptr::from_ref`.
4964+ if let Some ( pointee_ty) = ref_cast_pointee_ty {
4965+ val = val. map ( |val| mk ( ) . cast_expr ( val, mk ( ) . set_mutbl ( mutbl) . ptr_ty ( pointee_ty) ) ) ;
4966+ }
4967+
4968+ // Perform a final cast to the target type if needed.
4969+ if needs_cast {
4970+ let pointer_ty = self . convert_type ( pointer_cty. ctype ) ?;
4971+ val = val. map ( |val| mk ( ) . cast_expr ( val, pointer_ty) ) ;
4972+ }
4973+
4974+ Ok ( val)
4975+ }
4976+
49484977 pub fn implicit_default_expr (
49494978 & self ,
49504979 ty_id : CTypeId ,
0 commit comments