aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorRobin Voetter <robin@voetter.nl>2021-10-21 13:16:47 +0200
committerRobin Voetter <robin@voetter.nl>2021-10-21 16:24:18 +0200
commit1d3382202029cde2e00d7747ec0ea53a5df68047 (patch)
tree168f541921f59956be4d06982467cd636274fefb /src/Sema.zig
parenta0e195120dd3dd7919fd249a6ce2201da9395898 (diff)
downloadzig-1d3382202029cde2e00d7747ec0ea53a5df68047.tar.gz
zig-1d3382202029cde2e00d7747ec0ea53a5df68047.zip
stage2: forbid double dereference in Sema.elemVal
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig107
1 files changed, 26 insertions, 81 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 8ac31387f4..d0a94d3fd8 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -11494,117 +11494,62 @@ fn elemVal(
sema: *Sema,
block: *Block,
src: LazySrcLoc,
- array_maybe_ptr: Air.Inst.Ref,
+ array: Air.Inst.Ref,
elem_index: Air.Inst.Ref,
elem_index_src: LazySrcLoc,
) CompileError!Air.Inst.Ref {
- const array_ptr_src = src; // TODO better source location
- const maybe_ptr_ty = sema.typeOf(array_maybe_ptr);
- switch (maybe_ptr_ty.zigTypeTag()) {
- .Pointer => switch (maybe_ptr_ty.ptrSize()) {
+ const array_src = src; // TODO better source location
+ const array_ty = sema.typeOf(array);
+
+ if (!array_ty.isIndexable()) {
+ return sema.fail(block, src, "array access of non-indexable type '{}'", .{array_ty});
+ }
+
+ switch (array_ty.zigTypeTag()) {
+ .Pointer => switch (array_ty.ptrSize()) {
.Slice => {
- const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array_maybe_ptr);
+ const maybe_slice_val = try sema.resolveDefinedValue(block, array_src, array);
const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
const runtime_src = if (maybe_slice_val) |slice_val| rs: {
const index_val = maybe_index_val orelse break :rs elem_index_src;
const index = @intCast(usize, index_val.toUnsignedInt());
const elem_val = try slice_val.elemValue(sema.arena, index);
- return sema.addConstant(maybe_ptr_ty.elemType2(), elem_val);
- } else array_ptr_src;
+ return sema.addConstant(array_ty.elemType2(), elem_val);
+ } else array_src;
try sema.requireRuntimeBlock(block, runtime_src);
- return block.addBinOp(.slice_elem_val, array_maybe_ptr, elem_index);
+ return block.addBinOp(.slice_elem_val, array, elem_index);
},
.Many, .C => {
- if (try sema.resolveDefinedValue(block, src, array_maybe_ptr)) |ptr_val| {
+ if (try sema.resolveDefinedValue(block, src, array)) |ptr_val| {
_ = ptr_val;
return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{});
}
try sema.requireRuntimeBlock(block, src);
- return block.addBinOp(.ptr_elem_val, array_maybe_ptr, elem_index);
+ return block.addBinOp(.ptr_elem_val, array, elem_index);
},
.One => {
- const indexable_ty = maybe_ptr_ty.childType();
- switch (indexable_ty.zigTypeTag()) {
- .Pointer => switch (indexable_ty.ptrSize()) {
- .Slice => {
- // We have a pointer to a slice and we want an element value.
- if (try sema.isComptimeKnown(block, src, array_maybe_ptr)) {
- const slice = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src);
- if (try sema.resolveDefinedValue(block, src, slice)) |slice_val| {
- _ = slice_val;
- return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known slice", .{});
- }
- try sema.requireRuntimeBlock(block, src);
- return block.addBinOp(.slice_elem_val, slice, elem_index);
- }
- try sema.requireRuntimeBlock(block, src);
- return block.addBinOp(.ptr_slice_elem_val, array_maybe_ptr, elem_index);
- },
- .Many, .C => {
- // We have a pointer to a pointer and we want an element value.
- if (try sema.isComptimeKnown(block, src, array_maybe_ptr)) {
- const ptr = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src);
- if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| {
- _ = ptr_val;
- return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{});
- }
- try sema.requireRuntimeBlock(block, src);
- return block.addBinOp(.ptr_elem_val, ptr, elem_index);
- }
- try sema.requireRuntimeBlock(block, src);
- return block.addBinOp(.ptr_ptr_elem_val, array_maybe_ptr, elem_index);
- },
- .One => {
- const array_ty = indexable_ty.childType();
- if (array_ty.zigTypeTag() == .Array) {
- // We have a double pointer to an array, and we want an element
- // value. This can happen with this code for example:
- // var a: *[1]u8 = undefined; _ = a[0];
- const array_ptr = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src);
- const ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);
- return sema.analyzeLoad(block, src, ptr, elem_index_src);
- } else return sema.fail(
- block,
- array_ptr_src,
- "expected pointer, found '{}'",
- .{array_ty},
- );
- },
- },
- .Array => {
- const ptr = try sema.elemPtr(block, src, array_maybe_ptr, elem_index, elem_index_src);
- return sema.analyzeLoad(block, src, ptr, elem_index_src);
- },
- else => return sema.fail(
- block,
- array_ptr_src,
- "expected pointer, found '{}'",
- .{indexable_ty},
- ),
- }
+ assert(array_ty.childType().zigTypeTag() == .Array);
+ const elem_ptr = try sema.elemPtr(block, src, array, elem_index, elem_index_src);
+ return sema.analyzeLoad(block, src, elem_ptr, elem_index_src);
},
},
.Array => {
- if (try sema.resolveMaybeUndefVal(block, src, array_maybe_ptr)) |array_val| {
- const elem_ty = maybe_ptr_ty.childType();
- const opt_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
+ if (try sema.resolveMaybeUndefVal(block, src, array)) |array_val| {
+ const elem_ty = array_ty.childType();
if (array_val.isUndef()) return sema.addConstUndef(elem_ty);
- if (opt_index_val) |index_val| {
+ const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
+ if (maybe_index_val) |index_val| {
const index = @intCast(usize, index_val.toUnsignedInt());
const elem_val = try array_val.elemValue(sema.arena, index);
return sema.addConstant(elem_ty, elem_val);
}
}
try sema.requireRuntimeBlock(block, src);
- return block.addBinOp(.array_elem_val, array_maybe_ptr, elem_index);
+ return block.addBinOp(.array_elem_val, array, elem_index);
},
- else => return sema.fail(
- block,
- array_ptr_src,
- "expected pointer or array; found '{}'",
- .{maybe_ptr_ty},
- ),
+ .Vector => return sema.fail(block, src, "TODO implement Sema for elemVal for vector", .{}),
+ else => unreachable,
}
}