| 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 | 14360 | assert(unresolved_struct_ty.zigTypeTag() == .Struct); |
| 14361 | 14361 | |
| 14362 | 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 | 14367 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 14364 | 14368 | |
| 14365 | 14369 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse |
| ... | ... | @@ -14381,6 +14385,46 @@ fn structFieldVal( |
| 14381 | 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 | 14428 | fn unionFieldPtr( |
| 14385 | 14429 | sema: *Sema, |
| 14386 | 14430 | block: *Block, |
src/value.zig+29-11| ... | ... | @@ -1851,7 +1851,13 @@ pub const Value = extern union { |
| 1851 | 1851 | |
| 1852 | 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 | 1861 | .field_ptr => { |
| 1856 | 1862 | const a_payload = a.castTag(.field_ptr).?.data; |
| 1857 | 1863 | const b_payload = b.castTag(.field_ptr).?.data; |
| ... | ... | @@ -2327,21 +2333,33 @@ pub const Value = extern union { |
| 2327 | 2333 | } |
| 2328 | 2334 | |
| 2329 | 2335 | /// Returns a pointer to the element value at the index. |
| 2330 | pub fn elemPtr(self: Value, allocator: Allocator, index: usize) !Value { | |
| 2331 | switch (self.tag()) { | |
| 2336 | pub fn elemPtr(val: Value, arena: Allocator, index: usize) Allocator.Error!Value { | |
| 2337 | switch (val.tag()) { | |
| 2332 | 2338 | .elem_ptr => { |
| 2333 | const elem_ptr = self.castTag(.elem_ptr).?.data; | |
| 2334 | return Tag.elem_ptr.create(allocator, .{ | |
| 2339 | const elem_ptr = val.castTag(.elem_ptr).?.data; | |
| 2340 | return Tag.elem_ptr.create(arena, .{ | |
| 2335 | 2341 | .array_ptr = elem_ptr.array_ptr, |
| 2336 | 2342 | .index = elem_ptr.index + index, |
| 2337 | 2343 | }); |
| 2338 | 2344 | }, |
| 2339 | .slice => return Tag.elem_ptr.create(allocator, .{ | |
| 2340 | .array_ptr = self.castTag(.slice).?.data.ptr, | |
| 2341 | .index = index, | |
| 2342 | }), | |
| 2343 | else => return Tag.elem_ptr.create(allocator, .{ | |
| 2344 | .array_ptr = self, | |
| 2345 | .slice => { | |
| 2346 | const ptr_val = val.castTag(.slice).?.data.ptr; | |
| 2347 | switch (ptr_val.tag()) { | |
| 2348 | .elem_ptr => { | |
| 2349 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; | |
| 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 | 2363 | .index = index, |
| 2346 | 2364 | }), |
| 2347 | 2365 | } |
test/behavior/basic.zig+5-5| ... | ... | @@ -691,8 +691,6 @@ test "string escapes" { |
| 691 | 691 | } |
| 692 | 692 | |
| 693 | 693 | test "explicit cast optional pointers" { |
| 694 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 695 | ||
| 696 | 694 | const a: ?*i32 = undefined; |
| 697 | 695 | const b: ?*f32 = @ptrCast(?*f32, a); |
| 698 | 696 | _ = b; |
| ... | ... | @@ -735,7 +733,6 @@ test "string concatenation" { |
| 735 | 733 | } |
| 736 | 734 | |
| 737 | 735 | test "thread local variable" { |
| 738 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 739 | 736 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 740 | 737 | |
| 741 | 738 | const S = struct { |
| ... | ... | @@ -746,7 +743,11 @@ test "thread local variable" { |
| 746 | 743 | } |
| 747 | 744 | |
| 748 | 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 | 752 | const x = maybe(true) catch unreachable; |
| 752 | 753 | try expect(x.? == 42); |
| ... | ... | @@ -760,7 +761,6 @@ fn maybe(x: bool) anyerror!?u32 { |
| 760 | 761 | } |
| 761 | 762 | |
| 762 | 763 | test "pointer to thread local array" { |
| 763 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 764 | 764 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 765 | 765 | |
| 766 | 766 | const s = "Hello world"; |
test/behavior/defer.zig+3-1| ... | ... | @@ -97,7 +97,9 @@ fn runSomeErrorDefers(x: bool) !bool { |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | 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 | 104 | try expect(runSomeErrorDefers(true) catch unreachable); |
| 103 | 105 | try expect(result[0] == 'c'); |
test/behavior/eval.zig+1-5| ... | ... | @@ -553,8 +553,6 @@ var simple_struct = SimpleStruct{ .field = 1234 }; |
| 553 | 553 | const bound_fn = simple_struct.method; |
| 554 | 554 | |
| 555 | 555 | test "ptr to local array argument at comptime" { |
| 556 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 557 | ||
| 558 | 556 | comptime { |
| 559 | 557 | var bytes: [10]u8 = undefined; |
| 560 | 558 | modifySomeBytes(bytes[0..]); |
| ... | ... | @@ -591,8 +589,6 @@ fn testCompTimeUIntComparisons(x: u32) void { |
| 591 | 589 | const hi1 = "hi"; |
| 592 | 590 | const hi2 = hi1; |
| 593 | 591 | test "const global shares pointer with other same one" { |
| 594 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 595 | ||
| 596 | 592 | try assertEqualPtrs(&hi1[0], &hi2[0]); |
| 597 | 593 | comptime try expect(&hi1[0] == &hi2[0]); |
| 598 | 594 | } |
| ... | ... | @@ -704,7 +700,7 @@ fn loopNTimes(comptime n: usize) void { |
| 704 | 700 | } |
| 705 | 701 | |
| 706 | 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 | 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 | 235 | } |
| 236 | 236 | |
| 237 | 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 | 242 | const S = struct { |
| 241 | 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 | 177 | } |
| 178 | 178 | |
| 179 | 179 | test "compare equality of optional and non-optional pointer" { |
| 180 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 181 | ||
| 182 | 180 | const a = @intToPtr(*const usize, 0x12345678); |
| 183 | 181 | const b = @intToPtr(?*usize, 0x12345678); |
| 184 | 182 | try expect(a == b); |
test/behavior/slice.zig+2-1| ... | ... | @@ -565,7 +565,8 @@ test "array concat of slices gives slice" { |
| 565 | 565 | } |
| 566 | 566 | |
| 567 | 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 | 571 | const bs = comptime blk: { |
| 571 | 572 | const b = "........1........"; |
test/behavior/translate_c_macros.zig+3-7| ... | ... | @@ -30,16 +30,12 @@ test "initializer list expression" { |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | test "sizeof in macros" { |
| 33 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 34 | ||
| 35 | try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32)); | |
| 36 | try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32)); | |
| 33 | try expect(@as(c_int, @sizeOf(u32)) == h.MY_SIZEOF(u32)); | |
| 34 | try expect(@as(c_int, @sizeOf(u32)) == h.MY_SIZEOF2(u32)); | |
| 37 | 35 | } |
| 38 | 36 | |
| 39 | 37 | test "reference to a struct type" { |
| 40 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 41 | ||
| 42 | try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO); | |
| 38 | try expect(@sizeOf(h.struct_Foo) == h.SIZE_OF_FOO); | |
| 43 | 39 | } |
| 44 | 40 | |
| 45 | 41 | test "cast negative integer to pointer" { |