@@ -49,6 +49,7 @@ mod literals;
4949mod main_function;
5050mod named_references;
5151mod operators;
52+ mod pointers;
5253mod simd;
5354mod structs;
5455mod variadic;
@@ -302,34 +303,6 @@ fn cast_int(val: Box<Expr>, name: &str, need_lit_suffix: bool) -> Box<Expr> {
302303 }
303304}
304305
305- /// Pointer offset that casts its argument to isize
306- fn pointer_offset (
307- ptr : Box < Expr > ,
308- offset : Box < Expr > ,
309- multiply_by : Option < Box < Expr > > ,
310- neg : bool ,
311- mut deref : bool ,
312- ) -> Box < Expr > {
313- let mut offset = cast_int ( offset, "isize" , false ) ;
314-
315- if let Some ( mul) = multiply_by {
316- let mul = cast_int ( mul, "isize" , false ) ;
317- offset = mk ( ) . binary_expr ( BinOp :: Mul ( Default :: default ( ) ) , offset, mul) ;
318- deref = false ;
319- }
320-
321- if neg {
322- offset = mk ( ) . unary_expr ( UnOp :: Neg ( Default :: default ( ) ) , offset) ;
323- }
324-
325- let res = mk ( ) . method_call_expr ( ptr, "offset" , vec ! [ offset] ) ;
326- if deref {
327- mk ( ) . unary_expr ( UnOp :: Deref ( Default :: default ( ) ) , res)
328- } else {
329- res
330- }
331- }
332-
333306/// Given an expression with type Option<fn(...)->...>, unwrap
334307/// the Option and return the function.
335308fn unwrap_function_pointer ( ptr : Box < Expr > ) -> Box < Expr > {
@@ -3082,54 +3055,6 @@ impl<'c> Translation<'c> {
30823055 . convert ( & self . ast_context , type_id)
30833056 }
30843057
3085- fn convert_pointee_type ( & self , type_id : CTypeId ) -> TranslationResult < Box < Type > > {
3086- self . import_type ( type_id) ;
3087-
3088- self . type_converter
3089- . borrow_mut ( )
3090- . convert_pointee ( & self . ast_context , type_id)
3091- }
3092-
3093- /// Construct an expression for a NULL at any type, including forward declarations,
3094- /// function pointers, and normal pointers.
3095- fn null_ptr ( & self , type_id : CTypeId , is_static : bool ) -> TranslationResult < Box < Expr > > {
3096- if self . ast_context . is_function_pointer ( type_id) {
3097- return Ok ( mk ( ) . path_expr ( vec ! [ "None" ] ) ) ;
3098- }
3099-
3100- let pointer_qty = self
3101- . ast_context
3102- . get_pointee_qual_type ( type_id)
3103- . ok_or_else ( || TranslationError :: generic ( "null_ptr requires a pointer" ) ) ?;
3104-
3105- let func = if pointer_qty. qualifiers . is_const
3106- // static variable initializers aren't able to use null_mut
3107- // TODO: Rust 1.83: Allowed, so this can be removed.
3108- || is_static
3109- {
3110- "null"
3111- } else {
3112- "null_mut"
3113- } ;
3114- let pointee_ty = self . convert_pointee_type ( pointer_qty. ctype ) ?;
3115- let type_args = mk ( ) . angle_bracketed_args ( vec ! [ pointee_ty. clone( ) ] ) ;
3116- let mut val = mk ( ) . call_expr (
3117- mk ( ) . abs_path_expr ( vec ! [
3118- mk( ) . path_segment( "core" ) ,
3119- mk( ) . path_segment( "ptr" ) ,
3120- mk( ) . path_segment_with_args( func, type_args) ,
3121- ] ) ,
3122- vec ! [ ] ,
3123- ) ;
3124-
3125- // TODO: Rust 1.83: Remove.
3126- if is_static && !pointer_qty. qualifiers . is_const {
3127- val = mk ( ) . cast_expr ( val, mk ( ) . mutbl ( ) . ptr_ty ( pointee_ty) ) ;
3128- }
3129-
3130- Ok ( val)
3131- }
3132-
31333058 fn addr_lhs (
31343059 & self ,
31353060 lhs : Box < Expr > ,
@@ -3865,151 +3790,9 @@ impl<'c> Translation<'c> {
38653790 )
38663791 . map_err ( |e| e. add_loc ( self . ast_context . display_loc ( src_loc) ) ) ,
38673792
3868- ArraySubscript ( _, ref lhs, ref rhs, _) => {
3869- let lhs_node = & self . ast_context . index ( * lhs) . kind ;
3870- let rhs_node = & self . ast_context . index ( * rhs) . kind ;
3871-
3872- let lhs_node_type = lhs_node
3873- . get_type ( )
3874- . ok_or_else ( || format_err ! ( "lhs node bad type" ) ) ?;
3875- let lhs_node_kind = & self . ast_context . resolve_type ( lhs_node_type) . kind ;
3876- let lhs_is_indexable = lhs_node_kind. is_pointer ( ) || lhs_node_kind. is_vector ( ) ;
3877-
3878- // From here on in, the LHS is the pointer/array and the RHS the index
3879- let ( lhs, rhs, lhs_node) = if lhs_is_indexable {
3880- ( lhs, rhs, lhs_node)
3881- } else {
3882- ( rhs, lhs, rhs_node)
3883- } ;
3884-
3885- let lhs_node_type = lhs_node
3886- . get_type ( )
3887- . ok_or_else ( || format_err ! ( "lhs node bad type" ) ) ?;
3888- if self
3889- . ast_context
3890- . resolve_type ( lhs_node_type)
3891- . kind
3892- . is_vector ( )
3893- {
3894- return Err ( TranslationError :: new (
3895- self . ast_context . display_loc ( src_loc) ,
3896- err_msg ( "Attempting to index a vector type" )
3897- . context ( TranslationErrorKind :: OldLLVMSimd ) ,
3898- ) ) ;
3899- }
3900-
3901- let rhs = self . convert_expr ( ctx. used ( ) , * rhs, None ) ?;
3902- rhs. and_then ( |rhs| {
3903- let simple_index_array = if ctx. needs_address ( ) {
3904- // We can't necessarily index into an array if we're using
3905- // that element to compute an address.
3906- None
3907- } else {
3908- match lhs_node {
3909- & CExprKind :: ImplicitCast (
3910- _,
3911- arr,
3912- CastKind :: ArrayToPointerDecay ,
3913- _,
3914- _,
3915- ) => {
3916- match self . ast_context [ arr] . kind {
3917- CExprKind :: Member ( _, _, field_decl, _, _)
3918- if self
3919- . potential_flexible_array_members
3920- . borrow ( )
3921- . contains ( & field_decl) =>
3922- {
3923- None
3924- }
3925- ref kind => {
3926- let arr_type = kind
3927- . get_type ( )
3928- . ok_or_else ( || format_err ! ( "bad arr type" ) ) ?;
3929- match self . ast_context . resolve_type ( arr_type) . kind {
3930- // These get translated to 0-element arrays, this avoids the bounds check
3931- // that using an array subscript in Rust would cause
3932- CTypeKind :: IncompleteArray ( _) => None ,
3933- _ => Some ( arr) ,
3934- }
3935- }
3936- }
3937- }
3938- _ => None ,
3939- }
3940- } ;
3941-
3942- if let Some ( arr) = simple_index_array {
3943- // If the LHS just underwent an implicit cast from array to pointer, bypass that
3944- // to make an actual Rust indexing operation
3945-
3946- let t = self . ast_context [ arr]
3947- . kind
3948- . get_type ( )
3949- . ok_or_else ( || format_err ! ( "bad arr type" ) ) ?;
3950- let var_elt_type_id = match self . ast_context . resolve_type ( t) . kind {
3951- CTypeKind :: ConstantArray ( ..) => None ,
3952- CTypeKind :: IncompleteArray ( ..) => None ,
3953- CTypeKind :: VariableArray ( elt, _) => Some ( elt) ,
3954- ref other => panic ! ( "Unexpected array type {:?}" , other) ,
3955- } ;
3956-
3957- let lhs = self . convert_expr ( ctx. used ( ) , arr, None ) ?;
3958- lhs. and_then ( |lhs| {
3959- // stmts.extend(lhs.stmts_mut());
3960- // is_unsafe = is_unsafe || lhs.is_unsafe();
3961-
3962- // Don't dereference the offset if we're still within the variable portion
3963- if let Some ( elt_type_id) = var_elt_type_id {
3964- let mul = self . compute_size_of_expr ( elt_type_id) ;
3965- Ok ( WithStmts :: new_unsafe_val ( pointer_offset (
3966- lhs, rhs, mul, false , true ,
3967- ) ) )
3968- } else {
3969- Ok ( WithStmts :: new_val (
3970- mk ( ) . index_expr ( lhs, cast_int ( rhs, "usize" , false ) ) ,
3971- ) )
3972- }
3973- } )
3974- } else {
3975- // LHS must be ref decayed for the offset method call's self param
3976- let mut lhs = self . convert_expr ( ctx. used ( ) . decay_ref ( ) , * lhs, None ) ?;
3977- lhs. set_unsafe ( ) ; // `pointer_offset` is unsafe.
3978- lhs. result_map ( |lhs| {
3979- // stmts.extend(lhs.stmts_mut());
3980- // is_unsafe = is_unsafe || lhs.is_unsafe();
3981-
3982- let lhs_type_id = lhs_node
3983- . get_type ( )
3984- . ok_or_else ( || format_err ! ( "bad lhs type" ) ) ?;
3985-
3986- // Determine the type of element being indexed
3987- let pointee_type_id =
3988- match self . ast_context . resolve_type ( lhs_type_id) . kind {
3989- CTypeKind :: Pointer ( pointee_id) => pointee_id,
3990- _ => {
3991- return Err ( format_err ! (
3992- "Subscript applied to non-pointer: {:?}" ,
3993- lhs
3994- )
3995- . into ( ) ) ;
3996- }
3997- } ;
3998-
3999- let mul = self . compute_size_of_expr ( pointee_type_id. ctype ) ;
4000- let mut val = pointer_offset ( lhs, rhs, mul, false , true ) ;
4001- // if the context wants a different type, add a cast
4002- if let Some ( expected_ty) = override_ty {
4003- if expected_ty != pointee_type_id {
4004- val =
4005- mk ( ) . cast_expr ( val, self . convert_type ( expected_ty. ctype ) ?) ;
4006- }
4007- }
4008- Ok ( val)
4009- } )
4010- }
4011- } )
4012- }
3793+ ArraySubscript ( _, lhs, rhs, _) => self
3794+ . convert_array_subscript ( ctx, lhs, rhs, override_ty)
3795+ . map_err ( |e| e. add_loc ( self . ast_context . display_loc ( src_loc) ) ) ,
40133796
40143797 Call ( call_expr_ty, func, ref args) => {
40153798 let fn_ty =
@@ -4739,21 +4522,7 @@ impl<'c> Translation<'c> {
47394522 }
47404523
47414524 CastKind :: ArrayToPointerDecay => {
4742- // Because va_list is sometimes defined as a single-element
4743- // array in order for it to allocate memory as a local variable
4744- // and to be a pointer as a function argument we would get
4745- // spurious casts when trying to treat it like a VaList which
4746- // has reference semantics.
4747- if self . ast_context . is_va_list ( target_cty. ctype ) {
4748- return Ok ( val) ;
4749- }
4750-
4751- // Variable length arrays are already represented as pointers.
4752- if let CTypeKind :: VariableArray ( ..) = source_ty_kind {
4753- return Ok ( val) ;
4754- }
4755-
4756- self . convert_address_of ( ctx, expr, source_cty, target_cty, val, true )
4525+ self . convert_array_to_pointer_decay ( ctx, source_cty, target_cty, val, expr)
47574526 }
47584527
47594528 CastKind :: NullToPointer => {
@@ -4913,106 +4682,6 @@ impl<'c> Translation<'c> {
49134682 val. map ( |x| mk ( ) . cast_expr ( x, target_ty) )
49144683 }
49154684
4916- pub fn convert_address_of (
4917- & self ,
4918- ctx : ExprContext ,
4919- arg : Option < CExprId > ,
4920- arg_cty : CQualTypeId ,
4921- pointer_cty : CQualTypeId ,
4922- mut val : WithStmts < Box < Expr > > ,
4923- is_array_decay : bool ,
4924- ) -> TranslationResult < WithStmts < Box < Expr > > > {
4925- let arg_expr_kind = arg. map ( |arg| {
4926- let arg = self . ast_context . unwrap_predefined_ident ( arg) ;
4927- & self . ast_context . index ( arg) . kind
4928- } ) ;
4929- let pointee_cty = self
4930- . ast_context
4931- . get_pointee_qual_type ( pointer_cty. ctype )
4932- . ok_or_else ( || TranslationError :: generic ( "Address-of should return a pointer" ) ) ?;
4933- let arg_is_macro = arg. map_or ( false , |arg| {
4934- matches ! (
4935- self . convert_const_macro_expansion( ctx, arg, None ) ,
4936- Ok ( Some ( _) )
4937- )
4938- } ) ;
4939-
4940- let mut needs_cast = false ;
4941- let mut ref_cast_pointee_ty = None ;
4942- let mutbl = if pointee_cty. qualifiers . is_const {
4943- Mutability :: Immutable
4944- } else if ctx. is_static {
4945- // static variable initializers aren't able to use &mut, so we work around that
4946- // by using & and an extra cast through & to *const to *mut
4947- // TODO: Rust 1.83: Allowed, so this can be removed.
4948- needs_cast = true ;
4949- Mutability :: Immutable
4950- } else {
4951- Mutability :: Mutable
4952- } ;
4953-
4954- // String literals are translated with a transmute, which produces a temporary.
4955- // Taking the address of a temporary leaves a dangling pointer. So instead,
4956- // cast the string literal directly so that its 'static lifetime is preserved.
4957- if let (
4958- Some ( & CExprKind :: Literal ( literal_cty, CLiteral :: String ( ref bytes, element_size @ 1 ) ) ) ,
4959- false ,
4960- ) = ( arg_expr_kind, arg_is_macro)
4961- {
4962- let bytes_padded = self . string_literal_bytes ( literal_cty. ctype , bytes, element_size) ;
4963- let len = bytes_padded. len ( ) ;
4964- val = WithStmts :: new_val ( mk ( ) . lit_expr ( bytes_padded) ) ;
4965-
4966- if is_array_decay {
4967- ref_cast_pointee_ty = Some ( mk ( ) . ident_ty ( "u8" ) ) ;
4968- } else {
4969- ref_cast_pointee_ty =
4970- Some ( mk ( ) . array_ty ( mk ( ) . ident_ty ( "u8" ) , mk ( ) . lit_expr ( len as u128 ) ) ) ;
4971- }
4972- needs_cast = true ;
4973- } else {
4974- let arg_cty_kind = & self . ast_context . resolve_type ( arg_cty. ctype ) . kind ;
4975-
4976- if is_array_decay {
4977- let method = match mutbl {
4978- Mutability :: Mutable => "as_mut_ptr" ,
4979- Mutability :: Immutable => "as_ptr" ,
4980- } ;
4981- val = val. map ( |val| mk ( ) . method_call_expr ( val, method, vec ! [ ] ) ) ;
4982-
4983- // If the target pointee type is different from the source element type,
4984- // then we need to cast the ptr type as well.
4985- if arg_cty_kind. element_ty ( ) . map_or ( false , |arg_element_cty| {
4986- arg_element_cty != pointee_cty. ctype
4987- } ) {
4988- needs_cast = true ;
4989- }
4990- } else {
4991- val = val. map ( |val| mk ( ) . set_mutbl ( mutbl) . addr_of_expr ( val) ) ;
4992-
4993- // Add an intermediate reference-to-pointer cast if the context needs
4994- // reference-to-pointer decay, or if another cast follows.
4995- if ctx. decay_ref . is_yes ( ) || needs_cast {
4996- ref_cast_pointee_ty = Some ( self . convert_pointee_type ( arg_cty. ctype ) ?) ;
4997- }
4998- }
4999- }
5000-
5001- // Perform an intermediate reference-to-pointer cast if needed.
5002- // TODO: Rust 1.76: Use `ptr::from_ref`.
5003- if let Some ( pointee_ty) = ref_cast_pointee_ty {
5004- val = val. map ( |val| mk ( ) . cast_expr ( val, mk ( ) . set_mutbl ( mutbl) . ptr_ty ( pointee_ty) ) ) ;
5005- }
5006-
5007- // Perform a final cast to the target type if needed.
5008- if needs_cast {
5009- let pointer_ty = self . convert_type ( pointer_cty. ctype ) ?;
5010- val = val. map ( |val| mk ( ) . cast_expr ( val, pointer_ty) ) ;
5011- }
5012-
5013- Ok ( val)
5014- }
5015-
50164685 pub fn implicit_default_expr (
50174686 & self ,
50184687 ty_id : CTypeId ,
0 commit comments