| author | |
| committer | |
| log | df0f7f46923da9927df18809ad1d744102e78ebd |
| tree | 3b780c2a5b2ebc92328a58effe4b1b0e0ca28afe |
| parent | 5c28b8cd119979bb4b7d32edd1f4542165fc1f98 |
2 files changed, 127 insertions(+), 49 deletions(-)
src/translate_c.zig+77-17| ... | @@ -270,7 +270,10 @@ pub const Context = struct { | ... | @@ -270,7 +270,10 @@ pub const Context = struct { |
| 270 | global_scope: *Scope.Root, | 270 | global_scope: *Scope.Root, |
| 271 | clang_context: *clang.ASTContext, | 271 | clang_context: *clang.ASTContext, |
| 272 | mangle_count: u32 = 0, | 272 | mangle_count: u32 = 0, |
| 273 | /// Table of record decls that have been demoted to opaques. | ||
| 273 | opaque_demotes: std.AutoHashMapUnmanaged(usize, void) = .{}, | 274 | opaque_demotes: std.AutoHashMapUnmanaged(usize, void) = .{}, |
| 275 | /// Table of unnamed enums and records that are child types of typedefs. | ||
| 276 | unnamed_typedefs: std.AutoHashMapUnmanaged(usize, []const u8) = .{}, | ||
| 274 | 277 | ||
| 275 | /// This one is different than the root scope's name table. This contains | 278 | /// This one is different than the root scope's name table. This contains |
| 276 | /// a list of names that we found by visiting all the top level decls without | 279 | /// a list of names that we found by visiting all the top level decls without |
| ... | @@ -338,6 +341,7 @@ pub fn translate( | ... | @@ -338,6 +341,7 @@ pub fn translate( |
| 338 | context.alias_list.deinit(); | 341 | context.alias_list.deinit(); |
| 339 | context.global_names.deinit(gpa); | 342 | context.global_names.deinit(gpa); |
| 340 | context.opaque_demotes.deinit(gpa); | 343 | context.opaque_demotes.deinit(gpa); |
| 344 | context.unnamed_typedefs.deinit(gpa); | ||
| 341 | context.global_scope.deinit(); | 345 | context.global_scope.deinit(); |
| 342 | } | 346 | } |
| 343 | 347 | ||
| ... | @@ -401,6 +405,51 @@ fn declVisitorNamesOnly(c: *Context, decl: *const clang.Decl) Error!void { | ... | @@ -401,6 +405,51 @@ fn declVisitorNamesOnly(c: *Context, decl: *const clang.Decl) Error!void { |
| 401 | if (decl.castToNamedDecl()) |named_decl| { | 405 | if (decl.castToNamedDecl()) |named_decl| { |
| 402 | const decl_name = try c.str(named_decl.getName_bytes_begin()); | 406 | const decl_name = try c.str(named_decl.getName_bytes_begin()); |
| 403 | try c.global_names.put(c.gpa, decl_name, {}); | 407 | try c.global_names.put(c.gpa, decl_name, {}); |
| 408 | |||
| 409 | // Check for typedefs with unnamed enum/record child types. | ||
| 410 | if (decl.getKind() == .Typedef) { | ||
| 411 | const typedef_decl = @ptrCast(*const clang.TypedefNameDecl, decl); | ||
| 412 | var child_ty = typedef_decl.getUnderlyingType().getTypePtr(); | ||
| 413 | const addr: usize = while (true) switch (child_ty.getTypeClass()) { | ||
| 414 | .Enum => { | ||
| 415 | const enum_ty = @ptrCast(*const clang.EnumType, child_ty); | ||
| 416 | const enum_decl = enum_ty.getDecl(); | ||
| 417 | // check if this decl is unnamed | ||
| 418 | if (@ptrCast(*const clang.NamedDecl, enum_decl).getName_bytes_begin()[0] != 0) return; | ||
| 419 | break @ptrToInt(enum_decl.getCanonicalDecl()); | ||
| 420 | }, | ||
| 421 | .Record => { | ||
| 422 | const record_ty = @ptrCast(*const clang.RecordType, child_ty); | ||
| 423 | const record_decl = record_ty.getDecl(); | ||
| 424 | // check if this decl is unnamed | ||
| 425 | if (@ptrCast(*const clang.NamedDecl, record_decl).getName_bytes_begin()[0] != 0) return; | ||
| 426 | break @ptrToInt(record_decl.getCanonicalDecl()); | ||
| 427 | }, | ||
| 428 | .Elaborated => { | ||
| 429 | const elaborated_ty = @ptrCast(*const clang.ElaboratedType, child_ty); | ||
| 430 | child_ty = elaborated_ty.getNamedType().getTypePtr(); | ||
| 431 | }, | ||
| 432 | .Decayed => { | ||
| 433 | const decayed_ty = @ptrCast(*const clang.DecayedType, child_ty); | ||
| 434 | child_ty = decayed_ty.getDecayedType().getTypePtr(); | ||
| 435 | }, | ||
| 436 | .Attributed => { | ||
| 437 | const attributed_ty = @ptrCast(*const clang.AttributedType, child_ty); | ||
| 438 | child_ty = attributed_ty.getEquivalentType().getTypePtr(); | ||
| 439 | }, | ||
| 440 | .MacroQualified => { | ||
| 441 | const macroqualified_ty = @ptrCast(*const clang.MacroQualifiedType, child_ty); | ||
| 442 | child_ty = macroqualified_ty.getModifiedType().getTypePtr(); | ||
| 443 | }, | ||
| 444 | else => return, | ||
| 445 | } else unreachable; | ||
| 446 | // TODO https://github.com/ziglang/zig/issues/3756 | ||
| 447 | // TODO https://github.com/ziglang/zig/issues/1802 | ||
| 448 | const name = if (isZigPrimitiveType(decl_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ decl_name, c.getMangle() }) else decl_name; | ||
| 449 | try c.unnamed_typedefs.putNoClobber(c.gpa, addr, name); | ||
| 450 | // Put this typedef in the decl_table to avoid redefinitions. | ||
| 451 | try c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), name); | ||
| 452 | } | ||
| 404 | } | 453 | } |
| 405 | } | 454 | } |
| 406 | 455 | ||
| ... | @@ -752,17 +801,10 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD | ... | @@ -752,17 +801,10 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD |
| 752 | const toplevel = scope.id == .root; | 801 | const toplevel = scope.id == .root; |
| 753 | const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined; | 802 | const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined; |
| 754 | 803 | ||
| 755 | var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, record_decl).getName_bytes_begin()); | ||
| 756 | var is_unnamed = false; | ||
| 757 | // Record declarations such as `struct {...} x` have no name but they're not | ||
| 758 | // anonymous hence here isAnonymousStructOrUnion is not needed | ||
| 759 | if (bare_name.len == 0) { | ||
| 760 | bare_name = try std.fmt.allocPrint(c.arena, "unnamed_{d}", .{c.getMangle()}); | ||
| 761 | is_unnamed = true; | ||
| 762 | } | ||
| 763 | |||
| 764 | var container_kind_name: []const u8 = undefined; | ||
| 765 | var is_union = false; | 804 | var is_union = false; |
| 805 | var container_kind_name: []const u8 = undefined; | ||
| 806 | var bare_name: []const u8 = try c.str(@ptrCast(*const clang.NamedDecl, record_decl).getName_bytes_begin()); | ||
| 807 | |||
| 766 | if (record_decl.isUnion()) { | 808 | if (record_decl.isUnion()) { |
| 767 | container_kind_name = "union"; | 809 | container_kind_name = "union"; |
| 768 | is_union = true; | 810 | is_union = true; |
| ... | @@ -773,7 +815,20 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD | ... | @@ -773,7 +815,20 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD |
| 773 | return failDecl(c, record_loc, bare_name, "record {s} is not a struct or union", .{bare_name}); | 815 | return failDecl(c, record_loc, bare_name, "record {s} is not a struct or union", .{bare_name}); |
| 774 | } | 816 | } |
| 775 | 817 | ||
| 776 | var name: []const u8 = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ container_kind_name, bare_name }); | 818 | var is_unnamed = false; |
| 819 | var name = bare_name; | ||
| 820 | if (c.unnamed_typedefs.get(@ptrToInt(record_decl.getCanonicalDecl()))) |typedef_name| { | ||
| 821 | bare_name = typedef_name; | ||
| 822 | name = typedef_name; | ||
| 823 | } else { | ||
| 824 | // Record declarations such as `struct {...} x` have no name but they're not | ||
| 825 | // anonymous hence here isAnonymousStructOrUnion is not needed | ||
| 826 | if (bare_name.len == 0) { | ||
| 827 | bare_name = try std.fmt.allocPrint(c.arena, "unnamed_{d}", .{c.getMangle()}); | ||
| 828 | is_unnamed = true; | ||
| 829 | } | ||
| 830 | name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ container_kind_name, bare_name }); | ||
| 831 | } | ||
| 777 | if (!toplevel) name = try bs.makeMangledName(c, name); | 832 | if (!toplevel) name = try bs.makeMangledName(c, name); |
| 778 | try c.decl_table.putNoClobber(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), name); | 833 | try c.decl_table.putNoClobber(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), name); |
| 779 | 834 | ||
| ... | @@ -874,14 +929,19 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) E | ... | @@ -874,14 +929,19 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) E |
| 874 | const toplevel = scope.id == .root; | 929 | const toplevel = scope.id == .root; |
| 875 | const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined; | 930 | const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined; |
| 876 | 931 | ||
| 877 | var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_decl).getName_bytes_begin()); | ||
| 878 | var is_unnamed = false; | 932 | var is_unnamed = false; |
| 879 | if (bare_name.len == 0) { | 933 | var bare_name: []const u8 = try c.str(@ptrCast(*const clang.NamedDecl, enum_decl).getName_bytes_begin()); |
| 880 | bare_name = try std.fmt.allocPrint(c.arena, "unnamed_{d}", .{c.getMangle()}); | 934 | var name = bare_name; |
| 881 | is_unnamed = true; | 935 | if (c.unnamed_typedefs.get(@ptrToInt(enum_decl.getCanonicalDecl()))) |typedef_name| { |
| 936 | bare_name = typedef_name; | ||
| 937 | name = typedef_name; | ||
| 938 | } else { | ||
| 939 | if (bare_name.len == 0) { | ||
| 940 | bare_name = try std.fmt.allocPrint(c.arena, "unnamed_{d}", .{c.getMangle()}); | ||
| 941 | is_unnamed = true; | ||
| 942 | } | ||
| 943 | name = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name}); | ||
| 882 | } | 944 | } |
| 883 | |||
| 884 | var name: []const u8 = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name}); | ||
| 885 | if (!toplevel) _ = try bs.makeMangledName(c, name); | 945 | if (!toplevel) _ = try bs.makeMangledName(c, name); |
| 886 | try c.decl_table.putNoClobber(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name); | 946 | try c.decl_table.putNoClobber(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name); |
| 887 | 947 |
test/translate_c.zig+50-32| ... | @@ -3,6 +3,28 @@ const std = @import("std"); | ... | @@ -3,6 +3,28 @@ const std = @import("std"); |
| 3 | const CrossTarget = std.zig.CrossTarget; | 3 | const CrossTarget = std.zig.CrossTarget; |
| 4 | 4 | ||
| 5 | pub fn addCases(cases: *tests.TranslateCContext) void { | 5 | pub fn addCases(cases: *tests.TranslateCContext) void { |
| 6 | cases.add("unnamed child types of typedef receive typedef's name", | ||
| 7 | \\typedef enum { | ||
| 8 | \\ FooA, | ||
| 9 | \\ FooB, | ||
| 10 | \\} Foo; | ||
| 11 | \\typedef struct { | ||
| 12 | \\ int a, b; | ||
| 13 | \\} Bar; | ||
| 14 | , &[_][]const u8{ | ||
| 15 | \\pub const Foo = extern enum(c_int) { | ||
| 16 | \\ A, | ||
| 17 | \\ B, | ||
| 18 | \\ _, | ||
| 19 | \\}; | ||
| 20 | \\pub const FooA = @enumToInt(Foo.A); | ||
| 21 | \\pub const FooB = @enumToInt(Foo.B); | ||
| 22 | \\pub const Bar = extern struct { | ||
| 23 | \\ a: c_int, | ||
| 24 | \\ b: c_int, | ||
| 25 | \\}; | ||
| 26 | }); | ||
| 27 | |||
| 6 | cases.add("if as while stmt has semicolon", | 28 | cases.add("if as while stmt has semicolon", |
| 7 | \\void foo() { | 29 | \\void foo() { |
| 8 | \\ while (1) if (1) { | 30 | \\ while (1) if (1) { |
| ... | @@ -218,9 +240,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -218,9 +240,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 218 | \\} Bar; | 240 | \\} Bar; |
| 219 | , &[_][]const u8{ | 241 | , &[_][]const u8{ |
| 220 | \\source.h:1:9: warning: struct demoted to opaque type - unable to translate type of field foo | 242 | \\source.h:1:9: warning: struct demoted to opaque type - unable to translate type of field foo |
| 221 | \\const struct_unnamed_1 = opaque {}; | 243 | \\pub const Foo = opaque {}; |
| 222 | \\pub const Foo = struct_unnamed_1; | 244 | \\pub const Bar = extern struct { |
| 223 | \\const struct_unnamed_2 = extern struct { | ||
| 224 | \\ bar: ?*Foo, | 245 | \\ bar: ?*Foo, |
| 225 | \\}; | 246 | \\}; |
| 226 | }); | 247 | }); |
| ... | @@ -519,17 +540,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -519,17 +540,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 519 | \\} outer; | 540 | \\} outer; |
| 520 | \\void foo(outer *x) { x->y = x->x; } | 541 | \\void foo(outer *x) { x->y = x->x; } |
| 521 | , &[_][]const u8{ | 542 | , &[_][]const u8{ |
| 522 | \\const struct_unnamed_3 = extern struct { | 543 | \\const struct_unnamed_2 = extern struct { |
| 523 | \\ y: c_int, | 544 | \\ y: c_int, |
| 524 | \\}; | 545 | \\}; |
| 525 | \\const union_unnamed_2 = extern union { | 546 | \\const union_unnamed_1 = extern union { |
| 526 | \\ x: u8, | 547 | \\ x: u8, |
| 527 | \\ unnamed_0: struct_unnamed_3, | 548 | \\ unnamed_0: struct_unnamed_2, |
| 528 | \\}; | 549 | \\}; |
| 529 | \\const struct_unnamed_1 = extern struct { | 550 | \\pub const outer = extern struct { |
| 530 | \\ unnamed_0: union_unnamed_2, | 551 | \\ unnamed_0: union_unnamed_1, |
| 531 | \\}; | 552 | \\}; |
| 532 | \\pub const outer = struct_unnamed_1; | ||
| 533 | \\pub export fn foo(arg_x: [*c]outer) void { | 553 | \\pub export fn foo(arg_x: [*c]outer) void { |
| 534 | \\ var x = arg_x; | 554 | \\ var x = arg_x; |
| 535 | \\ x.*.unnamed_0.unnamed_0.y = @bitCast(c_int, @as(c_uint, x.*.unnamed_0.x)); | 555 | \\ x.*.unnamed_0.unnamed_0.y = @bitCast(c_int, @as(c_uint, x.*.unnamed_0.x)); |
| ... | @@ -565,21 +585,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -565,21 +585,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 565 | \\struct {int x,y;} s2 = {.y = 2, .x=1}; | 585 | \\struct {int x,y;} s2 = {.y = 2, .x=1}; |
| 566 | \\foo s3 = { 123 }; | 586 | \\foo s3 = { 123 }; |
| 567 | , &[_][]const u8{ | 587 | , &[_][]const u8{ |
| 568 | \\const struct_unnamed_1 = extern struct { | 588 | \\pub const foo = extern struct { |
| 569 | \\ x: c_int, | 589 | \\ x: c_int, |
| 570 | \\}; | 590 | \\}; |
| 571 | \\pub const foo = struct_unnamed_1; | 591 | \\const struct_unnamed_1 = extern struct { |
| 572 | \\const struct_unnamed_2 = extern struct { | ||
| 573 | \\ x: f64, | 592 | \\ x: f64, |
| 574 | \\ y: f64, | 593 | \\ y: f64, |
| 575 | \\ z: f64, | 594 | \\ z: f64, |
| 576 | \\}; | 595 | \\}; |
| 577 | \\pub export var s0: struct_unnamed_2 = struct_unnamed_2{ | 596 | \\pub export var s0: struct_unnamed_1 = struct_unnamed_1{ |
| 578 | \\ .x = 1.2, | 597 | \\ .x = 1.2, |
| 579 | \\ .y = 1.3, | 598 | \\ .y = 1.3, |
| 580 | \\ .z = 0, | 599 | \\ .z = 0, |
| 581 | \\}; | 600 | \\}; |
| 582 | \\const struct_unnamed_3 = extern struct { | 601 | \\const struct_unnamed_2 = extern struct { |
| 583 | \\ sec: c_int, | 602 | \\ sec: c_int, |
| 584 | \\ min: c_int, | 603 | \\ min: c_int, |
| 585 | \\ hour: c_int, | 604 | \\ hour: c_int, |
| ... | @@ -587,7 +606,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -587,7 +606,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 587 | \\ mon: c_int, | 606 | \\ mon: c_int, |
| 588 | \\ year: c_int, | 607 | \\ year: c_int, |
| 589 | \\}; | 608 | \\}; |
| 590 | \\pub export var s1: struct_unnamed_3 = struct_unnamed_3{ | 609 | \\pub export var s1: struct_unnamed_2 = struct_unnamed_2{ |
| 591 | \\ .sec = @as(c_int, 30), | 610 | \\ .sec = @as(c_int, 30), |
| 592 | \\ .min = @as(c_int, 15), | 611 | \\ .min = @as(c_int, 15), |
| 593 | \\ .hour = @as(c_int, 17), | 612 | \\ .hour = @as(c_int, 17), |
| ... | @@ -595,11 +614,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -595,11 +614,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 595 | \\ .mon = @as(c_int, 12), | 614 | \\ .mon = @as(c_int, 12), |
| 596 | \\ .year = @as(c_int, 2014), | 615 | \\ .year = @as(c_int, 2014), |
| 597 | \\}; | 616 | \\}; |
| 598 | \\const struct_unnamed_4 = extern struct { | 617 | \\const struct_unnamed_3 = extern struct { |
| 599 | \\ x: c_int, | 618 | \\ x: c_int, |
| 600 | \\ y: c_int, | 619 | \\ y: c_int, |
| 601 | \\}; | 620 | \\}; |
| 602 | \\pub export var s2: struct_unnamed_4 = struct_unnamed_4{ | 621 | \\pub export var s2: struct_unnamed_3 = struct_unnamed_3{ |
| 603 | \\ .x = @as(c_int, 1), | 622 | \\ .x = @as(c_int, 1), |
| 604 | \\ .y = @as(c_int, 2), | 623 | \\ .y = @as(c_int, 2), |
| 605 | \\}; | 624 | \\}; |
| ... | @@ -1639,37 +1658,36 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1639,37 +1658,36 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1639 | \\ p, | 1658 | \\ p, |
| 1640 | \\}; | 1659 | \\}; |
| 1641 | , &[_][]const u8{ | 1660 | , &[_][]const u8{ |
| 1642 | \\const enum_unnamed_1 = extern enum(c_int) { | 1661 | \\pub const d = extern enum(c_int) { |
| 1643 | \\ a, | 1662 | \\ a, |
| 1644 | \\ b, | 1663 | \\ b, |
| 1645 | \\ c, | 1664 | \\ c, |
| 1646 | \\ _, | 1665 | \\ _, |
| 1647 | \\}; | 1666 | \\}; |
| 1648 | \\pub const a = @enumToInt(enum_unnamed_1.a); | 1667 | \\pub const a = @enumToInt(d.a); |
| 1649 | \\pub const b = @enumToInt(enum_unnamed_1.b); | 1668 | \\pub const b = @enumToInt(d.b); |
| 1650 | \\pub const c = @enumToInt(enum_unnamed_1.c); | 1669 | \\pub const c = @enumToInt(d.c); |
| 1651 | \\pub const d = enum_unnamed_1; | 1670 | \\const enum_unnamed_1 = extern enum(c_int) { |
| 1652 | \\const enum_unnamed_2 = extern enum(c_int) { | ||
| 1653 | \\ e = 0, | 1671 | \\ e = 0, |
| 1654 | \\ f = 4, | 1672 | \\ f = 4, |
| 1655 | \\ g = 5, | 1673 | \\ g = 5, |
| 1656 | \\ _, | 1674 | \\ _, |
| 1657 | \\}; | 1675 | \\}; |
| 1658 | \\pub const e = @enumToInt(enum_unnamed_2.e); | 1676 | \\pub const e = @enumToInt(enum_unnamed_1.e); |
| 1659 | \\pub const f = @enumToInt(enum_unnamed_2.f); | 1677 | \\pub const f = @enumToInt(enum_unnamed_1.f); |
| 1660 | \\pub const g = @enumToInt(enum_unnamed_2.g); | 1678 | \\pub const g = @enumToInt(enum_unnamed_1.g); |
| 1661 | \\pub export var h: enum_unnamed_2 = @intToEnum(enum_unnamed_2, e); | 1679 | \\pub export var h: enum_unnamed_1 = @intToEnum(enum_unnamed_1, e); |
| 1662 | \\const enum_unnamed_3 = extern enum(c_int) { | 1680 | \\const enum_unnamed_2 = extern enum(c_int) { |
| 1663 | \\ i, | 1681 | \\ i, |
| 1664 | \\ j, | 1682 | \\ j, |
| 1665 | \\ k, | 1683 | \\ k, |
| 1666 | \\ _, | 1684 | \\ _, |
| 1667 | \\}; | 1685 | \\}; |
| 1668 | \\pub const i = @enumToInt(enum_unnamed_3.i); | 1686 | \\pub const i = @enumToInt(enum_unnamed_2.i); |
| 1669 | \\pub const j = @enumToInt(enum_unnamed_3.j); | 1687 | \\pub const j = @enumToInt(enum_unnamed_2.j); |
| 1670 | \\pub const k = @enumToInt(enum_unnamed_3.k); | 1688 | \\pub const k = @enumToInt(enum_unnamed_2.k); |
| 1671 | \\pub const struct_Baz = extern struct { | 1689 | \\pub const struct_Baz = extern struct { |
| 1672 | \\ l: enum_unnamed_3, | 1690 | \\ l: enum_unnamed_2, |
| 1673 | \\ m: d, | 1691 | \\ m: d, |
| 1674 | \\}; | 1692 | \\}; |
| 1675 | \\pub const enum_i = extern enum(c_int) { | 1693 | \\pub const enum_i = extern enum(c_int) { |