| author | |
| committer | |
| log | 7f604b6f48905faf0bbe1ad795b53aeb11332063 |
| tree | 578b321a86fad4e0a4f016f48df5753800a1cc9f |
| parent | 73827d2ea9a1275d2351b80fc357896793e7c9c6 |
| parent | 841b38aae8913972d12b08cf3e0e497be305efb1 |
| signature |
Misc fixes11 files changed, 150 insertions(+), 27 deletions(-)
lib/std/zig/tokenizer.zig+10-1| ... | ... | @@ -1151,7 +1151,13 @@ pub const Tokenizer = struct { |
| 1151 | 1151 | }, |
| 1152 | 1152 | }, |
| 1153 | 1153 | .line_comment => switch (c) { |
| 1154 | 0 => break, | |
| 1154 | 0 => { | |
| 1155 | if (self.index != self.buffer.len) { | |
| 1156 | result.tag = .invalid; | |
| 1157 | self.index += 1; | |
| 1158 | } | |
| 1159 | break; | |
| 1160 | }, | |
| 1155 | 1161 | '\n' => { |
| 1156 | 1162 | state = .start; |
| 1157 | 1163 | result.loc.start = self.index + 1; |
| ... | ... | @@ -1865,6 +1871,9 @@ test "null byte before eof" { |
| 1865 | 1871 | try testTokenize("//\x00", &.{.invalid}); |
| 1866 | 1872 | try testTokenize("\\\\\x00", &.{ .multiline_string_literal_line, .invalid }); |
| 1867 | 1873 | try testTokenize("\x00", &.{.invalid}); |
| 1874 | try testTokenize("// NUL\x00\n", &.{.invalid}); | |
| 1875 | try testTokenize("///\x00\n", &.{ .doc_comment, .invalid }); | |
| 1876 | try testTokenize("/// NUL\x00\n", &.{ .doc_comment, .invalid }); | |
| 1868 | 1877 | } |
| 1869 | 1878 | |
| 1870 | 1879 | fn testTokenize(source: [:0]const u8, expected_token_tags: []const Token.Tag) !void { |
src/AstGen.zig+21-4| ... | ... | @@ -3341,6 +3341,9 @@ fn ptrType( |
| 3341 | 3341 | return gz.astgen.failTok(ptr_info.allowzero_token.?, "C pointers always allow address zero", .{}); |
| 3342 | 3342 | } |
| 3343 | 3343 | |
| 3344 | const source_offset = gz.astgen.source_offset; | |
| 3345 | const source_line = gz.astgen.source_line; | |
| 3346 | const source_column = gz.astgen.source_column; | |
| 3344 | 3347 | const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type); |
| 3345 | 3348 | |
| 3346 | 3349 | var sentinel_ref: Zir.Inst.Ref = .none; |
| ... | ... | @@ -3351,17 +3354,31 @@ fn ptrType( |
| 3351 | 3354 | var trailing_count: u32 = 0; |
| 3352 | 3355 | |
| 3353 | 3356 | if (ptr_info.ast.sentinel != 0) { |
| 3357 | // These attributes can appear in any order and they all come before the | |
| 3358 | // element type so we need to reset the source cursor before generating them. | |
| 3359 | gz.astgen.source_offset = source_offset; | |
| 3360 | gz.astgen.source_line = source_line; | |
| 3361 | gz.astgen.source_column = source_column; | |
| 3362 | ||
| 3354 | 3363 | sentinel_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, ptr_info.ast.sentinel); |
| 3355 | 3364 | trailing_count += 1; |
| 3356 | 3365 | } |
| 3357 | if (ptr_info.ast.align_node != 0) { | |
| 3358 | align_ref = try expr(gz, scope, coerced_align_ri, ptr_info.ast.align_node); | |
| 3359 | trailing_count += 1; | |
| 3360 | } | |
| 3361 | 3366 | if (ptr_info.ast.addrspace_node != 0) { |
| 3367 | gz.astgen.source_offset = source_offset; | |
| 3368 | gz.astgen.source_line = source_line; | |
| 3369 | gz.astgen.source_column = source_column; | |
| 3370 | ||
| 3362 | 3371 | addrspace_ref = try expr(gz, scope, .{ .rl = .{ .ty = .address_space_type } }, ptr_info.ast.addrspace_node); |
| 3363 | 3372 | trailing_count += 1; |
| 3364 | 3373 | } |
| 3374 | if (ptr_info.ast.align_node != 0) { | |
| 3375 | gz.astgen.source_offset = source_offset; | |
| 3376 | gz.astgen.source_line = source_line; | |
| 3377 | gz.astgen.source_column = source_column; | |
| 3378 | ||
| 3379 | align_ref = try expr(gz, scope, coerced_align_ri, ptr_info.ast.align_node); | |
| 3380 | trailing_count += 1; | |
| 3381 | } | |
| 3365 | 3382 | if (ptr_info.ast.bit_range_start != 0) { |
| 3366 | 3383 | assert(ptr_info.ast.bit_range_end != 0); |
| 3367 | 3384 | bit_start_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start); |
src/Sema.zig+22-3| ... | ... | @@ -11288,6 +11288,7 @@ fn resolveSwitchItemVal( |
| 11288 | 11288 | // Only if we know for sure we need to report a compile error do we resolve the |
| 11289 | 11289 | // full source locations. |
| 11290 | 11290 | if (sema.resolveConstValue(block, .unneeded, item, "")) |val| { |
| 11291 | try sema.resolveLazyValue(val); | |
| 11291 | 11292 | return TypedValue{ .ty = item_ty, .val = val }; |
| 11292 | 11293 | } else |err| switch (err) { |
| 11293 | 11294 | error.NeededSourceLocation => { |
| ... | ... | @@ -16258,6 +16259,7 @@ fn typeInfoNamespaceDecls( |
| 16258 | 16259 | for (decls) |decl_index| { |
| 16259 | 16260 | const decl = sema.mod.declPtr(decl_index); |
| 16260 | 16261 | if (decl.kind == .@"usingnamespace") { |
| 16262 | if (decl.analysis == .in_progress) continue; | |
| 16261 | 16263 | try sema.mod.ensureDeclAnalyzed(decl_index); |
| 16262 | 16264 | var buf: Value.ToTypeBuffer = undefined; |
| 16263 | 16265 | const new_ns = decl.val.toType(&buf).getNamespace().?; |
| ... | ... | @@ -24820,8 +24822,13 @@ fn coerceExtra( |
| 24820 | 24822 | // empty tuple to zero-length slice |
| 24821 | 24823 | // note that this allows coercing to a mutable slice. |
| 24822 | 24824 | if (inst_child_ty.structFieldCount() == 0) { |
| 24825 | // Optional slice is represented with a null pointer so | |
| 24826 | // we use a dummy pointer value with the required alignment. | |
| 24823 | 24827 | const slice_val = try Value.Tag.slice.create(sema.arena, .{ |
| 24824 | .ptr = Value.undef, | |
| 24828 | .ptr = if (dest_info.@"align" != 0) | |
| 24829 | try Value.Tag.int_u64.create(sema.arena, dest_info.@"align") | |
| 24830 | else | |
| 24831 | try inst_child_ty.lazyAbiAlignment(target, sema.arena), | |
| 24825 | 24832 | .len = Value.zero, |
| 24826 | 24833 | }); |
| 24827 | 24834 | return sema.addConstant(dest_ty, slice_val); |
| ... | ... | @@ -26065,7 +26072,8 @@ fn coerceVarArgParam( |
| 26065 | 26072 | ) !Air.Inst.Ref { |
| 26066 | 26073 | if (block.is_typeof) return inst; |
| 26067 | 26074 | |
| 26068 | const coerced = switch (sema.typeOf(inst).zigTypeTag()) { | |
| 26075 | const uncasted_ty = sema.typeOf(inst); | |
| 26076 | const coerced = switch (uncasted_ty.zigTypeTag()) { | |
| 26069 | 26077 | // TODO consider casting to c_int/f64 if they fit |
| 26070 | 26078 | .ComptimeInt, .ComptimeFloat => return sema.fail( |
| 26071 | 26079 | block, |
| ... | ... | @@ -26079,6 +26087,17 @@ fn coerceVarArgParam( |
| 26079 | 26087 | break :blk try sema.analyzeDeclRef(fn_decl); |
| 26080 | 26088 | }, |
| 26081 | 26089 | .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}), |
| 26090 | .Float => float: { | |
| 26091 | const target = sema.mod.getTarget(); | |
| 26092 | const double_bits = @import("type.zig").CType.sizeInBits(.double, target); | |
| 26093 | const inst_bits = uncasted_ty.floatBits(sema.mod.getTarget()); | |
| 26094 | if (inst_bits >= double_bits) break :float inst; | |
| 26095 | switch (double_bits) { | |
| 26096 | 32 => break :float try sema.coerce(block, Type.f32, inst, inst_src), | |
| 26097 | 64 => break :float try sema.coerce(block, Type.f64, inst, inst_src), | |
| 26098 | else => unreachable, | |
| 26099 | } | |
| 26100 | }, | |
| 26082 | 26101 | else => inst, |
| 26083 | 26102 | }; |
| 26084 | 26103 | |
| ... | ... | @@ -27316,7 +27335,7 @@ fn coerceCompatiblePtrs( |
| 27316 | 27335 | return sema.addConstant(dest_ty, val); |
| 27317 | 27336 | } |
| 27318 | 27337 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 27319 | const inst_allows_zero = (inst_ty.zigTypeTag() == .Pointer and inst_ty.ptrAllowsZero()) or true; | |
| 27338 | const inst_allows_zero = inst_ty.zigTypeTag() != .Pointer or inst_ty.ptrAllowsZero(); | |
| 27320 | 27339 | if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero() and |
| 27321 | 27340 | try sema.typeHasRuntimeBits(dest_ty.elemType2())) |
| 27322 | 27341 | { |
src/codegen/llvm.zig+9-9| ... | ... | @@ -3370,7 +3370,7 @@ pub const DeclGen = struct { |
| 3370 | 3370 | return llvm_int.constIntToPtr(try dg.lowerType(tv.ty)); |
| 3371 | 3371 | }, |
| 3372 | 3372 | .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => { |
| 3373 | return dg.lowerParentPtr(tv.val); | |
| 3373 | return dg.lowerParentPtr(tv.val, tv.ty.ptrInfo().data.bit_offset % 8 == 0); | |
| 3374 | 3374 | }, |
| 3375 | 3375 | .null_value, .zero => { |
| 3376 | 3376 | const llvm_type = try dg.lowerType(tv.ty); |
| ... | ... | @@ -3378,7 +3378,7 @@ pub const DeclGen = struct { |
| 3378 | 3378 | }, |
| 3379 | 3379 | .opt_payload => { |
| 3380 | 3380 | const payload = tv.val.castTag(.opt_payload).?.data; |
| 3381 | return dg.lowerParentPtr(payload); | |
| 3381 | return dg.lowerParentPtr(payload, tv.ty.ptrInfo().data.bit_offset % 8 == 0); | |
| 3382 | 3382 | }, |
| 3383 | 3383 | else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{ |
| 3384 | 3384 | tv.ty.fmtDebug(), tag, |
| ... | ... | @@ -3967,7 +3967,7 @@ pub const DeclGen = struct { |
| 3967 | 3967 | return try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index); |
| 3968 | 3968 | } |
| 3969 | 3969 | |
| 3970 | fn lowerParentPtr(dg: *DeclGen, ptr_val: Value) Error!*llvm.Value { | |
| 3970 | fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { | |
| 3971 | 3971 | const target = dg.module.getTarget(); |
| 3972 | 3972 | switch (ptr_val.tag()) { |
| 3973 | 3973 | .decl_ref_mut => { |
| ... | ... | @@ -3996,7 +3996,7 @@ pub const DeclGen = struct { |
| 3996 | 3996 | }, |
| 3997 | 3997 | .field_ptr => { |
| 3998 | 3998 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 3999 | const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.container_ptr); | |
| 3999 | const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.container_ptr, byte_aligned); | |
| 4000 | 4000 | const parent_ty = field_ptr.container_ty; |
| 4001 | 4001 | |
| 4002 | 4002 | const field_index = @intCast(u32, field_ptr.field_index); |
| ... | ... | @@ -4026,6 +4026,7 @@ pub const DeclGen = struct { |
| 4026 | 4026 | }, |
| 4027 | 4027 | .Struct => { |
| 4028 | 4028 | if (parent_ty.containerLayout() == .Packed) { |
| 4029 | if (!byte_aligned) return parent_llvm_ptr; | |
| 4029 | 4030 | const llvm_usize = dg.context.intType(target.cpu.arch.ptrBitWidth()); |
| 4030 | 4031 | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); |
| 4031 | 4032 | // count bits of fields before this one |
| ... | ... | @@ -4072,7 +4073,7 @@ pub const DeclGen = struct { |
| 4072 | 4073 | }, |
| 4073 | 4074 | .elem_ptr => { |
| 4074 | 4075 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; |
| 4075 | const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr); | |
| 4076 | const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr, true); | |
| 4076 | 4077 | |
| 4077 | 4078 | const llvm_usize = try dg.lowerType(Type.usize); |
| 4078 | 4079 | const indices: [1]*llvm.Value = .{ |
| ... | ... | @@ -4083,7 +4084,7 @@ pub const DeclGen = struct { |
| 4083 | 4084 | }, |
| 4084 | 4085 | .opt_payload_ptr => { |
| 4085 | 4086 | const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; |
| 4086 | const parent_llvm_ptr = try dg.lowerParentPtr(opt_payload_ptr.container_ptr); | |
| 4087 | const parent_llvm_ptr = try dg.lowerParentPtr(opt_payload_ptr.container_ptr, true); | |
| 4087 | 4088 | var buf: Type.Payload.ElemType = undefined; |
| 4088 | 4089 | |
| 4089 | 4090 | const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf); |
| ... | ... | @@ -4105,7 +4106,7 @@ pub const DeclGen = struct { |
| 4105 | 4106 | }, |
| 4106 | 4107 | .eu_payload_ptr => { |
| 4107 | 4108 | const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; |
| 4108 | const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr); | |
| 4109 | const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, true); | |
| 4109 | 4110 | |
| 4110 | 4111 | const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload(); |
| 4111 | 4112 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| ... | ... | @@ -10667,8 +10668,7 @@ const ParamTypeIterator = struct { |
| 10667 | 10668 | .memory => { |
| 10668 | 10669 | it.zig_index += 1; |
| 10669 | 10670 | it.llvm_index += 1; |
| 10670 | it.byval_attr = true; | |
| 10671 | return .byref; | |
| 10671 | return .byref_mut; | |
| 10672 | 10672 | }, |
| 10673 | 10673 | .sse => { |
| 10674 | 10674 | it.zig_index += 1; |
test/behavior/packed-struct.zig+26| ... | ... | @@ -599,3 +599,29 @@ test "packed struct initialized in bitcast" { |
| 599 | 599 | const t = @bitCast(u8, T{ .val = val }); |
| 600 | 600 | try expect(t == val); |
| 601 | 601 | } |
| 602 | ||
| 603 | test "pointer to container level packed struct field" { | |
| 604 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 605 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 606 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 607 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 608 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 609 | ||
| 610 | const S = packed struct(u32) { | |
| 611 | test_bit: bool, | |
| 612 | someother_data: u12, | |
| 613 | other_test_bit: bool, | |
| 614 | someother_more_different_data: u12, | |
| 615 | other_bits: packed struct(u6) { | |
| 616 | enable_1: bool, | |
| 617 | enable_2: bool, | |
| 618 | enable_3: bool, | |
| 619 | enable_4: bool, | |
| 620 | enable_5: bool, | |
| 621 | enable_6: bool, | |
| 622 | }, | |
| 623 | var arr = [_]u32{0} ** 2; | |
| 624 | }; | |
| 625 | @ptrCast(*S, &S.arr[0]).other_bits.enable_3 = true; | |
| 626 | try expect(S.arr[0] == 0x10000000); | |
| 627 | } |
test/behavior/pointers.zig+10| ... | ... | @@ -522,3 +522,13 @@ test "ptrToInt on a generic function" { |
| 522 | 522 | }; |
| 523 | 523 | try S.doTheTest(&S.generic); |
| 524 | 524 | } |
| 525 | ||
| 526 | test "pointer alignment and element type include call expression" { | |
| 527 | const S = struct { | |
| 528 | fn T() type { | |
| 529 | return struct { _: i32 }; | |
| 530 | } | |
| 531 | const P = *align(@alignOf(T())) [@sizeOf(T())]u8; | |
| 532 | }; | |
| 533 | try expect(@alignOf(S.P) > 0); | |
| 534 | } |
test/behavior/switch.zig+14| ... | ... | @@ -686,3 +686,17 @@ test "enum value without tag name used as switch item" { |
| 686 | 686 | _ => return error.TestFailed, |
| 687 | 687 | } |
| 688 | 688 | } |
| 689 | ||
| 690 | test "switch item sizeof" { | |
| 691 | const S = struct { | |
| 692 | fn doTheTest() !void { | |
| 693 | var a: usize = 0; | |
| 694 | switch (a) { | |
| 695 | @sizeOf(struct {}) => {}, | |
| 696 | else => return error.TestFailed, | |
| 697 | } | |
| 698 | } | |
| 699 | }; | |
| 700 | try S.doTheTest(); | |
| 701 | comptime try S.doTheTest(); | |
| 702 | } |
test/behavior/type_info.zig+13| ... | ... | @@ -590,3 +590,16 @@ test "@typeInfo decls and usingnamespace" { |
| 590 | 590 | try expectEqualStrings(decls[1].name, "y"); |
| 591 | 591 | try expectEqualStrings(decls[2].name, "z"); |
| 592 | 592 | } |
| 593 | ||
| 594 | test "@typeInfo decls ignore dependency loops" { | |
| 595 | const S = struct { | |
| 596 | fn Def(comptime T: type) type { | |
| 597 | std.debug.assert(@typeInfo(T).Struct.decls.len == 1); | |
| 598 | return struct { | |
| 599 | const foo = u32; | |
| 600 | }; | |
| 601 | } | |
| 602 | usingnamespace Def(@This()); | |
| 603 | }; | |
| 604 | _ = S.foo; | |
| 605 | } |
test/c_abi/main.zig-1| ... | ... | @@ -1032,7 +1032,6 @@ extern fn c_modify_by_ref_param(ByRef) ByRef; |
| 1032 | 1032 | |
| 1033 | 1033 | test "C function modifies by ref param" { |
| 1034 | 1034 | if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest; |
| 1035 | if (builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows and builtin.mode != .Debug) return error.SkipZigTest; | |
| 1036 | 1035 | |
| 1037 | 1036 | const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined }); |
| 1038 | 1037 | try expect(res.val == 42); |
test/cases/compile_errors/invalid_store_to_comptime_field.zig+10-9| ... | ... | @@ -44,15 +44,15 @@ pub export fn entry5() void { |
| 44 | 44 | comptime var y = .{ 1, 2 }; |
| 45 | 45 | y = .{ 3, 4 }; |
| 46 | 46 | } |
| 47 | // pub export fn entry5() void { | |
| 48 | // var x: u32 = 15; | |
| 49 | // const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x }); | |
| 50 | // const S = struct { | |
| 51 | // fn foo(_: T) void {} | |
| 52 | // }; | |
| 53 | // _ = S.foo(.{ -1234, 5679, x }); | |
| 54 | // } | |
| 55 | 47 | pub export fn entry6() void { |
| 48 | var x: u32 = 15; | |
| 49 | const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x }); | |
| 50 | const S = struct { | |
| 51 | fn foo(_: T) void {} | |
| 52 | }; | |
| 53 | _ = S.foo(.{ -1234, 5679, x }); | |
| 54 | } | |
| 55 | pub export fn entry7() void { | |
| 56 | 56 | const State = struct { |
| 57 | 57 | comptime id: bool = true, |
| 58 | 58 | fn init(comptime id: bool) @This() { |
| ... | ... | @@ -61,7 +61,7 @@ pub export fn entry6() void { |
| 61 | 61 | }; |
| 62 | 62 | _ = State.init(false); |
| 63 | 63 | } |
| 64 | pub export fn entry7() void { | |
| 64 | pub export fn entry8() void { | |
| 65 | 65 | const list1 = .{ "sss", 1, 2, 3 }; |
| 66 | 66 | const list2 = @TypeOf(list1){ .@"0" = "xxx", .@"1" = 4, .@"2" = 5, .@"3" = 6 }; |
| 67 | 67 | _ = list2; |
| ... | ... | @@ -73,6 +73,7 @@ pub export fn entry7() void { |
| 73 | 73 | // |
| 74 | 74 | // :6:19: error: value stored in comptime field does not match the default value of the field |
| 75 | 75 | // :14:19: error: value stored in comptime field does not match the default value of the field |
| 76 | // :53:16: error: value stored in comptime field does not match the default value of the field | |
| 76 | 77 | // :19:38: error: value stored in comptime field does not match the default value of the field |
| 77 | 78 | // :31:19: error: value stored in comptime field does not match the default value of the field |
| 78 | 79 | // :25:29: note: default value set here |
test/cases/f32_passed_to_variadic_fn.zig created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | extern fn printf(format: [*:0]const u8, ...) c_int; | |
| 2 | pub fn main() void { | |
| 3 | var a: f64 = 2.0; | |
| 4 | var b: f32 = 10.0; | |
| 5 | _ = printf("f64: %f\n", a); | |
| 6 | _ = printf("f32: %f\n", b); | |
| 7 | } | |
| 8 | ||
| 9 | // run | |
| 10 | // backend=llvm | |
| 11 | // target=x86_64-linux-gnu | |
| 12 | // | |
| 13 | // f64: 2.000000 | |
| 14 | // f32: 10.000000 | |
| 15 | // | |
| \ No newline at end of file |