aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-11-29 14:29:50 +0200
committerVeikka Tuominen <git@vexu.eu>2022-11-29 15:47:02 +0200
commit6337c04244d9c27cc6535340347d4c127f4742eb (patch)
tree3e70b1474b28a0f10428255648b59ab64a71b35d /src/Sema.zig
parent6f9c7e33b956686ebfd4690c7f85a602d0ac9ffe (diff)
downloadzig-6337c04244d9c27cc6535340347d4c127f4742eb.tar.gz
zig-6337c04244d9c27cc6535340347d4c127f4742eb.zip
Sema: improve panic for slice start index being greater than end index
Closes #13689
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig64
1 files changed, 55 insertions, 9 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index b8b8f3738a..d35c4e3881 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -12437,7 +12437,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
else
try sema.resolveInst(.zero);
- return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src);
+ return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src, true);
}
fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -12460,7 +12460,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
else
try sema.resolveInst(.zero);
- return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src);
+ return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src, true);
}
fn zirArithmetic(
@@ -12480,7 +12480,7 @@ fn zirArithmetic(
const lhs = try sema.resolveInst(extra.lhs);
const rhs = try sema.resolveInst(extra.rhs);
- return sema.analyzeArithmetic(block, zir_tag, lhs, rhs, sema.src, lhs_src, rhs_src);
+ return sema.analyzeArithmetic(block, zir_tag, lhs, rhs, sema.src, lhs_src, rhs_src, true);
}
fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -13776,6 +13776,7 @@ fn analyzeArithmetic(
src: LazySrcLoc,
lhs_src: LazySrcLoc,
rhs_src: LazySrcLoc,
+ want_safety: bool,
) CompileError!Air.Inst.Ref {
const lhs_ty = sema.typeOf(lhs);
const rhs_ty = sema.typeOf(rhs);
@@ -14204,7 +14205,7 @@ fn analyzeArithmetic(
};
try sema.requireRuntimeBlock(block, src, rs.src);
- if (block.wantSafety()) {
+ if (block.wantSafety() and want_safety) {
if (scalar_tag == .Int) {
const maybe_op_ov: ?Air.Inst.Tag = switch (rs.air_tag) {
.add => .add_with_overflow,
@@ -22334,6 +22335,47 @@ fn panicIndexOutOfBounds(
try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
}
+fn panicStartLargerThanEnd(
+ sema: *Sema,
+ parent_block: *Block,
+ src: LazySrcLoc,
+ start: Air.Inst.Ref,
+ end: Air.Inst.Ref,
+) !void {
+ assert(!parent_block.is_comptime);
+ const ok = try parent_block.addBinOp(.cmp_lte, start, end);
+ const gpa = sema.gpa;
+
+ var fail_block: Block = .{
+ .parent = parent_block,
+ .sema = sema,
+ .src_decl = parent_block.src_decl,
+ .namespace = parent_block.namespace,
+ .wip_capture_scope = parent_block.wip_capture_scope,
+ .instructions = .{},
+ .inlining = parent_block.inlining,
+ .is_comptime = false,
+ };
+
+ defer fail_block.instructions.deinit(gpa);
+
+ {
+ const this_feature_is_implemented_in_the_backend =
+ sema.mod.comp.bin_file.options.use_llvm;
+
+ if (!this_feature_is_implemented_in_the_backend) {
+ // TODO implement this feature in all the backends and then delete this branch
+ _ = try fail_block.addNoOp(.breakpoint);
+ _ = try fail_block.addNoOp(.unreach);
+ } else {
+ const panic_fn = try sema.getBuiltin("panicStartGreaterThanEnd");
+ const args: [2]Air.Inst.Ref = .{ start, end };
+ _ = try sema.analyzeCall(&fail_block, panic_fn, src, src, .auto, false, &args, null);
+ }
+ }
+ try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
+}
+
fn panicSentinelMismatch(
sema: *Sema,
parent_block: *Block,
@@ -28028,7 +28070,11 @@ fn analyzeSlice(
}
}
- const new_len = try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src);
+ if (block.wantSafety() and !block.is_comptime) {
+ // requirement: start <= end
+ try sema.panicStartLargerThanEnd(block, src, start, end);
+ }
+ const new_len = try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src, false);
const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len);
const new_ptr_ty_info = sema.typeOf(new_ptr).ptrInfo().data;
@@ -28063,10 +28109,10 @@ fn analyzeSlice(
const actual_len = if (slice_ty.sentinel() == null)
slice_len_inst
else
- try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src);
+ try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);
const actual_end = if (slice_sentinel != null)
- try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src)
+ try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true)
else
end;
@@ -28131,11 +28177,11 @@ fn analyzeSlice(
if (slice_ty.sentinel() == null) break :blk slice_len_inst;
// we have to add one because slice lengths don't include the sentinel
- break :blk try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src);
+ break :blk try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);
} else null;
if (opt_len_inst) |len_inst| {
const actual_end = if (slice_sentinel != null)
- try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src)
+ try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true)
else
end;
try sema.panicIndexOutOfBounds(block, src, actual_end, len_inst, .cmp_lte);