Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions vlib/builtin/cfns.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -552,8 +552,23 @@ fn C.sysconf(name int) int
// 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.
@[typedef]
pub struct C.SYSTEM_INFO {
dwNumberOfProcessors u32
dwPageSize u32
// DUMMYUNIONNAME union {
// dwOemId u32
// DUMMYSTRUCTNAME struct {
// pub:
// wProcessorArchitecture u16
// wReserved u16
// }
//}
dwPageSize u32
lpMinimumApplicationAddress voidptr
lpMaximumApplicationAddress voidptr
dwActiveProcessorMask &u32 = unsafe { nil }
dwNumberOfProcessors u32
dwProcessorType u32
dwAllocationGranularity u32
wProcessorLevel u16
wProcessorRevision u16
}

fn C.GetSystemInfo(&C.SYSTEM_INFO)
Expand Down
3 changes: 2 additions & 1 deletion vlib/v/ast/types.v
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,8 @@ pub fn (t &TypeSymbol) is_array_fixed() bool {

pub fn (t &TypeSymbol) is_c_struct() bool {
if t.info is Struct {
return t.language == .c
// `C___VAnonStruct` need special handle, it need to create a new struct
return t.language == .c && !t.info.is_anon
} else if t.info is Alias {
return global_table.final_sym(t.info.parent_type).is_c_struct()
}
Expand Down
6 changes: 5 additions & 1 deletion vlib/v/gen/c/auto_str_methods.v
Original file line number Diff line number Diff line change
Expand Up @@ -1188,7 +1188,11 @@ fn struct_auto_str_func(sym &ast.TypeSymbol, lang ast.Language, _field_type ast.
if sym.kind == .struct {
if sym.info is ast.Struct && sym.info.is_anon && !_field_type.has_flag(.option)
&& !_field_type.has_flag(.shared_f) {
typed_obj := '*(${sym.cname}*)&(${obj})'
typed_obj := if lang == .c {
'(${sym.cname}*)&(${obj})'
} else {
'*(${sym.cname}*)&(${obj})'
}
Comment on lines +1191 to +1195
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this different for a C one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The V compiler handles C structs differently than V structs.

// V auto str functions:
static string SYSTEM_INFO_2_str(SYSTEM_INFO_2* it) { return indent_SYSTEM_INFO_2_str(it, 0);}
static string C___VAnonStruct1_str(C___VAnonStruct1* it) { return indent_C___VAnonStruct1_str(it, 0);}
static string C___VAnonStruct2_str(C___VAnonStruct2* it) { return indent_C___VAnonStruct2_str(it, 0);}
// V auto str functions:
static string main__DeepStruct_str(main__DeepStruct it) { return indent_main__DeepStruct_str(it, 0);}
static string main___VAnonStruct1_str(main___VAnonStruct1 it) { return indent_main___VAnonStruct1_str(it, 0);}
static string main___VAnonStruct2_str(main___VAnonStruct2 it) { return indent_main___VAnonStruct2_str(it, 0);}

As shown above, when the compiler encounters a C struct, it accesses the value via a pointer. In contrast, for a V struct, it passes the struct by value (making a copy).

To ensure auto_str works correctly with a V anonymous struct, a corresponding C___VAnonStruct1 instance must be created for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't direct access a C anon struct

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be better in the long term, to pass the V struct for the generated auto str methods by a reference too, to keep things consistent 🤔.

return '${fn_name}(${typed_obj})', true
}
}
Expand Down
10 changes: 8 additions & 2 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -1723,7 +1723,9 @@ fn (mut g Gen) cc_type(typ ast.Type, is_prefix_struct bool) string {
styp = styp[3..]
if sym.kind == .struct {
info := sym.info as ast.Struct
if !info.is_typedef {
if info.is_anon {
styp = 'C__' + styp
} else if !info.is_typedef {
styp = 'struct ${styp}'
}
}
Expand Down Expand Up @@ -6925,7 +6927,11 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
mut struct_names := map[string]bool{}
for sym in symbols {
if sym.name.starts_with('C.') {
continue
if sym.info is ast.Struct && sym.info.is_anon {
// For `C___VAnonStruct`, we need to create a new struct to make auto_str work.
} else {
continue
}
}
if sym.kind == .none && (!g.pref.skip_unused || g.table.used_features.used_none > 0) {
g.type_definitions.writeln('struct none {')
Expand Down
1 change: 1 addition & 0 deletions vlib/v/parser/parser.v
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ mut:
peek_tok token.Token
language ast.Language
fn_language ast.Language // .c for `fn C.abcd()` declarations
struct_language ast.Language // for `struct C.abcd{ embedded struct/union }` declarations
expr_level int // prevent too deep recursions for pathological programs
inside_vlib_file bool // true for all vlib/ files
inside_test_file bool // when inside _test.v or _test.vv file
Expand Down
12 changes: 11 additions & 1 deletion vlib/v/parser/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,18 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
} else {
p.check(.key_union)
}
language := p.parse_language()
mut language := p.parse_language()
name_pos := p.tok.pos()
if p.inside_struct_field_decl && language == .v {
// anon struct/union language should keep the same language of outside
language = p.struct_language
} else {
old_struct_language := p.struct_language
p.struct_language = language
defer(fn) {
p.struct_language = old_struct_language
}
}
p.check_for_impure_v(language, name_pos)
if p.disallow_declarations_in_script_mode() {
return ast.StructDecl{}
Expand Down
23 changes: 23 additions & 0 deletions vlib/v/tests/c_structs/cstruct_nested_anon_test.c.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module main

#insert "@VMODROOT/deep.h"

struct C.DeepStruct {
A1 int
S1 struct {
A2 int
S2 struct {
A3 int
S3 struct {
A4 int
}
}
}
}

fn test_cstruct_nested_anon() {
x := C.DeepStruct{}
y := C.DeepStruct{}
dump(x)
assert x == y
}
16 changes: 16 additions & 0 deletions vlib/v/tests/c_structs/deep.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef __DEEP_H__
#define __DEEP_H__

struct DeepStruct{
int A1;
struct {
int A2;
struct {
int A3;
struct {
int A4;
} S3;
} S2;
} S1;
};
#endif
Loading