@@ -2934,10 +2934,10 @@ impl<'c> Translation<'c> {
29342934 return Ok ( mk ( ) . path_expr ( vec ! [ "None" ] ) ) ;
29352935 }
29362936
2937- let pointee = match self . ast_context . resolve_type ( type_id ) . kind {
2938- CTypeKind :: Pointer ( pointee ) => pointee ,
2939- _ => return Err ( TranslationError :: generic ( "null_ptr requires a pointer" ) ) ,
2940- } ;
2937+ let pointee = self
2938+ . ast_context
2939+ . get_pointee_qual_type ( type_id )
2940+ . ok_or ( TranslationError :: generic ( "null_ptr requires a pointer" ) ) ? ;
29412941 let ty = self . convert_type ( type_id) ?;
29422942 let mut zero = mk ( ) . lit_expr ( mk ( ) . int_unsuffixed_lit ( 0 ) ) ;
29432943 if is_static && !pointee. qualifiers . is_const {
@@ -4293,15 +4293,15 @@ impl<'c> Translation<'c> {
42934293 fn convert_cast (
42944294 & self ,
42954295 ctx : ExprContext ,
4296- source_ty : CQualTypeId ,
4297- ty : CQualTypeId ,
4296+ source_cty : CQualTypeId ,
4297+ target_cty : CQualTypeId ,
42984298 val : WithStmts < Box < Expr > > ,
42994299 expr : Option < CExprId > ,
43004300 kind : Option < CastKind > ,
43014301 opt_field_id : Option < CFieldId > ,
43024302 ) -> TranslationResult < WithStmts < Box < Expr > > > {
4303- let source_ty_kind = & self . ast_context . resolve_type ( source_ty . ctype ) . kind ;
4304- let target_ty_kind = & self . ast_context . resolve_type ( ty . ctype ) . kind ;
4303+ let source_ty_kind = & self . ast_context . resolve_type ( source_cty . ctype ) . kind ;
4304+ let target_ty_kind = & self . ast_context . resolve_type ( target_cty . ctype ) . kind ;
43054305
43064306 if source_ty_kind == target_ty_kind {
43074307 return Ok ( val) ;
@@ -4382,24 +4382,26 @@ impl<'c> Translation<'c> {
43824382 match kind {
43834383 CastKind :: BitCast | CastKind :: NoOp => {
43844384 val. and_then ( |x| {
4385- if self . ast_context . is_function_pointer ( ty . ctype )
4386- || self . ast_context . is_function_pointer ( source_ty . ctype )
4385+ if self . ast_context . is_function_pointer ( target_cty . ctype )
4386+ || self . ast_context . is_function_pointer ( source_cty . ctype )
43874387 {
4388- let source_ty = self . convert_type ( source_ty . ctype ) ?;
4389- let target_ty = self . convert_type ( ty . ctype ) ?;
4388+ let source_ty = self . convert_type ( source_cty . ctype ) ?;
4389+ let target_ty = self . convert_type ( target_cty . ctype ) ?;
43904390 Ok ( WithStmts :: new_unsafe_val ( transmute_expr (
43914391 source_ty, target_ty, x,
43924392 ) ) )
43934393 } else {
43944394 // Normal case
4395- let target_ty = self . convert_type ( ty . ctype ) ?;
4395+ let target_ty = self . convert_type ( target_cty . ctype ) ?;
43964396 Ok ( WithStmts :: new_val ( mk ( ) . cast_expr ( x, target_ty) ) )
43974397 }
43984398 } )
43994399 }
44004400
4401- CastKind :: IntegralToPointer if self . ast_context . is_function_pointer ( ty. ctype ) => {
4402- let target_ty = self . convert_type ( ty. ctype ) ?;
4401+ CastKind :: IntegralToPointer
4402+ if self . ast_context . is_function_pointer ( target_cty. ctype ) =>
4403+ {
4404+ let target_ty = self . convert_type ( target_cty. ctype ) ?;
44034405 val. and_then ( |x| {
44044406 let intptr_t = mk ( ) . path_ty ( vec ! [ "libc" , "intptr_t" ] ) ;
44054407 let intptr = mk ( ) . cast_expr ( x, intptr_t. clone ( ) ) ;
@@ -4415,13 +4417,10 @@ impl<'c> Translation<'c> {
44154417 | CastKind :: FloatingCast
44164418 | CastKind :: FloatingToIntegral
44174419 | CastKind :: IntegralToFloating => {
4418- let target_ty = self . convert_type ( ty . ctype ) ?;
4419- let target_ty_ctype = & self . ast_context . resolve_type ( ty . ctype ) . kind ;
4420+ let target_ty = self . convert_type ( target_cty . ctype ) ?;
4421+ let source_ty = self . convert_type ( source_cty . ctype ) ? ;
44204422
4421- let source_ty_ctype_id = source_ty. ctype ;
4422-
4423- let source_ty = self . convert_type ( source_ty_ctype_id) ?;
4424- if let CTypeKind :: LongDouble = target_ty_ctype {
4423+ if let CTypeKind :: LongDouble = target_ty_kind {
44254424 if ctx. is_const {
44264425 return Err ( format_translation_err ! (
44274426 None ,
@@ -4433,21 +4432,28 @@ impl<'c> Translation<'c> {
44334432
44344433 let fn_path = mk ( ) . path_expr ( vec ! [ "f128" , "f128" , "new" ] ) ;
44354434 Ok ( val. map ( |val| mk ( ) . call_expr ( fn_path, vec ! [ val] ) ) )
4436- } else if let CTypeKind :: LongDouble = self . ast_context [ source_ty_ctype_id ] . kind {
4437- self . f128_cast_to ( val, target_ty_ctype )
4438- } else if let & CTypeKind :: Enum ( enum_decl_id) = target_ty_ctype {
4435+ } else if let CTypeKind :: LongDouble = self . ast_context [ source_cty . ctype ] . kind {
4436+ self . f128_cast_to ( val, target_ty_kind )
4437+ } else if let & CTypeKind :: Enum ( enum_decl_id) = target_ty_kind {
44394438 // Casts targeting `enum` types...
44404439 let expr =
44414440 expr. ok_or_else ( || format_err ! ( "Casts to enums require a C ExprId" ) ) ?;
4442- Ok ( self . enum_cast ( ty. ctype , enum_decl_id, expr, val, source_ty, target_ty) )
4443- } else if target_ty_ctype. is_floating_type ( ) && source_ty_kind. is_bool ( ) {
4441+ Ok ( self . enum_cast (
4442+ target_cty. ctype ,
4443+ enum_decl_id,
4444+ expr,
4445+ val,
4446+ source_ty,
4447+ target_ty,
4448+ ) )
4449+ } else if target_ty_kind. is_floating_type ( ) && source_ty_kind. is_bool ( ) {
44444450 val. and_then ( |x| {
44454451 Ok ( WithStmts :: new_val ( mk ( ) . cast_expr (
44464452 mk ( ) . cast_expr ( x, mk ( ) . path_ty ( vec ! [ "u8" ] ) ) ,
44474453 target_ty,
44484454 ) ) )
44494455 } )
4450- } else if target_ty_ctype . is_pointer ( ) && source_ty_kind. is_bool ( ) {
4456+ } else if target_ty_kind . is_pointer ( ) && source_ty_kind. is_bool ( ) {
44514457 val. and_then ( |x| {
44524458 Ok ( WithStmts :: new_val ( mk ( ) . cast_expr (
44534459 mk ( ) . cast_expr ( x, mk ( ) . path_ty ( vec ! [ "libc" , "size_t" ] ) ) ,
@@ -4458,7 +4464,7 @@ impl<'c> Translation<'c> {
44584464 // Other numeric casts translate to Rust `as` casts,
44594465 // unless the cast is to a function pointer then use `transmute`.
44604466 val. and_then ( |x| {
4461- if self . ast_context . is_function_pointer ( source_ty_ctype_id ) {
4467+ if self . ast_context . is_function_pointer ( source_cty . ctype ) {
44624468 Ok ( WithStmts :: new_unsafe_val ( transmute_expr (
44634469 source_ty, target_ty, x,
44644470 ) ) )
@@ -4481,21 +4487,21 @@ impl<'c> Translation<'c> {
44814487 // and to be a pointer as a function argument we would get
44824488 // spurious casts when trying to treat it like a VaList which
44834489 // has reference semantics.
4484- if self . ast_context . is_va_list ( ty . ctype ) {
4490+ if self . ast_context . is_va_list ( target_cty . ctype ) {
44854491 return Ok ( val) ;
44864492 }
44874493
4488- let pointee = match self . ast_context . resolve_type ( ty . ctype ) . kind {
4489- CTypeKind :: Pointer ( pointee ) => pointee ,
4490- _ => panic ! ( "Dereferencing a non-pointer" ) ,
4491- } ;
4494+ let pointee = self
4495+ . ast_context
4496+ . get_pointee_qual_type ( target_cty . ctype )
4497+ . unwrap_or_else ( || panic ! ( "dereferencing a non-pointer" ) ) ;
44924498
44934499 let is_const = pointee. qualifiers . is_const ;
44944500
44954501 let expr_kind = expr. map ( |e| & self . ast_context . index ( e) . kind ) ;
44964502 match expr_kind {
44974503 Some ( & CExprKind :: Literal ( _, CLiteral :: String ( ref bytes, 1 ) ) ) if is_const => {
4498- let target_ty = self . convert_type ( ty . ctype ) ?;
4504+ let target_ty = self . convert_type ( target_cty . ctype ) ?;
44994505
45004506 let mut bytes = bytes. to_owned ( ) ;
45014507 bytes. push ( 0 ) ;
@@ -4507,9 +4513,7 @@ impl<'c> Translation<'c> {
45074513 }
45084514 _ => {
45094515 // Variable length arrays are already represented as pointers.
4510- if let CTypeKind :: VariableArray ( ..) =
4511- self . ast_context . resolve_type ( source_ty. ctype ) . kind
4512- {
4516+ if let CTypeKind :: VariableArray ( ..) = source_ty_kind {
45134517 Ok ( val)
45144518 } else {
45154519 let method = if is_const || ctx. is_static {
@@ -4520,6 +4524,19 @@ impl<'c> Translation<'c> {
45204524
45214525 let call = val. map ( |x| mk ( ) . method_call_expr ( x, method, vec ! [ ] ) ) ;
45224526
4527+ // If the target pointee type is different from the source element type,
4528+ // then we need to cast the ptr type as well.
4529+ let call = match source_ty_kind. element_ty ( ) {
4530+ None => call,
4531+ Some ( source_element_ty) if source_element_ty == pointee. ctype => {
4532+ call
4533+ }
4534+ Some ( _) => {
4535+ let target_ty = self . convert_type ( target_cty. ctype ) ?;
4536+ call. map ( |ptr| mk ( ) . cast_expr ( ptr, target_ty) )
4537+ }
4538+ } ;
4539+
45234540 // Static arrays can now use as_ptr. Can also cast that const ptr to a
45244541 // mutable pointer as we do here:
45254542 if ctx. is_static && !is_const {
@@ -4538,7 +4555,9 @@ impl<'c> Translation<'c> {
45384555
45394556 CastKind :: NullToPointer => {
45404557 assert ! ( val. stmts( ) . is_empty( ) ) ;
4541- Ok ( WithStmts :: new_val ( self . null_ptr ( ty. ctype , ctx. is_static ) ?) )
4558+ Ok ( WithStmts :: new_val (
4559+ self . null_ptr ( target_cty. ctype , ctx. is_static ) ?,
4560+ ) )
45424561 }
45434562
45444563 CastKind :: ToUnion => {
@@ -4567,7 +4586,7 @@ impl<'c> Translation<'c> {
45674586 if let Some ( expr) = expr {
45684587 self . convert_condition ( ctx, true , expr)
45694588 } else {
4570- Ok ( val. map ( |e| self . match_bool ( true , source_ty . ctype , e) ) )
4589+ Ok ( val. map ( |e| self . match_bool ( true , source_cty . ctype , e) ) )
45714590 }
45724591 }
45734592
0 commit comments