mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Sema: add more validation to zirFieldParentPtr
This commit is contained in:
parent
e6ebf56dd6
commit
a6bf8c2593
10 changed files with 61 additions and 35 deletions
52
src/Sema.zig
52
src/Sema.zig
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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'
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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'
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Loading…
Add table
Reference in a new issue