Sema: validate deref operator type and value
This commit is contained in:
@@ -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) {
|
||||
|
||||
27
src/Sema.zig
27
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user