From d253a01aa98ad37076242803ef20bbc1e52f7286 Mon Sep 17 00:00:00 2001 From: dimgigov Date: Mon, 8 Jun 2026 20:00:58 +0300 Subject: [PATCH] fix(selfhost/c_backend): emit _Tag + struct wrapper for all enums Simple enums were emitted as plain C enums, but the rest of the codegen (and source code) expected them to have a .tag field like algebraic enums. This caused C compilation errors: - 'request for member tag in something not a structure or union' - 'field name not in record or union initializer' Fix: always emit the _Tag typedef + struct wrapper for every enum. For simple enums, the struct only contains the tag (no _Data union). For algebraic enums, keep the existing _Data union + struct behavior. This matches the bootstrap compiler's enum codegen. --- src/c_backend.bux | 58 ++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/src/c_backend.bux b/src/c_backend.bux index 492fedc..07a1aa0 100644 --- a/src/c_backend.bux +++ b/src/c_backend.bux @@ -778,44 +778,36 @@ func CBackend_Generate(mod: *HirModule) -> String { } vi = vi + 1; } - if !hasData { - // Simple enum: typedef enum { A, B } Name; - StringBuilder_Append(&cbe.sb, "typedef enum {\n"); - vi = 0; - while vi < en.variantCount { - StringBuilder_Append(&cbe.sb, " "); - StringBuilder_Append(&cbe.sb, en.name); - StringBuilder_Append(&cbe.sb, "_"); - StringBuilder_Append(&cbe.sb, en.variants[vi].name); - if vi < en.variantCount - 1 { - StringBuilder_Append(&cbe.sb, ","); - } - StringBuilder_Append(&cbe.sb, "\n"); - vi = vi + 1; + // Emit tag enum for all enums (simple and algebraic) + StringBuilder_Append(&cbe.sb, "typedef enum {\n"); + vi = 0; + while vi < en.variantCount { + StringBuilder_Append(&cbe.sb, " "); + StringBuilder_Append(&cbe.sb, en.name); + StringBuilder_Append(&cbe.sb, "_"); + StringBuilder_Append(&cbe.sb, en.variants[vi].name); + if vi < en.variantCount - 1 { + StringBuilder_Append(&cbe.sb, ","); } + StringBuilder_Append(&cbe.sb, "\n"); + vi = vi + 1; + } + StringBuilder_Append(&cbe.sb, "} "); + StringBuilder_Append(&cbe.sb, en.name); + StringBuilder_Append(&cbe.sb, "_Tag;\n\n"); + + if !hasData { + // Simple enum: struct wrapper with only tag + StringBuilder_Append(&cbe.sb, "typedef struct {\n"); + StringBuilder_Append(&cbe.sb, " "); + StringBuilder_Append(&cbe.sb, en.name); + StringBuilder_Append(&cbe.sb, "_Tag tag;\n"); StringBuilder_Append(&cbe.sb, "} "); StringBuilder_Append(&cbe.sb, en.name); StringBuilder_Append(&cbe.sb, ";\n\n"); } else { - // Algebraic enum: tag enum + data union + struct - // 1. Tag enum - StringBuilder_Append(&cbe.sb, "typedef enum {\n"); - vi = 0; - while vi < en.variantCount { - StringBuilder_Append(&cbe.sb, " "); - StringBuilder_Append(&cbe.sb, en.name); - StringBuilder_Append(&cbe.sb, "_"); - StringBuilder_Append(&cbe.sb, en.variants[vi].name); - if vi < en.variantCount - 1 { - StringBuilder_Append(&cbe.sb, ","); - } - StringBuilder_Append(&cbe.sb, "\n"); - vi = vi + 1; - } - StringBuilder_Append(&cbe.sb, "} "); - StringBuilder_Append(&cbe.sb, en.name); - StringBuilder_Append(&cbe.sb, "_Tag;\n\n"); - // 2. Data union + // Algebraic enum: data union + struct (tag enum already emitted above) + // 1. Data union StringBuilder_Append(&cbe.sb, "typedef union {\n"); vi = 0; while vi < en.variantCount {