From 5fe524d93570f3b5e83791f7eb5a77228834da11 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Sun, 1 Mar 2026 22:02:04 +0800 Subject: [PATCH] =?UTF-8?q?cgen:=20fix=20bit-field=20generation=20for=20op?= =?UTF-8?q?tion/result=20types=20in=20minified=20st=E2=80=A6=20(#26670)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * cgen: fix bit-field generation for option/result types in minified structs (fixes #26622) Option and result types are represented as structs in C, which cannot be used as bit-fields. Skip the bit-field optimization for these types in minified structs to avoid C compilation errors. Co-authored-by: iFlow CLI (glm-5) * tests: skip minify_option_field test on MSVC MSVC handles bit-fields differently than GCC/Clang, causing the minify_option_field test to fail on Windows MSVC CI. - Add _not_msvc_windows.vv suffix pattern to skip logic - Rename test files to use the new suffix This follows the existing naming convention for platform/compiler- specific test handling (similar to _nix.vv, _msvc_windows.vv). --- vlib/v/gen/c/coutput_test.v | 6 ++++ vlib/v/gen/c/struct.v | 3 +- ..._option_field_not_msvc_windows.c.must_have | 4 +++ .../minify_option_field_not_msvc_windows.out | 4 +++ .../minify_option_field_not_msvc_windows.vv | 35 +++++++++++++++++++ 5 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.c.must_have create mode 100644 vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.out create mode 100644 vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.vv diff --git a/vlib/v/gen/c/coutput_test.v b/vlib/v/gen/c/coutput_test.v index d86397983..bf3b634da 100644 --- a/vlib/v/gen/c/coutput_test.v +++ b/vlib/v/gen/c/coutput_test.v @@ -284,6 +284,12 @@ fn should_skip(relpath string) bool { return true } } + $if msvc { + if relpath.contains('_not_msvc_windows.vv') { + eprintln('> skipping ${relpath} on msvc') + return true + } + } } else { if relpath.contains('_windows.vv') { eprintln('> skipping ${relpath} on !windows') diff --git a/vlib/v/gen/c/struct.v b/vlib/v/gen/c/struct.v index 6515bedcf..aa809f496 100644 --- a/vlib/v/gen/c/struct.v +++ b/vlib/v/gen/c/struct.v @@ -703,7 +703,8 @@ fn (mut g Gen) struct_decl(s ast.Struct, name string, is_anon bool, is_option bo field_name := c_name(field.name) volatile_prefix := if field.is_volatile { 'volatile ' } else { '' } mut size_suffix := '' - if is_minify && !g.is_cc_msvc && !g.pref.output_cross_c { + if is_minify && !g.is_cc_msvc && !g.pref.output_cross_c && !field.typ.has_flag(.option) + && !field.typ.has_flag(.result) { if field.typ == ast.bool_type_idx { size_suffix = ' : 1' } else { diff --git a/vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.c.must_have b/vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.c.must_have new file mode 100644 index 000000000..b2e6d5dd2 --- /dev/null +++ b/vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.c.must_have @@ -0,0 +1,4 @@ +_option_bool optional; +main__Status status : 2; +_option_main__Priority priority; +bool done : 1; diff --git a/vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.out b/vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.out new file mode 100644 index 000000000..f486b9ab6 --- /dev/null +++ b/vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.out @@ -0,0 +1,4 @@ +active +low +false +false diff --git a/vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.vv b/vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.vv new file mode 100644 index 000000000..798e4f5cf --- /dev/null +++ b/vlib/v/gen/c/testdata/minify_option_field_not_msvc_windows.vv @@ -0,0 +1,35 @@ +// Test that minified structs with option fields don't use bit-fields +// Bit-fields can only have integral types in C, not struct types +// Option types are represented as structs in C + +module main + +enum Status as u8 { + pending + active + inactive +} + +enum Priority as u8 { + low + medium + high +} + +@[minify] +struct Task { + status Status + priority ?Priority + done bool + optional ?bool +} + +fn main() { + task := Task{ + status: .active + } + println(task.status) + println(task.priority or { Priority.low }) + println(task.done) + println(task.optional or { false }) +} -- 2.39.5