Skip to content

cgen: fix eq for anon C structs#25152

Merged
spytheman merged 1 commit into
vlang:masterfrom
dy-tea:cstruct-anon-eq
Aug 22, 2025
Merged

cgen: fix eq for anon C structs#25152
spytheman merged 1 commit into
vlang:masterfrom
dy-tea:cstruct-anon-eq

Conversation

@dy-tea

@dy-tea dy-tea commented Aug 22, 2025

Copy link
Copy Markdown
Member

Given the below C struct (typedef is not required to repro):

// anon.h

typedef struct {
      struct {
               int x;
       } inner;
} outer;
// cstruct_anon_eq_test.c.v

#insert "@VMODROOT/anon.h"

@[typedef]
struct C.outer {
      inner struct {
            x int
      }
}

fn test_main() {
      a := C.outer{}
      b := C.outer{}
      assert a == b
}

Currently generates invalid eq functions:

======== Output of the C Compiler (/home/dylan/Downloads/v_linux/v/thirdparty/tcc/tcc.exe) ========
/tmp/v_1000/cstruct_anon_eq_test.01K37GBP8GYEP9GV6HW3RTH1D4.tmp.c:2416: error: cannot convert 'struct <anonymous>' to 'struct main___VAnonStruct1'
===================================================================================================
======== Output of the C Compiler (cc) ========
/tmp/v_1000/cstruct_anon_eq_test.01K37GBP8GYEP9GV6HW3RTH1D4.tmp.c: In function ‘indent_outer_str’:
/tmp/v_1000/cstruct_anon_eq_test.01K37GBP8GYEP9GV6HW3RTH1D4.tmp.c:2416:55: error: incompatible type for argument 1 of ‘indent_main___VAnonStruct1_str’
 2416 |         string _t1 = indent_main___VAnonStruct1_str(it->inner, indent_count + 1);
      |                                                     ~~^~~~~~~
      |                                                       |
      |                                                       struct <anonymous>
/tmp/v_1000/cstruct_anon_eq_test.01K37GBP8GYEP9GV6HW3RTH1D4.tmp.c:1886:66: note: expected ‘main___VAnonStruct1’ but argument is of type ‘struct <anonymous>’
 1886 | static string indent_main___VAnonStruct1_str(main___VAnonStruct1 it, int indent_count);
      |                                              ~~~~~~~~~~~~~~~~~~~~^~
/tmp/v_1000/cstruct_anon_eq_test.01K37GBP8GYEP9GV6HW3RTH1D4.tmp.c: In function ‘outer_struct_eq’:
/tmp/v_1000/cstruct_anon_eq_test.01K37GBP8GYEP9GV6HW3RTH1D4.tmp.c:2452:47: error: incompatible type for argument 1 of ‘main___VAnonStruct1_struct_eq’
 2452 |         return main___VAnonStruct1_struct_eq(a.inner, b.inner);
      |                                              ~^~~~~~
      |                                               |
      |                                               struct <anonymous>
/tmp/v_1000/cstruct_anon_eq_test.01K37GBP8GYEP9GV6HW3RTH1D4.tmp.c:2447:63: note: expected ‘main___VAnonStruct1’ but argument is of type ‘struct <anonymous>’
 2447 | inline bool main___VAnonStruct1_struct_eq(main___VAnonStruct1 a, main___VAnonStruct1 b) {
      |                                           ~~~~~~~~~~~~~~~~~~~~^
/tmp/v_1000/cstruct_anon_eq_test.01K37GBP8GYEP9GV6HW3RTH1D4.tmp.c:2452:56: error: incompatible type for argument 2 of ‘main___VAnonStruct1_struct_eq’
 2452 |         return main___VAnonStruct1_struct_eq(a.inner, b.inner);
      |                                                       ~^~~~~~
      |                                                        |
      |                                                        struct <anonymous>
/tmp/v_1000/cstruct_anon_eq_test.01K37GBP8GYEP9GV6HW3RTH1D4.tmp.c:2447:86: note: expected ‘main___VAnonStruct1’ but argument is of type ‘struct <anonymous>’
 2447 | inline bool main___VAnonStruct1_struct_eq(main___VAnonStruct1 a, main___VAnonStruct1 b) {
      |                                                                  ~~~~~~~~~~~~~~~~~~~~^
===============================================

struct <anonymous> and struct main___VAnonStruct1 are the same struct so we can cast to struct main___VAnonStruct1, which makes:

inline bool outer_struct_eq(outer a, outer b) {
	return main___VAnonStruct1_struct_eq(*(main___VAnonStruct1*)&(a.inner), *(main___VAnonStruct1*)&(b.inner));
}

I am unfamiliar with the codebase so let me know if something looks wrong.

@huly-for-github

Copy link
Copy Markdown

Connected to Huly®: V_0.6-23793

@spytheman spytheman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Excellent work.
Thank you 🙇🏻‍♂️.

@spytheman spytheman merged commit 752eb5c into vlang:master Aug 22, 2025
83 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants