Skip to content

Commit 2c8e8f0

Browse files
committed
cgen: typedef enum fix
1 parent 4a6eea9 commit 2c8e8f0

1 file changed

Lines changed: 25 additions & 0 deletions

File tree

vlib/v/gen/c/cgen.v

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6298,6 +6298,31 @@ fn (mut g Gen) debugger_stmt(node ast.DebuggerStmt) {
62986298
fn (mut g Gen) enum_decl(node ast.EnumDecl) {
62996299
enum_name := util.no_dots(node.name)
63006300
is_flag := node.is_flag
6301+
// @[typedef] enums are already defined in a C header — don't redefine the enum,
6302+
// but emit #define aliases so that V-mangled field names resolve to the correct values.
6303+
if node.attrs.contains('typedef') {
6304+
c_name := node.name.all_after_last('.')
6305+
g.enum_typedefs.writeln('')
6306+
g.enum_typedefs.writeln('// @[typedef] enum ${c_name} — defined in C header')
6307+
g.enum_typedefs.writeln('typedef ${c_name} ${enum_name};')
6308+
mut cur_value := 0
6309+
for field in node.fields {
6310+
if field.has_expr {
6311+
expr_str := g.expr_string(field.expr)
6312+
g.enum_typedefs.writeln('#define ${enum_name}__${field.name} (${expr_str})')
6313+
// Try to track the integer value for subsequent fields
6314+
cur_value = expr_str.int() + 1
6315+
} else if is_flag {
6316+
// Not applicable for @[typedef] flag enums from C headers typically
6317+
g.enum_typedefs.writeln('#define ${enum_name}__${field.name} ${cur_value}')
6318+
cur_value++
6319+
} else {
6320+
g.enum_typedefs.writeln('#define ${enum_name}__${field.name} ${cur_value}')
6321+
cur_value++
6322+
}
6323+
}
6324+
return
6325+
}
63016326
// Explicit-size enums are emitted as typedef + defines, so all C compilers
63026327
// (including tinyc) respect the selected storage size.
63036328
if g.is_cc_msvc || node.typ != ast.int_type {

0 commit comments

Comments
 (0)