@@ -7,8 +7,8 @@ use crate::{
77 diagnostics:: TranslationResult ,
88 translator:: { signed_int_expr, ConvertedDecl , EnumMode , ExprContext , Translation } ,
99 with_stmts:: WithStmts ,
10- CDeclKind , CEnumConstantId , CEnumId , CExprId , CExprKind , CLiteral , CQualTypeId , CTypeKind ,
11- ConstIntExpr ,
10+ CDeclKind , CEnumConstantId , CEnumId , CExprId , CExprKind , CLiteral , CQualTypeId , CTypeId ,
11+ CTypeKind , ConstIntExpr ,
1212} ;
1313
1414impl < ' c > Translation < ' c > {
@@ -87,11 +87,17 @@ impl<'c> Translation<'c> {
8787 enum_constant_id : CEnumConstantId ,
8888 target_type_id : CQualTypeId ,
8989 ) -> TranslationResult < WithStmts < Box < Expr > > > {
90- let enum_id = self . ast_context . parents [ & enum_constant_id] ;
91- let val = self . enum_constant_expr ( enum_constant_id) ;
90+ let mut val = WithStmts :: new_val ( self . enum_constant_expr ( enum_constant_id) ) ;
91+
92+ if !self . enum_constant_matches_type ( target_type_id. ctype , enum_constant_id) {
93+ // Add a cast to the expected integral type.
94+ let enum_id = self . ast_context . parents [ & enum_constant_id] ;
95+ val = val. and_then_try ( |val| {
96+ self . convert_cast_from_enum ( ctx, enum_id, target_type_id, val)
97+ } ) ?;
98+ }
9299
93- // Add a cast to the expected integral type.
94- self . convert_cast_from_enum ( ctx, enum_id, target_type_id, val)
100+ Ok ( val)
95101 }
96102
97103 /// Translate a cast where the source type, but not the target type, is an `enum` type.
@@ -140,23 +146,6 @@ impl<'c> Translation<'c> {
140146 ) -> TranslationResult < WithStmts < Box < Expr > > > {
141147 if let Some ( expr) = expr {
142148 match self . ast_context [ expr] . kind {
143- // This is the case of finding a variable which is an `EnumConstant` of the same
144- // enum we are casting to. Here, we can just remove the extraneous cast instead of
145- // generating a new one.
146- CExprKind :: DeclRef ( _, enum_constant_id, _)
147- if self . is_variant_of_enum ( enum_id, enum_constant_id) =>
148- {
149- // `enum`s shouldn't need portable `override_ty`s.
150- let expr_is_macro = self . expr_is_expanded_macro ( ctx, expr, None ) ;
151-
152- // If this DeclRef expanded to a const macro, we actually need to insert a cast,
153- // because the translation of a const macro skips implicit casts in its context.
154- if !expr_is_macro {
155- val = self . enum_constant_expr ( enum_constant_id) ;
156- return Ok ( WithStmts :: new_val ( val) ) ;
157- }
158- }
159-
160149 CExprKind :: Literal ( _, CLiteral :: Integer ( i, _) ) => {
161150 val = self . enum_for_i64 ( enum_id, i as i64 ) ;
162151 return Ok ( WithStmts :: new_val ( val) ) ;
@@ -272,13 +261,17 @@ impl<'c> Translation<'c> {
272261 }
273262 }
274263
275- fn is_variant_of_enum ( & self , enum_id : CEnumId , enum_constant_id : CEnumConstantId ) -> bool {
276- let variants = match self . ast_context [ enum_id] . kind {
277- CDeclKind :: Enum { ref variants, .. } => variants,
278- _ => panic ! ( "{:?} does not point to an `enum` declaration" , enum_id) ,
264+ pub fn enum_constant_matches_type (
265+ & self ,
266+ type_id : CTypeId ,
267+ enum_constant_id : CEnumConstantId ,
268+ ) -> bool {
269+ let type_enum_id = match self . ast_context . resolve_type_no_typedef ( type_id) . kind {
270+ CTypeKind :: Enum ( enum_id) => enum_id,
271+ _ => return false ,
279272 } ;
280-
281- variants . contains ( & enum_constant_id )
273+ let constant_enum_id = self . ast_context . parents [ & enum_constant_id ] ;
274+ type_enum_id == constant_enum_id
282275 }
283276
284277 pub fn enum_integral_type ( & self , enum_id : CEnumId ) -> CQualTypeId {
0 commit comments