| ... | @@ -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 | } |
| 624 | | 624 | |
| 625 | fn transQualTypeMaybeInitialized(c: *Context, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!Node { | 625 | fn 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 | else | 628 | else |
| 629 | transQualType(c, qt, loc); | 629 | transQualType(c, scope, qt, loc); |
| 630 | } | 630 | } |
| 631 | | 631 | |
| 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; |
| 660 | | 660 | |
| 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 | } |
| 735 | | 735 | |
| 736 | fn 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 | | | |
| 741 | const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{ | 736 | const 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 | }); |
| 755 | | 750 | |
| 756 | fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?Node { | 751 | fn 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 twice | 753 | 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; |
| 759 | | 756 | |
| 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()); |
| 761 | | 758 | |
| 762 | // TODO https://github.com/ziglang/zig/issues/3756 | 759 | // TODO https://github.com/ziglang/zig/issues/3756 |
| 763 | // TODO https://github.com/ziglang/zig/issues/1802 | 760 | // 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); |
| 769 | | 767 | |
| 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 | | | |
| 780 | fn 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 | } |
| 806 | | 793 | |
| 807 | fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Node { | 794 | fn 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 twice | 796 | 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; |
| 811 | | 800 | |
| 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 | } |
| 832 | | 821 | |
| 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); |
| 835 | | 825 | |
| 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 |
| 854 | | 844 | |
| 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 | } |
| 860 | | 850 | |
| 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 | } |
| 866 | | 856 | |
| ... | @@ -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 | }; |
| 892 | | 882 | |
| 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 | } |
| 896 | | 886 | |
| 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 | }; |
| 923 | | 913 | |
| 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 | } |
| 929 | | 922 | |
| 930 | fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node { | 923 | fn 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 twice | 925 | 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; |
| 934 | | 929 | |
| 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 | } |
| 941 | | 936 | |
| 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); |
| 944 | | 940 | |
| 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(); |
| 946 | | 944 | |
| 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 and | 966 | const init_arg_expr = if (int_type.ptr != null and |
| 969 | !isCBuiltinType(int_type, .UInt) and | 967 | !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 { |
| 1001 | | 998 | |
| 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 | } |
| 1010 | | 1007 | |
| 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 | }; |
| 1028 | | 1025 | |
| 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 | } |
| 1034 | | 1046 | |
| 1035 | const ResultUsed = enum { | 1047 | const 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(); |
| 1309 | | 1321 | |
| 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); |
| 1312 | | 1324 | |
| 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 | }, |
| 1339 | | 1352 | .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 | }, |
| 1342 | | 1355 | .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 | } |
| 1357 | | 1367 | |
| 1358 | fn transDeclStmt(c: *Context, scope: *Scope, stmt: *const clang.DeclStmt) TransError!Node { | 1368 | fn 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); |
| 1360 | | 1370 | |
| 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 | } |
| 1375 | | 1378 | |
| 1376 | fn transDeclRefExpr( | 1379 | fn transDeclRefExpr( |
| ... | @@ -1619,7 +1622,7 @@ fn transIntegerLiteral( | ... | @@ -1619,7 +1622,7 @@ fn transIntegerLiteral( |
| 1619 | | 1622 | |
| 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); |
| 1699 | | 1702 | |
| 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); |
| 1703 | | 1706 | |
| ... | @@ -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); |
| 1748 | | 1751 | |
| 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 type | 1754 | // 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() orelse | 1906 | const record_def = record_decl.getDefinition() orelse |
| 1904 | unreachable; | 1907 | unreachable; |
| 1905 | | 1908 | |
| 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"); |
| 2334 | | 2337 | |
| ... | @@ -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"); |
| 2372 | | 2375 | |
| ... | @@ -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); |
| 2661 | | 2665 | |
| 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 | else | 2925 | else |
| 2922 | try transQualType(c, getExprQualType(c, lhs), loc); | 2926 | try transQualType(c, scope, getExprQualType(c, lhs), loc); |
| 2923 | | 2927 | |
| 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 | else | 2968 | else |
| 2965 | try transQualType(c, getExprQualType(c, lhs), loc); | 2969 | try transQualType(c, scope, getExprQualType(c, lhs), loc); |
| 2966 | | 2970 | |
| 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( |
| 2981 | | 2985 | |
| 2982 | fn transCPtrCast( | 2986 | fn 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); |
| 2994 | | 2999 | |
| 2995 | if ((src_child_type.isConstQualified() and | 3000 | if ((src_child_type.isConstQualified() and |
| 2996 | !child_type.isConstQualified()) or | 3001 | !child_type.isConstQualified()) or |
| ... | @@ -3011,7 +3016,7 @@ fn transCPtrCast( | ... | @@ -3011,7 +3016,7 @@ fn transCPtrCast( |
| 3011 | // For opaque types a ptrCast is enough | 3016 | // For opaque types a ptrCast is enough |
| 3012 | expr | 3017 | 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 initializer | 3165 | /// by the size of the initializer |
| 3161 | fn transQualTypeInitialized( | 3166 | fn 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); |
| 3171 | | 3177 | |
| 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 | } |
| 3189 | | 3195 | |
| 3190 | fn transQualType(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) TypeError!Node { | 3196 | fn 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 | } |
| 3193 | | 3199 | |
| 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 | } |
| 3275 | | 3281 | |
| 3276 | fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) !Node { | 3282 | fn 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); |
| 3278 | | 3284 | |
| 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 | } |
| 3284 | | 3290 | |
| 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 | } |
| 3288 | | 3294 | |
| ... | @@ -3641,14 +3647,14 @@ fn transCreateNodeShiftOp( | ... | @@ -3641,14 +3647,14 @@ fn transCreateNodeShiftOp( |
| 3641 | | 3647 | |
| 3642 | const lhs = try transExpr(c, scope, lhs_expr, .used); | 3648 | const lhs = try transExpr(c, scope, lhs_expr, .used); |
| 3643 | | 3649 | |
| 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 }); |
| 3647 | | 3653 | |
| 3648 | return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used); | 3654 | return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used); |
| 3649 | } | 3655 | } |
| 3650 | | 3656 | |
| 3651 | fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node { | 3657 | fn 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 |
| 3709 | | 3715 | |
| 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); |
| 3713 | | 3719 | |
| 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); |
| 3723 | | 3729 | |
| 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); |
| 3728 | | 3734 | |
| 3729 | const typedef_decl = typedef_ty.getDecl(); | 3735 | const typedef_decl = typedef_ty.getDecl(); |
| 3730 | return (try transTypeDef(c, typedef_decl, false)) orelse | 3736 | 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); |
| 3735 | | 3742 | |
| 3736 | const record_decl = record_ty.getDecl(); | 3743 | const record_decl = record_ty.getDecl(); |
| 3737 | return (try transRecordDecl(c, record_decl)) orelse | 3744 | 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); |
| 3742 | | 3750 | |
| 3743 | const enum_decl = enum_ty.getDecl(); | 3751 | const enum_decl = enum_ty.getDecl(); |
| 3744 | return (try transEnumDecl(c, enum_decl)) orelse | 3752 | 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; |
| 3893 | | 3903 | |
| 3894 | // TODO check for always_inline attribute | 3904 | // TODO check for always_inline attribute |
| 3895 | // TODO check for align attribute | 3905 | // TODO check for align attribute |
| ... | @@ -3914,7 +3924,7 @@ fn finishTransFnProto( | ... | @@ -3914,7 +3924,7 @@ fn finishTransFnProto( |
| 3914 | | 3924 | |
| 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); |
| 3918 | | 3928 | |
| 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, |