Sema: add more validation to zirFieldParentPtr

This commit is contained in:
Veikka Tuominen 2022-06-30 22:57:20 +03:00
parent e6ebf56dd6
commit a6bf8c2593
10 changed files with 61 additions and 35 deletions

View file

@ -8378,19 +8378,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
block,
src,
msg,
"unhandled error value: error.{s}",
"unhandled error value: 'error.{s}'",
.{error_name},
);
}
}
if (maybe_msg) |msg| {
try sema.mod.errNoteNonLazy(
operand_ty.declSrcLoc(sema.mod),
msg,
"error set '{}' declared here",
.{operand_ty.fmt(sema.mod)},
);
maybe_msg = null;
try sema.addDeclaredHereNote(msg, operand_ty);
return sema.failWithOwnedErrorMsg(block, msg);
}
@ -17143,9 +17139,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
const field_index = struct_obj.fields.getIndex(field_name) orelse
return sema.failWithBadStructFieldAccess(block, struct_obj, name_src, field_name);
if (field_ptr_ty.zigTypeTag() != .Pointer) {
return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{field_ptr_ty.fmt(sema.mod)});
}
try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);
const field = struct_obj.fields.values()[field_index];
const field_ptr_ty_info = field_ptr_ty.ptrInfo().data;
@ -17168,8 +17162,29 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);
if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {
const payload = field_ptr_val.castTag(.field_ptr).?.data;
return sema.addConstant(result_ptr, payload.container_ptr);
const payload = field_ptr_val.castTag(.field_ptr) orelse {
return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{});
};
if (payload.data.field_index != field_index) {
const msg = msg: {
const msg = try sema.errMsg(
block,
src,
"field '{s}' has index '{d}' but pointer value is index '{d}' of struct '{}'",
.{
field_name,
field_index,
payload.data.field_index,
struct_ty.fmt(sema.mod),
},
);
errdefer msg.destroy(sema.gpa);
try sema.addDeclaredHereNote(msg, struct_ty);
break :msg msg;
};
return sema.failWithOwnedErrorMsg(block, msg);
}
return sema.addConstant(result_ptr, payload.data.container_ptr);
}
try sema.requireRuntimeBlock(block, src);
@ -18515,7 +18530,16 @@ fn fieldVal(
kw_name, child_type.fmt(sema.mod), field_name,
});
},
else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}),
else => {
const msg = msg: {
const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa);
if (child_type.isSlice()) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{});
if (child_type.zigTypeTag() == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{});
break :msg msg;
};
return sema.failWithOwnedErrorMsg(block, msg);
},
}
},
.Struct => if (is_pointer_to) {
@ -18739,7 +18763,7 @@ fn fieldPtr(
},
else => {},
}
return sema.fail(block, src, "type '{}' does not support field access (fieldPtr, {}.{s})", .{ object_ty.fmt(sema.mod), object_ptr_ty.fmt(sema.mod), field_name });
return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)});
}
fn fieldCallBind(

View file

@ -6,13 +6,12 @@ const float_x = @as(f32, 1.0) / @as(f32, 0.0);
export fn entry1() usize { return @sizeOf(@TypeOf(lit_int_x)); }
export fn entry2() usize { return @sizeOf(@TypeOf(lit_float_x)); }
export fn entry3() usize { return @sizeOf(@TypeOf(int_x)); }
export fn entry4() usize { return @sizeOf(@TypeOf(float_x)); }
export fn entry4() usize { return @sizeOf(@TypeOf(float_x)); } // no error on purpose
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:1:21: error: division by zero
// tmp.zig:2:25: error: division by zero
// tmp.zig:3:27: error: division by zero
// tmp.zig:4:31: error: division by zero
// :1:23: error: division by zero here causes undefined behavior
// :2:27: error: division by zero here causes undefined behavior
// :3:29: error: division by zero here causes undefined behavior

View file

@ -13,8 +13,9 @@ fn foo(x: i32) !void {
}
// error
// backend=stage1
// backend=llvm
// target=native
//
// tmp.zig:2:26: error: error.Baz not handled in switch
// tmp.zig:2:26: error: error.Bar not handled in switch
// :2:26: error: switch must handle all possibilities
// :2:26: note: unhandled error value: 'error.Bar'
// :2:26: note: unhandled error value: 'error.Baz'

View file

@ -11,7 +11,7 @@ comptime {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:9:55: error: pointer value not based on parent struct
// :9:55: error: pointer value not based on parent struct

View file

@ -10,7 +10,8 @@ comptime {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:8:29: error: field 'b' has index 1 but pointer value is index 0 of struct 'Foo'
// :8:29: error: field 'b' has index '1' but pointer value is index '0' of struct 'tmp.Foo'
// :1:13: note: struct declared here

View file

@ -6,7 +6,7 @@ export fn foo(a: i32) *Foo {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:5:38: error: expected pointer, found 'i32'
// :5:38: error: expected pointer type, found 'i32'

View file

@ -10,7 +10,7 @@ fn bar(x: *MyType) bool {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:9:13: error: no member named 'blah' in opaque type 'MyType'
// :9:13: error: type '*tmp.MyType' does not support field access

View file

@ -5,7 +5,8 @@ export fn entry() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:3:32: error: type 'type' does not support field access
// :3:32: error: type '[]i32' has no members
// :3:32: note: slice values have 'len' and 'ptr' members

View file

@ -7,7 +7,7 @@ export fn entry(foo: [*]Foo) void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:6:8: error: type '[*]Foo' does not support field access
// :6:8: error: type '[*]tmp.Foo' does not support field access