Skip to content
Open
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
16 changes: 9 additions & 7 deletions c2rust-transpile/src/translator/literals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,13 @@ impl<'c> Translation<'c> {
opt_union_field_id: Option<CFieldId>,
) -> TranslationResult<WithStmts<Box<Expr>>> {
match self.ast_context.resolve_type(ty.ctype).kind {
CTypeKind::ConstantArray(ty, n) => {
CTypeKind::ConstantArray(element_ty, n) => {
// Convert all of the provided initializer values

let to_array_element = |id: CExprId| -> TranslationResult<_> {
self.convert_expr(ctx.used(), id, None)?.try_map(|x| {
let val =
self.convert_expr(ctx.used(), id, Some(CQualTypeId::new(element_ty)))?;
val.try_map(|x| {
// Array literals require all of their elements to be
// the correct type; they will not use implicit casts to
// change mut to const. This becomes a problem when an
Expand Down Expand Up @@ -258,7 +260,7 @@ impl<'c> Translation<'c> {
// * the element type of the array being `CTypeKind::Char` (w/o this, `array_of_arrays` is included)
// * the expr kind being a string literal (`CExprKind::Literal` of a `CLiteral::String`).
let is_string_literal = |id: CExprId| {
let ty_kind = &self.ast_context.resolve_type(ty).kind;
let ty_kind = &self.ast_context.resolve_type(element_ty).kind;
let expr_kind = &self.ast_context.index(id).kind;
let is_char_array = matches!(*ty_kind, CTypeKind::Char);
let is_str_literal =
Expand All @@ -278,7 +280,7 @@ impl<'c> Translation<'c> {
// This was likely a C array of the form `int x[16] = {}`.
// We'll emit that as [0; 16].
let len = mk().lit_expr(mk().int_unsuffixed_lit(n as u128));
let zeroed = self.implicit_default_expr(ctx, ty)?;
let zeroed = self.implicit_default_expr(ctx, element_ty)?;
Ok(zeroed.map(|default_value| mk().repeat_expr(default_value, len)))
}
&[single] if is_string_literal(single) => {
Expand All @@ -287,7 +289,7 @@ impl<'c> Translation<'c> {
// * `ptr_extra_braces`
// * `array_of_ptrs`
// * `array_of_arrays`
self.convert_expr(ctx.used(), single, None)
self.convert_expr(ctx.used(), single, Some(ty))
}
&[single] if is_zero_literal(single) && n > 1 => {
// This was likely a C array of the form `int x[16] = { 0 }`.
Expand All @@ -303,7 +305,7 @@ impl<'c> Translation<'c> {
.map(to_array_element)
.chain(
// Pad out the array literal with default values to the desired size
iter::repeat(self.implicit_default_expr(ctx, ty))
iter::repeat(self.implicit_default_expr(ctx, element_ty))
.take(n - ids.len()),
)
.collect::<TranslationResult<WithStmts<_>>>()?
Expand All @@ -322,7 +324,7 @@ impl<'c> Translation<'c> {
}
ref kind if kind.is_scalar() => {
if let Some(&first) = ids.first() {
self.convert_expr(ctx.used(), first, None)
self.convert_expr(ctx.used(), first, Some(ty))
} else {
self.implicit_default_expr(ctx.used(), ty.ctype)
}
Expand Down
2 changes: 1 addition & 1 deletion c2rust-transpile/src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3404,7 +3404,7 @@ impl<'c> Translation<'c> {
CompoundLiteral(qty, val) => self.convert_compound_literal(ctx, qty, val, override_ty),

InitList(ty, ref ids, opt_union_field_id, _) => {
self.convert_init_list(ctx, ty, ids, opt_union_field_id)
self.convert_init_list(ctx, override_ty.unwrap_or(ty), ids, opt_union_field_id)
}

ImplicitValueInit(ty) => self.implicit_default_expr(ctx, ty.ctype),
Expand Down
5 changes: 5 additions & 0 deletions c2rust-transpile/tests/snapshots/arrays.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ char static_char_array[] = "mystring";
char *static_char_ptr = "mystring";
void *static_void_ptr = (void*) static_char_array;

typedef int int_t;

void entry(void) {
int int_2d[1][1] = { 1 };
int_2d[0][0] += 9;
Expand All @@ -14,6 +16,9 @@ void entry(void) {
int int_too_short[16] = {0};
int_too_short[15] += 9;

int_t override_ty[] = { 1 };
int_t override_ty_neg[] = { -1 };

struct {char* x; int y;} struct_init_too_short[1] = {};
struct_init_too_short[0].y += 9;
struct {short; int y;} struct_init_too_long[1] = { { 1, 2 } };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ expression: cat tests/snapshots/arrays.2021.clang15.rs
unused_mut
)]
#![feature(raw_ref_op)]
pub type int_t = ::core::ffi::c_int;
#[derive(Copy, Clone)]
#[repr(C)]
pub struct C2Rust_Unnamed {
Expand Down Expand Up @@ -56,6 +57,8 @@ pub unsafe extern "C" fn entry() {
let mut int_zero: [::core::ffi::c_int; 0] = [0; 0];
let mut int_too_short: [::core::ffi::c_int; 16] = [0 as ::core::ffi::c_int; 16];
int_too_short[15 as ::core::ffi::c_int as usize] += 9 as ::core::ffi::c_int;
let mut override_ty: [int_t; 1] = [1 as int_t];
let mut override_ty_neg: [int_t; 1] = [-1 as int_t];
let mut struct_init_too_short: [C2Rust_Unnamed_0; 1] = [C2Rust_Unnamed_0 {
x: ::core::ptr::null_mut::<::core::ffi::c_char>(),
y: 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ expression: cat tests/snapshots/arrays.2024.clang15.rs
unused_assignments,
unused_mut
)]
pub type int_t = ::core::ffi::c_int;
#[derive(Copy, Clone)]
#[repr(C)]
pub struct C2Rust_Unnamed {
Expand Down Expand Up @@ -56,6 +57,8 @@ pub unsafe extern "C" fn entry() {
let mut int_zero: [::core::ffi::c_int; 0] = [0; 0];
let mut int_too_short: [::core::ffi::c_int; 16] = [0 as ::core::ffi::c_int; 16];
int_too_short[15 as ::core::ffi::c_int as usize] += 9 as ::core::ffi::c_int;
let mut override_ty: [int_t; 1] = [1 as int_t];
let mut override_ty_neg: [int_t; 1] = [-1 as int_t];
let mut struct_init_too_short: [C2Rust_Unnamed_0; 1] = [C2Rust_Unnamed_0 {
x: ::core::ptr::null_mut::<::core::ffi::c_char>(),
y: 0,
Expand Down
Loading