diff --git a/c2rust-transpile/src/c_ast/conversion.rs b/c2rust-transpile/src/c_ast/conversion.rs index 54edf960c9..0fbd335904 100644 --- a/c2rust-transpile/src/c_ast/conversion.rs +++ b/c2rust-transpile/src/c_ast/conversion.rs @@ -2294,12 +2294,12 @@ impl ConversionContext { }) .collect(); - let integral_type = node.type_id.map(|x| self.visit_qualified_type(x)); + let underlying_type_id = node.type_id.map(|x| self.visit_qualified_type(x)); let enum_decl = CDeclKind::Enum { name, variants, - integral_type, + underlying_type_id, }; self.add_decl(new_id, located(node, enum_decl)); diff --git a/c2rust-transpile/src/c_ast/iterators.rs b/c2rust-transpile/src/c_ast/iterators.rs index a7c1522250..123c3777f6 100644 --- a/c2rust-transpile/src/c_ast/iterators.rs +++ b/c2rust-transpile/src/c_ast/iterators.rs @@ -171,11 +171,11 @@ fn immediate_decl_children(kind: &CDeclKind) -> Vec { } Enum { ref variants, - integral_type, + underlying_type_id, .. } => { let mut res: Vec = variants.iter().map(|&x| x.into()).collect(); - if let Some(qty) = integral_type { + if let Some(qty) = underlying_type_id { res.push(qty.ctype.into()); } res diff --git a/c2rust-transpile/src/c_ast/mod.rs b/c2rust-transpile/src/c_ast/mod.rs index fb1e73a1e3..2968ced03a 100644 --- a/c2rust-transpile/src/c_ast/mod.rs +++ b/c2rust-transpile/src/c_ast/mod.rs @@ -530,7 +530,7 @@ impl TypedAstContext { Struct { fields: None, .. } | Union { fields: None, .. } | Enum { - integral_type: None, + underlying_type_id: None, .. } ) @@ -1832,7 +1832,7 @@ pub enum CDeclKind { Enum { name: Option, variants: Vec, - integral_type: Option, + underlying_type_id: Option, }, EnumConstant { diff --git a/c2rust-transpile/src/cfg/mod.rs b/c2rust-transpile/src/cfg/mod.rs index 94daca5eb0..e75faac2ac 100644 --- a/c2rust-transpile/src/cfg/mod.rs +++ b/c2rust-transpile/src/cfg/mod.rs @@ -2026,7 +2026,7 @@ impl CfgBuilder { .kind; if let CTypeKind::Enum(enum_id) = *castee_type_kind { - if target_type_id == translator.enum_integral_type(enum_id) { + if target_type_id == translator.enum_underlying_type(enum_id) { expected_type_id = Some(castee_type_id); } } diff --git a/c2rust-transpile/src/translator/enums.rs b/c2rust-transpile/src/translator/enums.rs index 65c81bf884..06529c41d2 100644 --- a/c2rust-transpile/src/translator/enums.rs +++ b/c2rust-transpile/src/translator/enums.rs @@ -15,7 +15,7 @@ impl<'c> Translation<'c> { &self, enum_id: CEnumId, span: Span, - integral_type: CQualTypeId, + underlying_type_id: CQualTypeId, variants: &[CEnumConstantId], ) -> TranslationResult { let enum_name = &self @@ -23,8 +23,8 @@ impl<'c> Translation<'c> { .borrow() .resolve_decl_name(enum_id) .expect("Enums should already be renamed"); - let integral_type_rs = self.convert_type(integral_type.ctype)?; - let field = mk().pub_().enum_field(integral_type_rs); + let underlying_type_rs = self.convert_type(underlying_type_id.ctype)?; + let field = mk().pub_().enum_field(underlying_type_rs); let enum_item = mk() .span(span) .call_attr("derive", vec!["Clone", "Copy", "PartialEq", "Eq"]) @@ -36,6 +36,8 @@ impl<'c> Translation<'c> { return Ok(ConvertedDecl::Item(enum_item)); } + let underlying_type_kind = &self.ast_context.resolve_type(underlying_type_id.ctype).kind; + let underlying_type_is_bool = underlying_type_kind.is_bool(); let enum_type = mk().ident_ty("Self"); let constants = variants .iter() @@ -49,7 +51,8 @@ impl<'c> Translation<'c> { enum_constant_id, name, ); - let (span, init) = self.make_enum_constant_init(enum_constant_id); + let (span, init) = + self.make_enum_constant_init(enum_constant_id, underlying_type_is_bool); mk().span(span) .pub_() .const_impl_item(name_rs, enum_type.clone(), init) @@ -62,14 +65,26 @@ impl<'c> Translation<'c> { Ok(ConvertedDecl::Items(vec![enum_item, impl_block])) } - fn make_enum_constant_init(&self, enum_constant_id: CEnumConstantId) -> (Span, Box) { + fn make_enum_constant_init( + &self, + enum_constant_id: CEnumConstantId, + is_bool: bool, + ) -> (Span, Box) { let value = match self.ast_context[enum_constant_id].kind { CDeclKind::EnumConstant { value, .. } => value, _ => panic!("{:?} does not point to an enum variant", enum_constant_id), }; let value_rs = match value { ConstIntExpr::I(value) => signed_int_expr(value), - ConstIntExpr::U(value) => mk().lit_expr(mk().int_unsuffixed_lit(value as u128)), + ConstIntExpr::U(value) => { + let lit = if is_bool { + mk().bool_lit(value != 0) + } else { + mk().int_unsuffixed_lit(value as u128) + }; + + mk().lit_expr(lit) + } }; let enum_id = self.ast_context.parents[&enum_constant_id]; let init = self.enum_constructor_expr(enum_id, value_rs, true); @@ -116,16 +131,16 @@ impl<'c> Translation<'c> { )); } - // First extract the enum's inner type... - val = self.integer_from_enum(val); + // First extract the enum's underlying type... + val = self.make_enum_to_underlying_cast(val); - // Cast from the enum's integral type to the expected integral type. - let source_cty = self.enum_integral_type(enum_id); + // Cast from the underlying type to the expected type. + let source_cty = self.enum_underlying_type(enum_id); self.make_cast(ctx, source_cty, target_cty, WithStmts::new_val(val)) } - /// Gets the inner integral value of an enum value. - pub fn integer_from_enum(&self, val: Box) -> Box { + /// Gets the underlying value of an enum value. + pub fn make_enum_to_underlying_cast(&self, val: Box) -> Box { mk().anon_field_expr(val, 0) } @@ -152,14 +167,14 @@ impl<'c> Translation<'c> { )); } - // Enum-to-enum casts need to be translated via the inner value as an intermediate. - val = self.integer_from_enum(val); - source_cty = self.enum_integral_type(source_enum_id); + // Enum-to-enum casts need to be translated via the underlying value as an intermediate. + val = self.make_enum_to_underlying_cast(val); + source_cty = self.enum_underlying_type(source_enum_id); } - let enum_integral_type = self.enum_integral_type(enum_id); + let underlying_type_id = self.enum_underlying_type(enum_id); let mut val = WithStmts::new_val(val); - val = self.make_cast(ctx, source_cty, enum_integral_type, val)?; + val = self.make_cast(ctx, source_cty, underlying_type_id, val)?; val = val.map(|val| self.enum_constructor_expr(enum_id, val, false)); Ok(val) @@ -172,7 +187,7 @@ impl<'c> Translation<'c> { return self.enum_constant_expr(enum_constant_id); } - let underlying_type_id = self.enum_integral_type(enum_id); + let underlying_type_id = self.enum_underlying_type(enum_id); let value = match self.ast_context.resolve_type(underlying_type_id.ctype).kind { CTypeKind::UInt => mk().lit_expr(mk().int_unsuffixed_lit((value as u32) as u128)), CTypeKind::ULong => mk().lit_expr(mk().int_unsuffixed_lit((value as u64) as u128)), @@ -261,14 +276,14 @@ impl<'c> Translation<'c> { type_enum_id == constant_enum_id } - pub(crate) fn enum_integral_type(&self, enum_id: CEnumId) -> CQualTypeId { + pub(crate) fn enum_underlying_type(&self, enum_id: CEnumId) -> CQualTypeId { match self.ast_context[enum_id].kind { CDeclKind::Enum { - integral_type: Some(integral_type), + underlying_type_id: Some(underlying_type_id), .. - } => integral_type, + } => underlying_type_id, _ => panic!( - "{:?} does not point to an integral `enum` declaration", + "{:?} does not point to a non-extern `enum` declaration", enum_id ), } diff --git a/c2rust-transpile/src/translator/mod.rs b/c2rust-transpile/src/translator/mod.rs index 5a0a6450db..1233f1e3dc 100644 --- a/c2rust-transpile/src/translator/mod.rs +++ b/c2rust-transpile/src/translator/mod.rs @@ -2067,7 +2067,7 @@ impl<'c> Translation<'c> { Struct { fields: None, .. } | Union { fields: None, .. } | Enum { - integral_type: None, + underlying_type_id: None, .. } => { self.use_feature("extern_types"); @@ -2110,9 +2110,9 @@ impl<'c> Translation<'c> { Enum { ref variants, - integral_type: Some(integral_type), + underlying_type_id: Some(underlying_type_id), .. - } => self.convert_enum(decl_id, span, integral_type, variants), + } => self.convert_enum(decl_id, span, underlying_type_id, variants), // EnumConstant is translated as part of Enum. EnumConstant { .. } => Ok(ConvertedDecl::NoItem), @@ -4165,16 +4165,16 @@ impl<'c> Translation<'c> { let target_type_kind = &self.ast_context.resolve_type(target_type_id.ctype).kind; if let CTypeKind::Enum(target_enum_id) = *target_type_kind { - let target_integral_type_id = self.enum_integral_type(target_enum_id); - let target_integral_type_kind = &self + let target_underlying_type_id = self.enum_underlying_type(target_enum_id); + let target_underlying_type_kind = &self .ast_context - .resolve_type(target_integral_type_id.ctype) + .resolve_type(target_underlying_type_id.ctype) .kind; // We are casting to an enum type, from its underlying integral type. // Skip the cast to the integral type and cast to the enum type directly. if cast_kind == CastKind::IntegralCast - && source_type_kind == target_integral_type_kind + && source_type_kind == target_underlying_type_kind { return true; } @@ -4191,14 +4191,14 @@ impl<'c> Translation<'c> { } let source_enum_id = self.ast_context.parents[&decl_id]; - let source_integral_type_id = self.enum_integral_type(source_enum_id); + let source_underlying_type_id = self.enum_underlying_type(source_enum_id); let target_type_resolved_id = self .ast_context .resolve_type_id_no_typedef(target_type_id.ctype); - // Likewise, if we are casting to the inner integral type of the enum, then + // Likewise, if we are casting to the underlying type of the enum, then // translate the enum constant directly as that. - if target_type_resolved_id == source_integral_type_id.ctype { + if target_type_resolved_id == source_underlying_type_id.ctype { return true; } } @@ -4695,7 +4695,7 @@ impl<'c> Translation<'c> { } let val = if ty.is_enum() { - self.integer_from_enum(val) + self.make_enum_to_underlying_cast(val) } else { val }; diff --git a/c2rust-transpile/src/translator/operators.rs b/c2rust-transpile/src/translator/operators.rs index 4c2de512b8..f85193f5fc 100644 --- a/c2rust-transpile/src/translator/operators.rs +++ b/c2rust-transpile/src/translator/operators.rs @@ -664,7 +664,7 @@ impl<'c> Translation<'c> { one_type_id = CQualTypeId::new(self.ast_context.type_for_kind(&CTypeKind::Int)); } CTypeKind::Enum(enum_id) => { - one_type_id = self.enum_integral_type(enum_id); + one_type_id = self.enum_underlying_type(enum_id); compute_lhs_type_id = one_type_id; compute_res_type_id = one_type_id; } diff --git a/c2rust-transpile/src/translator/variadic.rs b/c2rust-transpile/src/translator/variadic.rs index bacdf9f362..e86286c62b 100644 --- a/c2rust-transpile/src/translator/variadic.rs +++ b/c2rust-transpile/src/translator/variadic.rs @@ -192,9 +192,9 @@ impl<'c> Translation<'c> { match self.ast_context.resolve_type(ty.ctype).kind { CTypeKind::Enum(enum_id) => { - let integral_type_id = self.enum_integral_type(enum_id); + let underlying_type_id = self.enum_underlying_type(enum_id); cast_kind = Some(VaArgCastKind::Enum(enum_id)); - arg_ty = Some(self.convert_type(integral_type_id.ctype).unwrap()); + arg_ty = Some(self.convert_type(underlying_type_id.ctype).unwrap()); } CTypeKind::Pointer(p) => {