@@ -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
@@ -3265,7 +3271,7 @@ impl<'c> Translation<'c> {
32653271 // But for some expression types, if we don't absolutely have to cast,
32663272 // we would rather the expression is translated according to the type we're
32673273 // expecting, and then we can skip the cast entirely.
3268- if !is_explicit && self . can_propagate_cast ( expr, target_ty) {
3274+ if !is_explicit && self . can_propagate_cast ( ctx , expr, target_ty) {
32693275 return self . convert_expr ( ctx, expr, Some ( target_ty) ) ;
32703276 }
32713277
@@ -3514,8 +3520,33 @@ impl<'c> Translation<'c> {
35143520 }
35153521 }
35163522
3517- fn can_propagate_cast ( & self , expr_id : CExprId , target_type_id : CQualTypeId ) -> bool {
3523+ fn can_propagate_cast (
3524+ & self ,
3525+ ctx : ExprContext ,
3526+ expr_id : CExprId ,
3527+ target_type_id : CQualTypeId ,
3528+ ) -> bool {
35183529 let expr_kind = & self . ast_context [ expr_id] . kind ;
3530+
3531+ if let & CExprKind :: DeclRef ( _, decl_id, _) = expr_kind {
3532+ if let CDeclKind :: EnumConstant { .. } = self . ast_context [ decl_id] . kind {
3533+ // In C, `EnumConstant`s have some integral type, _not_ the enum type.
3534+ // However, if we then immediately have a cast to convert this variable back into
3535+ // the enum type, we would like to produce Rust with _no_ casts.
3536+ if self . enum_constant_matches_type ( target_type_id. ctype , decl_id) {
3537+ // `enum`s shouldn't need portable `override_ty`s.
3538+ let expr_is_macro = self . expr_is_expanded_macro ( ctx, expr_id, None ) ;
3539+
3540+ // If this DeclRef expanded to a const macro, we actually need to insert
3541+ // a cast, because the translation of a const macro skips implicit casts
3542+ // in its context.
3543+ if !expr_is_macro {
3544+ return true ;
3545+ }
3546+ }
3547+ }
3548+ }
3549+
35193550 let mut literal_expr_kind = expr_kind;
35203551 let mut is_negated = false ;
35213552
@@ -3742,11 +3773,9 @@ impl<'c> Translation<'c> {
37423773 self . ast_context [ source_cty. ctype ] . kind
37433774 {
37443775 self . f128_cast_to ( val, target_ty_kind)
3745- } else if let & CTypeKind :: Enum ( enum_decl_id ) = target_ty_kind {
3776+ } else if let & CTypeKind :: Enum ( _ ) = target_ty_kind {
37463777 // Casts targeting `enum` types...
3747- val. result_map ( |val| {
3748- self . convert_cast_to_enum ( ctx, target_cty. ctype , enum_decl_id, expr, val)
3749- } )
3778+ val. result_map ( |val| self . convert_cast_to_enum ( target_cty. ctype , expr, val) )
37503779 } else if target_ty_kind. is_floating_type ( ) && source_ty_kind. is_bool ( ) {
37513780 Ok ( val. map ( |val| {
37523781 mk ( ) . cast_expr ( mk ( ) . cast_expr ( val, mk ( ) . path_ty ( vec ! [ "u8" ] ) ) , target_ty)
0 commit comments