cgen: fix generated str method for enums that have C values (use ifs, instead of switch) (fix #25135) (#25157)

This commit is contained in:
Delyan Angelov 2025-08-23 09:45:25 +03:00 committed by GitHub
parent a40e86ad7c
commit 83385a8bf8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 57 additions and 0 deletions

View file

@ -378,6 +378,13 @@ fn (mut g Gen) gen_str_for_enum(info ast.Enum, styp string, str_fn_name string)
}
g.auto_str_funcs.writeln('\tret = string__plus(ret, _S("}"));')
g.auto_str_funcs.writeln('\treturn ret;')
} else if info.uses_exprs {
// The enum values could be C macros, expanded later to duplicate values, and we do not know if that is the case, so we can not use a switch here.
// Instead we generate multiple if statements, which is slower, but is guaranteed to work in the presence of duplicates.
for val in info.vals {
g.auto_str_funcs.writeln('\t\tif(it == ${s}__${val}){ return _S("${val}"); }')
}
g.auto_str_funcs.writeln('\t\treturn _S("unknown enum value");')
} else {
g.auto_str_funcs.writeln('\tswitch(it) {')
// Only use the first multi value on the lookup

View file

@ -6,3 +6,16 @@ fn test_using_c_code_in_the_same_module_works() {
modc.destroy_vtype(x)
assert true
}
fn test_enum_with_dups_on_the_cside() {
for e in [modc.MyEnum.unknown, .name1, .name2, .name3, .name4, .name5, .name6, .common_name1,
.common_name2, .common_name3] {
println('>>> e: ${e} | int(e): ${int(e)}')
}
assert modc.MyEnum.name1 == modc.MyEnum.common_name1
assert modc.MyEnum.name2 == modc.MyEnum.common_name2
assert modc.MyEnum.name3 == modc.MyEnum.common_name3
assert modc.MyEnum.name4 != modc.MyEnum.common_name1
assert modc.MyEnum.name5 != modc.MyEnum.common_name2
assert modc.MyEnum.name6 != modc.MyEnum.common_name3
}

View file

@ -15,5 +15,29 @@ void handle_array2(void *p, int n);
void destroy_atype(void *p);
// The following emulates the structure of the SDL3 header SDL_pixels.h, and the enum SDL_PixelFormat.
// See also https://github.com/vlang/v/issues/25135 .
#define ABC 1
#define XYZ 1
typedef enum EnumWithDuplicates {
UNKNOWN = 0,
NAME1 = 0x1u,
NAME2 = 0x2u,
NAME3 = 0x3u,
NAME4 = 0x4u,
NAME5 = 0x5u,
NAME6 = 0x6u,
#if ABC == XYZ
COMMON_NAME1 = NAME1,
COMMON_NAME2 = NAME2,
COMMON_NAME3 = NAME3
#else
COMMON_NAME1 = NAME4,
COMMON_NAME2 = NAME5,
COMMON_NAME3 = NAME6
#endif
} EnumWithDuplicates;
#endif

View file

@ -51,3 +51,16 @@ pub fn call_with_array_param(arr []Vtype) {
pub fn destroy_vtype(t Vtype) {
C.destroy_atype(t.p)
}
pub enum MyEnum {
unknown = C.UNKNOWN
name1 = C.NAME1
name2 = C.NAME2
name3 = C.NAME3
name4 = C.NAME4
name5 = C.NAME5
name6 = C.NAME6
common_name1 = C.COMMON_NAME1
common_name2 = C.COMMON_NAME2
common_name3 = C.COMMON_NAME3
}