Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions c2rust-transpile/src/c_ast/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
4 changes: 2 additions & 2 deletions c2rust-transpile/src/c_ast/iterators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,11 @@ fn immediate_decl_children(kind: &CDeclKind) -> Vec<SomeId> {
}
Enum {
ref variants,
integral_type,
underlying_type_id,
..
} => {
let mut res: Vec<SomeId> = 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
Expand Down
4 changes: 2 additions & 2 deletions c2rust-transpile/src/c_ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ impl TypedAstContext {
Struct { fields: None, .. }
| Union { fields: None, .. }
| Enum {
integral_type: None,
underlying_type_id: None,
..
}
)
Expand Down Expand Up @@ -1832,7 +1832,7 @@ pub enum CDeclKind {
Enum {
name: Option<String>,
variants: Vec<CEnumConstantId>,
integral_type: Option<CQualTypeId>,
underlying_type_id: Option<CQualTypeId>,
},

EnumConstant {
Expand Down
2 changes: 1 addition & 1 deletion c2rust-transpile/src/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
59 changes: 37 additions & 22 deletions c2rust-transpile/src/translator/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ impl<'c> Translation<'c> {
&self,
enum_id: CEnumId,
span: Span,
integral_type: CQualTypeId,
underlying_type_id: CQualTypeId,
variants: &[CEnumConstantId],
) -> TranslationResult<ConvertedDecl> {
let enum_name = &self
.type_converter
.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"])
Expand All @@ -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()
Expand All @@ -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)
Expand All @@ -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<Expr>) {
fn make_enum_constant_init(
&self,
enum_constant_id: CEnumConstantId,
is_bool: bool,
) -> (Span, Box<Expr>) {
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);
Expand Down Expand Up @@ -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<Expr>) -> Box<Expr> {
/// Gets the underlying value of an enum value.
pub fn make_enum_to_underlying_cast(&self, val: Box<Expr>) -> Box<Expr> {
mk().anon_field_expr(val, 0)
}

Expand All @@ -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)
Expand All @@ -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)),
Expand Down Expand Up @@ -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
),
}
Expand Down
22 changes: 11 additions & 11 deletions c2rust-transpile/src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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
};
Expand Down
2 changes: 1 addition & 1 deletion c2rust-transpile/src/translator/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions c2rust-transpile/src/translator/variadic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
Loading