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