From c3cf9ee83299c2b947a0e5b252aa44467bbbdad9 Mon Sep 17 00:00:00 2001 From: shove Date: Fri, 17 Nov 2023 02:33:47 +0800 Subject: [PATCH] cgen: fix temporary var name conflicts between const definitions with or_block in different files(fix #19149) (#19894) --- vlib/v/gen/c/cgen.v | 34 ++++++++++++++----- .../config.v | 5 +++ .../consts_should_not_conflict_test.v | 10 ++++++ 3 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 vlib/v/tests/modules/consts_with_or_blocks_in_different_files/config.v create mode 100644 vlib/v/tests/modules/consts_with_or_blocks_in_different_files/consts_should_not_conflict_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 75c15dc0a5d2ab..ebf7fb6a945d7f 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5315,7 +5315,8 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { dep_names: g.table.dependent_names_in_expr(field_expr) } } else { - g.const_decl_init_later(field.mod, name, field.expr, field.typ, false) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, false, + false) } } ast.StringLiteral { @@ -5332,9 +5333,11 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { || field.expr.return_type.has_flag(.result) { g.inside_const_opt_or_res = true unwrap_opt_res := field.expr.or_block.kind != .absent - g.const_decl_init_later(field.mod, name, field.expr, field.typ, unwrap_opt_res) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, unwrap_opt_res, + unwrap_opt_res) } else { - g.const_decl_init_later(field.mod, name, field.expr, field.typ, false) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, false, + false) } g.inside_const_opt_or_res = false } @@ -5376,9 +5379,20 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { continue } } - g.const_decl_init_later(field.mod, name, field.expr, field.typ, false) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, false, + false) + } else if field.expr is ast.InfixExpr { + mut has_unwrap_opt_res := false + if field.expr.left is ast.CallExpr { + has_unwrap_opt_res = field.expr.left.or_block.kind != .absent + } else if field.expr.right is ast.CallExpr { + has_unwrap_opt_res = field.expr.right.or_block.kind != .absent + } + g.const_decl_init_later(field.mod, name, field.expr, field.typ, false, + has_unwrap_opt_res) } else { - g.const_decl_init_later(field.mod, name, field.expr, field.typ, false) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, false, + false) } } } @@ -5534,7 +5548,7 @@ fn (mut g Gen) c_const_name(name string) string { return if g.pref.translated && !g.is_builtin_mod { name } else { '_const_${name}' } } -fn (mut g Gen) const_decl_init_later(mod string, name string, expr ast.Expr, typ ast.Type, unwrap_option bool) { +fn (mut g Gen) const_decl_init_later(mod string, name string, expr ast.Expr, typ ast.Type, unwrap_option bool, surround_cbr bool) { // Initialize more complex consts in `void _vinit/2{}` // (C doesn't allow init expressions that can't be resolved at compile time). mut styp := g.typ(typ) @@ -5547,13 +5561,17 @@ fn (mut g Gen) const_decl_init_later(mod string, name string, expr ast.Expr, typ init.writeln('\t_const_os__args = os__init_os_args(___argc, (byte**)___argv);') } } else { - if unwrap_option { + if surround_cbr { init.writeln('{') + } + if unwrap_option { init.writeln(g.expr_string_surround('\t${cname} = *(${styp}*)', expr, '.data;')) - init.writeln('}') } else { init.writeln(g.expr_string_surround('\t${cname} = ', expr, ';')) } + if surround_cbr { + init.writeln('}') + } } mut def := '${styp} ${cname}' expr_sym := g.table.sym(typ) diff --git a/vlib/v/tests/modules/consts_with_or_blocks_in_different_files/config.v b/vlib/v/tests/modules/consts_with_or_blocks_in_different_files/config.v new file mode 100644 index 00000000000000..95c788c5c15770 --- /dev/null +++ b/vlib/v/tests/modules/consts_with_or_blocks_in_different_files/config.v @@ -0,0 +1,5 @@ +module consts_with_or_blocks_in_different_files + +import os + +const a_const = os.config_dir() or { panic(err) } + '/a' diff --git a/vlib/v/tests/modules/consts_with_or_blocks_in_different_files/consts_should_not_conflict_test.v b/vlib/v/tests/modules/consts_with_or_blocks_in_different_files/consts_should_not_conflict_test.v new file mode 100644 index 00000000000000..c4442e51d355dc --- /dev/null +++ b/vlib/v/tests/modules/consts_with_or_blocks_in_different_files/consts_should_not_conflict_test.v @@ -0,0 +1,10 @@ +module consts_with_or_blocks_in_different_files + +import os + +const b_const = os.config_dir() or { panic(err) } + '/b' + +// Just to test the two files in this folder are compiled normally +fn test_consts_with_or_blocks_in_different_files() { + assert true +}