@@ -4605,84 +4605,12 @@ impl<'c> Translation<'c> {
46054605 return Ok ( val) ;
46064606 }
46074607
4608- let pointee = self
4609- . ast_context
4610- . get_pointee_qual_type ( target_cty. ctype )
4611- . unwrap_or_else ( || panic ! ( "dereferencing a non-pointer" ) ) ;
4612-
4613- let is_const = pointee. qualifiers . is_const ;
4614-
4615- // Handle literals by looking at the next level of expr nesting. Avoid doing this
4616- // for expressions that will be translated as const macros, because emitting the
4617- // name of the const macro only occurs if we process the expr_id with a direct call
4618- // to `convert_expr`.
4619- let expr_kind = expr. map ( |e| & self . ast_context . index ( e) . kind ) ;
4620- let translate_as_macro = expr
4621- . map ( |e| {
4622- self . convert_const_macro_expansion ( ctx, e, None )
4623- . ok ( )
4624- . flatten ( )
4625- . is_some ( )
4626- } )
4627- . unwrap_or ( false ) ;
4628- match expr_kind {
4629- Some ( & CExprKind :: Literal (
4630- literal_cqual_type,
4631- CLiteral :: String ( ref bytes, element_size @ 1 ) ,
4632- ) ) if is_const && !translate_as_macro => {
4633- let target_ty = self . convert_type ( target_cty. ctype ) ?;
4634-
4635- let bytes_padded = self . string_literal_bytes (
4636- literal_cqual_type. ctype ,
4637- bytes,
4638- element_size,
4639- ) ;
4640- let element_ty = mk ( ) . ident_ty ( "u8" ) ;
4641- let bytes_literal = mk ( ) . lit_expr ( bytes_padded) ;
4642- let val = mk ( ) . cast_expr ( bytes_literal, mk ( ) . ptr_ty ( element_ty) ) ;
4643- let val = mk ( ) . cast_expr ( val, target_ty) ;
4644- Ok ( WithStmts :: new_val ( val) )
4645- }
4646- _ => {
4647- // Variable length arrays are already represented as pointers.
4648- if let CTypeKind :: VariableArray ( ..) = source_ty_kind {
4649- Ok ( val)
4650- } else {
4651- let method = if is_const || ctx. is_static {
4652- "as_ptr"
4653- } else {
4654- "as_mut_ptr"
4655- } ;
4656-
4657- let call = val. map ( |x| mk ( ) . method_call_expr ( x, method, vec ! [ ] ) ) ;
4658-
4659- // If the target pointee type is different from the source element type,
4660- // then we need to cast the ptr type as well.
4661- let call = match source_ty_kind. element_ty ( ) {
4662- None => call,
4663- Some ( source_element_ty) if source_element_ty == pointee. ctype => {
4664- call
4665- }
4666- Some ( _) => {
4667- let target_ty = self . convert_type ( target_cty. ctype ) ?;
4668- call. map ( |ptr| mk ( ) . cast_expr ( ptr, target_ty) )
4669- }
4670- } ;
4671-
4672- // Static arrays can now use as_ptr. Can also cast that const ptr to a
4673- // mutable pointer as we do here:
4674- if ctx. is_static && !is_const {
4675- return Ok ( call. map ( |val| {
4676- let inferred_type = mk ( ) . infer_ty ( ) ;
4677- let ptr_type = mk ( ) . mutbl ( ) . ptr_ty ( inferred_type) ;
4678- mk ( ) . cast_expr ( val, ptr_type)
4679- } ) ) ;
4680- }
4681-
4682- Ok ( call)
4683- }
4684- }
4608+ // Variable length arrays are already represented as pointers.
4609+ if let CTypeKind :: VariableArray ( ..) = source_ty_kind {
4610+ return Ok ( val) ;
46854611 }
4612+
4613+ self . convert_address_of ( ctx, expr, source_cty, target_cty, val, true )
46864614 }
46874615
46884616 CastKind :: NullToPointer => {
@@ -4842,6 +4770,103 @@ impl<'c> Translation<'c> {
48424770 val. map ( |x| mk ( ) . cast_expr ( x, target_ty) )
48434771 }
48444772
4773+ pub fn convert_address_of (
4774+ & self ,
4775+ ctx : ExprContext ,
4776+ arg : Option < CExprId > ,
4777+ arg_cty : CQualTypeId ,
4778+ pointer_cty : CQualTypeId ,
4779+ mut val : WithStmts < Box < Expr > > ,
4780+ is_array_decay : bool ,
4781+ ) -> TranslationResult < WithStmts < Box < Expr > > > {
4782+ let arg_expr_kind = arg. map ( |arg| & self . ast_context . index ( arg) . kind ) ;
4783+ let pointee_cty = self
4784+ . ast_context
4785+ . get_pointee_qual_type ( pointer_cty. ctype )
4786+ . ok_or_else ( || TranslationError :: generic ( "Address-of should return a pointer" ) ) ?;
4787+ let arg_is_macro = arg. map_or ( false , |arg| {
4788+ matches ! (
4789+ self . convert_const_macro_expansion( ctx, arg, None ) ,
4790+ Ok ( Some ( _) )
4791+ )
4792+ } ) ;
4793+
4794+ let mut needs_cast = false ;
4795+ let mut ref_cast_pointee_ty = None ;
4796+ let mutbl = if pointee_cty. qualifiers . is_const {
4797+ Mutability :: Immutable
4798+ } else if ctx. is_static {
4799+ // static variable initializers aren't able to use &mut, so we work around that
4800+ // by using & and an extra cast through & to *const to *mut
4801+ // TODO: Rust 1.83: Allowed, so this can be removed.
4802+ needs_cast = true ;
4803+ Mutability :: Immutable
4804+ } else {
4805+ Mutability :: Mutable
4806+ } ;
4807+
4808+ // String literals are translated with a transmute, which produces a temporary.
4809+ // Taking the address of a temporary leaves a dangling pointer. So instead,
4810+ // cast the string literal directly so that its 'static lifetime is preserved.
4811+ if let (
4812+ Some ( & CExprKind :: Literal ( literal_cty, CLiteral :: String ( ref bytes, element_size @ 1 ) ) ) ,
4813+ false ,
4814+ ) = ( arg_expr_kind, arg_is_macro)
4815+ {
4816+ let bytes_padded = self . string_literal_bytes ( literal_cty. ctype , bytes, element_size) ;
4817+ let len = bytes_padded. len ( ) ;
4818+ val = WithStmts :: new_val ( mk ( ) . lit_expr ( bytes_padded) ) ;
4819+
4820+ ref_cast_pointee_ty =
4821+ Some ( mk ( ) . array_ty ( mk ( ) . ident_ty ( "u8" ) , mk ( ) . lit_expr ( len as u128 ) ) ) ;
4822+ needs_cast = true ;
4823+ } else {
4824+ let arg_cty_kind = & self . ast_context . resolve_type ( arg_cty. ctype ) . kind ;
4825+
4826+ if is_array_decay {
4827+ let method = match mutbl {
4828+ Mutability :: Mutable => "as_mut_ptr" ,
4829+ Mutability :: Immutable => "as_ptr" ,
4830+ } ;
4831+ val = val. map ( |val| mk ( ) . method_call_expr ( val, method, vec ! [ ] ) ) ;
4832+
4833+ // If the target pointee type is different from the source element type,
4834+ // then we need to cast the ptr type as well.
4835+ if arg_cty_kind. element_ty ( ) . map_or ( false , |arg_element_cty| {
4836+ arg_element_cty != pointee_cty. ctype
4837+ } ) {
4838+ needs_cast = true ;
4839+ }
4840+ } else {
4841+ val = val. map ( |val| mk ( ) . set_mutbl ( mutbl) . addr_of_expr ( val) ) ;
4842+
4843+ // Add an intermediate reference-to-pointer cast if the context needs
4844+ // reference-to-pointer decay, or if another cast follows.
4845+ if ctx. decay_ref . is_yes ( ) || needs_cast {
4846+ ref_cast_pointee_ty = Some (
4847+ self . type_converter
4848+ . borrow_mut ( )
4849+ . convert_pointee ( & self . ast_context , arg_cty. ctype ) ?,
4850+ ) ;
4851+ }
4852+ }
4853+ }
4854+
4855+ // Perform an intermediate reference-to-pointer cast if needed.
4856+ // TODO: Rust 1.76: Use `ptr::from_ref`.
4857+ if let Some ( pointee_ty) = ref_cast_pointee_ty {
4858+ val = val. map ( |val| mk ( ) . cast_expr ( val, mk ( ) . set_mutbl ( mutbl) . ptr_ty ( pointee_ty) ) ) ;
4859+ }
4860+
4861+ // Perform a final cast to the target type if needed.
4862+ if needs_cast {
4863+ let pointer_ty = self . convert_type ( pointer_cty. ctype ) ?;
4864+ val = val. map ( |val| mk ( ) . cast_expr ( val, pointer_ty) ) ;
4865+ }
4866+
4867+ Ok ( val)
4868+ }
4869+
48454870 pub fn implicit_default_expr (
48464871 & self ,
48474872 ty_id : CTypeId ,
0 commit comments