| author | |
| committer | |
| log | 032c722d2019a475362c0ae01241a80417bdd8a2 |
| tree | 97e0d9229e2f1173d2bfb8f53351476656042db4 |
| parent | 609896a6e8180ec32844d2b4656b52ef41fe7757 |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
* Sema: Correctly determine whether array_cat lhs and rhs are single ptrs
Many-pointers are also not single-pointers and wouldn't be considered
here. This commit makes the conditions use the appropriately-named
isSinglePointer instead.
* Sema: Correctly obtain ArrayInfo for many-pointer concatenation
Many-pointers at comptime have a known size like slices and can be used
in array concatenation. This fixes a stage1 regression.
* test: Add comptime manyptr concatenation test
Co-authored-by: sin-ack <sin-ack@users.noreply.github.com>2 files changed, 41 insertions(+), 12 deletions(-)
src/Sema.zig+16-12| ... | ... | @@ -9106,8 +9106,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9106 | 9106 | const rhs_len = try sema.usizeCast(block, lhs_src, rhs_info.len); |
| 9107 | 9107 | const final_len = lhs_len + rhs_len; |
| 9108 | 9108 | const final_len_including_sent = final_len + @boolToInt(res_sent != null); |
| 9109 | const lhs_single_ptr = lhs_ty.zigTypeTag() == .Pointer and !lhs_ty.isSlice(); | |
| 9110 | const rhs_single_ptr = rhs_ty.zigTypeTag() == .Pointer and !rhs_ty.isSlice(); | |
| 9109 | const lhs_single_ptr = lhs_ty.isSinglePointer(); | |
| 9110 | const rhs_single_ptr = rhs_ty.isSinglePointer(); | |
| 9111 | 9111 | const lhs_sub_val = if (lhs_single_ptr) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val; |
| 9112 | 9112 | const rhs_sub_val = if (rhs_single_ptr) (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).? else rhs_val; |
| 9113 | 9113 | var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded); |
| ... | ... | @@ -9160,17 +9160,21 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, inst: Air.Inst.R |
| 9160 | 9160 | .Array => t.arrayInfo(), |
| 9161 | 9161 | .Pointer => blk: { |
| 9162 | 9162 | const ptrinfo = t.ptrInfo().data; |
| 9163 | if (ptrinfo.size == .Slice) { | |
| 9164 | const val = try sema.resolveConstValue(block, src, inst); | |
| 9165 | return Type.ArrayInfo{ | |
| 9166 | .elem_type = t.childType(), | |
| 9167 | .sentinel = t.sentinel(), | |
| 9168 | .len = val.sliceLen(sema.mod), | |
| 9169 | }; | |
| 9163 | switch (ptrinfo.size) { | |
| 9164 | .Slice, .Many => { | |
| 9165 | const val = try sema.resolveConstValue(block, src, inst); | |
| 9166 | return Type.ArrayInfo{ | |
| 9167 | .elem_type = t.childType(), | |
| 9168 | .sentinel = t.sentinel(), | |
| 9169 | .len = val.sliceLen(sema.mod), | |
| 9170 | }; | |
| 9171 | }, | |
| 9172 | .One => { | |
| 9173 | if (ptrinfo.pointee_type.zigTypeTag() != .Array) return null; | |
| 9174 | break :blk ptrinfo.pointee_type.arrayInfo(); | |
| 9175 | }, | |
| 9176 | .C => return null, | |
| 9170 | 9177 | } |
| 9171 | if (ptrinfo.pointee_type.zigTypeTag() != .Array) return null; | |
| 9172 | if (ptrinfo.size != .One) return null; | |
| 9173 | break :blk ptrinfo.pointee_type.arrayInfo(); | |
| 9174 | 9178 | }, |
| 9175 | 9179 | else => null, |
| 9176 | 9180 | }; |
test/behavior/basic.zig+25| ... | ... | @@ -709,6 +709,31 @@ test "string concatenation" { |
| 709 | 709 | try expect(b[len] == 0); |
| 710 | 710 | } |
| 711 | 711 | |
| 712 | fn manyptrConcat(comptime s: [*:0]const u8) [*:0]const u8 { | |
| 713 | return "very " ++ s; | |
| 714 | } | |
| 715 | ||
| 716 | test "comptime manyptr concatenation" { | |
| 717 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 718 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 719 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 720 | ||
| 721 | const s = "epic"; | |
| 722 | const actual = manyptrConcat(s); | |
| 723 | const expected = "very epic"; | |
| 724 | ||
| 725 | const len = mem.len(actual); | |
| 726 | const len_with_null = len + 1; | |
| 727 | { | |
| 728 | var i: u32 = 0; | |
| 729 | while (i < len_with_null) : (i += 1) { | |
| 730 | try expect(actual[i] == expected[i]); | |
| 731 | } | |
| 732 | } | |
| 733 | try expect(actual[len] == 0); | |
| 734 | try expect(expected[len] == 0); | |
| 735 | } | |
| 736 | ||
| 712 | 737 | test "thread local variable" { |
| 713 | 738 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 714 | 739 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |