| author | |
| committer | |
| log | 27eb42c15e4e9ab547eaf02cca8810cc0e10e6bf |
| tree | 83cd40198ef1f55946163766a04fe9202a510206 |
| parent | adb746a7017ba6f91974d5e940bc8a8f64bb45f5 |
9 files changed, 90 insertions(+), 33 deletions(-)
src/Sema.zig+44| ... | @@ -14360,6 +14360,10 @@ fn structFieldVal( | ... | @@ -14360,6 +14360,10 @@ fn structFieldVal( |
| 14360 | assert(unresolved_struct_ty.zigTypeTag() == .Struct); | 14360 | assert(unresolved_struct_ty.zigTypeTag() == .Struct); |
| 14361 | 14361 | ||
| 14362 | const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty); | 14362 | const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty); |
| 14363 | if (struct_ty.isTuple()) { | ||
| 14364 | return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty); | ||
| 14365 | } | ||
| 14366 | |||
| 14363 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 14367 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 14364 | 14368 | ||
| 14365 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse | 14369 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse |
| ... | @@ -14381,6 +14385,46 @@ fn structFieldVal( | ... | @@ -14381,6 +14385,46 @@ fn structFieldVal( |
| 14381 | return block.addStructFieldVal(struct_byval, field_index, field.ty); | 14385 | return block.addStructFieldVal(struct_byval, field_index, field.ty); |
| 14382 | } | 14386 | } |
| 14383 | 14387 | ||
| 14388 | fn tupleFieldVal( | ||
| 14389 | sema: *Sema, | ||
| 14390 | block: *Block, | ||
| 14391 | src: LazySrcLoc, | ||
| 14392 | tuple_byval: Air.Inst.Ref, | ||
| 14393 | field_name: []const u8, | ||
| 14394 | field_name_src: LazySrcLoc, | ||
| 14395 | tuple_ty: Type, | ||
| 14396 | ) CompileError!Air.Inst.Ref { | ||
| 14397 | const tuple = tuple_ty.castTag(.tuple).?.data; | ||
| 14398 | |||
| 14399 | if (mem.eql(u8, field_name, "len")) { | ||
| 14400 | return sema.addIntUnsigned(Type.usize, tuple.types.len); | ||
| 14401 | } | ||
| 14402 | |||
| 14403 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| { | ||
| 14404 | return sema.fail(block, field_name_src, "tuple {} has no such field '{s}': {s}", .{ | ||
| 14405 | tuple_ty, field_name, @errorName(err), | ||
| 14406 | }); | ||
| 14407 | }; | ||
| 14408 | |||
| 14409 | const field_ty = tuple.types[field_index]; | ||
| 14410 | |||
| 14411 | if (tuple.values[field_index].tag() != .unreachable_value) { | ||
| 14412 | return sema.addConstant(field_ty, tuple.values[field_index]); | ||
| 14413 | } | ||
| 14414 | |||
| 14415 | if (try sema.resolveMaybeUndefVal(block, src, tuple_byval)) |tuple_val| { | ||
| 14416 | if (tuple_val.isUndef()) return sema.addConstUndef(field_ty); | ||
| 14417 | if ((try sema.typeHasOnePossibleValue(block, src, field_ty))) |opv| { | ||
| 14418 | return sema.addConstant(field_ty, opv); | ||
| 14419 | } | ||
| 14420 | const field_values = tuple_val.castTag(.@"struct").?.data; | ||
| 14421 | return sema.addConstant(field_ty, field_values[field_index]); | ||
| 14422 | } | ||
| 14423 | |||
| 14424 | try sema.requireRuntimeBlock(block, src); | ||
| 14425 | return block.addStructFieldVal(tuple_byval, field_index, field_ty); | ||
| 14426 | } | ||
| 14427 | |||
| 14384 | fn unionFieldPtr( | 14428 | fn unionFieldPtr( |
| 14385 | sema: *Sema, | 14429 | sema: *Sema, |
| 14386 | block: *Block, | 14430 | block: *Block, |
src/value.zig+29-11| ... | @@ -1851,7 +1851,13 @@ pub const Value = extern union { | ... | @@ -1851,7 +1851,13 @@ pub const Value = extern union { |
| 1851 | 1851 | ||
| 1852 | return eql(a_payload.ptr, b_payload.ptr, ptr_ty); | 1852 | return eql(a_payload.ptr, b_payload.ptr, ptr_ty); |
| 1853 | }, | 1853 | }, |
| 1854 | .elem_ptr => @panic("TODO: Implement more pointer eql cases"), | 1854 | .elem_ptr => { |
| 1855 | const a_payload = a.castTag(.elem_ptr).?.data; | ||
| 1856 | const b_payload = b.castTag(.elem_ptr).?.data; | ||
| 1857 | if (a_payload.index != b_payload.index) return false; | ||
| 1858 | |||
| 1859 | return eql(a_payload.array_ptr, b_payload.array_ptr, ty); | ||
| 1860 | }, | ||
| 1855 | .field_ptr => { | 1861 | .field_ptr => { |
| 1856 | const a_payload = a.castTag(.field_ptr).?.data; | 1862 | const a_payload = a.castTag(.field_ptr).?.data; |
| 1857 | const b_payload = b.castTag(.field_ptr).?.data; | 1863 | const b_payload = b.castTag(.field_ptr).?.data; |
| ... | @@ -2327,21 +2333,33 @@ pub const Value = extern union { | ... | @@ -2327,21 +2333,33 @@ pub const Value = extern union { |
| 2327 | } | 2333 | } |
| 2328 | 2334 | ||
| 2329 | /// Returns a pointer to the element value at the index. | 2335 | /// Returns a pointer to the element value at the index. |
| 2330 | pub fn elemPtr(self: Value, allocator: Allocator, index: usize) !Value { | 2336 | pub fn elemPtr(val: Value, arena: Allocator, index: usize) Allocator.Error!Value { |
| 2331 | switch (self.tag()) { | 2337 | switch (val.tag()) { |
| 2332 | .elem_ptr => { | 2338 | .elem_ptr => { |
| 2333 | const elem_ptr = self.castTag(.elem_ptr).?.data; | 2339 | const elem_ptr = val.castTag(.elem_ptr).?.data; |
| 2334 | return Tag.elem_ptr.create(allocator, .{ | 2340 | return Tag.elem_ptr.create(arena, .{ |
| 2335 | .array_ptr = elem_ptr.array_ptr, | 2341 | .array_ptr = elem_ptr.array_ptr, |
| 2336 | .index = elem_ptr.index + index, | 2342 | .index = elem_ptr.index + index, |
| 2337 | }); | 2343 | }); |
| 2338 | }, | 2344 | }, |
| 2339 | .slice => return Tag.elem_ptr.create(allocator, .{ | 2345 | .slice => { |
| 2340 | .array_ptr = self.castTag(.slice).?.data.ptr, | 2346 | const ptr_val = val.castTag(.slice).?.data.ptr; |
| 2341 | .index = index, | 2347 | switch (ptr_val.tag()) { |
| 2342 | }), | 2348 | .elem_ptr => { |
| 2343 | else => return Tag.elem_ptr.create(allocator, .{ | 2349 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; |
| 2344 | .array_ptr = self, | 2350 | return Tag.elem_ptr.create(arena, .{ |
| 2351 | .array_ptr = elem_ptr.array_ptr, | ||
| 2352 | .index = elem_ptr.index + index, | ||
| 2353 | }); | ||
| 2354 | }, | ||
| 2355 | else => return Tag.elem_ptr.create(arena, .{ | ||
| 2356 | .array_ptr = ptr_val, | ||
| 2357 | .index = index, | ||
| 2358 | }), | ||
| 2359 | } | ||
| 2360 | }, | ||
| 2361 | else => return Tag.elem_ptr.create(arena, .{ | ||
| 2362 | .array_ptr = val, | ||
| 2345 | .index = index, | 2363 | .index = index, |
| 2346 | }), | 2364 | }), |
| 2347 | } | 2365 | } |
test/behavior/basic.zig+5-5| ... | @@ -691,8 +691,6 @@ test "string escapes" { | ... | @@ -691,8 +691,6 @@ test "string escapes" { |
| 691 | } | 691 | } |
| 692 | 692 | ||
| 693 | test "explicit cast optional pointers" { | 693 | test "explicit cast optional pointers" { |
| 694 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 695 | |||
| 696 | const a: ?*i32 = undefined; | 694 | const a: ?*i32 = undefined; |
| 697 | const b: ?*f32 = @ptrCast(?*f32, a); | 695 | const b: ?*f32 = @ptrCast(?*f32, a); |
| 698 | _ = b; | 696 | _ = b; |
| ... | @@ -735,7 +733,6 @@ test "string concatenation" { | ... | @@ -735,7 +733,6 @@ test "string concatenation" { |
| 735 | } | 733 | } |
| 736 | 734 | ||
| 737 | test "thread local variable" { | 735 | test "thread local variable" { |
| 738 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 739 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 736 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 740 | 737 | ||
| 741 | const S = struct { | 738 | const S = struct { |
| ... | @@ -746,7 +743,11 @@ test "thread local variable" { | ... | @@ -746,7 +743,11 @@ test "thread local variable" { |
| 746 | } | 743 | } |
| 747 | 744 | ||
| 748 | test "result location is optional inside error union" { | 745 | test "result location is optional inside error union" { |
| 749 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 746 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 747 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 748 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 749 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 750 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 750 | 751 | ||
| 751 | const x = maybe(true) catch unreachable; | 752 | const x = maybe(true) catch unreachable; |
| 752 | try expect(x.? == 42); | 753 | try expect(x.? == 42); |
| ... | @@ -760,7 +761,6 @@ fn maybe(x: bool) anyerror!?u32 { | ... | @@ -760,7 +761,6 @@ fn maybe(x: bool) anyerror!?u32 { |
| 760 | } | 761 | } |
| 761 | 762 | ||
| 762 | test "pointer to thread local array" { | 763 | test "pointer to thread local array" { |
| 763 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 764 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 764 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 765 | 765 | ||
| 766 | const s = "Hello world"; | 766 | const s = "Hello world"; |
test/behavior/defer.zig+3-1| ... | @@ -97,7 +97,9 @@ fn runSomeErrorDefers(x: bool) !bool { | ... | @@ -97,7 +97,9 @@ fn runSomeErrorDefers(x: bool) !bool { |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | test "mixing normal and error defers" { | 99 | test "mixing normal and error defers" { |
| 100 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 100 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 101 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 102 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 101 | 103 | ||
| 102 | try expect(runSomeErrorDefers(true) catch unreachable); | 104 | try expect(runSomeErrorDefers(true) catch unreachable); |
| 103 | try expect(result[0] == 'c'); | 105 | try expect(result[0] == 'c'); |
test/behavior/eval.zig+1-5| ... | @@ -553,8 +553,6 @@ var simple_struct = SimpleStruct{ .field = 1234 }; | ... | @@ -553,8 +553,6 @@ var simple_struct = SimpleStruct{ .field = 1234 }; |
| 553 | const bound_fn = simple_struct.method; | 553 | const bound_fn = simple_struct.method; |
| 554 | 554 | ||
| 555 | test "ptr to local array argument at comptime" { | 555 | test "ptr to local array argument at comptime" { |
| 556 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 557 | |||
| 558 | comptime { | 556 | comptime { |
| 559 | var bytes: [10]u8 = undefined; | 557 | var bytes: [10]u8 = undefined; |
| 560 | modifySomeBytes(bytes[0..]); | 558 | modifySomeBytes(bytes[0..]); |
| ... | @@ -591,8 +589,6 @@ fn testCompTimeUIntComparisons(x: u32) void { | ... | @@ -591,8 +589,6 @@ fn testCompTimeUIntComparisons(x: u32) void { |
| 591 | const hi1 = "hi"; | 589 | const hi1 = "hi"; |
| 592 | const hi2 = hi1; | 590 | const hi2 = hi1; |
| 593 | test "const global shares pointer with other same one" { | 591 | test "const global shares pointer with other same one" { |
| 594 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 595 | |||
| 596 | try assertEqualPtrs(&hi1[0], &hi2[0]); | 592 | try assertEqualPtrs(&hi1[0], &hi2[0]); |
| 597 | comptime try expect(&hi1[0] == &hi2[0]); | 593 | comptime try expect(&hi1[0] == &hi2[0]); |
| 598 | } | 594 | } |
| ... | @@ -704,7 +700,7 @@ fn loopNTimes(comptime n: usize) void { | ... | @@ -704,7 +700,7 @@ fn loopNTimes(comptime n: usize) void { |
| 704 | } | 700 | } |
| 705 | 701 | ||
| 706 | test "variable inside inline loop that has different types on different iterations" { | 702 | test "variable inside inline loop that has different types on different iterations" { |
| 707 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 703 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 708 | 704 | ||
| 709 | try testVarInsideInlineLoop(.{ true, @as(u32, 42) }); | 705 | try testVarInsideInlineLoop(.{ true, @as(u32, 42) }); |
| 710 | } | 706 | } |
test/behavior/optional.zig+3-1| ... | @@ -235,7 +235,9 @@ test "assigning to an unwrapped optional field in an inline loop" { | ... | @@ -235,7 +235,9 @@ test "assigning to an unwrapped optional field in an inline loop" { |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | test "coerce an anon struct literal to optional struct" { | 237 | test "coerce an anon struct literal to optional struct" { |
| 238 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 238 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 239 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 240 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 239 | 241 | ||
| 240 | const S = struct { | 242 | const S = struct { |
| 241 | const Struct = struct { | 243 | const Struct = struct { |
test/behavior/pointers.zig-2| ... | @@ -177,8 +177,6 @@ test "implicit cast error unions with non-optional to optional pointer" { | ... | @@ -177,8 +177,6 @@ test "implicit cast error unions with non-optional to optional pointer" { |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | test "compare equality of optional and non-optional pointer" { | 179 | test "compare equality of optional and non-optional pointer" { |
| 180 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | ||
| 181 | |||
| 182 | const a = @intToPtr(*const usize, 0x12345678); | 180 | const a = @intToPtr(*const usize, 0x12345678); |
| 183 | const b = @intToPtr(?*usize, 0x12345678); | 181 | const b = @intToPtr(?*usize, 0x12345678); |
| 184 | try expect(a == b); | 182 | try expect(a == b); |
test/behavior/slice.zig+2-1| ... | @@ -565,7 +565,8 @@ test "array concat of slices gives slice" { | ... | @@ -565,7 +565,8 @@ test "array concat of slices gives slice" { |
| 565 | } | 565 | } |
| 566 | 566 | ||
| 567 | test "slice bounds in comptime concatenation" { | 567 | test "slice bounds in comptime concatenation" { |
| 568 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 568 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 569 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 569 | 570 | ||
| 570 | const bs = comptime blk: { | 571 | const bs = comptime blk: { |
| 571 | const b = "........1........"; | 572 | const b = "........1........"; |
test/behavior/translate_c_macros.zig+3-7| ... | @@ -30,16 +30,12 @@ test "initializer list expression" { | ... | @@ -30,16 +30,12 @@ test "initializer list expression" { |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | test "sizeof in macros" { | 32 | test "sizeof in macros" { |
| 33 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 33 | try expect(@as(c_int, @sizeOf(u32)) == h.MY_SIZEOF(u32)); |
| 34 | 34 | try expect(@as(c_int, @sizeOf(u32)) == h.MY_SIZEOF2(u32)); | |
| 35 | try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32)); | ||
| 36 | try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32)); | ||
| 37 | } | 35 | } |
| 38 | 36 | ||
| 39 | test "reference to a struct type" { | 37 | test "reference to a struct type" { |
| 40 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 38 | try expect(@sizeOf(h.struct_Foo) == h.SIZE_OF_FOO); |
| 41 | |||
| 42 | try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO); | ||
| 43 | } | 39 | } |
| 44 | 40 | ||
| 45 | test "cast negative integer to pointer" { | 41 | test "cast negative integer to pointer" { |