authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-17 16:26:11+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-17 16:26:11+02:00
logd5fecbd0bacd986fc02c8a98aea07ac42303f0ce
tree95f8bad785c2f41e800a439635b4f57ae4470f8d
parente2974759dd62e15f04e1aeb8babee65e6ffb3413
signature Commit is signed but in an unrecognized format.

translate-c: support scoped typedef, enum and record decls

Closes #5256

3 files changed, 318 insertions(+), 169 deletions(-)

src/translate_c.zig+150-140
...@@ -433,13 +433,13 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void {...@@ -433,13 +433,13 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void {
433 return visitFnDecl(c, @ptrCast(*const clang.FunctionDecl, decl));433 return visitFnDecl(c, @ptrCast(*const clang.FunctionDecl, decl));
434 },434 },
435 .Typedef => {435 .Typedef => {
436 _ = try transTypeDef(c, @ptrCast(*const clang.TypedefNameDecl, decl), true);436 try transTypeDef(c, &c.global_scope.base, @ptrCast(*const clang.TypedefNameDecl, decl));
437 },437 },
438 .Enum => {438 .Enum => {
439 _ = try transEnumDecl(c, @ptrCast(*const clang.EnumDecl, decl));439 try transEnumDecl(c, &c.global_scope.base, @ptrCast(*const clang.EnumDecl, decl));
440 },440 },
441 .Record => {441 .Record => {
442 _ = try transRecordDecl(c, @ptrCast(*const clang.RecordDecl, decl));442 try transRecordDecl(c, &c.global_scope.base, @ptrCast(*const clang.RecordDecl, decl));
443 },443 },
444 .Var => {444 .Var => {
445 return visitVarDecl(c, @ptrCast(*const clang.VarDecl, decl), null);445 return visitVarDecl(c, @ptrCast(*const clang.VarDecl, decl), null);
...@@ -622,11 +622,11 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -622,11 +622,11 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
622 return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));622 return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
623}623}
624624
625fn transQualTypeMaybeInitialized(c: *Context, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!Node {625fn transQualTypeMaybeInitialized(c: *Context, scope: *Scope, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!Node {
626 return if (decl_init) |init_expr|626 return if (decl_init) |init_expr|
627 transQualTypeInitialized(c, qt, init_expr, loc)627 transQualTypeInitialized(c, scope, qt, init_expr, loc)
628 else628 else
629 transQualType(c, qt, loc);629 transQualType(c, scope, qt, loc);
630}630}
631631
632/// if mangled_name is not null, this var decl was declared in a block scope.632/// if mangled_name is not null, this var decl was declared in a block scope.
...@@ -658,7 +658,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -658,7 +658,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
658 var is_extern = storage_class == .Extern and !has_init;658 var is_extern = storage_class == .Extern and !has_init;
659 var is_export = !is_extern and storage_class != .Static;659 var is_export = !is_extern and storage_class != .Static;
660660
661 const type_node = transQualTypeMaybeInitialized(c, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {661 const type_node = transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, var_decl_loc) catch |err| switch (err) {
662 error.UnsupportedTranslation, error.UnsupportedType => {662 error.UnsupportedTranslation, error.UnsupportedType => {
663 return failDecl(c, var_decl_loc, checked_name, "unable to resolve variable type", .{});663 return failDecl(c, var_decl_loc, checked_name, "unable to resolve variable type", .{});
664 },664 },
...@@ -733,11 +733,6 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -733,11 +733,6 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
733 return addTopLevelDecl(c, checked_name, node);733 return addTopLevelDecl(c, checked_name, node);
734}734}
735735
736fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !Node {
737 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name);
738 return Tag.identifier.create(c.arena, builtin_name);
739}
740
741const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{736const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
742 .{ "uint8_t", "u8" },737 .{ "uint8_t", "u8" },
743 .{ "int8_t", "i8" },738 .{ "int8_t", "i8" },
...@@ -753,42 +748,28 @@ const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{...@@ -753,42 +748,28 @@ const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
753 .{ "size_t", "usize" },748 .{ "size_t", "usize" },
754});749});
755750
756fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?Node {751fn transTypeDef(c: *Context, scope: *Scope, typedef_decl: *const clang.TypedefNameDecl) Error!void {
757 if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name|752 if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name|
758 return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice753 return; // Avoid processing this decl twice
754 const toplevel = scope.id == .root;
755 const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined;
759756
760 const typedef_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());757 const bare_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());
761758
762 // TODO https://github.com/ziglang/zig/issues/3756759 // TODO https://github.com/ziglang/zig/issues/3756
763 // TODO https://github.com/ziglang/zig/issues/1802760 // TODO https://github.com/ziglang/zig/issues/1802
764 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ typedef_name, c.getMangle() }) else typedef_name;761 var name: []const u8 = if (isZigPrimitiveType(bare_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ bare_name, c.getMangle() }) else bare_name;
765 if (builtin_typedef_map.get(checked_name)) |builtin| {762 if (builtin_typedef_map.get(name)) |builtin| {
766 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);763 return c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);
767 return try Tag.identifier.create(c.arena, builtin);
768 }764 }
765 if (!toplevel) name = try bs.makeMangledName(c, name);
766 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), name);
769767
770 if (!top_level_visit) {
771 return try Tag.identifier.create(c.arena, checked_name);
772 }
773
774 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), checked_name);
775 const node = (try transCreateNodeTypedef(c, typedef_decl, true, checked_name)) orelse return null;
776 try addTopLevelDecl(c, checked_name, node);
777 return try Tag.identifier.create(c.arena, checked_name);
778}
779
780fn transCreateNodeTypedef(
781 c: *Context,
782 typedef_decl: *const clang.TypedefNameDecl,
783 toplevel: bool,
784 checked_name: []const u8,
785) Error!?Node {
786 const child_qt = typedef_decl.getUnderlyingType();768 const child_qt = typedef_decl.getUnderlyingType();
787 const typedef_loc = typedef_decl.getLocation();769 const typedef_loc = typedef_decl.getLocation();
788 const init_node = transQualType(c, child_qt, typedef_loc) catch |err| switch (err) {770 const init_node = transQualType(c, scope, child_qt, typedef_loc) catch |err| switch (err) {
789 error.UnsupportedType => {771 error.UnsupportedType => {
790 try failDecl(c, typedef_loc, checked_name, "unable to resolve typedef child type", .{});772 return failDecl(c, typedef_loc, name, "unable to resolve typedef child type", .{});
791 return null;
792 },773 },
793 error.OutOfMemory => |e| return e,774 error.OutOfMemory => |e| return e,
794 };775 };
...@@ -797,17 +778,25 @@ fn transCreateNodeTypedef(...@@ -797,17 +778,25 @@ fn transCreateNodeTypedef(
797 payload.* = .{778 payload.* = .{
798 .base = .{ .tag = ([2]Tag{ .var_simple, .pub_var_simple })[@boolToInt(toplevel)] },779 .base = .{ .tag = ([2]Tag{ .var_simple, .pub_var_simple })[@boolToInt(toplevel)] },
799 .data = .{780 .data = .{
800 .name = checked_name,781 .name = name,
801 .init = init_node,782 .init = init_node,
802 },783 },
803 };784 };
804 return Node.initPayload(&payload.base);785 const node = Node.initPayload(&payload.base);
786
787 if (toplevel) {
788 try addTopLevelDecl(c, name, node);
789 } else {
790 try scope.appendNode(node);
791 }
805}792}
806793
807fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Node {794fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordDecl) Error!void {
808 if (c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl()))) |name|795 if (c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl()))) |name|
809 return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice796 return; // Avoid processing this decl twice
810 const record_loc = record_decl.getLocation();797 const record_loc = record_decl.getLocation();
798 const toplevel = scope.id == .root;
799 const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined;
811800
812 var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, record_decl).getName_bytes_begin());801 var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, record_decl).getName_bytes_begin());
813 var is_unnamed = false;802 var is_unnamed = false;
...@@ -826,14 +815,15 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod...@@ -826,14 +815,15 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
826 } else if (record_decl.isStruct()) {815 } else if (record_decl.isStruct()) {
827 container_kind_name = "struct";816 container_kind_name = "struct";
828 } else {817 } else {
829 try warn(c, &c.global_scope.base, record_loc, "record {s} is not a struct or union", .{bare_name});818 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), bare_name);
830 return null;819 return failDecl(c, record_loc, bare_name, "record {s} is not a struct or union", .{bare_name});
831 }820 }
832821
833 const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ container_kind_name, bare_name });822 var name: []const u8 = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ container_kind_name, bare_name });
834 _ = try c.decl_table.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), name);823 if (!toplevel) name = try bs.makeMangledName(c, name);
824 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), name);
835825
836 const is_pub = !is_unnamed;826 const is_pub = toplevel and !is_unnamed;
837 const init_node = blk: {827 const init_node = blk: {
838 const record_def = record_decl.getDefinition() orelse {828 const record_def = record_decl.getDefinition() orelse {
839 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});829 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
...@@ -854,13 +844,13 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod...@@ -854,13 +844,13 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
854844
855 if (field_decl.isBitField()) {845 if (field_decl.isBitField()) {
856 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});846 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
857 try warn(c, &c.global_scope.base, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name});847 try warn(c, scope, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name});
858 break :blk Tag.opaque_literal.init();848 break :blk Tag.opaque_literal.init();
859 }849 }
860850
861 if (qualTypeCanon(field_qt).isIncompleteOrZeroLengthArrayType(c.clang_context)) {851 if (qualTypeCanon(field_qt).isIncompleteOrZeroLengthArrayType(c.clang_context)) {
862 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});852 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
863 try warn(c, &c.global_scope.base, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name});853 try warn(c, scope, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name});
864 break :blk Tag.opaque_literal.init();854 break :blk Tag.opaque_literal.init();
865 }855 }
866856
...@@ -872,10 +862,10 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod...@@ -872,10 +862,10 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
872 unnamed_field_count += 1;862 unnamed_field_count += 1;
873 is_anon = true;863 is_anon = true;
874 }864 }
875 const field_type = transQualType(c, field_qt, field_loc) catch |err| switch (err) {865 const field_type = transQualType(c, scope, field_qt, field_loc) catch |err| switch (err) {
876 error.UnsupportedType => {866 error.UnsupportedType => {
877 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});867 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
878 try warn(c, &c.global_scope.base, record_loc, "{s} demoted to opaque type - unable to translate type of field {s}", .{ container_kind_name, field_name });868 try warn(c, scope, record_loc, "{s} demoted to opaque type - unable to translate type of field {s}", .{ container_kind_name, field_name });
879 break :blk Tag.opaque_literal.init();869 break :blk Tag.opaque_literal.init();
880 },870 },
881 else => |e| return e,871 else => |e| return e,
...@@ -891,7 +881,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod...@@ -891,7 +881,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
891 };881 };
892882
893 if (is_anon) {883 if (is_anon) {
894 _ = try c.decl_table.put(c.gpa, @ptrToInt(field_decl.getCanonicalDecl()), field_name);884 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(field_decl.getCanonicalDecl()), field_name);
895 }885 }
896886
897 try fields.append(.{887 try fields.append(.{
...@@ -921,16 +911,21 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod...@@ -921,16 +911,21 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
921 },911 },
922 };912 };
923913
924 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));914 if (toplevel) {
925 if (!is_unnamed)915 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
926 try c.alias_list.append(.{ .alias = bare_name, .name = name });916 if (!is_unnamed)
927 return try Tag.identifier.create(c.arena, name);917 try c.alias_list.append(.{ .alias = bare_name, .name = name });
918 } else {
919 try scope.appendNode(Node.initPayload(&payload.base));
920 }
928}921}
929922
930fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {923fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) Error!void {
931 if (c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl()))) |name|924 if (c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl()))) |name|
932 return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice925 return; // Avoid processing this decl twice
933 const enum_loc = enum_decl.getLocation();926 const enum_loc = enum_decl.getLocation();
927 const toplevel = scope.id == .root;
928 const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined;
934929
935 var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_decl).getName_bytes_begin());930 var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_decl).getName_bytes_begin());
936 var is_unnamed = false;931 var is_unnamed = false;
...@@ -939,10 +934,13 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {...@@ -939,10 +934,13 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
939 is_unnamed = true;934 is_unnamed = true;
940 }935 }
941936
942 const name = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name});937 var name: []const u8 = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name});
943 _ = try c.decl_table.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name);938 if (!toplevel) _ = try bs.makeMangledName(c, name);
939 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name);
944940
945 const is_pub = !is_unnamed;941 const is_pub = toplevel and !is_unnamed;
942 var redecls = std.ArrayList(Tag.enum_redecl.Data()).init(c.gpa);
943 defer redecls.deinit();
946944
947 const init_node = if (enum_decl.getDefinition()) |enum_def| blk: {945 const init_node = if (enum_decl.getDefinition()) |enum_def| blk: {
948 var pure_enum = true;946 var pure_enum = true;
...@@ -968,10 +966,9 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {...@@ -968,10 +966,9 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
968 const init_arg_expr = if (int_type.ptr != null and966 const init_arg_expr = if (int_type.ptr != null and
969 !isCBuiltinType(int_type, .UInt) and967 !isCBuiltinType(int_type, .UInt) and
970 !isCBuiltinType(int_type, .Int))968 !isCBuiltinType(int_type, .Int))
971 transQualType(c, int_type, enum_loc) catch |err| switch (err) {969 transQualType(c, scope, int_type, enum_loc) catch |err| switch (err) {
972 error.UnsupportedType => {970 error.UnsupportedType => {
973 try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});971 return failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
974 return null;
975 },972 },
976 else => |e| return e,973 else => |e| return e,
977 }974 }
...@@ -1001,11 +998,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {...@@ -1001,11 +998,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
1001998
1002 // In C each enum value is in the global namespace. So we put them there too.999 // In C each enum value is in the global namespace. So we put them there too.
1003 // At this point we can rely on the enum emitting successfully.1000 // At this point we can rely on the enum emitting successfully.
1004 try addTopLevelDecl(c, field_name, try Tag.enum_redecl.create(c.arena, .{1001 try redecls.append(.{
1005 .enum_val_name = enum_val_name,1002 .enum_val_name = enum_val_name,
1006 .field_name = field_name,1003 .field_name = field_name,
1007 .enum_name = name,1004 .enum_name = name,
1008 }));1005 });
1009 }1006 }
10101007
1011 break :blk try Tag.@"enum".create(c.arena, .{1008 break :blk try Tag.@"enum".create(c.arena, .{
...@@ -1026,10 +1023,25 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {...@@ -1026,10 +1023,25 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
1026 },1023 },
1027 };1024 };
10281025
1029 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));1026 if (toplevel) {
1030 if (!is_unnamed)1027 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
1031 try c.alias_list.append(.{ .alias = bare_name, .name = name });1028 if (!is_unnamed)
1032 return try Tag.identifier.create(c.arena, name);1029 try c.alias_list.append(.{ .alias = bare_name, .name = name });
1030 } else {
1031 try scope.appendNode(Node.initPayload(&payload.base));
1032 }
1033
1034 for (redecls.items) |redecl| {
1035 if (toplevel) {
1036 try addTopLevelDecl(c, redecl.field_name, try Tag.pub_enum_redecl.create(c.arena, redecl));
1037 } else {
1038 try scope.appendNode(try Tag.enum_redecl.create(c.arena, .{
1039 .enum_val_name = try bs.makeMangledName(c, redecl.enum_val_name),
1040 .field_name = redecl.field_name,
1041 .enum_name = redecl.enum_name,
1042 }));
1043 }
1044 }
1033}1045}
10341046
1035const ResultUsed = enum {1047const ResultUsed = enum {
...@@ -1251,6 +1263,7 @@ fn transCompoundStmtInline(...@@ -1251,6 +1263,7 @@ fn transCompoundStmtInline(
1251 const end_it = stmt.body_end();1263 const end_it = stmt.body_end();
1252 while (it != end_it) : (it += 1) {1264 while (it != end_it) : (it += 1) {
1253 const result = try transStmt(c, parent_scope, it[0], .unused);1265 const result = try transStmt(c, parent_scope, it[0], .unused);
1266 if (result.tag() == .declaration) continue;
1254 try block.statements.append(result);1267 try block.statements.append(result);
1255 }1268 }
1256}1269}
...@@ -1285,7 +1298,7 @@ fn transDeclStmtOne(...@@ -1285,7 +1298,7 @@ fn transDeclStmtOne(
1285 scope: *Scope,1298 scope: *Scope,
1286 decl: *const clang.Decl,1299 decl: *const clang.Decl,
1287 block_scope: *Scope.Block,1300 block_scope: *Scope.Block,
1288) TransError!Node {1301) TransError!void {
1289 switch (decl.getKind()) {1302 switch (decl.getKind()) {
1290 .Var => {1303 .Var => {
1291 const var_decl = @ptrCast(*const clang.VarDecl, decl);1304 const var_decl = @ptrCast(*const clang.VarDecl, decl);
...@@ -1299,8 +1312,7 @@ fn transDeclStmtOne(...@@ -1299,8 +1312,7 @@ fn transDeclStmtOne(
1299 .Extern, .Static => {1312 .Extern, .Static => {
1300 // This is actually a global variable, put it in the global scope and reference it.1313 // This is actually a global variable, put it in the global scope and reference it.
1301 // `_ = mangled_name;`1314 // `_ = mangled_name;`
1302 try visitVarDecl(c, var_decl, mangled_name);1315 return visitVarDecl(c, var_decl, mangled_name);
1303 return try maybeSuppressResult(c, scope, .unused, try Tag.identifier.create(c.arena, mangled_name));
1304 },1316 },
1305 else => {},1317 else => {},
1306 }1318 }
...@@ -1308,7 +1320,7 @@ fn transDeclStmtOne(...@@ -1308,7 +1320,7 @@ fn transDeclStmtOne(
1308 const is_const = qual_type.isConstQualified();1320 const is_const = qual_type.isConstQualified();
13091321
1310 const loc = decl.getLocation();1322 const loc = decl.getLocation();
1311 const type_node = try transQualTypeMaybeInitialized(c, qual_type, decl_init, loc);1323 const type_node = try transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, loc);
13121324
1313 var init_node = if (decl_init) |expr|1325 var init_node = if (decl_init) |expr|
1314 if (expr.getStmtClass() == .StringLiteralClass)1326 if (expr.getStmtClass() == .StringLiteralClass)
...@@ -1320,7 +1332,7 @@ fn transDeclStmtOne(...@@ -1320,7 +1332,7 @@ fn transDeclStmtOne(
1320 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {1332 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
1321 init_node = try Tag.bool_to_int.create(c.arena, init_node);1333 init_node = try Tag.bool_to_int.create(c.arena, init_node);
1322 }1334 }
1323 return Tag.var_decl.create(c.arena, .{1335 const node = try Tag.var_decl.create(c.arena, .{
1324 .is_pub = false,1336 .is_pub = false,
1325 .is_const = is_const,1337 .is_const = is_const,
1326 .is_extern = false,1338 .is_extern = false,
...@@ -1332,18 +1344,16 @@ fn transDeclStmtOne(...@@ -1332,18 +1344,16 @@ fn transDeclStmtOne(
1332 .type = type_node,1344 .type = type_node,
1333 .init = init_node,1345 .init = init_node,
1334 });1346 });
1347 try block_scope.statements.append(node);
1335 },1348 },
1336 .Typedef => {1349 .Typedef => {
1337 const typedef_decl = @ptrCast(*const clang.TypedefNameDecl, decl);1350 try transTypeDef(c, scope, @ptrCast(*const clang.TypedefNameDecl, decl));
1338 const name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());1351 },
13391352 .Record => {
1340 const underlying_qual = typedef_decl.getUnderlyingType();1353 try transRecordDecl(c, scope, @ptrCast(*const clang.RecordDecl, decl));
1341 const underlying_type = underlying_qual.getTypePtr();1354 },
13421355 .Enum => {
1343 const mangled_name = try block_scope.makeMangledName(c, name);1356 try transEnumDecl(c, scope, @ptrCast(*const clang.EnumDecl, decl));
1344 const node = (try transCreateNodeTypedef(c, typedef_decl, false, mangled_name)) orelse
1345 return error.UnsupportedTranslation;
1346 return node;
1347 },1357 },
1348 else => |kind| return fail(1358 else => |kind| return fail(
1349 c,1359 c,
...@@ -1356,21 +1366,14 @@ fn transDeclStmtOne(...@@ -1356,21 +1366,14 @@ fn transDeclStmtOne(
1356}1366}
13571367
1358fn transDeclStmt(c: *Context, scope: *Scope, stmt: *const clang.DeclStmt) TransError!Node {1368fn transDeclStmt(c: *Context, scope: *Scope, stmt: *const clang.DeclStmt) TransError!Node {
1359 const block_scope = scope.findBlockScope(c) catch unreachable;1369 const block_scope = try scope.findBlockScope(c);
13601370
1361 var it = stmt.decl_begin();1371 var it = stmt.decl_begin();
1362 const end_it = stmt.decl_end();1372 const end_it = stmt.decl_end();
1363 assert(it != end_it);1373 while (it != end_it) : (it += 1) {
1364 while (true) : (it += 1) {1374 try transDeclStmtOne(c, scope, it[0], block_scope);
1365 const node = try transDeclStmtOne(c, scope, it[0], block_scope);
1366
1367 if (it + 1 == end_it) {
1368 return node;
1369 } else {
1370 try block_scope.statements.append(node);
1371 }
1372 }1375 }
1373 unreachable;1376 return Tag.declaration.init();
1374}1377}
13751378
1376fn transDeclRefExpr(1379fn transDeclRefExpr(
...@@ -1619,7 +1622,7 @@ fn transIntegerLiteral(...@@ -1619,7 +1622,7 @@ fn transIntegerLiteral(
16191622
1620 // @as(T, x)1623 // @as(T, x)
1621 const expr_base = @ptrCast(*const clang.Expr, expr);1624 const expr_base = @ptrCast(*const clang.Expr, expr);
1622 const ty_node = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc());1625 const ty_node = try transQualType(c, scope, expr_base.getType(), expr_base.getBeginLoc());
1623 const rhs = try transCreateNodeAPInt(c, eval_result.Val.getInt());1626 const rhs = try transCreateNodeAPInt(c, eval_result.Val.getInt());
1624 const as = try Tag.as.create(c.arena, .{ .lhs = ty_node, .rhs = rhs });1627 const as = try Tag.as.create(c.arena, .{ .lhs = ty_node, .rhs = rhs });
1625 return maybeSuppressResult(c, scope, result_used, as);1628 return maybeSuppressResult(c, scope, result_used, as);
...@@ -1697,7 +1700,7 @@ fn transStringLiteralAsArray(...@@ -1697,7 +1700,7 @@ fn transStringLiteralAsArray(
1697 const ty = expr_base.getType().getTypePtr();1700 const ty = expr_base.getType().getTypePtr();
1698 const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);1701 const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);
16991702
1700 const elem_type = try transQualType(c, const_arr_ty.getElementType(), expr_base.getBeginLoc());1703 const elem_type = try transQualType(c, scope, const_arr_ty.getElementType(), expr_base.getBeginLoc());
1701 const arr_type = try Tag.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_type });1704 const arr_type = try Tag.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_type });
1702 const init_list = try c.arena.alloc(Node, array_size);1705 const init_list = try c.arena.alloc(Node, array_size);
17031706
...@@ -1744,9 +1747,9 @@ fn transCCast(...@@ -1744,9 +1747,9 @@ fn transCCast(
1744 if (qualTypeCanon(dst_type).isVoidType()) return expr;1747 if (qualTypeCanon(dst_type).isVoidType()) return expr;
1745 if (dst_type.eq(src_type)) return expr;1748 if (dst_type.eq(src_type)) return expr;
1746 if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type))1749 if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type))
1747 return transCPtrCast(c, loc, dst_type, src_type, expr);1750 return transCPtrCast(c, scope, loc, dst_type, src_type, expr);
17481751
1749 const dst_node = try transQualType(c, dst_type, loc);1752 const dst_node = try transQualType(c, scope, dst_type, loc);
1750 if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) {1753 if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) {
1751 // 1. If src_type is an enum, determine the underlying signed int type1754 // 1. If src_type is an enum, determine the underlying signed int type
1752 // 2. Extend or truncate without changing signed-ness.1755 // 2. Extend or truncate without changing signed-ness.
...@@ -1903,7 +1906,7 @@ fn transInitListExprRecord(...@@ -1903,7 +1906,7 @@ fn transInitListExprRecord(
1903 const record_def = record_decl.getDefinition() orelse1906 const record_def = record_decl.getDefinition() orelse
1904 unreachable;1907 unreachable;
19051908
1906 const ty_node = try transType(c, ty, loc);1909 const ty_node = try transType(c, scope, ty, loc);
1907 const init_count = expr.getNumInits();1910 const init_count = expr.getNumInits();
1908 var field_inits = std.ArrayList(ast.Payload.ContainerInit.Initializer).init(c.gpa);1911 var field_inits = std.ArrayList(ast.Payload.ContainerInit.Initializer).init(c.gpa);
1909 defer field_inits.deinit();1912 defer field_inits.deinit();
...@@ -1952,7 +1955,7 @@ fn transInitListExprArray(...@@ -1952,7 +1955,7 @@ fn transInitListExprArray(
1952) TransError!Node {1955) TransError!Node {
1953 const arr_type = ty.getAsArrayTypeUnsafe();1956 const arr_type = ty.getAsArrayTypeUnsafe();
1954 const child_qt = arr_type.getElementType();1957 const child_qt = arr_type.getElementType();
1955 const child_type = try transQualType(c, child_qt, loc);1958 const child_type = try transQualType(c, scope, child_qt, loc);
1956 const init_count = expr.getNumInits();1959 const init_count = expr.getNumInits();
1957 assert(@ptrCast(*const clang.Type, arr_type).isConstantArrayType());1960 assert(@ptrCast(*const clang.Type, arr_type).isConstantArrayType());
1958 const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, arr_type);1961 const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, arr_type);
...@@ -2217,7 +2220,7 @@ fn transForLoop(...@@ -2217,7 +2220,7 @@ fn transForLoop(
2217 block_scope = try Scope.Block.init(c, scope, false);2220 block_scope = try Scope.Block.init(c, scope, false);
2218 loop_scope.parent = &block_scope.?.base;2221 loop_scope.parent = &block_scope.?.base;
2219 const init_node = try transStmt(c, &block_scope.?.base, init, .unused);2222 const init_node = try transStmt(c, &block_scope.?.base, init, .unused);
2220 try block_scope.?.statements.append(init_node);2223 if (init_node.tag() != .declaration) try block_scope.?.statements.append(init_node);
2221 }2224 }
2222 var cond_scope = Scope.Condition{2225 var cond_scope = Scope.Condition{
2223 .base = .{2226 .base = .{
...@@ -2328,7 +2331,7 @@ fn transCase(...@@ -2328,7 +2331,7 @@ fn transCase(
2328 scope: *Scope,2331 scope: *Scope,
2329 stmt: *const clang.CaseStmt,2332 stmt: *const clang.CaseStmt,
2330) TransError!Node {2333) TransError!Node {
2331 const block_scope = scope.findBlockScope(c) catch unreachable;2334 const block_scope = try scope.findBlockScope(c);
2332 const switch_scope = scope.getSwitch();2335 const switch_scope = scope.getSwitch();
2333 const label = try block_scope.makeMangledName(c, "case");2336 const label = try block_scope.makeMangledName(c, "case");
23342337
...@@ -2366,7 +2369,7 @@ fn transDefault(...@@ -2366,7 +2369,7 @@ fn transDefault(
2366 scope: *Scope,2369 scope: *Scope,
2367 stmt: *const clang.DefaultStmt,2370 stmt: *const clang.DefaultStmt,
2368) TransError!Node {2371) TransError!Node {
2369 const block_scope = scope.findBlockScope(c) catch unreachable;2372 const block_scope = try scope.findBlockScope(c);
2370 const switch_scope = scope.getSwitch();2373 const switch_scope = scope.getSwitch();
2371 switch_scope.default_label = try block_scope.makeMangledName(c, "default");2374 switch_scope.default_label = try block_scope.makeMangledName(c, "default");
23722375
...@@ -2400,7 +2403,7 @@ fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used:...@@ -2400,7 +2403,7 @@ fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used:
2400 // @as(T, x)2403 // @as(T, x)
2401 const expr_base = @ptrCast(*const clang.Expr, expr);2404 const expr_base = @ptrCast(*const clang.Expr, expr);
2402 const as_node = try Tag.as.create(c.arena, .{2405 const as_node = try Tag.as.create(c.arena, .{
2403 .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),2406 .lhs = try transQualType(c, scope, expr_base.getType(), expr_base.getBeginLoc()),
2404 .rhs = try transCreateNodeAPInt(c, result.Val.getInt()),2407 .rhs = try transCreateNodeAPInt(c, result.Val.getInt()),
2405 });2408 });
2406 return maybeSuppressResult(c, scope, used, as_node);2409 return maybeSuppressResult(c, scope, used, as_node);
...@@ -2446,7 +2449,7 @@ fn transCharLiteral(...@@ -2446,7 +2449,7 @@ fn transCharLiteral(
2446 // @as(T, x)2449 // @as(T, x)
2447 const expr_base = @ptrCast(*const clang.Expr, stmt);2450 const expr_base = @ptrCast(*const clang.Expr, stmt);
2448 const as_node = try Tag.as.create(c.arena, .{2451 const as_node = try Tag.as.create(c.arena, .{
2449 .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),2452 .lhs = try transQualType(c, scope, expr_base.getType(), expr_base.getBeginLoc()),
2450 .rhs = int_lit_node,2453 .rhs = int_lit_node,
2451 });2454 });
2452 return maybeSuppressResult(c, scope, result_used, as_node);2455 return maybeSuppressResult(c, scope, result_used, as_node);
...@@ -2464,6 +2467,7 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:...@@ -2464,6 +2467,7 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
2464 const end_it = comp.body_end();2467 const end_it = comp.body_end();
2465 while (it != end_it - 1) : (it += 1) {2468 while (it != end_it - 1) : (it += 1) {
2466 const result = try transStmt(c, &block_scope.base, it[0], .unused);2469 const result = try transStmt(c, &block_scope.base, it[0], .unused);
2470 if (result.tag() == .declaration) continue;
2467 try block_scope.statements.append(result);2471 try block_scope.statements.append(result);
2468 }2472 }
2469 const break_node = try Tag.break_val.create(c.arena, .{2473 const break_node = try Tag.break_val.create(c.arena, .{
...@@ -2657,7 +2661,7 @@ fn transUnaryExprOrTypeTraitExpr(...@@ -2657,7 +2661,7 @@ fn transUnaryExprOrTypeTraitExpr(
2657 result_used: ResultUsed,2661 result_used: ResultUsed,
2658) TransError!Node {2662) TransError!Node {
2659 const loc = stmt.getBeginLoc();2663 const loc = stmt.getBeginLoc();
2660 const type_node = try transQualType(c, stmt.getTypeOfArgument(), loc);2664 const type_node = try transQualType(c, scope, stmt.getTypeOfArgument(), loc);
26612665
2662 const kind = stmt.getKind();2666 const kind = stmt.getKind();
2663 switch (kind) {2667 switch (kind) {
...@@ -2917,9 +2921,9 @@ fn transCreateCompoundAssign(...@@ -2917,9 +2921,9 @@ fn transCreateCompoundAssign(
2917 if (is_shift or requires_int_cast) {2921 if (is_shift or requires_int_cast) {
2918 // @intCast(rhs)2922 // @intCast(rhs)
2919 const cast_to_type = if (is_shift)2923 const cast_to_type = if (is_shift)
2920 try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)2924 try qualTypeToLog2IntRef(c, scope, getExprQualType(c, rhs), loc)
2921 else2925 else
2922 try transQualType(c, getExprQualType(c, lhs), loc);2926 try transQualType(c, scope, getExprQualType(c, lhs), loc);
29232927
2924 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });2928 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
2925 }2929 }
...@@ -2960,9 +2964,9 @@ fn transCreateCompoundAssign(...@@ -2960,9 +2964,9 @@ fn transCreateCompoundAssign(
2960 if (is_shift or requires_int_cast) {2964 if (is_shift or requires_int_cast) {
2961 // @intCast(rhs)2965 // @intCast(rhs)
2962 const cast_to_type = if (is_shift)2966 const cast_to_type = if (is_shift)
2963 try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)2967 try qualTypeToLog2IntRef(c, scope, getExprQualType(c, rhs), loc)
2964 else2968 else
2965 try transQualType(c, getExprQualType(c, lhs), loc);2969 try transQualType(c, scope, getExprQualType(c, lhs), loc);
29662970
2967 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });2971 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
2968 }2972 }
...@@ -2981,6 +2985,7 @@ fn transCreateCompoundAssign(...@@ -2981,6 +2985,7 @@ fn transCreateCompoundAssign(
29812985
2982fn transCPtrCast(2986fn transCPtrCast(
2983 c: *Context,2987 c: *Context,
2988 scope: *Scope,
2984 loc: clang.SourceLocation,2989 loc: clang.SourceLocation,
2985 dst_type: clang.QualType,2990 dst_type: clang.QualType,
2986 src_type: clang.QualType,2991 src_type: clang.QualType,
...@@ -2990,7 +2995,7 @@ fn transCPtrCast(...@@ -2990,7 +2995,7 @@ fn transCPtrCast(
2990 const child_type = ty.getPointeeType();2995 const child_type = ty.getPointeeType();
2991 const src_ty = src_type.getTypePtr();2996 const src_ty = src_type.getTypePtr();
2992 const src_child_type = src_ty.getPointeeType();2997 const src_child_type = src_ty.getPointeeType();
2993 const dst_type_node = try transType(c, ty, loc);2998 const dst_type_node = try transType(c, scope, ty, loc);
29942999
2995 if ((src_child_type.isConstQualified() and3000 if ((src_child_type.isConstQualified() and
2996 !child_type.isConstQualified()) or3001 !child_type.isConstQualified()) or
...@@ -3011,7 +3016,7 @@ fn transCPtrCast(...@@ -3011,7 +3016,7 @@ fn transCPtrCast(
3011 // For opaque types a ptrCast is enough3016 // For opaque types a ptrCast is enough
3012 expr3017 expr
3013 else blk: {3018 else blk: {
3014 const child_type_node = try transQualType(c, child_type, loc);3019 const child_type_node = try transQualType(c, scope, child_type, loc);
3015 const alignof = try Tag.alignof.create(c.arena, child_type_node);3020 const alignof = try Tag.alignof.create(c.arena, child_type_node);
3016 const align_cast = try Tag.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr });3021 const align_cast = try Tag.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr });
3017 break :blk align_cast;3022 break :blk align_cast;
...@@ -3160,6 +3165,7 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void {...@@ -3160,6 +3165,7 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void {
3160/// by the size of the initializer3165/// by the size of the initializer
3161fn transQualTypeInitialized(3166fn transQualTypeInitialized(
3162 c: *Context,3167 c: *Context,
3168 scope: *Scope,
3163 qt: clang.QualType,3169 qt: clang.QualType,
3164 decl_init: *const clang.Expr,3170 decl_init: *const clang.Expr,
3165 source_loc: clang.SourceLocation,3171 source_loc: clang.SourceLocation,
...@@ -3167,7 +3173,7 @@ fn transQualTypeInitialized(...@@ -3167,7 +3173,7 @@ fn transQualTypeInitialized(
3167 const ty = qt.getTypePtr();3173 const ty = qt.getTypePtr();
3168 if (ty.getTypeClass() == .IncompleteArray) {3174 if (ty.getTypeClass() == .IncompleteArray) {
3169 const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty);3175 const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty);
3170 const elem_ty = try transType(c, incomplete_array_ty.getElementType().getTypePtr(), source_loc);3176 const elem_ty = try transType(c, scope, incomplete_array_ty.getElementType().getTypePtr(), source_loc);
31713177
3172 switch (decl_init.getStmtClass()) {3178 switch (decl_init.getStmtClass()) {
3173 .StringLiteralClass => {3179 .StringLiteralClass => {
...@@ -3184,11 +3190,11 @@ fn transQualTypeInitialized(...@@ -3184,11 +3190,11 @@ fn transQualTypeInitialized(
3184 else => {},3190 else => {},
3185 }3191 }
3186 }3192 }
3187 return transQualType(c, qt, source_loc);3193 return transQualType(c, scope, qt, source_loc);
3188}3194}
31893195
3190fn transQualType(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) TypeError!Node {3196fn transQualType(c: *Context, scope: *Scope, qt: clang.QualType, source_loc: clang.SourceLocation) TypeError!Node {
3191 return transType(c, qt.getTypePtr(), source_loc);3197 return transType(c, scope, qt.getTypePtr(), source_loc);
3192}3198}
31933199
3194/// Produces a Zig AST node by translating a Clang QualType, respecting the width, but modifying the signed-ness.3200/// Produces a Zig AST node by translating a Clang QualType, respecting the width, but modifying the signed-ness.
...@@ -3273,7 +3279,7 @@ fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType) !u32 {...@@ -3273,7 +3279,7 @@ fn qualTypeIntBitWidth(c: *Context, qt: clang.QualType) !u32 {
3273 }3279 }
3274}3280}
32753281
3276fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !Node {3282fn qualTypeToLog2IntRef(c: *Context, scope: *Scope, qt: clang.QualType, source_loc: clang.SourceLocation) !Node {
3277 const int_bit_width = try qualTypeIntBitWidth(c, qt);3283 const int_bit_width = try qualTypeIntBitWidth(c, qt);
32783284
3279 if (int_bit_width != 0) {3285 if (int_bit_width != 0) {
...@@ -3282,7 +3288,7 @@ fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.Sourc...@@ -3282,7 +3288,7 @@ fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.Sourc
3282 return Tag.log2_int_type.create(c.arena, cast_bit_width);3288 return Tag.log2_int_type.create(c.arena, cast_bit_width);
3283 }3289 }
32843290
3285 const zig_type = try transQualType(c, qt, source_loc);3291 const zig_type = try transQualType(c, scope, qt, source_loc);
3286 return Tag.std_math_Log2Int.create(c.arena, zig_type);3292 return Tag.std_math_Log2Int.create(c.arena, zig_type);
3287}3293}
32883294
...@@ -3641,14 +3647,14 @@ fn transCreateNodeShiftOp(...@@ -3641,14 +3647,14 @@ fn transCreateNodeShiftOp(
36413647
3642 const lhs = try transExpr(c, scope, lhs_expr, .used);3648 const lhs = try transExpr(c, scope, lhs_expr, .used);
36433649
3644 const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location);3650 const rhs_type = try qualTypeToLog2IntRef(c, scope, stmt.getType(), rhs_location);
3645 const rhs = try transExprCoercing(c, scope, rhs_expr, .used);3651 const rhs = try transExprCoercing(c, scope, rhs_expr, .used);
3646 const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs });3652 const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs });
36473653
3648 return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used);3654 return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used);
3649}3655}
36503656
3651fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node {3657fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node {
3652 switch (ty.getTypeClass()) {3658 switch (ty.getTypeClass()) {
3653 .Builtin => {3659 .Builtin => {
3654 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);3660 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
...@@ -3687,16 +3693,16 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio...@@ -3687,16 +3693,16 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
3687 },3693 },
3688 .Paren => {3694 .Paren => {
3689 const paren_ty = @ptrCast(*const clang.ParenType, ty);3695 const paren_ty = @ptrCast(*const clang.ParenType, ty);
3690 return transQualType(c, paren_ty.getInnerType(), source_loc);3696 return transQualType(c, scope, paren_ty.getInnerType(), source_loc);
3691 },3697 },
3692 .Pointer => {3698 .Pointer => {
3693 const child_qt = ty.getPointeeType();3699 const child_qt = ty.getPointeeType();
3694 if (qualTypeChildIsFnProto(child_qt)) {3700 if (qualTypeChildIsFnProto(child_qt)) {
3695 return Tag.optional_type.create(c.arena, try transQualType(c, child_qt, source_loc));3701 return Tag.optional_type.create(c.arena, try transQualType(c, scope, child_qt, source_loc));
3696 }3702 }
3697 const is_const = child_qt.isConstQualified();3703 const is_const = child_qt.isConstQualified();
3698 const is_volatile = child_qt.isVolatileQualified();3704 const is_volatile = child_qt.isVolatileQualified();
3699 const elem_type = try transQualType(c, child_qt, source_loc);3705 const elem_type = try transQualType(c, scope, child_qt, source_loc);
3700 if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) {3706 if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) {
3701 const ptr = try Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });3707 const ptr = try Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
3702 return Tag.optional_type.create(c.arena, ptr);3708 return Tag.optional_type.create(c.arena, ptr);
...@@ -3709,7 +3715,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio...@@ -3709,7 +3715,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
37093715
3710 const size_ap_int = const_arr_ty.getSize();3716 const size_ap_int = const_arr_ty.getSize();
3711 const size = size_ap_int.getLimitedValue(math.maxInt(usize));3717 const size = size_ap_int.getLimitedValue(math.maxInt(usize));
3712 const elem_type = try transType(c, const_arr_ty.getElementType().getTypePtr(), source_loc);3718 const elem_type = try transType(c, scope, const_arr_ty.getElementType().getTypePtr(), source_loc);
37133719
3714 return Tag.array_type.create(c.arena, .{ .len = size, .elem_type = elem_type });3720 return Tag.array_type.create(c.arena, .{ .len = size, .elem_type = elem_type });
3715 },3721 },
...@@ -3719,7 +3725,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio...@@ -3719,7 +3725,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
3719 const child_qt = incomplete_array_ty.getElementType();3725 const child_qt = incomplete_array_ty.getElementType();
3720 const is_const = child_qt.isConstQualified();3726 const is_const = child_qt.isConstQualified();
3721 const is_volatile = child_qt.isVolatileQualified();3727 const is_volatile = child_qt.isVolatileQualified();
3722 const elem_type = try transQualType(c, child_qt, source_loc);3728 const elem_type = try transQualType(c, scope, child_qt, source_loc);
37233729
3724 return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });3730 return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
3725 },3731 },
...@@ -3727,38 +3733,41 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio...@@ -3727,38 +3733,41 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
3727 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);3733 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
37283734
3729 const typedef_decl = typedef_ty.getDecl();3735 const typedef_decl = typedef_ty.getDecl();
3730 return (try transTypeDef(c, typedef_decl, false)) orelse3736 try transTypeDef(c, scope, typedef_decl);
3731 fail(c, error.UnsupportedType, source_loc, "unable to translate typedef declaration", .{});3737 const name = c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl())).?;
3738 return Tag.identifier.create(c.arena, name);
3732 },3739 },
3733 .Record => {3740 .Record => {
3734 const record_ty = @ptrCast(*const clang.RecordType, ty);3741 const record_ty = @ptrCast(*const clang.RecordType, ty);
37353742
3736 const record_decl = record_ty.getDecl();3743 const record_decl = record_ty.getDecl();
3737 return (try transRecordDecl(c, record_decl)) orelse3744 try transRecordDecl(c, scope, record_decl);
3738 fail(c, error.UnsupportedType, source_loc, "unable to resolve record declaration", .{});3745 const name = c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl())).?;
3746 return Tag.identifier.create(c.arena, name);
3739 },3747 },
3740 .Enum => {3748 .Enum => {
3741 const enum_ty = @ptrCast(*const clang.EnumType, ty);3749 const enum_ty = @ptrCast(*const clang.EnumType, ty);
37423750
3743 const enum_decl = enum_ty.getDecl();3751 const enum_decl = enum_ty.getDecl();
3744 return (try transEnumDecl(c, enum_decl)) orelse3752 try transEnumDecl(c, scope, enum_decl);
3745 fail(c, error.UnsupportedType, source_loc, "unable to translate enum declaration", .{});3753 const name = c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl())).?;
3754 return Tag.identifier.create(c.arena, name);
3746 },3755 },
3747 .Elaborated => {3756 .Elaborated => {
3748 const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);3757 const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);
3749 return transQualType(c, elaborated_ty.getNamedType(), source_loc);3758 return transQualType(c, scope, elaborated_ty.getNamedType(), source_loc);
3750 },3759 },
3751 .Decayed => {3760 .Decayed => {
3752 const decayed_ty = @ptrCast(*const clang.DecayedType, ty);3761 const decayed_ty = @ptrCast(*const clang.DecayedType, ty);
3753 return transQualType(c, decayed_ty.getDecayedType(), source_loc);3762 return transQualType(c, scope, decayed_ty.getDecayedType(), source_loc);
3754 },3763 },
3755 .Attributed => {3764 .Attributed => {
3756 const attributed_ty = @ptrCast(*const clang.AttributedType, ty);3765 const attributed_ty = @ptrCast(*const clang.AttributedType, ty);
3757 return transQualType(c, attributed_ty.getEquivalentType(), source_loc);3766 return transQualType(c, scope, attributed_ty.getEquivalentType(), source_loc);
3758 },3767 },
3759 .MacroQualified => {3768 .MacroQualified => {
3760 const macroqualified_ty = @ptrCast(*const clang.MacroQualifiedType, ty);3769 const macroqualified_ty = @ptrCast(*const clang.MacroQualifiedType, ty);
3761 return transQualType(c, macroqualified_ty.getModifiedType(), source_loc);3770 return transQualType(c, scope, macroqualified_ty.getModifiedType(), source_loc);
3762 },3771 },
3763 else => {3772 else => {
3764 const type_name = c.str(ty.getTypeClassName());3773 const type_name = c.str(ty.getTypeClassName());
...@@ -3890,6 +3899,7 @@ fn finishTransFnProto(...@@ -3890,6 +3899,7 @@ fn finishTransFnProto(
3890) !*ast.Payload.Func {3899) !*ast.Payload.Func {
3891 const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;3900 const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;
3892 const is_extern = if (fn_decl_context) |ctx| !ctx.has_body else false;3901 const is_extern = if (fn_decl_context) |ctx| !ctx.has_body else false;
3902 const scope = &c.global_scope.base;
38933903
3894 // TODO check for always_inline attribute3904 // TODO check for always_inline attribute
3895 // TODO check for align attribute3905 // TODO check for align attribute
...@@ -3914,7 +3924,7 @@ fn finishTransFnProto(...@@ -3914,7 +3924,7 @@ fn finishTransFnProto(
39143924
3915 break :blk param_name;3925 break :blk param_name;
3916 } else null;3926 } else null;
3917 const type_node = try transQualType(c, param_qt, source_loc);3927 const type_node = try transQualType(c, scope, param_qt, source_loc);
39183928
3919 fn_params.addOneAssumeCapacity().* = .{3929 fn_params.addOneAssumeCapacity().* = .{
3920 .is_noalias = is_noalias,3930 .is_noalias = is_noalias,
...@@ -3955,9 +3965,9 @@ fn finishTransFnProto(...@@ -3955,9 +3965,9 @@ fn finishTransFnProto(
3955 // convert primitive c_void to actual void (only for return type)3965 // convert primitive c_void to actual void (only for return type)
3956 break :blk Tag.void_type.init();3966 break :blk Tag.void_type.init();
3957 } else {3967 } else {
3958 break :blk transQualType(c, return_qt, source_loc) catch |err| switch (err) {3968 break :blk transQualType(c, scope, return_qt, source_loc) catch |err| switch (err) {
3959 error.UnsupportedType => {3969 error.UnsupportedType => {
3960 try warn(c, &c.global_scope.base, source_loc, "unsupported function proto return type", .{});3970 try warn(c, scope, source_loc, "unsupported function proto return type", .{});
3961 return err;3971 return err;
3962 },3972 },
3963 error.OutOfMemory => |e| return e,3973 error.OutOfMemory => |e| return e,
src/translate_c/ast.zig+11-4
...@@ -14,6 +14,8 @@ pub const Node = extern union {...@@ -14,6 +14,8 @@ pub const Node = extern union {
14 ptr_otherwise: *Payload,14 ptr_otherwise: *Payload,
1515
16 pub const Tag = enum {16 pub const Tag = enum {
17 /// Declarations add themselves to the correct scopes and should not be emitted as this tag.
18 declaration,
17 null_literal,19 null_literal,
18 undefined_literal,20 undefined_literal,
19 /// opaque {}21 /// opaque {}
...@@ -186,6 +188,7 @@ pub const Node = extern union {...@@ -186,6 +188,7 @@ pub const Node = extern union {
186 /// pub const name = init;188 /// pub const name = init;
187 pub_var_simple,189 pub_var_simple,
188 /// pub const enum_field_name = @enumToInt(enum_name.field_name);190 /// pub const enum_field_name = @enumToInt(enum_name.field_name);
191 pub_enum_redecl,
189 enum_redecl,192 enum_redecl,
190193
191 /// pub inline fn name(params) return_type body194 /// pub inline fn name(params) return_type body
...@@ -201,6 +204,7 @@ pub const Node = extern union {...@@ -201,6 +204,7 @@ pub const Node = extern union {
201204
202 pub fn Type(comptime t: Tag) type {205 pub fn Type(comptime t: Tag) type {
203 return switch (t) {206 return switch (t) {
207 .declaration,
204 .null_literal,208 .null_literal,
205 .undefined_literal,209 .undefined_literal,
206 .opaque_literal,210 .opaque_literal,
...@@ -325,7 +329,7 @@ pub const Node = extern union {...@@ -325,7 +329,7 @@ pub const Node = extern union {
325 .arg_redecl, .alias, .fail_decl => Payload.ArgRedecl,329 .arg_redecl, .alias, .fail_decl => Payload.ArgRedecl,
326 .log2_int_type => Payload.Log2IntType,330 .log2_int_type => Payload.Log2IntType,
327 .var_simple, .pub_var_simple => Payload.SimpleVarDecl,331 .var_simple, .pub_var_simple => Payload.SimpleVarDecl,
328 .enum_redecl => Payload.EnumRedecl,332 .pub_enum_redecl, .enum_redecl => Payload.EnumRedecl,
329 .array_filler => Payload.ArrayFiller,333 .array_filler => Payload.ArrayFiller,
330 .pub_inline_fn => Payload.PubInlineFn,334 .pub_inline_fn => Payload.PubInlineFn,
331 .field_access => Payload.FieldAccess,335 .field_access => Payload.FieldAccess,
...@@ -742,6 +746,7 @@ fn renderNodes(c: *Context, nodes: []const Node) Allocator.Error!NodeSubRange {...@@ -742,6 +746,7 @@ fn renderNodes(c: *Context, nodes: []const Node) Allocator.Error!NodeSubRange {
742746
743fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {747fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
744 switch (node.tag()) {748 switch (node.tag()) {
749 .declaration => unreachable,
745 .warning => {750 .warning => {
746 const payload = node.castTag(.warning).?.data;751 const payload = node.castTag(.warning).?.data;
747 try c.buf.appendSlice(payload);752 try c.buf.appendSlice(payload);
...@@ -1585,9 +1590,9 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1585,9 +1590,9 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1585 },1590 },
1586 });1591 });
1587 },1592 },
1588 .enum_redecl => {1593 .pub_enum_redecl, .enum_redecl => {
1589 const payload = node.castTag(.enum_redecl).?.data;1594 const payload = @fieldParentPtr(Payload.EnumRedecl, "base", node.ptr_otherwise).data;
1590 _ = try c.addToken(.keyword_pub, "pub");1595 if (node.tag() == .pub_enum_redecl) _ = try c.addToken(.keyword_pub, "pub");
1591 const const_tok = try c.addToken(.keyword_const, "const");1596 const const_tok = try c.addToken(.keyword_const, "const");
1592 _ = try c.addIdentifier(payload.enum_val_name);1597 _ = try c.addIdentifier(payload.enum_val_name);
1593 _ = try c.addToken(.equal, "=");1598 _ = try c.addToken(.equal, "=");
...@@ -1878,6 +1883,7 @@ fn addSemicolonIfNotBlock(c: *Context, node: Node) !void {...@@ -1878,6 +1883,7 @@ fn addSemicolonIfNotBlock(c: *Context, node: Node) !void {
18781883
1879fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {1884fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
1880 switch (node.tag()) {1885 switch (node.tag()) {
1886 .declaration => unreachable,
1881 .null_literal,1887 .null_literal,
1882 .undefined_literal,1888 .undefined_literal,
1883 .true_literal,1889 .true_literal,
...@@ -1991,6 +1997,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {...@@ -1991,6 +1997,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
1991 .alias,1997 .alias,
1992 .var_simple,1998 .var_simple,
1993 .pub_var_simple,1999 .pub_var_simple,
2000 .pub_enum_redecl,
1994 .enum_redecl,2001 .enum_redecl,
1995 .@"while",2002 .@"while",
1996 .@"switch",2003 .@"switch",
test/translate_c.zig+157-25
...@@ -3,6 +3,136 @@ const std = @import("std");...@@ -3,6 +3,136 @@ const std = @import("std");
3const CrossTarget = std.zig.CrossTarget;3const CrossTarget = std.zig.CrossTarget;
44
5pub fn addCases(cases: *tests.TranslateCContext) void {5pub fn addCases(cases: *tests.TranslateCContext) void {
6 cases.add("scoped enum",
7 \\void foo() {
8 \\ enum Foo {
9 \\ A,
10 \\ B,
11 \\ C,
12 \\ };
13 \\ enum Foo a = B;
14 \\ {
15 \\ enum Foo {
16 \\ A,
17 \\ B,
18 \\ C,
19 \\ };
20 \\ enum Foo a = B;
21 \\ }
22 \\}
23 , &[_][]const u8{
24 \\pub export fn foo() void {
25 \\ const enum_Foo = extern enum(c_int) {
26 \\ A,
27 \\ B,
28 \\ C,
29 \\ _,
30 \\ };
31 \\ const A = @enumToInt(enum_Foo.A);
32 \\ const B = @enumToInt(enum_Foo.B);
33 \\ const C = @enumToInt(enum_Foo.C);
34 \\ var a: enum_Foo = @intToEnum(enum_Foo, B);
35 \\ {
36 \\ const enum_Foo = extern enum(c_int) {
37 \\ A,
38 \\ B,
39 \\ C,
40 \\ _,
41 \\ };
42 \\ const A_2 = @enumToInt(enum_Foo.A);
43 \\ const B_3 = @enumToInt(enum_Foo.B);
44 \\ const C_4 = @enumToInt(enum_Foo.C);
45 \\ var a_5: enum_Foo = @intToEnum(enum_Foo, B_3);
46 \\ }
47 \\}
48 });
49
50 cases.add("scoped record",
51 \\void foo() {
52 \\ struct Foo {
53 \\ int A;
54 \\ int B;
55 \\ int C;
56 \\ };
57 \\ struct Foo a = {0};
58 \\ {
59 \\ struct Foo {
60 \\ int A;
61 \\ int B;
62 \\ int C;
63 \\ };
64 \\ struct Foo a = {0};
65 \\ }
66 \\}
67 , &[_][]const u8{
68 \\pub export fn foo() void {
69 \\ const struct_Foo = extern struct {
70 \\ A: c_int,
71 \\ B: c_int,
72 \\ C: c_int,
73 \\ };
74 \\ var a: struct_Foo = struct_Foo{
75 \\ .A = @as(c_int, 0),
76 \\ .B = 0,
77 \\ .C = 0,
78 \\ };
79 \\ {
80 \\ const struct_Foo_1 = extern struct {
81 \\ A: c_int,
82 \\ B: c_int,
83 \\ C: c_int,
84 \\ };
85 \\ var a_2: struct_Foo_1 = struct_Foo_1{
86 \\ .A = @as(c_int, 0),
87 \\ .B = 0,
88 \\ .C = 0,
89 \\ };
90 \\ }
91 \\}
92 });
93
94 cases.add("scoped typedef",
95 \\void foo() {
96 \\ typedef union {
97 \\ int A;
98 \\ int B;
99 \\ int C;
100 \\ } Foo;
101 \\ Foo a = {0};
102 \\ {
103 \\ typedef union {
104 \\ int A;
105 \\ int B;
106 \\ int C;
107 \\ } Foo;
108 \\ Foo a = {0};
109 \\ }
110 \\}
111 , &[_][]const u8{
112 \\pub export fn foo() void {
113 \\ const union_unnamed_1 = extern union {
114 \\ A: c_int,
115 \\ B: c_int,
116 \\ C: c_int,
117 \\ };
118 \\ const Foo = union_unnamed_1;
119 \\ var a: Foo = Foo{
120 \\ .A = @as(c_int, 0),
121 \\ };
122 \\ {
123 \\ const union_unnamed_2 = extern union {
124 \\ A: c_int,
125 \\ B: c_int,
126 \\ C: c_int,
127 \\ };
128 \\ const Foo_1 = union_unnamed_2;
129 \\ var a_2: Foo_1 = Foo_1{
130 \\ .A = @as(c_int, 0),
131 \\ };
132 \\ }
133 \\}
134 });
135
6 cases.add("use cast param as macro fn return type",136 cases.add("use cast param as macro fn return type",
7 \\#define MEM_PHYSICAL_TO_K0(x) (void*)((u32)(x) + SYS_BASE_CACHED)137 \\#define MEM_PHYSICAL_TO_K0(x) (void*)((u32)(x) + SYS_BASE_CACHED)
8 , &[_][]const u8{138 , &[_][]const u8{
...@@ -62,7 +192,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -62,7 +192,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
62 \\pub export var bar: f32 = @import("std").mem.zeroes(f32);192 \\pub export var bar: f32 = @import("std").mem.zeroes(f32);
63 \\threadlocal var bar_1: c_int = 2;193 \\threadlocal var bar_1: c_int = 2;
64 \\pub export fn foo() c_int {194 \\pub export fn foo() c_int {
65 \\ _ = bar_1;
66 \\ return 0;195 \\ return 0;
67 \\}196 \\}
68 });197 });
...@@ -579,9 +708,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -579,9 +708,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
579 \\ '2',708 \\ '2',
580 \\ 0,709 \\ 0,
581 \\};710 \\};
582 \\pub export fn foo() void {711 \\pub export fn foo() void {}
583 \\ _ = v2;
584 \\}
585 });712 });
586713
587 cases.add("simple function definition",714 cases.add("simple function definition",
...@@ -1355,11 +1482,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1355,11 +1482,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1355 \\extern enum enum_ty my_enum;1482 \\extern enum enum_ty my_enum;
1356 \\enum enum_ty { FOO };1483 \\enum enum_ty { FOO };
1357 , &[_][]const u8{1484 , &[_][]const u8{
1358 \\pub const FOO = @enumToInt(enum_enum_ty.FOO);
1359 \\pub const enum_enum_ty = extern enum(c_int) {1485 \\pub const enum_enum_ty = extern enum(c_int) {
1360 \\ FOO,1486 \\ FOO,
1361 \\ _,1487 \\ _,
1362 \\};1488 \\};
1489 \\pub const FOO = @enumToInt(enum_enum_ty.FOO);
1363 \\pub extern var my_enum: enum_enum_ty;1490 \\pub extern var my_enum: enum_enum_ty;
1364 });1491 });
13651492
...@@ -1501,48 +1628,48 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1501,48 +1628,48 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1501 \\ p,1628 \\ p,
1502 \\};1629 \\};
1503 , &[_][]const u8{1630 , &[_][]const u8{
1504 \\pub const a = @enumToInt(enum_unnamed_1.a);
1505 \\pub const b = @enumToInt(enum_unnamed_1.b);
1506 \\pub const c = @enumToInt(enum_unnamed_1.c);
1507 \\const enum_unnamed_1 = extern enum(c_int) {1631 \\const enum_unnamed_1 = extern enum(c_int) {
1508 \\ a,1632 \\ a,
1509 \\ b,1633 \\ b,
1510 \\ c,1634 \\ c,
1511 \\ _,1635 \\ _,
1512 \\};1636 \\};
1637 \\pub const a = @enumToInt(enum_unnamed_1.a);
1638 \\pub const b = @enumToInt(enum_unnamed_1.b);
1639 \\pub const c = @enumToInt(enum_unnamed_1.c);
1513 \\pub const d = enum_unnamed_1;1640 \\pub const d = enum_unnamed_1;
1514 \\pub const e = @enumToInt(enum_unnamed_2.e);
1515 \\pub const f = @enumToInt(enum_unnamed_2.f);
1516 \\pub const g = @enumToInt(enum_unnamed_2.g);
1517 \\const enum_unnamed_2 = extern enum(c_int) {1641 \\const enum_unnamed_2 = extern enum(c_int) {
1518 \\ e = 0,1642 \\ e = 0,
1519 \\ f = 4,1643 \\ f = 4,
1520 \\ g = 5,1644 \\ g = 5,
1521 \\ _,1645 \\ _,
1522 \\};1646 \\};
1647 \\pub const e = @enumToInt(enum_unnamed_2.e);
1648 \\pub const f = @enumToInt(enum_unnamed_2.f);
1649 \\pub const g = @enumToInt(enum_unnamed_2.g);
1523 \\pub export var h: enum_unnamed_2 = @intToEnum(enum_unnamed_2, e);1650 \\pub export var h: enum_unnamed_2 = @intToEnum(enum_unnamed_2, e);
1524 \\pub const i = @enumToInt(enum_unnamed_3.i);
1525 \\pub const j = @enumToInt(enum_unnamed_3.j);
1526 \\pub const k = @enumToInt(enum_unnamed_3.k);
1527 \\const enum_unnamed_3 = extern enum(c_int) {1651 \\const enum_unnamed_3 = extern enum(c_int) {
1528 \\ i,1652 \\ i,
1529 \\ j,1653 \\ j,
1530 \\ k,1654 \\ k,
1531 \\ _,1655 \\ _,
1532 \\};1656 \\};
1657 \\pub const i = @enumToInt(enum_unnamed_3.i);
1658 \\pub const j = @enumToInt(enum_unnamed_3.j);
1659 \\pub const k = @enumToInt(enum_unnamed_3.k);
1533 \\pub const struct_Baz = extern struct {1660 \\pub const struct_Baz = extern struct {
1534 \\ l: enum_unnamed_3,1661 \\ l: enum_unnamed_3,
1535 \\ m: d,1662 \\ m: d,
1536 \\};1663 \\};
1537 \\pub const n = @enumToInt(enum_i.n);
1538 \\pub const o = @enumToInt(enum_i.o);
1539 \\pub const p = @enumToInt(enum_i.p);
1540 \\pub const enum_i = extern enum(c_int) {1664 \\pub const enum_i = extern enum(c_int) {
1541 \\ n,1665 \\ n,
1542 \\ o,1666 \\ o,
1543 \\ p,1667 \\ p,
1544 \\ _,1668 \\ _,
1545 \\};1669 \\};
1670 \\pub const n = @enumToInt(enum_i.n);
1671 \\pub const o = @enumToInt(enum_i.o);
1672 \\pub const p = @enumToInt(enum_i.p);
1546 ,1673 ,
1547 \\pub const Baz = struct_Baz;1674 \\pub const Baz = struct_Baz;
1548 });1675 });
...@@ -1989,13 +2116,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1989,13 +2116,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1989 \\ Two,2116 \\ Two,
1990 \\};2117 \\};
1991 , &[_][]const u8{2118 , &[_][]const u8{
1992 \\pub const One = @enumToInt(enum_unnamed_1.One);
1993 \\pub const Two = @enumToInt(enum_unnamed_1.Two);
1994 \\const enum_unnamed_1 = extern enum(c_int) {2119 \\const enum_unnamed_1 = extern enum(c_int) {
1995 \\ One,2120 \\ One,
1996 \\ Two,2121 \\ Two,
1997 \\ _,2122 \\ _,
1998 \\};2123 \\};
2124 \\pub const One = @enumToInt(enum_unnamed_1.One);
2125 \\pub const Two = @enumToInt(enum_unnamed_1.Two);
1999 });2126 });
20002127
2001 cases.add("c style cast",2128 cases.add("c style cast",
...@@ -2093,15 +2220,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2093,15 +2220,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2093 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);2220 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
2094 \\}2221 \\}
2095 , &[_][]const u8{2222 , &[_][]const u8{
2096 \\pub const FooA = @enumToInt(enum_Foo.A);
2097 \\pub const FooB = @enumToInt(enum_Foo.B);
2098 \\pub const FooC = @enumToInt(enum_Foo.C);
2099 \\pub const enum_Foo = extern enum(c_int) {2223 \\pub const enum_Foo = extern enum(c_int) {
2100 \\ A,2224 \\ A,
2101 \\ B,2225 \\ B,
2102 \\ C,2226 \\ C,
2103 \\ _,2227 \\ _,
2104 \\};2228 \\};
2229 \\pub const FooA = @enumToInt(enum_Foo.A);
2230 \\pub const FooB = @enumToInt(enum_Foo.B);
2231 \\pub const FooC = @enumToInt(enum_Foo.C);
2105 \\pub const SomeTypedef = c_int;2232 \\pub const SomeTypedef = c_int;
2106 \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {2233 \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
2107 \\ var a = arg_a;2234 \\ var a = arg_a;
...@@ -2147,6 +2274,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2147,6 +2274,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2147 \\ B,2274 \\ B,
2148 \\ _,2275 \\ _,
2149 \\};2276 \\};
2277 \\pub const BarA = @enumToInt(enum_Bar.A);
2278 \\pub const BarB = @enumToInt(enum_Bar.B);
2150 \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;2279 \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
2151 ,2280 ,
2152 \\pub const Foo = struct_Foo;2281 \\pub const Foo = struct_Foo;
...@@ -2413,6 +2542,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2413,6 +2542,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2413 \\ C,2542 \\ C,
2414 \\ _,2543 \\ _,
2415 \\};2544 \\};
2545 \\pub const A = @enumToInt(enum_SomeEnum.A);
2546 \\pub const B = @enumToInt(enum_SomeEnum.B);
2547 \\pub const C = @enumToInt(enum_SomeEnum.C);
2416 \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {2548 \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
2417 \\ var a = arg_a;2549 \\ var a = arg_a;
2418 \\ var b = arg_b;2550 \\ var b = arg_b;
...@@ -2872,15 +3004,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2872,15 +3004,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2872 \\ Foo1,3004 \\ Foo1,
2873 \\};3005 \\};
2874 , &[_][]const u8{3006 , &[_][]const u8{
2875 \\pub const FooA = @enumToInt(enum_Foo.A);
2876 \\pub const FooB = @enumToInt(enum_Foo.B);
2877 \\pub const Foo1 = @enumToInt(enum_Foo.@"1");
2878 \\pub const enum_Foo = extern enum(c_int) {3007 \\pub const enum_Foo = extern enum(c_int) {
2879 \\ A = 2,3008 \\ A = 2,
2880 \\ B = 5,3009 \\ B = 5,
2881 \\ @"1" = 6,3010 \\ @"1" = 6,
2882 \\ _,3011 \\ _,
2883 \\};3012 \\};
3013 \\pub const FooA = @enumToInt(enum_Foo.A);
3014 \\pub const FooB = @enumToInt(enum_Foo.B);
3015 \\pub const Foo1 = @enumToInt(enum_Foo.@"1");
2884 ,3016 ,
2885 \\pub const Foo = enum_Foo;3017 \\pub const Foo = enum_Foo;
2886 });3018 });