Skip to content

Commit dfc0d3d

Browse files
committed
transpile: propagate expected types down to translation of literals
this removes lots of ugly extra casts
1 parent 187148c commit dfc0d3d

File tree

4 files changed

+28
-5
lines changed

4 files changed

+28
-5
lines changed

c2rust-transpile/src/translator/literals.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,17 @@ impl<'c> Translation<'c> {
7272
mk().cast_expr(value, target_ty)
7373
}
7474

75+
/// Return whether the literal can be directly translated as this type
76+
pub fn literal_matches_ty(&self, kind: &CLiteral, ty: CQualTypeId) -> bool {
77+
let ty_kind = &self.ast_context.resolve_type(ty.ctype).kind;
78+
match *kind {
79+
CLiteral::Integer(..) if ty_kind.is_integral_type() && !ty_kind.is_bool() => true,
80+
CLiteral::Character(..) if ty_kind.is_integral_type() && !ty_kind.is_bool() => true,
81+
CLiteral::Floating(..) if ty_kind.is_floating_type() => true,
82+
_ => false,
83+
}
84+
}
85+
7586
/// Convert a C literal expression to a Rust expression
7687
pub fn convert_literal(
7788
&self,

c2rust-transpile/src/translator/mod.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3485,7 +3485,7 @@ impl<'c> Translation<'c> {
34853485
}
34863486
},
34873487

3488-
Literal(ty, ref kind) => self.convert_literal(ctx, ty, kind),
3488+
Literal(ty, ref kind) => self.convert_literal(ctx, override_ty.unwrap_or(ty), kind),
34893489

34903490
ImplicitCast(ty, expr, kind, opt_field_id, _)
34913491
| ExplicitCast(ty, expr, kind, opt_field_id, _) => {
@@ -3513,6 +3513,18 @@ impl<'c> Translation<'c> {
35133513
val.prepend_stmts(stmts);
35143514
val
35153515
} else {
3516+
// In general, if we are casting the result of an expression, then the inner
3517+
// expression should be translated to whatever type it normally would.
3518+
// But for literals, if we don't absolutely have to cast, we would rather the
3519+
// literal is translated according to the type we're expecting, and then we can
3520+
// skip the cast entirely.
3521+
if let (Some(ty), CExprKind::Literal(_ty, lit)) =
3522+
(override_ty, &self.ast_context[expr].kind)
3523+
{
3524+
if self.literal_matches_ty(lit, ty) {
3525+
return self.convert_expr(ctx, expr, override_ty);
3526+
}
3527+
}
35163528
self.convert_expr(ctx, expr, None)?
35173529
};
35183530
// Shuffle Vector "function" builtins will add a cast to the output of the

c2rust-transpile/tests/snapshots/factorial.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
)]
1010
#[no_mangle]
1111
pub unsafe extern "C" fn factorial(mut n: std::ffi::c_ushort) -> std::ffi::c_ushort {
12-
let mut result: std::ffi::c_ushort = 1 as std::ffi::c_int as std::ffi::c_ushort;
13-
let mut i: std::ffi::c_ushort = 1 as std::ffi::c_int as std::ffi::c_ushort;
12+
let mut result: std::ffi::c_ushort = 1 as std::ffi::c_ushort;
13+
let mut i: std::ffi::c_ushort = 1 as std::ffi::c_ushort;
1414
while (i as std::ffi::c_int) < n as std::ffi::c_int {
1515
result = (result as std::ffi::c_int * i as std::ffi::c_int)
1616
as std::ffi::c_ushort;

c2rust-transpile/tests/snapshots/[email protected]

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ input_file: c2rust-transpile/tests/snapshots/factorial.c
1414
)]
1515
#[no_mangle]
1616
pub unsafe extern "C" fn factorial(mut n: std::ffi::c_ushort) -> std::ffi::c_ushort {
17-
let mut result: std::ffi::c_ushort = 1 as std::ffi::c_int as std::ffi::c_ushort;
18-
let mut i: std::ffi::c_ushort = 1 as std::ffi::c_int as std::ffi::c_ushort;
17+
let mut result: std::ffi::c_ushort = 1 as std::ffi::c_ushort;
18+
let mut i: std::ffi::c_ushort = 1 as std::ffi::c_ushort;
1919
while (i as std::ffi::c_int) < n as std::ffi::c_int {
2020
result = (result as std::ffi::c_int * i as std::ffi::c_int)
2121
as std::ffi::c_ushort;

0 commit comments

Comments
 (0)