| ... | ... | @@ -433,13 +433,13 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void { |
| 433 | 433 | return visitFnDecl(c, @ptrCast(*const clang.FunctionDecl, decl)); |
| 434 | 434 | }, |
| 435 | 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 | 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 | 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 | 444 | .Var => { |
| 445 | 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 | 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 | 626 | return if (decl_init) |init_expr| |
| 627 | | transQualTypeInitialized(c, qt, init_expr, loc) |
| 627 | transQualTypeInitialized(c, scope, qt, init_expr, loc) |
| 628 | 628 | else |
| 629 | | transQualType(c, qt, loc); |
| 629 | transQualType(c, scope, qt, loc); |
| 630 | 630 | } |
| 631 | 631 | |
| 632 | 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 | 658 | var is_extern = storage_class == .Extern and !has_init; |
| 659 | 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 | 662 | error.UnsupportedTranslation, error.UnsupportedType => { |
| 663 | 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 | 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 | 736 | const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{ |
| 742 | 737 | .{ "uint8_t", "u8" }, |
| 743 | 738 | .{ "int8_t", "i8" }, |
| ... | ... | @@ -753,42 +748,28 @@ const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{ |
| 753 | 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 | 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 | 759 | // TODO https://github.com/ziglang/zig/issues/3756 |
| 763 | 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; |
| 765 | | if (builtin_typedef_map.get(checked_name)) |builtin| { |
| 766 | | _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin); |
| 767 | | return try Tag.identifier.create(c.arena, builtin); |
| 761 | var name: []const u8 = if (isZigPrimitiveType(bare_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ bare_name, c.getMangle() }) else bare_name; |
| 762 | if (builtin_typedef_map.get(name)) |builtin| { |
| 763 | return c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), 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 | 768 | const child_qt = typedef_decl.getUnderlyingType(); |
| 787 | 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 | 771 | error.UnsupportedType => { |
| 790 | | try failDecl(c, typedef_loc, checked_name, "unable to resolve typedef child type", .{}); |
| 791 | | return null; |
| 772 | return failDecl(c, typedef_loc, name, "unable to resolve typedef child type", .{}); |
| 792 | 773 | }, |
| 793 | 774 | error.OutOfMemory => |e| return e, |
| 794 | 775 | }; |
| ... | ... | @@ -797,17 +778,25 @@ fn transCreateNodeTypedef( |
| 797 | 778 | payload.* = .{ |
| 798 | 779 | .base = .{ .tag = ([2]Tag{ .var_simple, .pub_var_simple })[@boolToInt(toplevel)] }, |
| 799 | 780 | .data = .{ |
| 800 | | .name = checked_name, |
| 781 | .name = name, |
| 801 | 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 | 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 | 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 | 801 | var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, record_decl).getName_bytes_begin()); |
| 813 | 802 | var is_unnamed = false; |
| ... | ... | @@ -826,14 +815,15 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod |
| 826 | 815 | } else if (record_decl.isStruct()) { |
| 827 | 816 | container_kind_name = "struct"; |
| 828 | 817 | } else { |
| 829 | | try warn(c, &c.global_scope.base, record_loc, "record {s} is not a struct or union", .{bare_name}); |
| 830 | | return null; |
| 818 | try c.decl_table.putNoClobber(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), bare_name); |
| 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 }); |
| 834 | | _ = try c.decl_table.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), name); |
| 822 | var name: []const u8 = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ container_kind_name, bare_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 | 827 | const init_node = blk: { |
| 838 | 828 | const record_def = record_decl.getDefinition() orelse { |
| 839 | 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 | 844 | |
| 855 | 845 | if (field_decl.isBitField()) { |
| 856 | 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 | 848 | break :blk Tag.opaque_literal.init(); |
| 859 | 849 | } |
| 860 | 850 | |
| 861 | 851 | if (qualTypeCanon(field_qt).isIncompleteOrZeroLengthArrayType(c.clang_context)) { |
| 862 | 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 | 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 | 862 | unnamed_field_count += 1; |
| 873 | 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 | 866 | error.UnsupportedType => { |
| 877 | 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 | 869 | break :blk Tag.opaque_literal.init(); |
| 880 | 870 | }, |
| 881 | 871 | else => |e| return e, |
| ... | ... | @@ -891,7 +881,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod |
| 891 | 881 | }; |
| 892 | 882 | |
| 893 | 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 | 887 | try fields.append(.{ |
| ... | ... | @@ -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)); |
| 925 | | if (!is_unnamed) |
| 926 | | try c.alias_list.append(.{ .alias = bare_name, .name = name }); |
| 927 | | return try Tag.identifier.create(c.arena, name); |
| 914 | if (toplevel) { |
| 915 | try addTopLevelDecl(c, name, Node.initPayload(&payload.base)); |
| 916 | if (!is_unnamed) |
| 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 | 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 | 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 | 930 | var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_decl).getName_bytes_begin()); |
| 936 | 931 | var is_unnamed = false; |
| ... | ... | @@ -939,10 +934,13 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node { |
| 939 | 934 | is_unnamed = true; |
| 940 | 935 | } |
| 941 | 936 | |
| 942 | | const name = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name}); |
| 943 | | _ = try c.decl_table.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name); |
| 937 | var name: []const u8 = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_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 | 945 | const init_node = if (enum_decl.getDefinition()) |enum_def| blk: { |
| 948 | 946 | var pure_enum = true; |
| ... | ... | @@ -968,10 +966,9 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node { |
| 968 | 966 | const init_arg_expr = if (int_type.ptr != null and |
| 969 | 967 | !isCBuiltinType(int_type, .UInt) and |
| 970 | 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 | 970 | error.UnsupportedType => { |
| 973 | | try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{}); |
| 974 | | return null; |
| 971 | return failDecl(c, enum_loc, name, "unable to translate enum tag type", .{}); |
| 975 | 972 | }, |
| 976 | 973 | else => |e| return e, |
| 977 | 974 | } |
| ... | ... | @@ -1001,11 +998,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node { |
| 1001 | 998 | |
| 1002 | 999 | // In C each enum value is in the global namespace. So we put them there too. |
| 1003 | 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 | 1002 | .enum_val_name = enum_val_name, |
| 1006 | 1003 | .field_name = field_name, |
| 1007 | 1004 | .enum_name = name, |
| 1008 | | })); |
| 1005 | }); |
| 1009 | 1006 | } |
| 1010 | 1007 | |
| 1011 | 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 | 1023 | }, |
| 1027 | 1024 | }; |
| 1028 | 1025 | |
| 1029 | | try addTopLevelDecl(c, name, Node.initPayload(&payload.base)); |
| 1030 | | if (!is_unnamed) |
| 1031 | | try c.alias_list.append(.{ .alias = bare_name, .name = name }); |
| 1032 | | return try Tag.identifier.create(c.arena, name); |
| 1026 | if (toplevel) { |
| 1027 | try addTopLevelDecl(c, name, Node.initPayload(&payload.base)); |
| 1028 | if (!is_unnamed) |
| 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 | 1047 | const ResultUsed = enum { |
| ... | ... | @@ -1251,6 +1263,7 @@ fn transCompoundStmtInline( |
| 1251 | 1263 | const end_it = stmt.body_end(); |
| 1252 | 1264 | while (it != end_it) : (it += 1) { |
| 1253 | 1265 | const result = try transStmt(c, parent_scope, it[0], .unused); |
| 1266 | if (result.tag() == .declaration) continue; |
| 1254 | 1267 | try block.statements.append(result); |
| 1255 | 1268 | } |
| 1256 | 1269 | } |
| ... | ... | @@ -1285,7 +1298,7 @@ fn transDeclStmtOne( |
| 1285 | 1298 | scope: *Scope, |
| 1286 | 1299 | decl: *const clang.Decl, |
| 1287 | 1300 | block_scope: *Scope.Block, |
| 1288 | | ) TransError!Node { |
| 1301 | ) TransError!void { |
| 1289 | 1302 | switch (decl.getKind()) { |
| 1290 | 1303 | .Var => { |
| 1291 | 1304 | const var_decl = @ptrCast(*const clang.VarDecl, decl); |
| ... | ... | @@ -1299,8 +1312,7 @@ fn transDeclStmtOne( |
| 1299 | 1312 | .Extern, .Static => { |
| 1300 | 1313 | // This is actually a global variable, put it in the global scope and reference it. |
| 1301 | 1314 | // `_ = mangled_name;` |
| 1302 | | try visitVarDecl(c, var_decl, mangled_name); |
| 1303 | | return try maybeSuppressResult(c, scope, .unused, try Tag.identifier.create(c.arena, mangled_name)); |
| 1315 | return visitVarDecl(c, var_decl, mangled_name); |
| 1304 | 1316 | }, |
| 1305 | 1317 | else => {}, |
| 1306 | 1318 | } |
| ... | ... | @@ -1308,7 +1320,7 @@ fn transDeclStmtOne( |
| 1308 | 1320 | const is_const = qual_type.isConstQualified(); |
| 1309 | 1321 | |
| 1310 | 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 | 1325 | var init_node = if (decl_init) |expr| |
| 1314 | 1326 | if (expr.getStmtClass() == .StringLiteralClass) |
| ... | ... | @@ -1320,7 +1332,7 @@ fn transDeclStmtOne( |
| 1320 | 1332 | if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) { |
| 1321 | 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 | 1336 | .is_pub = false, |
| 1325 | 1337 | .is_const = is_const, |
| 1326 | 1338 | .is_extern = false, |
| ... | ... | @@ -1332,18 +1344,16 @@ fn transDeclStmtOne( |
| 1332 | 1344 | .type = type_node, |
| 1333 | 1345 | .init = init_node, |
| 1334 | 1346 | }); |
| 1347 | try block_scope.statements.append(node); |
| 1335 | 1348 | }, |
| 1336 | 1349 | .Typedef => { |
| 1337 | | const typedef_decl = @ptrCast(*const clang.TypedefNameDecl, decl); |
| 1338 | | const name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin()); |
| 1339 | | |
| 1340 | | const underlying_qual = typedef_decl.getUnderlyingType(); |
| 1341 | | const underlying_type = underlying_qual.getTypePtr(); |
| 1342 | | |
| 1343 | | const mangled_name = try block_scope.makeMangledName(c, name); |
| 1344 | | const node = (try transCreateNodeTypedef(c, typedef_decl, false, mangled_name)) orelse |
| 1345 | | return error.UnsupportedTranslation; |
| 1346 | | return node; |
| 1350 | try transTypeDef(c, scope, @ptrCast(*const clang.TypedefNameDecl, decl)); |
| 1351 | }, |
| 1352 | .Record => { |
| 1353 | try transRecordDecl(c, scope, @ptrCast(*const clang.RecordDecl, decl)); |
| 1354 | }, |
| 1355 | .Enum => { |
| 1356 | try transEnumDecl(c, scope, @ptrCast(*const clang.EnumDecl, decl)); |
| 1347 | 1357 | }, |
| 1348 | 1358 | else => |kind| return fail( |
| 1349 | 1359 | c, |
| ... | ... | @@ -1356,21 +1366,14 @@ fn transDeclStmtOne( |
| 1356 | 1366 | } |
| 1357 | 1367 | |
| 1358 | 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 | 1371 | var it = stmt.decl_begin(); |
| 1362 | 1372 | const end_it = stmt.decl_end(); |
| 1363 | | assert(it != end_it); |
| 1364 | | while (true) : (it += 1) { |
| 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 | | } |
| 1373 | while (it != end_it) : (it += 1) { |
| 1374 | try transDeclStmtOne(c, scope, it[0], block_scope); |
| 1372 | 1375 | } |
| 1373 | | unreachable; |
| 1376 | return Tag.declaration.init(); |
| 1374 | 1377 | } |
| 1375 | 1378 | |
| 1376 | 1379 | fn transDeclRefExpr( |
| ... | ... | @@ -1619,7 +1622,7 @@ fn transIntegerLiteral( |
| 1619 | 1622 | |
| 1620 | 1623 | // @as(T, x) |
| 1621 | 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 | 1626 | const rhs = try transCreateNodeAPInt(c, eval_result.Val.getInt()); |
| 1624 | 1627 | const as = try Tag.as.create(c.arena, .{ .lhs = ty_node, .rhs = rhs }); |
| 1625 | 1628 | return maybeSuppressResult(c, scope, result_used, as); |
| ... | ... | @@ -1697,7 +1700,7 @@ fn transStringLiteralAsArray( |
| 1697 | 1700 | const ty = expr_base.getType().getTypePtr(); |
| 1698 | 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 | 1704 | const arr_type = try Tag.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_type }); |
| 1702 | 1705 | const init_list = try c.arena.alloc(Node, array_size); |
| 1703 | 1706 | |
| ... | ... | @@ -1744,9 +1747,9 @@ fn transCCast( |
| 1744 | 1747 | if (qualTypeCanon(dst_type).isVoidType()) return expr; |
| 1745 | 1748 | if (dst_type.eq(src_type)) return expr; |
| 1746 | 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 | 1753 | if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) { |
| 1751 | 1754 | // 1. If src_type is an enum, determine the underlying signed int type |
| 1752 | 1755 | // 2. Extend or truncate without changing signed-ness. |
| ... | ... | @@ -1903,7 +1906,7 @@ fn transInitListExprRecord( |
| 1903 | 1906 | const record_def = record_decl.getDefinition() orelse |
| 1904 | 1907 | unreachable; |
| 1905 | 1908 | |
| 1906 | | const ty_node = try transType(c, ty, loc); |
| 1909 | const ty_node = try transType(c, scope, ty, loc); |
| 1907 | 1910 | const init_count = expr.getNumInits(); |
| 1908 | 1911 | var field_inits = std.ArrayList(ast.Payload.ContainerInit.Initializer).init(c.gpa); |
| 1909 | 1912 | defer field_inits.deinit(); |
| ... | ... | @@ -1952,7 +1955,7 @@ fn transInitListExprArray( |
| 1952 | 1955 | ) TransError!Node { |
| 1953 | 1956 | const arr_type = ty.getAsArrayTypeUnsafe(); |
| 1954 | 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 | 1959 | const init_count = expr.getNumInits(); |
| 1957 | 1960 | assert(@ptrCast(*const clang.Type, arr_type).isConstantArrayType()); |
| 1958 | 1961 | const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, arr_type); |
| ... | ... | @@ -2217,7 +2220,7 @@ fn transForLoop( |
| 2217 | 2220 | block_scope = try Scope.Block.init(c, scope, false); |
| 2218 | 2221 | loop_scope.parent = &block_scope.?.base; |
| 2219 | 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 | 2225 | var cond_scope = Scope.Condition{ |
| 2223 | 2226 | .base = .{ |
| ... | ... | @@ -2328,7 +2331,7 @@ fn transCase( |
| 2328 | 2331 | scope: *Scope, |
| 2329 | 2332 | stmt: *const clang.CaseStmt, |
| 2330 | 2333 | ) TransError!Node { |
| 2331 | | const block_scope = scope.findBlockScope(c) catch unreachable; |
| 2334 | const block_scope = try scope.findBlockScope(c); |
| 2332 | 2335 | const switch_scope = scope.getSwitch(); |
| 2333 | 2336 | const label = try block_scope.makeMangledName(c, "case"); |
| 2334 | 2337 | |
| ... | ... | @@ -2366,7 +2369,7 @@ fn transDefault( |
| 2366 | 2369 | scope: *Scope, |
| 2367 | 2370 | stmt: *const clang.DefaultStmt, |
| 2368 | 2371 | ) TransError!Node { |
| 2369 | | const block_scope = scope.findBlockScope(c) catch unreachable; |
| 2372 | const block_scope = try scope.findBlockScope(c); |
| 2370 | 2373 | const switch_scope = scope.getSwitch(); |
| 2371 | 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 | 2403 | // @as(T, x) |
| 2401 | 2404 | const expr_base = @ptrCast(*const clang.Expr, expr); |
| 2402 | 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 | 2407 | .rhs = try transCreateNodeAPInt(c, result.Val.getInt()), |
| 2405 | 2408 | }); |
| 2406 | 2409 | return maybeSuppressResult(c, scope, used, as_node); |
| ... | ... | @@ -2446,7 +2449,7 @@ fn transCharLiteral( |
| 2446 | 2449 | // @as(T, x) |
| 2447 | 2450 | const expr_base = @ptrCast(*const clang.Expr, stmt); |
| 2448 | 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 | 2453 | .rhs = int_lit_node, |
| 2451 | 2454 | }); |
| 2452 | 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 | 2467 | const end_it = comp.body_end(); |
| 2465 | 2468 | while (it != end_it - 1) : (it += 1) { |
| 2466 | 2469 | const result = try transStmt(c, &block_scope.base, it[0], .unused); |
| 2470 | if (result.tag() == .declaration) continue; |
| 2467 | 2471 | try block_scope.statements.append(result); |
| 2468 | 2472 | } |
| 2469 | 2473 | const break_node = try Tag.break_val.create(c.arena, .{ |
| ... | ... | @@ -2657,7 +2661,7 @@ fn transUnaryExprOrTypeTraitExpr( |
| 2657 | 2661 | result_used: ResultUsed, |
| 2658 | 2662 | ) TransError!Node { |
| 2659 | 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 | 2666 | const kind = stmt.getKind(); |
| 2663 | 2667 | switch (kind) { |
| ... | ... | @@ -2917,9 +2921,9 @@ fn transCreateCompoundAssign( |
| 2917 | 2921 | if (is_shift or requires_int_cast) { |
| 2918 | 2922 | // @intCast(rhs) |
| 2919 | 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 | 2925 | else |
| 2922 | | try transQualType(c, getExprQualType(c, lhs), loc); |
| 2926 | try transQualType(c, scope, getExprQualType(c, lhs), loc); |
| 2923 | 2927 | |
| 2924 | 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 | 2964 | if (is_shift or requires_int_cast) { |
| 2961 | 2965 | // @intCast(rhs) |
| 2962 | 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 | 2968 | else |
| 2965 | | try transQualType(c, getExprQualType(c, lhs), loc); |
| 2969 | try transQualType(c, scope, getExprQualType(c, lhs), loc); |
| 2966 | 2970 | |
| 2967 | 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 | 2985 | |
| 2982 | 2986 | fn transCPtrCast( |
| 2983 | 2987 | c: *Context, |
| 2988 | scope: *Scope, |
| 2984 | 2989 | loc: clang.SourceLocation, |
| 2985 | 2990 | dst_type: clang.QualType, |
| 2986 | 2991 | src_type: clang.QualType, |
| ... | ... | @@ -2990,7 +2995,7 @@ fn transCPtrCast( |
| 2990 | 2995 | const child_type = ty.getPointeeType(); |
| 2991 | 2996 | const src_ty = src_type.getTypePtr(); |
| 2992 | 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 | 3000 | if ((src_child_type.isConstQualified() and |
| 2996 | 3001 | !child_type.isConstQualified()) or |
| ... | ... | @@ -3011,7 +3016,7 @@ fn transCPtrCast( |
| 3011 | 3016 | // For opaque types a ptrCast is enough |
| 3012 | 3017 | expr |
| 3013 | 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 | 3020 | const alignof = try Tag.alignof.create(c.arena, child_type_node); |
| 3016 | 3021 | const align_cast = try Tag.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr }); |
| 3017 | 3022 | break :blk align_cast; |
| ... | ... | @@ -3160,6 +3165,7 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void { |
| 3160 | 3165 | /// by the size of the initializer |
| 3161 | 3166 | fn transQualTypeInitialized( |
| 3162 | 3167 | c: *Context, |
| 3168 | scope: *Scope, |
| 3163 | 3169 | qt: clang.QualType, |
| 3164 | 3170 | decl_init: *const clang.Expr, |
| 3165 | 3171 | source_loc: clang.SourceLocation, |
| ... | ... | @@ -3167,7 +3173,7 @@ fn transQualTypeInitialized( |
| 3167 | 3173 | const ty = qt.getTypePtr(); |
| 3168 | 3174 | if (ty.getTypeClass() == .IncompleteArray) { |
| 3169 | 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 | 3178 | switch (decl_init.getStmtClass()) { |
| 3173 | 3179 | .StringLiteralClass => { |
| ... | ... | @@ -3184,11 +3190,11 @@ fn transQualTypeInitialized( |
| 3184 | 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 { |
| 3191 | | return transType(c, qt.getTypePtr(), source_loc); |
| 3196 | fn transQualType(c: *Context, scope: *Scope, qt: clang.QualType, source_loc: clang.SourceLocation) TypeError!Node { |
| 3197 | return transType(c, scope, qt.getTypePtr(), source_loc); |
| 3192 | 3198 | } |
| 3193 | 3199 | |
| 3194 | 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 | 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 | 3283 | const int_bit_width = try qualTypeIntBitWidth(c, qt); |
| 3278 | 3284 | |
| 3279 | 3285 | if (int_bit_width != 0) { |
| ... | ... | @@ -3282,7 +3288,7 @@ fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.Sourc |
| 3282 | 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 | 3292 | return Tag.std_math_Log2Int.create(c.arena, zig_type); |
| 3287 | 3293 | } |
| 3288 | 3294 | |
| ... | ... | @@ -3641,14 +3647,14 @@ fn transCreateNodeShiftOp( |
| 3641 | 3647 | |
| 3642 | 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 | 3651 | const rhs = try transExprCoercing(c, scope, rhs_expr, .used); |
| 3646 | 3652 | const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs }); |
| 3647 | 3653 | |
| 3648 | 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 | 3658 | switch (ty.getTypeClass()) { |
| 3653 | 3659 | .Builtin => { |
| 3654 | 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 | 3693 | }, |
| 3688 | 3694 | .Paren => { |
| 3689 | 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 | 3698 | .Pointer => { |
| 3693 | 3699 | const child_qt = ty.getPointeeType(); |
| 3694 | 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 | 3703 | const is_const = child_qt.isConstQualified(); |
| 3698 | 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 | 3706 | if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) { |
| 3701 | 3707 | const ptr = try Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type }); |
| 3702 | 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 | 3715 | |
| 3710 | 3716 | const size_ap_int = const_arr_ty.getSize(); |
| 3711 | 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 | 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 | 3725 | const child_qt = incomplete_array_ty.getElementType(); |
| 3720 | 3726 | const is_const = child_qt.isConstQualified(); |
| 3721 | 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 | 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 | 3733 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); |
| 3728 | 3734 | |
| 3729 | 3735 | const typedef_decl = typedef_ty.getDecl(); |
| 3730 | | return (try transTypeDef(c, typedef_decl, false)) orelse |
| 3731 | | fail(c, error.UnsupportedType, source_loc, "unable to translate typedef declaration", .{}); |
| 3736 | try transTypeDef(c, scope, typedef_decl); |
| 3737 | const name = c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl())).?; |
| 3738 | return Tag.identifier.create(c.arena, name); |
| 3732 | 3739 | }, |
| 3733 | 3740 | .Record => { |
| 3734 | 3741 | const record_ty = @ptrCast(*const clang.RecordType, ty); |
| 3735 | 3742 | |
| 3736 | 3743 | const record_decl = record_ty.getDecl(); |
| 3737 | | return (try transRecordDecl(c, record_decl)) orelse |
| 3738 | | fail(c, error.UnsupportedType, source_loc, "unable to resolve record declaration", .{}); |
| 3744 | try transRecordDecl(c, scope, record_decl); |
| 3745 | const name = c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl())).?; |
| 3746 | return Tag.identifier.create(c.arena, name); |
| 3739 | 3747 | }, |
| 3740 | 3748 | .Enum => { |
| 3741 | 3749 | const enum_ty = @ptrCast(*const clang.EnumType, ty); |
| 3742 | 3750 | |
| 3743 | 3751 | const enum_decl = enum_ty.getDecl(); |
| 3744 | | return (try transEnumDecl(c, enum_decl)) orelse |
| 3745 | | fail(c, error.UnsupportedType, source_loc, "unable to translate enum declaration", .{}); |
| 3752 | try transEnumDecl(c, scope, enum_decl); |
| 3753 | const name = c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl())).?; |
| 3754 | return Tag.identifier.create(c.arena, name); |
| 3746 | 3755 | }, |
| 3747 | 3756 | .Elaborated => { |
| 3748 | 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 | 3760 | .Decayed => { |
| 3752 | 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 | 3764 | .Attributed => { |
| 3756 | 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 | 3768 | .MacroQualified => { |
| 3760 | 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 | 3772 | else => { |
| 3764 | 3773 | const type_name = c.str(ty.getTypeClassName()); |
| ... | ... | @@ -3890,6 +3899,7 @@ fn finishTransFnProto( |
| 3890 | 3899 | ) !*ast.Payload.Func { |
| 3891 | 3900 | const is_export = if (fn_decl_context) |ctx| ctx.is_export else false; |
| 3892 | 3901 | const is_extern = if (fn_decl_context) |ctx| !ctx.has_body else false; |
| 3902 | const scope = &c.global_scope.base; |
| 3893 | 3903 | |
| 3894 | 3904 | // TODO check for always_inline attribute |
| 3895 | 3905 | // TODO check for align attribute |
| ... | ... | @@ -3914,7 +3924,7 @@ fn finishTransFnProto( |
| 3914 | 3924 | |
| 3915 | 3925 | break :blk param_name; |
| 3916 | 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 | 3929 | fn_params.addOneAssumeCapacity().* = .{ |
| 3920 | 3930 | .is_noalias = is_noalias, |
| ... | ... | @@ -3955,9 +3965,9 @@ fn finishTransFnProto( |
| 3955 | 3965 | // convert primitive c_void to actual void (only for return type) |
| 3956 | 3966 | break :blk Tag.void_type.init(); |
| 3957 | 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 | 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 | 3971 | return err; |
| 3962 | 3972 | }, |
| 3963 | 3973 | error.OutOfMemory => |e| return e, |