aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-06-30 17:22:16 +0300
committerVeikka Tuominen <git@vexu.eu>2022-07-01 10:22:25 +0300
commitae7b32eb62cb00a09fe2e0e30b307eb83e9f0a86 (patch)
treeabe5edeef5d656feb5dcf82d5a8e93db67fd2afc /src
parent3c73f711771e41e9176e973c64484f0ce5e0eeed (diff)
downloadzig-ae7b32eb62cb00a09fe2e0e30b307eb83e9f0a86.tar.gz
zig-ae7b32eb62cb00a09fe2e0e30b307eb83e9f0a86.zip
Sema: validate deref operator type and value
Diffstat (limited to 'src')
-rw-r--r--src/AstGen.zig2
-rw-r--r--src/Sema.zig27
-rw-r--r--src/Zir.zig6
-rw-r--r--src/print_zir.zig1
4 files changed, 36 insertions, 0 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index c9abb1859b..8707728313 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -812,6 +812,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
.deref => {
const lhs = try expr(gz, scope, .none, node_datas[node].lhs);
+ _ = try gz.addUnTok(.validate_deref, lhs, main_tokens[node]);
switch (rl) {
.ref => return lhs,
else => {
@@ -2500,6 +2501,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.memset,
.validate_array_init_ty,
.validate_struct_init_ty,
+ .validate_deref,
=> break :b true,
}
} else switch (maybe_unused_result) {
diff --git a/src/Sema.zig b/src/Sema.zig
index 30cebe18b3..0e7188a6c9 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1080,6 +1080,11 @@ fn analyzeBodyInner(
i += 1;
continue;
},
+ .validate_deref => {
+ try sema.zirValidateDeref(block, inst);
+ i += 1;
+ continue;
+ },
.@"export" => {
try sema.zirExport(block, inst);
i += 1;
@@ -3849,6 +3854,28 @@ fn zirValidateArrayInit(
}
}
+fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
+ const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
+ const src = inst_data.src();
+ const operand_src: LazySrcLoc = .{ .token_offset = inst_data.src_tok + 1 };
+ const operand = try sema.resolveInst(inst_data.operand);
+ const operand_ty = sema.typeOf(operand);
+
+ if (operand_ty.zigTypeTag() != .Pointer) {
+ return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(sema.mod)});
+ } else switch (operand_ty.ptrSize()) {
+ .One, .C => {},
+ .Many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{}'", .{operand_ty.fmt(sema.mod)}),
+ .Slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(sema.mod)}),
+ }
+
+ if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
+ if (val.isUndef()) {
+ return sema.fail(block, src, "cannot dereference undefined value", .{});
+ }
+ }
+}
+
fn failWithBadMemberAccess(
sema: *Sema,
block: *Block,
diff --git a/src/Zir.zig b/src/Zir.zig
index e6acfe8ed2..26bb09860d 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -729,6 +729,9 @@ pub const Inst = struct {
/// Same as `validate_array_init` but additionally communicates that the
/// resulting array initialization value is within a comptime scope.
validate_array_init_comptime,
+ /// Check that operand type supports the dereference operand (.*).
+ /// Uses the `un_tok` field.
+ validate_deref,
/// A struct literal with a specified type, with no fields.
/// Uses the `un_node` field.
struct_init_empty,
@@ -1156,6 +1159,7 @@ pub const Inst = struct {
.validate_struct_init_comptime,
.validate_array_init,
.validate_array_init_comptime,
+ .validate_deref,
.struct_init_empty,
.struct_init,
.struct_init_ref,
@@ -1309,6 +1313,7 @@ pub const Inst = struct {
.validate_struct_init_comptime,
.validate_array_init,
.validate_array_init_comptime,
+ .validate_deref,
.@"export",
.export_value,
.set_cold,
@@ -1709,6 +1714,7 @@ pub const Inst = struct {
.validate_struct_init_comptime = .pl_node,
.validate_array_init = .pl_node,
.validate_array_init_comptime = .pl_node,
+ .validate_deref = .un_tok,
.struct_init_empty = .un_node,
.field_type = .pl_node,
.field_type_ref = .pl_node,
diff --git a/src/print_zir.zig b/src/print_zir.zig
index 480a3e2a4f..fe8446b34a 100644
--- a/src/print_zir.zig
+++ b/src/print_zir.zig
@@ -242,6 +242,7 @@ const Writer = struct {
.ret_tok,
.ensure_err_payload_void,
.closure_capture,
+ .validate_deref,
=> try self.writeUnTok(stream, inst),
.bool_br_and,