Skip to content

Commit e861b73

Browse files
authored
parser: fix the language support for a nested anonymous C.struct (fix #25807) (#25789)
1 parent 1d3467e commit e861b73

File tree

8 files changed

+83
-7
lines changed

8 files changed

+83
-7
lines changed

vlib/builtin/cfns.c.v

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -552,8 +552,23 @@ fn C.sysconf(name int) int
552552
// C.SYSTEM_INFO contains information about the current computer system. This includes the architecture and type of the processor, the number of processors in the system, the page size, and other such information.
553553
@[typedef]
554554
pub struct C.SYSTEM_INFO {
555-
dwNumberOfProcessors u32
556-
dwPageSize u32
555+
// DUMMYUNIONNAME union {
556+
// dwOemId u32
557+
// DUMMYSTRUCTNAME struct {
558+
// pub:
559+
// wProcessorArchitecture u16
560+
// wReserved u16
561+
// }
562+
//}
563+
dwPageSize u32
564+
lpMinimumApplicationAddress voidptr
565+
lpMaximumApplicationAddress voidptr
566+
dwActiveProcessorMask &u32 = unsafe { nil }
567+
dwNumberOfProcessors u32
568+
dwProcessorType u32
569+
dwAllocationGranularity u32
570+
wProcessorLevel u16
571+
wProcessorRevision u16
557572
}
558573

559574
fn C.GetSystemInfo(&C.SYSTEM_INFO)

vlib/v/ast/types.v

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,8 @@ pub fn (t &TypeSymbol) is_array_fixed() bool {
10911091

10921092
pub fn (t &TypeSymbol) is_c_struct() bool {
10931093
if t.info is Struct {
1094-
return t.language == .c
1094+
// `C___VAnonStruct` need special handle, it need to create a new struct
1095+
return t.language == .c && !t.info.is_anon
10951096
} else if t.info is Alias {
10961097
return global_table.final_sym(t.info.parent_type).is_c_struct()
10971098
}

vlib/v/gen/c/auto_str_methods.v

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,11 @@ fn struct_auto_str_func(sym &ast.TypeSymbol, lang ast.Language, _field_type ast.
11881188
if sym.kind == .struct {
11891189
if sym.info is ast.Struct && sym.info.is_anon && !_field_type.has_flag(.option)
11901190
&& !_field_type.has_flag(.shared_f) {
1191-
typed_obj := '*(${sym.cname}*)&(${obj})'
1191+
typed_obj := if lang == .c {
1192+
'(${sym.cname}*)&(${obj})'
1193+
} else {
1194+
'*(${sym.cname}*)&(${obj})'
1195+
}
11921196
return '${fn_name}(${typed_obj})', true
11931197
}
11941198
}

vlib/v/gen/c/cgen.v

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,7 +1723,9 @@ fn (mut g Gen) cc_type(typ ast.Type, is_prefix_struct bool) string {
17231723
styp = styp[3..]
17241724
if sym.kind == .struct {
17251725
info := sym.info as ast.Struct
1726-
if !info.is_typedef {
1726+
if info.is_anon {
1727+
styp = 'C__' + styp
1728+
} else if !info.is_typedef {
17271729
styp = 'struct ${styp}'
17281730
}
17291731
}
@@ -6925,7 +6927,11 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
69256927
mut struct_names := map[string]bool{}
69266928
for sym in symbols {
69276929
if sym.name.starts_with('C.') {
6928-
continue
6930+
if sym.info is ast.Struct && sym.info.is_anon {
6931+
// For `C___VAnonStruct`, we need to create a new struct to make auto_str work.
6932+
} else {
6933+
continue
6934+
}
69296935
}
69306936
if sym.kind == .none && (!g.pref.skip_unused || g.table.used_features.used_none > 0) {
69316937
g.type_definitions.writeln('struct none {')

vlib/v/parser/parser.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ mut:
3030
peek_tok token.Token
3131
language ast.Language
3232
fn_language ast.Language // .c for `fn C.abcd()` declarations
33+
struct_language ast.Language // for `struct C.abcd{ embedded struct/union }` declarations
3334
expr_level int // prevent too deep recursions for pathological programs
3435
inside_vlib_file bool // true for all vlib/ files
3536
inside_test_file bool // when inside _test.v or _test.vv file

vlib/v/parser/struct.v

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,18 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
3131
} else {
3232
p.check(.key_union)
3333
}
34-
language := p.parse_language()
34+
mut language := p.parse_language()
3535
name_pos := p.tok.pos()
36+
if p.inside_struct_field_decl && language == .v {
37+
// anon struct/union language should keep the same language of outside
38+
language = p.struct_language
39+
} else {
40+
old_struct_language := p.struct_language
41+
p.struct_language = language
42+
defer(fn) {
43+
p.struct_language = old_struct_language
44+
}
45+
}
3646
p.check_for_impure_v(language, name_pos)
3747
if p.disallow_declarations_in_script_mode() {
3848
return ast.StructDecl{}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module main
2+
3+
#insert "@VMODROOT/deep.h"
4+
5+
struct C.DeepStruct {
6+
A1 int
7+
S1 struct {
8+
A2 int
9+
S2 struct {
10+
A3 int
11+
S3 struct {
12+
A4 int
13+
}
14+
}
15+
}
16+
}
17+
18+
fn test_cstruct_nested_anon() {
19+
x := C.DeepStruct{}
20+
y := C.DeepStruct{}
21+
dump(x)
22+
assert x == y
23+
}

vlib/v/tests/c_structs/deep.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef __DEEP_H__
2+
#define __DEEP_H__
3+
4+
struct DeepStruct{
5+
int A1;
6+
struct {
7+
int A2;
8+
struct {
9+
int A3;
10+
struct {
11+
int A4;
12+
} S3;
13+
} S2;
14+
} S1;
15+
};
16+
#endif

0 commit comments

Comments
 (0)