| ... | ... | @@ -715,6 +715,7 @@ fn zirStructDecl( |
| 715 | 715 | } else sema.src; |
| 716 | 716 | |
| 717 | 717 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| 718 | errdefer new_decl_arena.deinit(); |
| 718 | 719 | |
| 719 | 720 | const struct_obj = try new_decl_arena.allocator.create(Module.Struct); |
| 720 | 721 | const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj); |
| ... | ... | @@ -779,6 +780,7 @@ fn zirEnumDecl( |
| 779 | 780 | const tracy = trace(@src()); |
| 780 | 781 | defer tracy.end(); |
| 781 | 782 | |
| 783 | const mod = sema.mod; |
| 782 | 784 | const gpa = sema.gpa; |
| 783 | 785 | const small = @bitCast(Zir.Inst.EnumDecl.Small, extended.small); |
| 784 | 786 | var extra_index: usize = extended.operand; |
| ... | ... | @@ -814,6 +816,7 @@ fn zirEnumDecl( |
| 814 | 816 | } else 0; |
| 815 | 817 | |
| 816 | 818 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); |
| 819 | errdefer new_decl_arena.deinit(); |
| 817 | 820 | |
| 818 | 821 | const tag_ty = blk: { |
| 819 | 822 | if (tag_type_ref != .none) { |
| ... | ... | @@ -835,7 +838,7 @@ fn zirEnumDecl( |
| 835 | 838 | const enum_ty = Type.initPayload(&enum_ty_payload.base); |
| 836 | 839 | const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty); |
| 837 | 840 | const type_name = try sema.createTypeName(block, small.name_strategy); |
| 838 | | const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{ |
| 841 | const new_decl = try mod.createAnonymousDeclNamed(&block.base, .{ |
| 839 | 842 | .ty = Type.initTag(.type), |
| 840 | 843 | .val = enum_val, |
| 841 | 844 | }, type_name); |
| ... | ... | @@ -855,7 +858,7 @@ fn zirEnumDecl( |
| 855 | 858 | &enum_obj.namespace, new_decl, new_decl.name, |
| 856 | 859 | }); |
| 857 | 860 | |
| 858 | | extra_index = try sema.mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl); |
| 861 | extra_index = try mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl); |
| 859 | 862 | |
| 860 | 863 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 861 | 864 | if (fields_len == 0) { |
| ... | ... | @@ -883,7 +886,7 @@ fn zirEnumDecl( |
| 883 | 886 | // Within the field type, default value, and alignment expressions, the "owner decl" |
| 884 | 887 | // should be the enum itself. Thus we need a new Sema. |
| 885 | 888 | var enum_sema: Sema = .{ |
| 886 | | .mod = sema.mod, |
| 889 | .mod = mod, |
| 887 | 890 | .gpa = gpa, |
| 888 | 891 | .arena = &new_decl_arena.allocator, |
| 889 | 892 | .code = sema.code, |
| ... | ... | @@ -932,7 +935,18 @@ fn zirEnumDecl( |
| 932 | 935 | const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir); |
| 933 | 936 | |
| 934 | 937 | const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name); |
| 935 | | assert(!gop.found_existing); |
| 938 | if (gop.found_existing) { |
| 939 | const tree = try sema.getAstTree(block); |
| 940 | const field_src = enumFieldSrcLoc(block.src_decl, tree.*, src.node_offset, field_i); |
| 941 | const other_tag_src = enumFieldSrcLoc(block.src_decl, tree.*, src.node_offset, gop.index); |
| 942 | const msg = msg: { |
| 943 | const msg = try mod.errMsg(&block.base, field_src, "duplicate enum tag", .{}); |
| 944 | errdefer msg.destroy(gpa); |
| 945 | try mod.errNote(&block.base, other_tag_src, msg, "other tag here", .{}); |
| 946 | break :msg msg; |
| 947 | }; |
| 948 | return mod.failWithOwnedErrorMsg(&block.base, msg); |
| 949 | } |
| 936 | 950 | |
| 937 | 951 | if (has_tag_value) { |
| 938 | 952 | const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| ... | ... | @@ -981,6 +995,7 @@ fn zirUnionDecl( |
| 981 | 995 | } else 0; |
| 982 | 996 | |
| 983 | 997 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| 998 | errdefer new_decl_arena.deinit(); |
| 984 | 999 | |
| 985 | 1000 | const union_obj = try new_decl_arena.allocator.create(Module.Union); |
| 986 | 1001 | const union_ty = try Type.Tag.@"union".create(&new_decl_arena.allocator, union_obj); |
| ... | ... | @@ -1046,6 +1061,7 @@ fn zirErrorSetDecl( |
| 1046 | 1061 | const fields = sema.code.extra[extra.end..][0..extra.data.fields_len]; |
| 1047 | 1062 | |
| 1048 | 1063 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); |
| 1064 | errdefer new_decl_arena.deinit(); |
| 1049 | 1065 | |
| 1050 | 1066 | const error_set = try new_decl_arena.allocator.create(Module.ErrorSet); |
| 1051 | 1067 | const error_set_ty = try Type.Tag.error_set.create(&new_decl_arena.allocator, error_set); |
| ... | ... | @@ -7446,3 +7462,53 @@ fn typeHasOnePossibleValue( |
| 7446 | 7462 | .inferred_alloc_mut => unreachable, |
| 7447 | 7463 | }; |
| 7448 | 7464 | } |
| 7465 | |
| 7466 | fn getAstTree(sema: *Sema, block: *Scope.Block) InnerError!*const std.zig.ast.Tree { |
| 7467 | return block.src_decl.namespace.file_scope.getTree(sema.gpa) catch |err| { |
| 7468 | log.err("unable to load AST to report compile error: {s}", .{@errorName(err)}); |
| 7469 | return error.AnalysisFail; |
| 7470 | }; |
| 7471 | } |
| 7472 | |
| 7473 | fn enumFieldSrcLoc( |
| 7474 | decl: *Decl, |
| 7475 | tree: std.zig.ast.Tree, |
| 7476 | node_offset: i32, |
| 7477 | field_index: usize, |
| 7478 | ) LazySrcLoc { |
| 7479 | @setCold(true); |
| 7480 | const enum_node = decl.relativeToNodeIndex(node_offset); |
| 7481 | const node_tags = tree.nodes.items(.tag); |
| 7482 | var buffer: [2]std.zig.ast.Node.Index = undefined; |
| 7483 | const container_decl = switch (node_tags[enum_node]) { |
| 7484 | .container_decl, |
| 7485 | .container_decl_trailing, |
| 7486 | => tree.containerDecl(enum_node), |
| 7487 | |
| 7488 | .container_decl_two, |
| 7489 | .container_decl_two_trailing, |
| 7490 | => tree.containerDeclTwo(&buffer, enum_node), |
| 7491 | |
| 7492 | .container_decl_arg, |
| 7493 | .container_decl_arg_trailing, |
| 7494 | => tree.containerDeclArg(enum_node), |
| 7495 | |
| 7496 | else => unreachable, |
| 7497 | }; |
| 7498 | var it_index: usize = 0; |
| 7499 | for (container_decl.ast.members) |member_node| { |
| 7500 | switch (node_tags[member_node]) { |
| 7501 | .container_field_init, |
| 7502 | .container_field_align, |
| 7503 | .container_field, |
| 7504 | => { |
| 7505 | if (it_index == field_index) { |
| 7506 | return .{ .node_offset = decl.nodeIndexToRelative(member_node) }; |
| 7507 | } |
| 7508 | it_index += 1; |
| 7509 | }, |
| 7510 | |
| 7511 | else => continue, |
| 7512 | } |
| 7513 | } else unreachable; |
| 7514 | } |