From 424a797ede5c61071ff24c7344fad212a3c931f3 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 25 Mar 2026 16:42:26 +0300 Subject: [PATCH] cgen: fix c compilation issue with quoted items in xdoc attrs (fixes #23045) --- vlib/flag/quoted_xdoc_attr_test.v | 13 +++++++++++++ vlib/v/gen/c/comptime.v | 2 +- vlib/v/gen/c/reflection.v | 26 +++++++++++++------------- 3 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 vlib/flag/quoted_xdoc_attr_test.v diff --git a/vlib/flag/quoted_xdoc_attr_test.v b/vlib/flag/quoted_xdoc_attr_test.v new file mode 100644 index 000000000..b03723fbe --- /dev/null +++ b/vlib/flag/quoted_xdoc_attr_test.v @@ -0,0 +1,13 @@ +import flag + +struct QuotedXdocConfig { + p_fpga_ver string @[long: fp_ver; name: 'FPGA Version'; xdoc: 'String to use as simulated FPGA version in Version responses. Must be in the form "a.bb.cccc"'] + p_cm_ver string @[long: cm_ver; name: 'CM Version'; xdoc: 'String to use as simulated CM version in Version responses. Must be in the form "a.bb.cccc"'] +} + +fn test_flag_to_doc_with_quoted_xdoc_attrs() { + doc := flag.to_doc[QuotedXdocConfig]()! + assert doc.contains('--fp-ver ') + assert doc.contains('--cm-ver ') + assert doc.contains('Must be in the form "a.bb.cccc"') +} diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index eef5f3680..4174e1723 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -364,7 +364,7 @@ fn cgen_attrs(attrs []ast.Attr) []string { } s += ': ${arg}' } - res << '_S("${escape_quotes(s)}")' + res << '_S("${cescape_nonascii(util.smart_quote(s, false))}")' } return res } diff --git a/vlib/v/gen/c/reflection.v b/vlib/v/gen/c/reflection.v index e2b646d00..cc94f12cc 100644 --- a/vlib/v/gen/c/reflection.v +++ b/vlib/v/gen/c/reflection.v @@ -65,7 +65,6 @@ fn (mut g Gen) gen_reflection_fn(node ast.Fn) string { v_name := node.name.all_after_last('.') arg_str += '.mod_name=_S("${node.mod}"),' arg_str += '.name=_S("${v_name}"),' - arg_str += '.attrs=${g.gen_attrs_array(node.attrs)},' arg_str += '.args=${g.gen_functionarg_array(cprefix + 'FunctionArg', node)},' arg_str += '.file_idx=${g.reflection_string(util.cescaped_path(node.file))},' arg_str += '.line_start=${node.pos.line_nr},' @@ -88,26 +87,27 @@ fn (mut g Gen) gen_reflection_sym(tsym ast.TypeSymbol) string { return '(${cprefix}TypeSymbol){.name=_S("${name}"),.mod=_S("${tsym.mod}"),.idx=${tsym.idx},.parent_idx=${tsym.parent_idx},.language=${cprefix}VLanguage__${tsym.language},.kind=${cprefix}VKind__${kind_name},.info=${info},.methods=${methods}}' } -// gen_attrs_array generates C code for []VAttribute. +// gen_attrs_array generates C code for []Attr @[inline] fn (g &Gen) gen_attrs_array(attrs []ast.Attr) string { if attrs.len == 0 { - return g.gen_empty_array('VAttribute') + return g.gen_empty_array('string') + } + mut items := []string{cap: attrs.len} + for attr in attrs { + mut s := attr.name + if attr.has_arg { + s += '=${attr.arg}' + } + items << '_S("${cescape_nonascii(util.smart_quote(s, false))}")' } - mut out := 'builtin__new_array_from_c_array(${attrs.len},${attrs.len},sizeof(VAttribute),' - out += '_MOV((VAttribute[${attrs.len}]){' - out += attrs.map(attr_to_vattribute_init(it)).join(',') + mut out := 'builtin__new_array_from_c_array(${attrs.len},${attrs.len},sizeof(string),' + out += '_MOV((string[${attrs.len}]){' + out += items.join(',') out += '}))' return out } -@[inline] -fn attr_to_vattribute_init(attr ast.Attr) string { - name := cescape_nonascii(util.smart_quote(attr.name, false)) - arg := cescape_nonascii(util.smart_quote(attr.arg, false)) - return '(VAttribute){.name=_S("${name}"),.has_arg=${attr.has_arg},.arg=_S("${arg}"),.kind=${int(attr.kind)}}' -} - // gen_fields_array generates C code for []StructField @[inline] fn (g &Gen) gen_fields_array(fields []ast.StructField) string { -- 2.39.5