diff options
| author | sin-ack <77421532+sin-ack@users.noreply.github.com> | 2022-04-30 05:53:06 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-04-29 22:53:06 -0400 |
| commit | 032c722d2019a475362c0ae01241a80417bdd8a2 (patch) | |
| tree | 97e0d9229e2f1173d2bfb8f53351476656042db4 | |
| parent | 609896a6e8180ec32844d2b4656b52ef41fe7757 (diff) | |
| download | zig-032c722d2019a475362c0ae01241a80417bdd8a2.tar.gz zig-032c722d2019a475362c0ae01241a80417bdd8a2.zip | |
Sema: Fix many-pointer array concatenation at comptime (#11512)
* 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>
| -rw-r--r-- | src/Sema.zig | 28 | ||||
| -rw-r--r-- | test/behavior/basic.zig | 25 |
2 files changed, 41 insertions, 12 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index ccfb11e639..b17ca031c2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9106,8 +9106,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const rhs_len = try sema.usizeCast(block, lhs_src, rhs_info.len); const final_len = lhs_len + rhs_len; const final_len_including_sent = final_len + @boolToInt(res_sent != null); - const lhs_single_ptr = lhs_ty.zigTypeTag() == .Pointer and !lhs_ty.isSlice(); - const rhs_single_ptr = rhs_ty.zigTypeTag() == .Pointer and !rhs_ty.isSlice(); + const lhs_single_ptr = lhs_ty.isSinglePointer(); + const rhs_single_ptr = rhs_ty.isSinglePointer(); const lhs_sub_val = if (lhs_single_ptr) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val; const rhs_sub_val = if (rhs_single_ptr) (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).? else rhs_val; var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded); @@ -9160,17 +9160,21 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, inst: Air.Inst.R .Array => t.arrayInfo(), .Pointer => blk: { const ptrinfo = t.ptrInfo().data; - if (ptrinfo.size == .Slice) { - const val = try sema.resolveConstValue(block, src, inst); - return Type.ArrayInfo{ - .elem_type = t.childType(), - .sentinel = t.sentinel(), - .len = val.sliceLen(sema.mod), - }; + switch (ptrinfo.size) { + .Slice, .Many => { + const val = try sema.resolveConstValue(block, src, inst); + return Type.ArrayInfo{ + .elem_type = t.childType(), + .sentinel = t.sentinel(), + .len = val.sliceLen(sema.mod), + }; + }, + .One => { + if (ptrinfo.pointee_type.zigTypeTag() != .Array) return null; + break :blk ptrinfo.pointee_type.arrayInfo(); + }, + .C => return null, } - if (ptrinfo.pointee_type.zigTypeTag() != .Array) return null; - if (ptrinfo.size != .One) return null; - break :blk ptrinfo.pointee_type.arrayInfo(); }, else => null, }; diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index d608cba98b..12ead179f4 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -709,6 +709,31 @@ test "string concatenation" { try expect(b[len] == 0); } +fn manyptrConcat(comptime s: [*:0]const u8) [*:0]const u8 { + return "very " ++ s; +} + +test "comptime manyptr concatenation" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + + const s = "epic"; + const actual = manyptrConcat(s); + const expected = "very epic"; + + const len = mem.len(actual); + const len_with_null = len + 1; + { + var i: u32 = 0; + while (i < len_with_null) : (i += 1) { + try expect(actual[i] == expected[i]); + } + } + try expect(actual[len] == 0); + try expect(expected[len] == 0); +} + test "thread local variable" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
