From 22a4f43f49e5b39a353647b44f196a000d2d6cd3 Mon Sep 17 00:00:00 2001 From: Rua Date: Wed, 22 Apr 2026 11:30:23 +0200 Subject: [PATCH] ast-exporter: handle foreign/extern enums properly --- c2rust-ast-exporter/src/AstExporter.cpp | 11 ++++++++++- tests/unit/enums/src/enum_fwd_decl.c | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/c2rust-ast-exporter/src/AstExporter.cpp b/c2rust-ast-exporter/src/AstExporter.cpp index abc92f7ae7..70a06fe4b9 100644 --- a/c2rust-ast-exporter/src/AstExporter.cpp +++ b/c2rust-ast-exporter/src/AstExporter.cpp @@ -2625,11 +2625,20 @@ class TranslateASTVisitor final void TypeEncoder::VisitEnumType(const EnumType *T) { auto ed = T->getDecl()->getDefinition(); + + // getDefinition can return NULL if there is only a forward declaration like `enum Foo;` + // Forward declarations of enums are not actually allowed by the C standard, + // but are supported by LLVM and are used in real code, see + // https://github.com/immunant/c2rust/pull/1743#discussion_r3120875668 + if (!ed) { + ed = T->getDecl()->getCanonicalDecl(); + } + encodeType(T, TagEnumType, [T, ed](CborEncoder *local) { cbor_encode_uint(local, uintptr_t(ed)); }); - if (ed != nullptr) astEncoder->TraverseDecl(ed); + astEncoder->TraverseDecl(ed); } void TypeEncoder::VisitRecordType(const RecordType *T) { diff --git a/tests/unit/enums/src/enum_fwd_decl.c b/tests/unit/enums/src/enum_fwd_decl.c index e23e446a2b..4a90052755 100644 --- a/tests/unit/enums/src/enum_fwd_decl.c +++ b/tests/unit/enums/src/enum_fwd_decl.c @@ -10,4 +10,4 @@ struct _Evas_Func }; // dummy item imported by `test_enums.rs` -int foo(int i) { return i;} \ No newline at end of file +struct _Evas_Func foo(struct _Evas_Func i) { return i;}