@@ -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 ,
@@ -3527,6 +3534,26 @@ impl<'c> Translation<'c> {
35273534 }
35283535
35293536 let expr_kind = & self . ast_context [ expr_id] . kind ;
3537+
3538+ if let & CExprKind :: DeclRef ( _, decl_id, _) = expr_kind {
3539+ if let CDeclKind :: EnumConstant { .. } = self . ast_context [ decl_id] . kind {
3540+ // In C, `EnumConstant`s have some integral type, _not_ the enum type.
3541+ // However, if we then immediately have a cast to convert this variable back into
3542+ // the enum type, we would like to produce Rust with _no_ casts.
3543+ if self . enum_constant_matches_type ( target_type_id. ctype , decl_id) {
3544+ // `enum`s shouldn't need portable `override_ty`s.
3545+ let expr_is_macro = self . expr_is_expanded_macro ( ctx, expr_id, None ) ;
3546+
3547+ // If this DeclRef expanded to a const macro, we actually need to insert
3548+ // a cast, because the translation of a const macro skips implicit casts
3549+ // in its context.
3550+ if !expr_is_macro {
3551+ return true ;
3552+ }
3553+ }
3554+ }
3555+ }
3556+
35303557 let mut literal_expr_kind = expr_kind;
35313558 let mut is_negated = false ;
35323559
@@ -3753,11 +3780,9 @@ impl<'c> Translation<'c> {
37533780 self . ast_context [ source_cty. ctype ] . kind
37543781 {
37553782 self . f128_cast_to ( val, target_ty_kind)
3756- } else if let & CTypeKind :: Enum ( enum_decl_id ) = target_ty_kind {
3783+ } else if let & CTypeKind :: Enum ( _ ) = target_ty_kind {
37573784 // Casts targeting `enum` types...
3758- val. result_map ( |val| {
3759- self . convert_cast_to_enum ( ctx, target_cty. ctype , enum_decl_id, expr, val)
3760- } )
3785+ val. result_map ( |val| self . convert_cast_to_enum ( target_cty. ctype , expr, val) )
37613786 } else if target_ty_kind. is_floating_type ( ) && source_ty_kind. is_bool ( ) {
37623787 Ok ( val. map ( |val| {
37633788 mk ( ) . cast_expr ( mk ( ) . cast_expr ( val, mk ( ) . path_ty ( vec ! [ "u8" ] ) ) , target_ty)
0 commit comments