@@ -3104,7 +3104,13 @@ impl<'c> Translation<'c> {
31043104 // If the variable is actually an `EnumConstant`, we need to add a cast to the
31053105 // expected integral type.
31063106 if let & CDeclKind :: EnumConstant { .. } = decl {
3107- val = self . convert_cast_from_enum ( qual_ty. ctype , val) ?;
3107+ if !self
3108+ . enum_constant_matches_type ( override_ty. unwrap_or ( qual_ty) . ctype , decl_id)
3109+ {
3110+ val = self . convert_cast_from_enum ( qual_ty. ctype , val) ?;
3111+ }
3112+
3113+ return Ok ( WithStmts :: new_val ( val) ) ;
31083114 }
31093115
31103116 // If we are referring to a function and need its address, we
@@ -3246,7 +3252,7 @@ impl<'c> Translation<'c> {
32463252 // But for some expression types, if we don't absolutely have to cast,
32473253 // we would rather the expression is translated according to the type we're
32483254 // expecting, and then we can skip the cast entirely.
3249- if self . can_propagate_cast ( expr, target_ty, is_explicit) {
3255+ if self . can_propagate_cast ( ctx , expr, target_ty, is_explicit) {
32503256 return self . convert_expr ( ctx, expr, Some ( target_ty) ) ;
32513257 }
32523258
@@ -3517,6 +3523,7 @@ impl<'c> Translation<'c> {
35173523
35183524 fn can_propagate_cast (
35193525 & self ,
3526+ ctx : ExprContext ,
35203527 expr_id : CExprId ,
35213528 target_type_id : CQualTypeId ,
35223529 is_explicit : bool ,
@@ -3526,6 +3533,26 @@ impl<'c> Translation<'c> {
35263533 }
35273534
35283535 let expr_kind = & self . ast_context [ expr_id] . kind ;
3536+
3537+ if let & CExprKind :: DeclRef ( _, decl_id, _) = expr_kind {
3538+ if let CDeclKind :: EnumConstant { .. } = self . ast_context [ decl_id] . kind {
3539+ // In C, `EnumConstant`s have some integral type, _not_ the enum type.
3540+ // However, if we then immediately have a cast to convert this variable back into
3541+ // the enum type, we would like to produce Rust with _no_ casts.
3542+ if self . enum_constant_matches_type ( target_type_id. ctype , decl_id) {
3543+ // `enum`s shouldn't need portable `override_ty`s.
3544+ let expr_is_macro = self . expr_is_expanded_macro ( ctx, expr_id, None ) ;
3545+
3546+ // If this DeclRef expanded to a const macro, we actually need to insert
3547+ // a cast, because the translation of a const macro skips implicit casts
3548+ // in its context.
3549+ if !expr_is_macro {
3550+ return true ;
3551+ }
3552+ }
3553+ }
3554+ }
3555+
35293556 let mut literal_expr_kind = expr_kind;
35303557 let mut is_negated = false ;
35313558
@@ -3752,11 +3779,9 @@ impl<'c> Translation<'c> {
37523779 self . ast_context [ source_cty. ctype ] . kind
37533780 {
37543781 self . f128_cast_to ( val, target_ty_kind)
3755- } else if let & CTypeKind :: Enum ( enum_decl_id ) = target_ty_kind {
3782+ } else if let & CTypeKind :: Enum ( _ ) = target_ty_kind {
37563783 // Casts targeting `enum` types...
3757- val. result_map ( |val| {
3758- self . convert_cast_to_enum ( ctx, target_cty. ctype , enum_decl_id, expr, val)
3759- } )
3784+ val. result_map ( |val| self . convert_cast_to_enum ( target_cty. ctype , expr, val) )
37603785 } else if target_ty_kind. is_floating_type ( ) && source_ty_kind. is_bool ( ) {
37613786 Ok ( val. map ( |val| {
37623787 mk ( ) . cast_expr ( mk ( ) . cast_expr ( val, mk ( ) . path_ty ( vec ! [ "u8" ] ) ) , target_ty)
0 commit comments