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
3 changes: 1 addition & 2 deletions c2rust-transpile/src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4174,8 +4174,6 @@ impl<'c> Translation<'c> {
decl_id: CDeclId,
type_id: CTypeId,
) -> TranslationResult<WithStmts<Box<Expr>>> {
self.import_type(type_id);

let name = self.type_converter.borrow().resolve_decl_name(decl_id);
let name = name.as_deref().unwrap_or("???");

Expand All @@ -4190,6 +4188,7 @@ impl<'c> Translation<'c> {
let func_name = func_name.as_deref().unwrap_or("<none>");
log::debug!("deferring imports to save them for {name} in {func_name}");
self.defer_imports();
self.import_type(type_id);

let name_decl_id = match self.ast_context.resolve_type_no_typedef(type_id).kind {
CTypeKind::Typedef(decl_id) => decl_id,
Expand Down
15 changes: 15 additions & 0 deletions c2rust-transpile/tests/snapshots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,21 @@ fn test_wide_strings() {
.run();
}

#[test]
fn test_zero_init_typedef_reorg_imports() {
let c_path = Path::new("tests/snapshots/zero_init_typedef_reorg.c");
let mut cfg = config(Edition2021);
cfg.reorganize_definitions = true;
cfg.disable_refactoring = true;
compile_and_transpile_file(c_path, cfg);

let rs_path = c_path.with_extension("rs");
rustc(&rs_path)
.edition(Edition2021)
.crate_name("zero_init_typedef_reorg")
.run();
}

// arch-os-specific

#[test]
Expand Down
25 changes: 25 additions & 0 deletions c2rust-transpile/tests/snapshots/zero_init_typedef_reorg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
typedef struct Stat {
int mode;
long size;
} STAT_T;

/* The implicit zero-initializer for the `st` field is the first one created
* for `struct Stat`, so it populates the cache. Because the field is spelled
* with the typedef, the cached expression is rendered as `STAT_T { ... }`. */
struct OuterMain {
int x;
STAT_T st;
};

static void before_include(void) {
struct OuterMain o = {0};
(void)o;
}

#include "zero_init_typedef_reorg.h"

int main(void) {
before_include();
after_include();
return 0;
}
14 changes: 14 additions & 0 deletions c2rust-transpile/tests/snapshots/zero_init_typedef_reorg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* Zero-initializing this struct reuses the cached `STAT_T { ... }`
* initializer for the `st` field, even though the field is spelled with the
* struct tag. The `use STAT_T` this header module needs must therefore be
* replayed from the imports cached alongside the initializer; the imports
* derived from the type of the hit site only cover `Stat`. */
struct OuterHeader {
int y;
struct Stat st;
};

static void after_include(void) {
struct OuterHeader o = {0};
(void)o;
}
Loading