From a1e890bc3107dd28b2a28fd8fbc18b2cb6426163 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 25 Mar 2026 16:42:23 +0300 Subject: [PATCH] cgen: fix incorrect comptime return with $if/$else (fixes #17262) --- vlib/v/gen/c/cgen.v | 4 +- vlib/v/gen/c/comptime.v | 39 +++++++++++++++++-- .../comptime_if_return_termux.c.must_have | 3 ++ .../c/testdata/comptime_if_return_termux.vv | 14 +++++++ .../platform_wrapper_emscripten.c.must_have | 2 +- 5 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 vlib/v/gen/c/testdata/comptime_if_return_termux.c.must_have create mode 100644 vlib/v/gen/c/testdata/comptime_if_return_termux.vv diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 18013e4a4..5fbbc8350 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -7885,9 +7885,7 @@ fn (mut g Gen) gen_hash_stmts(mut sb strings.Builder, node &ast.HashStmtNode, se } else { sb.write_string('\n#elif ') } - // directly use `checker` evaluate results - // for `cgen`, we can use `is_true.c_str` or `is_true.value` here - sb.writeln('${is_true.c_str}') + sb.writeln(g.comptime_if_condition_for_c(branch.cond, is_true)) $if debug_comptime_branch_context ? { sb.writeln('/* ${node.branches[i].cond} | generic=[${comptime_branch_context_str}] */') } diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index 1388679f6..897af3276 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -528,6 +528,41 @@ fn (mut g Gen) gen_branch_context_string() string { return arr.join(',') } +fn (g &Gen) can_preserve_comptime_if_condition_in_c(cond ast.Expr) bool { + match cond { + ast.BoolLiteral { + return true + } + ast.ParExpr { + return g.can_preserve_comptime_if_condition_in_c(cond.expr) + } + ast.PrefixExpr { + return cond.op == .not && g.can_preserve_comptime_if_condition_in_c(cond.right) + } + ast.InfixExpr { + return cond.op in [.and, .logical_or] + && g.can_preserve_comptime_if_condition_in_c(cond.left) + && g.can_preserve_comptime_if_condition_in_c(cond.right) + } + ast.PostfixExpr { + return cond.op == .question && cond.expr is ast.Ident + } + else { + return false + } + } +} + +fn (g &Gen) comptime_if_condition_for_c(cond ast.Expr, result ast.ComptTimeCondResult) string { + if g.pref.output_cross_c || g.can_preserve_comptime_if_condition_in_c(cond) { + return result.c_str + } + // For normal C generation, honor the branch result that V already resolved. + // Re-evaluating built-in comptime conditions in the C preprocessor can pick + // a different branch than the V checker, e.g. `termux` vs `linux`. + return if result.val { '1' } else { '0' } +} + fn (mut g Gen) comptime_if(node ast.IfExpr) { tmp_var := g.new_tmp_var() mut inferred_typ := node.typ @@ -594,9 +629,7 @@ fn (mut g Gen) comptime_if(node ast.IfExpr) { } else { g.write('#elif ') } - // directly use `checker` evaluate results - // for `cgen`, we can use `is_true.c_str` or `is_true.value` here - g.writeln('${is_true.c_str}') + g.writeln(g.comptime_if_condition_for_c(branch.cond, is_true)) $if debug_comptime_branch_context ? { g.writeln('/* ${node.branches[i].cond} | generic=[${comptime_branch_context_str}] */') } diff --git a/vlib/v/gen/c/testdata/comptime_if_return_termux.c.must_have b/vlib/v/gen/c/testdata/comptime_if_return_termux.c.must_have new file mode 100644 index 000000000..2c18867f4 --- /dev/null +++ b/vlib/v/gen/c/testdata/comptime_if_return_termux.c.must_have @@ -0,0 +1,3 @@ +#if 0 +#elif 1 +return _S("linux-aarch64"); diff --git a/vlib/v/gen/c/testdata/comptime_if_return_termux.vv b/vlib/v/gen/c/testdata/comptime_if_return_termux.vv new file mode 100644 index 000000000..63b3a43e3 --- /dev/null +++ b/vlib/v/gen/c/testdata/comptime_if_return_termux.vv @@ -0,0 +1,14 @@ +// vtest vflags: -gc none -os termux +fn host_arch() string { + $if linux { + return 'linux-x86_64' + } $else $if termux { + return 'linux-aarch64' + } $else { + return 'unknown' + } +} + +fn main() { + println(host_arch()) +} diff --git a/vlib/v/gen/c/testdata/platform_wrapper_emscripten.c.must_have b/vlib/v/gen/c/testdata/platform_wrapper_emscripten.c.must_have index e53842fdc..9c3b04b5b 100644 --- a/vlib/v/gen/c/testdata/platform_wrapper_emscripten.c.must_have +++ b/vlib/v/gen/c/testdata/platform_wrapper_emscripten.c.must_have @@ -1,7 +1,7 @@ #if defined(CUSTOM_DEFINE_emscripten) println(_S("> inside then branch of if emscripten")); -#if defined(__EMSCRIPTEN__) +#if 1 println(_S("> inside then branch of if wasm32_emscripten")); v__gen__c__testdata__platform_wrapper__fn_defined_in_wasm32_emscripten(); -- 2.39.5