Skip to content

Conversation

@dotcarmen
Copy link

closes #202
closes #212

As discussed in #212 (comment) and #22 (comment), it's probably better to not demangle method names

// };
// pub const outer = extern struct {
// unnamed_0: union_unnamed_1 = @import("std").mem.zeroes(union_unnamed_1),
// pub const foo = __root.foo;
Copy link
Author

@dotcarmen dotcarmen Oct 28, 2025

Choose a reason for hiding this comment

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

if this is too aggressive, i can reuse some of the deleted logic from Scope.zig to ensure there is at least some underscore-mangling (but only to gatekeep inclusion as a member)

Copy link
Author

@dotcarmen dotcarmen Oct 28, 2025

Choose a reason for hiding this comment

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

gatekeeping patch
diff --git a/src/Scope.zig b/src/Scope.zig
index d62c09b5c4..645d53e864 100644
--- a/src/Scope.zig
+++ b/src/Scope.zig
@@ -286,6 +286,9 @@
             var count: u32 = 0;
             for (members.member_fns.items) |func| {
                 const func_name = func.data.name.?;
+                const last_index = std.mem.lastIndexOf(u8, func_name, "_");
+                if (last_index == null or std.mem.allEqual(u8, func_name[0..last_index.?], '_')) continue;
+
                 func_ref_vars[count] = try ast.Node.Tag.pub_var_simple.create(arena, .{
                     .name = func_name,
                     .init = try ast.Node.Tag.root_ref.create(arena, func_name),
diff --git a/test/cases/translate/anonymous_struct_&_unions.c b/test/cases/translate/anonymous_struct_&_unions.c
index 008cd5b217..7d70c24a49 100644
--- a/test/cases/translate/anonymous_struct_&_unions.c
+++ b/test/cases/translate/anonymous_struct_&_unions.c
@@ -17,7 +17,6 @@
 // };
 // pub const outer = extern struct {
 //     unnamed_0: union_unnamed_1 = @import("std").mem.zeroes(union_unnamed_1),
-//     pub const foo = __root.foo;
 // };
 // pub export fn foo(arg_x: [*c]outer) void {
 //     var x = arg_x;
diff --git a/test/cases/translate/detect_member_func.c b/test/cases/translate/detect_member_func.c
index 130a129392..161c662008 100644
--- a/test/cases/translate/detect_member_func.c
+++ b/test/cases/translate/detect_member_func.c
@@ -35,7 +35,6 @@
 //     foo: c_int = 0,
 //     bar: [*c]u8 = null,
 //     pub const Foo_bar = __root.Foo_bar;
-//     pub const baz = __root.baz;
 //     pub const libsomething_quux = __root.libsomething_quux;
 //     pub const foo1_bar = __root.foo1_bar;
 //     pub const foo2_bar = __root.foo2_bar;
@@ -49,7 +48,6 @@
 //     foo: c_int,
 //     numb: f32,
 //     pub const UFoo_bar = __root.UFoo_bar;
-//     pub const ubaz = __root.ubaz;
 //     pub const libsomething_union_quux = __root.libsomething_union_quux;
 // };
 // pub extern fn UFoo_bar(ufoo: UFoo) c_int;
diff --git a/test/cases/translate/qualified_struct_and_enum.c b/test/cases/translate/qualified_struct_and_enum.c
index 89c3873f34..4e0a28f48c 100644
--- a/test/cases/translate/qualified_struct_and_enum.c
+++ b/test/cases/translate/qualified_struct_and_enum.c
@@ -14,7 +14,6 @@
 // pub const struct_Foo = extern struct {
 //     x: c_int = 0,
 //     y: c_int = 0,
-//     pub const func = __root.func;
 // };
 // pub const BarA: c_int = 0;
 // pub const BarB: c_int = 1;
diff --git a/test/cases/translate/qualified_struct_and_enum_msvc.c b/test/cases/translate/qualified_struct_and_enum_msvc.c
index 0648b409fd..80b7e64e13 100644
--- a/test/cases/translate/qualified_struct_and_enum_msvc.c
+++ b/test/cases/translate/qualified_struct_and_enum_msvc.c
@@ -14,7 +14,6 @@
 // pub const struct_Foo = extern struct {
 //     x: c_int = 0,
 //     y: c_int = 0,
-//     pub const func = __root.func;
 // };
 // pub const BarA: c_int = 0;
 // pub const BarB: c_int = 1;
diff --git a/test/cases/translate/simple_ptrCast_for_casts_between_opaque_types.c b/test/cases/translate/simple_ptrCast_for_casts_between_opaque_types.c
index c9df65a5cd..0f86db9a94 100644
--- a/test/cases/translate/simple_ptrCast_for_casts_between_opaque_types.c
+++ b/test/cases/translate/simple_ptrCast_for_casts_between_opaque_types.c
@@ -6,9 +6,7 @@
 
 // translate
 //
-// pub const struct_opaque = opaque {
-//     pub const function = __root.function;
-// };
+// pub const struct_opaque = opaque {};
 // pub const struct_opaque_2 = opaque {};
 // pub export fn function(arg_opaque_1: ?*struct_opaque) void {
 //     var opaque_1 = arg_opaque_1;

@Vexu
Copy link
Member

Vexu commented Oct 28, 2025

The member functions shouldn't be mangled but it should still try to remove prefixes after all the untrimmed ones have been added.

@dotcarmen
Copy link
Author

i'm not sure i follow. can you share some example output of what you mean?

@Vexu
Copy link
Member

Vexu commented Oct 28, 2025

I mean that after all the untrimmed member functions are added it should try to add trimmed aliases that don't shadow anything:

struct Foo {
    int a;
};
void foo_bar(struct Foo *);
void foo_baz(struct Foo *);
void baz(struct Foo *);

-->

pub const struct_Foo = extern struct {
    a: c_int = 0,
    pub const foo_bar = __root.foo_bar;
    pub const foo_baz = __root.foo_baz;
    pub const baz = __root.baz;
    pub const bar = __root.foo_bar;
};
pub extern fn foo_bar([*c]struct_Foo) void;
pub extern fn foo_baz([*c]struct_Foo) void;
pub extern fn baz([*c]struct_Foo) void;

Copy link
Member

@Vexu Vexu left a comment

Choose a reason for hiding this comment

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

This is otherwise good but you added mangling again.

@dotcarmen
Copy link
Author

Yes, that's to avoid name collisions. Should members with name collisions be skipped?

@Vexu
Copy link
Member

Vexu commented Oct 29, 2025

Yes.

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.

generates empty identifier when a member function name ends with _

2 participants