authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-19 14:36:41+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-20 00:50:13+03:00
log541b3e3a31946475f29d21e7a742bf80c5952791
tree4516d103301ab7913786679f3f2e988bf7029eb5
parentfb91483e48fe6cfa21edc613f266e27bd6bf9dbf

Sema: check pointer qualifiers before implicit cast

Closes #12881

28 files changed, 243 insertions(+), 175 deletions(-)

lib/std/json.zig+3-3
......@@ -1560,7 +1560,7 @@ fn parseInternal(
15601560 }
15611561 }
15621562 if (field.is_comptime) {
1563 if (!try parsesTo(field.field_type, @ptrCast(*const field.field_type, field.default_value.?).*, tokens, child_options)) {
1563 if (!try parsesTo(field.field_type, @ptrCast(*align(1) const field.field_type, field.default_value.?).*, tokens, child_options)) {
15641564 return error.UnexpectedValue;
15651565 }
15661566 } else {
......@@ -1587,7 +1587,7 @@ fn parseInternal(
15871587 if (!fields_seen[i]) {
15881588 if (field.default_value) |default_ptr| {
15891589 if (!field.is_comptime) {
1590 const default = @ptrCast(*const field.field_type, default_ptr).*;
1590 const default = @ptrCast(*align(1) const field.field_type, default_ptr).*;
15911591 @field(r, field.name) = default;
15921592 }
15931593 } else {
......@@ -1667,7 +1667,7 @@ fn parseInternal(
16671667 }
16681668
16691669 if (ptrInfo.sentinel) |some| {
1670 const sentinel_value = @ptrCast(*const ptrInfo.child, some).*;
1670 const sentinel_value = @ptrCast(*align(1) const ptrInfo.child, some).*;
16711671 try arraylist.append(sentinel_value);
16721672 const output = arraylist.toOwnedSlice();
16731673 return output[0 .. output.len - 1 :sentinel_value];
lib/std/mem.zig+12-11
......@@ -297,7 +297,7 @@ pub fn zeroes(comptime T: type) T {
297297 },
298298 .Array => |info| {
299299 if (info.sentinel) |sentinel_ptr| {
300 const sentinel = @ptrCast(*const info.child, sentinel_ptr).*;
300 const sentinel = @ptrCast(*align(1) const info.child, sentinel_ptr).*;
301301 return [_:sentinel]info.child{zeroes(info.child)} ** info.len;
302302 }
303303 return [_]info.child{zeroes(info.child)} ** info.len;
......@@ -443,7 +443,7 @@ pub fn zeroInit(comptime T: type, init: anytype) T {
443443
444444 inline for (struct_info.fields) |field| {
445445 if (field.default_value) |default_value_ptr| {
446 const default_value = @ptrCast(*const field.field_type, default_value_ptr).*;
446 const default_value = @ptrCast(*align(1) const field.field_type, default_value_ptr).*;
447447 @field(value, field.name) = default_value;
448448 }
449449 }
......@@ -687,7 +687,7 @@ pub fn span(ptr: anytype) Span(@TypeOf(ptr)) {
687687 const l = len(ptr);
688688 const ptr_info = @typeInfo(Result).Pointer;
689689 if (ptr_info.sentinel) |s_ptr| {
690 const s = @ptrCast(*const ptr_info.child, s_ptr).*;
690 const s = @ptrCast(*align(1) const ptr_info.child, s_ptr).*;
691691 return ptr[0..l :s];
692692 } else {
693693 return ptr[0..l];
......@@ -719,7 +719,7 @@ fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type {
719719 // to find the value searched for, which is only the case if it matches
720720 // the sentinel of the type passed.
721721 if (array_info.sentinel) |sentinel_ptr| {
722 const sentinel = @ptrCast(*const array_info.child, sentinel_ptr).*;
722 const sentinel = @ptrCast(*align(1) const array_info.child, sentinel_ptr).*;
723723 if (end == sentinel) {
724724 new_ptr_info.sentinel = &end;
725725 } else {
......@@ -734,7 +734,7 @@ fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type {
734734 // to find the value searched for, which is only the case if it matches
735735 // the sentinel of the type passed.
736736 if (ptr_info.sentinel) |sentinel_ptr| {
737 const sentinel = @ptrCast(*const ptr_info.child, sentinel_ptr).*;
737 const sentinel = @ptrCast(*align(1) const ptr_info.child, sentinel_ptr).*;
738738 if (end == sentinel) {
739739 new_ptr_info.sentinel = &end;
740740 } else {
......@@ -772,7 +772,7 @@ pub fn sliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) SliceTo(@Typ
772772 const length = lenSliceTo(ptr, end);
773773 const ptr_info = @typeInfo(Result).Pointer;
774774 if (ptr_info.sentinel) |s_ptr| {
775 const s = @ptrCast(*const ptr_info.child, s_ptr).*;
775 const s = @ptrCast(*align(1) const ptr_info.child, s_ptr).*;
776776 return ptr[0..length :s];
777777 } else {
778778 return ptr[0..length];
......@@ -825,7 +825,7 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize {
825825 .One => switch (@typeInfo(ptr_info.child)) {
826826 .Array => |array_info| {
827827 if (array_info.sentinel) |sentinel_ptr| {
828 const sentinel = @ptrCast(*const array_info.child, sentinel_ptr).*;
828 const sentinel = @ptrCast(*align(1) const array_info.child, sentinel_ptr).*;
829829 if (sentinel == end) {
830830 return indexOfSentinel(array_info.child, end, ptr);
831831 }
......@@ -835,7 +835,7 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize {
835835 else => {},
836836 },
837837 .Many => if (ptr_info.sentinel) |sentinel_ptr| {
838 const sentinel = @ptrCast(*const ptr_info.child, sentinel_ptr).*;
838 const sentinel = @ptrCast(*align(1) const ptr_info.child, sentinel_ptr).*;
839839 // We may be looking for something other than the sentinel,
840840 // but iterating past the sentinel would be a bug so we need
841841 // to check for both.
......@@ -849,7 +849,7 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize {
849849 },
850850 .Slice => {
851851 if (ptr_info.sentinel) |sentinel_ptr| {
852 const sentinel = @ptrCast(*const ptr_info.child, sentinel_ptr).*;
852 const sentinel = @ptrCast(*align(1) const ptr_info.child, sentinel_ptr).*;
853853 if (sentinel == end) {
854854 return indexOfSentinel(ptr_info.child, sentinel, ptr);
855855 }
......@@ -911,7 +911,7 @@ pub fn len(value: anytype) usize {
911911 .Many => {
912912 const sentinel_ptr = info.sentinel orelse
913913 @compileError("length of pointer with no sentinel");
914 const sentinel = @ptrCast(*const info.child, sentinel_ptr).*;
914 const sentinel = @ptrCast(*align(1) const info.child, sentinel_ptr).*;
915915 return indexOfSentinel(info.child, sentinel, value);
916916 },
917917 .C => {
......@@ -2882,7 +2882,8 @@ fn AsBytesReturnType(comptime P: type) type {
28822882/// Given a pointer to a single item, returns a slice of the underlying bytes, preserving pointer attributes.
28832883pub fn asBytes(ptr: anytype) AsBytesReturnType(@TypeOf(ptr)) {
28842884 const P = @TypeOf(ptr);
2885 return @ptrCast(AsBytesReturnType(P), ptr);
2885 const T = AsBytesReturnType(P);
2886 return @ptrCast(T, @alignCast(meta.alignment(T), ptr));
28862887}
28872888
28882889test "asBytes" {
lib/std/meta.zig+2-2
......@@ -204,12 +204,12 @@ pub fn sentinel(comptime T: type) ?Elem(T) {
204204 switch (info.size) {
205205 .Many, .Slice => {
206206 const sentinel_ptr = info.sentinel orelse return null;
207 return @ptrCast(*const info.child, sentinel_ptr).*;
207 return @ptrCast(*align(1) const info.child, sentinel_ptr).*;
208208 },
209209 .One => switch (@typeInfo(info.child)) {
210210 .Array => |array_info| {
211211 const sentinel_ptr = array_info.sentinel orelse return null;
212 return @ptrCast(*const array_info.child, sentinel_ptr).*;
212 return @ptrCast(*align(1) const array_info.child, sentinel_ptr).*;
213213 },
214214 else => {},
215215 },
lib/std/os/linux.zig+1-1
......@@ -888,7 +888,7 @@ else
888888const vdso_clock_gettime_ty = if (builtin.zig_backend == .stage1)
889889 fn (i32, *timespec) callconv(.C) usize
890890else
891 *const fn (i32, *timespec) callconv(.C) usize;
891 *align(1) const fn (i32, *timespec) callconv(.C) usize;
892892
893893pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
894894 if (@hasDecl(VDSO, "CGT_SYM")) {
lib/std/zig/c_translation.zig+1-1
......@@ -193,7 +193,7 @@ pub fn sizeof(target: anytype) usize {
193193 const array_info = @typeInfo(ptr.child).Array;
194194 if ((array_info.child == u8 or array_info.child == u16) and
195195 array_info.sentinel != null and
196 @ptrCast(*const array_info.child, array_info.sentinel.?).* == 0)
196 @ptrCast(*align(1) const array_info.child, array_info.sentinel.?).* == 0)
197197 {
198198 // length of the string plus one for the null terminator.
199199 return (array_info.len + 1) * @sizeOf(array_info.child);
src/Sema.zig+64-17
......@@ -22811,6 +22811,7 @@ fn coerceExtra(
2281122811 if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and
2281222812 inst_ty.isPtrLikeOptional() and inst_ty.elemType2().zigTypeTag() != .Pointer)
2281322813 {
22814 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;
2281422815 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
2281522816 }
2281622817
......@@ -22843,14 +22844,12 @@ fn coerceExtra(
2284322844 single_item: {
2284422845 if (dest_info.size != .One) break :single_item;
2284522846 if (!inst_ty.isSinglePointer()) break :single_item;
22847 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
2284622848 const ptr_elem_ty = inst_ty.childType();
2284722849 const array_ty = dest_info.pointee_type;
2284822850 if (array_ty.zigTypeTag() != .Array) break :single_item;
2284922851 const array_elem_ty = array_ty.childType();
2285022852 const dest_is_mut = dest_info.mutable;
22851 if (inst_ty.isConstPtr() and dest_is_mut) break :single_item;
22852 if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :single_item;
22853 if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :single_item;
2285422853 switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) {
2285522854 .ok => {},
2285622855 else => break :single_item,
......@@ -22861,14 +22860,11 @@ fn coerceExtra(
2286122860 // Coercions where the source is a single pointer to an array.
2286222861 src_array_ptr: {
2286322862 if (!inst_ty.isSinglePointer()) break :src_array_ptr;
22863 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
2286422864 const array_ty = inst_ty.childType();
2286522865 if (array_ty.zigTypeTag() != .Array) break :src_array_ptr;
22866 const len0 = array_ty.arrayLen() == 0;
2286722866 const array_elem_type = array_ty.childType();
2286822867 const dest_is_mut = dest_info.mutable;
22869 if (inst_ty.isConstPtr() and dest_is_mut and !len0) break :src_array_ptr;
22870 if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :src_array_ptr;
22871 if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :src_array_ptr;
2287222868
2287322869 const dst_elem_type = dest_info.pointee_type;
2287422870 switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src)) {
......@@ -22905,6 +22901,7 @@ fn coerceExtra(
2290522901
2290622902 // coercion from C pointer
2290722903 if (inst_ty.isCPtr()) src_c_ptr: {
22904 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :src_c_ptr;
2290822905 // In this case we must add a safety check because the C pointer
2290922906 // could be null.
2291022907 const src_elem_ty = inst_ty.childType();
......@@ -22920,7 +22917,7 @@ fn coerceExtra(
2292022917 // cast from *T and [*]T to *anyopaque
2292122918 // but don't do it if the source type is a double pointer
2292222919 if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer and
22923 inst_ty.childType().zigTypeTag() != .Pointer)
22920 inst_ty.childType().zigTypeTag() != .Pointer and sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2292422921 {
2292522922 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
2292622923 }
......@@ -22954,6 +22951,7 @@ fn coerceExtra(
2295422951 return try sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src);
2295522952 },
2295622953 .Pointer => p: {
22954 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :p;
2295722955 const inst_info = inst_ty.ptrInfo().data;
2295822956 switch (try sema.coerceInMemoryAllowed(
2295922957 block,
......@@ -22984,7 +22982,7 @@ fn coerceExtra(
2298422982 // pointer to anonymous struct to pointer to union
2298522983 if (inst_ty.isSinglePointer() and
2298622984 inst_ty.childType().isAnonStruct() and
22987 !dest_info.mutable)
22985 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2298822986 {
2298922987 return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
2299022988 }
......@@ -22993,7 +22991,7 @@ fn coerceExtra(
2299322991 // pointer to anonymous struct to pointer to struct
2299422992 if (inst_ty.isSinglePointer() and
2299522993 inst_ty.childType().isAnonStruct() and
22996 !dest_info.mutable)
22994 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2299722995 {
2299822996 return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
2299922997 }
......@@ -23002,7 +23000,7 @@ fn coerceExtra(
2300223000 // pointer to tuple to pointer to array
2300323001 if (inst_ty.isSinglePointer() and
2300423002 inst_ty.childType().isTuple() and
23005 !dest_info.mutable)
23003 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2300623004 {
2300723005 return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
2300823006 }
......@@ -23011,10 +23009,8 @@ fn coerceExtra(
2301123009 },
2301223010 .Slice => {
2301323011 // pointer to tuple to slice
23014 if (inst_ty.isSinglePointer() and
23015 inst_ty.childType().isTuple() and
23016 (!dest_info.mutable or inst_ty.ptrIsMutable() or inst_ty.childType().tupleFields().types.len == 0) and
23017 dest_info.size == .Slice)
23012 if (inst_ty.isSinglePointer() and inst_ty.childType().isTuple() and dest_info.size == .Slice and
23013 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2301823014 {
2301923015 return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src);
2302023016 }
......@@ -23043,6 +23039,7 @@ fn coerceExtra(
2304323039 },
2304423040 .Many => p: {
2304523041 if (!inst_ty.isSlice()) break :p;
23042 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :p;
2304623043 const inst_info = inst_ty.ptrInfo().data;
2304723044
2304823045 switch (try sema.coerceInMemoryAllowed(
......@@ -25438,6 +25435,57 @@ fn coerceArrayPtrToSlice(
2543825435 return block.addTyOp(.array_to_slice, dest_ty, inst);
2543925436}
2544025437
25438fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_result: *InMemoryCoercionResult) bool {
25439 const dest_info = dest_ty.ptrInfo().data;
25440 const inst_info = inst_ty.ptrInfo().data;
25441 const len0 = (inst_info.pointee_type.zigTypeTag() == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel() == 0 or
25442 (inst_info.pointee_type.arrayLen() == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or
25443 (inst_info.pointee_type.isTuple() and inst_info.pointee_type.tupleFields().types.len == 0);
25444
25445 const ok_cv_qualifiers =
25446 ((inst_info.mutable or !dest_info.mutable) or len0) and
25447 (!inst_info.@"volatile" or dest_info.@"volatile");
25448
25449 if (!ok_cv_qualifiers) {
25450 in_memory_result.* = .{ .ptr_qualifiers = .{
25451 .actual_const = !inst_info.mutable,
25452 .wanted_const = !dest_info.mutable,
25453 .actual_volatile = inst_info.@"volatile",
25454 .wanted_volatile = dest_info.@"volatile",
25455 } };
25456 return false;
25457 }
25458 if (dest_info.@"addrspace" != inst_info.@"addrspace") {
25459 in_memory_result.* = .{ .ptr_addrspace = .{
25460 .actual = inst_info.@"addrspace",
25461 .wanted = dest_info.@"addrspace",
25462 } };
25463 return false;
25464 }
25465 if (inst_info.@"align" == 0 and dest_info.@"align" == 0) return true;
25466 if (len0) return true;
25467 const target = sema.mod.getTarget();
25468
25469 const inst_align = if (inst_info.@"align" != 0)
25470 inst_info.@"align"
25471 else
25472 inst_info.pointee_type.abiAlignment(target);
25473
25474 const dest_align = if (dest_info.@"align" != 0)
25475 dest_info.@"align"
25476 else
25477 dest_info.pointee_type.abiAlignment(target);
25478
25479 if (dest_align > inst_align) {
25480 in_memory_result.* = .{ .ptr_alignment = .{
25481 .actual = inst_align,
25482 .wanted = dest_align,
25483 } };
25484 return false;
25485 }
25486 return true;
25487}
25488
2544125489fn coerceCompatiblePtrs(
2544225490 sema: *Sema,
2544325491 block: *Block,
......@@ -25445,13 +25493,12 @@ fn coerceCompatiblePtrs(
2544525493 inst: Air.Inst.Ref,
2544625494 inst_src: LazySrcLoc,
2544725495) !Air.Inst.Ref {
25448 // TODO check const/volatile/alignment
25496 const inst_ty = sema.typeOf(inst);
2544925497 if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {
2545025498 // The comptime Value representation is compatible with both types.
2545125499 return sema.addConstant(dest_ty, val);
2545225500 }
2545325501 try sema.requireRuntimeBlock(block, inst_src, null);
25454 const inst_ty = sema.typeOf(inst);
2545525502 const inst_allows_zero = (inst_ty.zigTypeTag() == .Pointer and inst_ty.ptrAllowsZero()) or true;
2545625503 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero() and
2545725504 try sema.typeHasRuntimeBits(block, sema.src, dest_ty.elemType2()))
test/behavior/bugs/4328.zig+1-1
......@@ -13,7 +13,7 @@ extern fn fopen([*c]const u8, [*c]const u8) [*c]FILE;
1313const S = extern struct {
1414 state: c_short,
1515
16 extern fn s_do_thing([*c]S, b: c_int) c_short;
16 extern fn s_do_thing([*c]const S, b: c_int) c_short;
1717};
1818
1919test "Extern function calls in @TypeOf" {
test/behavior/cast.zig+2-2
......@@ -1242,13 +1242,13 @@ test "implicit cast *[0]T to E![]const u8" {
12421242
12431243var global_array: [4]u8 = undefined;
12441244test "cast from array reference to fn: comptime fn ptr" {
1245 const f = @ptrCast(*const fn () callconv(.C) void, &global_array);
1245 const f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array);
12461246 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
12471247}
12481248test "cast from array reference to fn: runtime fn ptr" {
12491249 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12501250
1251 var f = @ptrCast(*const fn () callconv(.C) void, &global_array);
1251 var f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array);
12521252 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
12531253}
12541254
test/behavior/slice.zig+2-1
......@@ -322,11 +322,12 @@ test "empty array to slice" {
322322
323323test "@ptrCast slice to pointer" {
324324 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
325 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
325326
326327 const S = struct {
327328 fn doTheTest() !void {
328329 var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
329 var slice: []u8 = &array;
330 var slice: []align(@alignOf(u16)) u8 = &array;
330331 var ptr = @ptrCast(*u16, slice);
331332 try expect(ptr.* == 65535);
332333 }
test/behavior/struct.zig+1-1
......@@ -521,7 +521,7 @@ test "packed struct fields are ordered from LSB to MSB" {
521521 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
522522
523523 var all: u64 = 0x7765443322221111;
524 var bytes: [8]u8 = undefined;
524 var bytes: [8]u8 align(@alignOf(Bitfields)) = undefined;
525525 @memcpy(&bytes, @ptrCast([*]u8, &all), 8);
526526 var bitfields = @ptrCast(*Bitfields, &bytes).*;
527527
test/behavior/type.zig+2-2
......@@ -293,7 +293,7 @@ test "Type.Struct" {
293293 try testing.expectEqual(@as(?*const anyopaque, null), infoB.fields[0].default_value);
294294 try testing.expectEqualSlices(u8, "y", infoB.fields[1].name);
295295 try testing.expectEqual(u32, infoB.fields[1].field_type);
296 try testing.expectEqual(@as(u32, 5), @ptrCast(*const u32, infoB.fields[1].default_value.?).*);
296 try testing.expectEqual(@as(u32, 5), @ptrCast(*align(1) const u32, infoB.fields[1].default_value.?).*);
297297 try testing.expectEqual(@as(usize, 0), infoB.decls.len);
298298 try testing.expectEqual(@as(bool, false), infoB.is_tuple);
299299
......@@ -305,7 +305,7 @@ test "Type.Struct" {
305305 try testing.expectEqual(@as(u8, 3), @ptrCast(*const u8, infoC.fields[0].default_value.?).*);
306306 try testing.expectEqualSlices(u8, "y", infoC.fields[1].name);
307307 try testing.expectEqual(u32, infoC.fields[1].field_type);
308 try testing.expectEqual(@as(u32, 5), @ptrCast(*const u32, infoC.fields[1].default_value.?).*);
308 try testing.expectEqual(@as(u32, 5), @ptrCast(*align(1) const u32, infoC.fields[1].default_value.?).*);
309309 try testing.expectEqual(@as(usize, 0), infoC.decls.len);
310310 try testing.expectEqual(@as(bool, false), infoC.is_tuple);
311311
test/behavior/type_info.zig+3-3
......@@ -295,8 +295,8 @@ fn testStruct() !void {
295295 try expect(unpacked_struct_info.Struct.is_tuple == false);
296296 try expect(unpacked_struct_info.Struct.backing_integer == null);
297297 try expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
298 try expect(@ptrCast(*const u32, unpacked_struct_info.Struct.fields[0].default_value.?).* == 4);
299 try expect(mem.eql(u8, "foobar", @ptrCast(*const *const [6:0]u8, unpacked_struct_info.Struct.fields[1].default_value.?).*));
298 try expect(@ptrCast(*align(1) const u32, unpacked_struct_info.Struct.fields[0].default_value.?).* == 4);
299 try expect(mem.eql(u8, "foobar", @ptrCast(*align(1) const *const [6:0]u8, unpacked_struct_info.Struct.fields[1].default_value.?).*));
300300}
301301
302302const TestStruct = struct {
......@@ -321,7 +321,7 @@ fn testPackedStruct() !void {
321321 try expect(struct_info.Struct.fields[0].alignment == 0);
322322 try expect(struct_info.Struct.fields[2].field_type == f32);
323323 try expect(struct_info.Struct.fields[2].default_value == null);
324 try expect(@ptrCast(*const u32, struct_info.Struct.fields[3].default_value.?).* == 4);
324 try expect(@ptrCast(*align(1) const u32, struct_info.Struct.fields[3].default_value.?).* == 4);
325325 try expect(struct_info.Struct.fields[3].alignment == 0);
326326 try expect(struct_info.Struct.decls.len == 2);
327327 try expect(struct_info.Struct.decls[0].is_pub);
test/cases/compile_errors/attempted_implicit_cast_from_const_T_to_sliceT.zig+1
......@@ -9,3 +9,4 @@ export fn entry() void {
99// target=native
1010//
1111// :3:22: error: expected type '[]u32', found '*const u32'
12// :3:22: note: cast discards const qualifier
test/cases/compile_errors/implicit_cast_between_C_pointer_and_Zig_pointer-bad_const-align-child.zig created+47
......@@ -0,0 +1,47 @@
1export fn a() void {
2 var x: [*c]u8 = undefined;
3 var y: *align(4) u8 = x;
4 _ = y;
5}
6export fn b() void {
7 var x: [*c]const u8 = undefined;
8 var y: *u8 = x;
9 _ = y;
10}
11export fn c() void {
12 var x: [*c]u8 = undefined;
13 var y: *u32 = x;
14 _ = y;
15}
16export fn d() void {
17 var y: *align(1) u32 = undefined;
18 var x: [*c]u32 = y;
19 _ = x;
20}
21export fn e() void {
22 var y: *const u8 = undefined;
23 var x: [*c]u8 = y;
24 _ = x;
25}
26export fn f() void {
27 var y: *u8 = undefined;
28 var x: [*c]u32 = y;
29 _ = x;
30}
31
32// error
33// backend=stage2
34// target=native
35//
36// :3:27: error: expected type '*align(4) u8', found '[*c]u8'
37// :3:27: note: pointer alignment '1' cannot cast into pointer alignment '4'
38// :8:18: error: expected type '*u8', found '[*c]const u8'
39// :8:18: note: cast discards const qualifier
40// :13:19: error: expected type '*u32', found '[*c]u8'
41// :13:19: note: pointer type child 'u8' cannot cast into pointer type child 'u32'
42// :18:22: error: expected type '[*c]u32', found '*align(1) u32'
43// :18:22: note: pointer alignment '1' cannot cast into pointer alignment '4'
44// :23:21: error: expected type '[*c]u8', found '*const u8'
45// :23:21: note: cast discards const qualifier
46// :28:22: error: expected type '[*c]u32', found '*u8'
47// :28:22: note: pointer type child 'u8' cannot cast into pointer type child 'u32'
test/cases/compile_errors/implicit_cast_const_array_to_mutable_slice.zig created+26
......@@ -0,0 +1,26 @@
1export fn entry() void {
2 const buffer: [1]u8 = [_]u8{8};
3 const sliceA: []u8 = &buffer;
4 _ = sliceA;
5}
6export fn entry1() void {
7 const str: *const [0:0]u8 = "";
8 const slice: [:0]u8 = str;
9 _ = slice;
10}
11export fn entry2() void {
12 const str: *const [0:0]u8 = "";
13 const many: [*]u8 = str;
14 _ = many;
15}
16
17// error
18// backend=stage2
19// target=native
20//
21// :3:26: error: expected type '[]u8', found '*const [1]u8'
22// :3:26: note: cast discards const qualifier
23// :8:27: error: expected type '[:0]u8', found '*const [0:0]u8'
24// :8:27: note: cast discards const qualifier
25// :13:25: error: expected type '[*]u8', found '*const [0:0]u8'
26// :13:25: note: cast discards const qualifier
test/cases/compile_errors/implicitly_increasing_slice_alignment.zig created+21
......@@ -0,0 +1,21 @@
1const Foo = packed struct {
2 a: u8,
3 b: u32,
4};
5
6export fn entry() void {
7 var foo = Foo { .a = 1, .b = 10 };
8 foo.b += 1;
9 bar(@as(*[1]u32, &foo.b)[0..]);
10}
11
12fn bar(x: []u32) void {
13 x[0] += 1;
14}
15
16// error
17// backend=stage2
18// target=native
19//
20// :9:22: error: expected type '*[1]u32', found '*align(1) u32'
21// :9:22: note: pointer alignment '1' cannot cast into pointer alignment '4'
test/cases/compile_errors/issue_5221_invalid_struct_init_type_referenced_by_typeInfo_and_passed_into_function.zig created+16
......@@ -0,0 +1,16 @@
1fn ignore(comptime param: anytype) void {_ = param;}
2
3export fn foo() void {
4 const MyStruct = struct {
5 wrong_type: []u8 = "foo",
6 };
7
8 comptime ignore(@typeInfo(MyStruct).Struct.fields[0]);
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :4:22: error: expected type '[]u8', found '*const [3:0]u8'
16// :4:22: note: cast discards const qualifier
test/cases/compile_errors/load_too_many_bytes_from_comptime_reinterpreted_pointer.zig+1-1
......@@ -1,5 +1,5 @@
11export fn entry() void {
2 const float: f32 = 5.99999999999994648725e-01;
2 const float: f32 align(@alignOf(i64)) = 5.99999999999994648725e-01;
33 const float_ptr = &float;
44 const int_ptr = @ptrCast(*const i64, float_ptr);
55 const int_val = int_ptr.*;
test/cases/compile_errors/peer_cast_then_implicit_cast_const_pointer_to_mutable_C_pointer.zig created+11
......@@ -0,0 +1,11 @@
1export fn func() void {
2 var strValue: [*c]u8 = undefined;
3 strValue = strValue orelse "";
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :3:32: error: expected type '[*c]u8', found '*const [0:0]u8'
11// :3:32: note: cast discards const qualifier
test/cases/compile_errors/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig created+24
......@@ -0,0 +1,24 @@
1comptime {
2 const c: [][]const u8 = &.{ "hello", "world" };
3 _ = c;
4}
5comptime {
6 const c: *[2][]const u8 = &.{ "hello", "world" };
7 _ = c;
8}
9const S = struct { a: u8 = 1, b: u32 = 2 };
10comptime {
11 const c: *S = &.{ .a = 2 };
12 _ = c;
13}
14
15// error
16// backend=stage2
17// target=native
18//
19// :2:29: error: expected type '[][]const u8', found '*const tuple{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'
20// :2:29: note: cast discards const qualifier
21// :6:31: error: expected type '*[2][]const u8', found '*const tuple{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'
22// :6:31: note: cast discards const qualifier
23// :11:19: error: expected type '*tmp.S', found '*const struct{comptime a: comptime_int = 2}'
24// :11:19: note: cast discards const qualifier
test/cases/compile_errors/reading_past_end_of_pointer_casted_array.zig+1-1
......@@ -1,7 +1,7 @@
11comptime {
22 const array: [4]u8 = "aoeu".*;
33 const sub_array = array[1..];
4 const int_ptr = @ptrCast(*const u24, sub_array);
4 const int_ptr = @ptrCast(*const u24, @alignCast(@alignOf(u24), sub_array));
55 const deref = int_ptr.*;
66 _ = deref;
77}
test/cases/compile_errors/slice_cannot_have_its_bytes_reinterpreted.zig+1-1
......@@ -1,5 +1,5 @@
11export fn foo() void {
2 const bytes = [1]u8{ 0xfa } ** 16;
2 const bytes align(@alignOf([]const u8)) = [1]u8{0xfa} ** 16;
33 var value = @ptrCast(*const []const u8, &bytes).*;
44 _ = value;
55}
test/cases/compile_errors/stage1/obj/implicit_cast_between_C_pointer_and_Zig_pointer-bad_const-align-child.zig deleted-42
......@@ -1,42 +0,0 @@
1export fn a() void {
2 var x: [*c]u8 = undefined;
3 var y: *align(4) u8 = x;
4 _ = y;
5}
6export fn b() void {
7 var x: [*c]const u8 = undefined;
8 var y: *u8 = x;
9 _ = y;
10}
11export fn c() void {
12 var x: [*c]u8 = undefined;
13 var y: *u32 = x;
14 _ = y;
15}
16export fn d() void {
17 var y: *align(1) u32 = undefined;
18 var x: [*c]u32 = y;
19 _ = x;
20}
21export fn e() void {
22 var y: *const u8 = undefined;
23 var x: [*c]u8 = y;
24 _ = x;
25}
26export fn f() void {
27 var y: *u8 = undefined;
28 var x: [*c]u32 = y;
29 _ = x;
30}
31
32// error
33// backend=stage1
34// target=native
35//
36// tmp.zig:3:27: error: cast increases pointer alignment
37// tmp.zig:8:18: error: cast discards const qualifier
38// tmp.zig:13:19: error: expected type '*u32', found '[*c]u8'
39// tmp.zig:13:19: note: pointer type child 'u8' cannot cast into pointer type child 'u32'
40// tmp.zig:18:22: error: cast increases pointer alignment
41// tmp.zig:23:21: error: cast discards const qualifier
42// tmp.zig:28:22: error: expected type '[*c]u32', found '*u8'
test/cases/compile_errors/stage1/obj/implicit_cast_const_array_to_mutable_slice.zig deleted-12
......@@ -1,12 +0,0 @@
1export fn entry() void {
2 const buffer: [1]u8 = [_]u8{8};
3 const sliceA: []u8 = &buffer;
4 _ = sliceA;
5}
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:3:27: error: cannot cast pointer to array literal to slice type '[]u8'
12// tmp.zig:3:27: note: cast discards const qualifier
test/cases/compile_errors/stage1/obj/implicitly_increasing_slice_alignment.zig deleted-22
......@@ -1,22 +0,0 @@
1const Foo = packed struct {
2 a: u8,
3 b: u32,
4};
5
6export fn entry() void {
7 var foo = Foo { .a = 1, .b = 10 };
8 foo.b += 1;
9 bar(@as(*[1]u32, &foo.b)[0..]);
10}
11
12fn bar(x: []u32) void {
13 x[0] += 1;
14}
15
16// error
17// backend=stage1
18// target=native
19//
20// tmp.zig:9:26: error: cast increases pointer alignment
21// tmp.zig:9:26: note: '*align(1) u32' has alignment 1
22// tmp.zig:9:26: note: '*[1]u32' has alignment 4
test/cases/compile_errors/stage1/obj/issue_5221_invalid_struct_init_type_referenced_by_typeInfo_and_passed_into_function.zig deleted-16
......@@ -1,16 +0,0 @@
1fn ignore(comptime param: anytype) void {_ = param;}
2
3export fn foo() void {
4 const MyStruct = struct {
5 wrong_type: []u8 = "foo",
6 };
7
8 comptime ignore(@typeInfo(MyStruct).Struct.fields[0]);
9}
10
11// error
12// backend=stage1
13// target=native
14//
15// :5:28: error: cannot cast pointer to array literal to slice type '[]u8'
16// :5:28: note: cast discards const qualifier
test/cases/compile_errors/stage1/obj/peer_cast_then_implicit_cast_const_pointer_to_mutable_C_pointer.zig deleted-11
......@@ -1,11 +0,0 @@
1export fn func() void {
2 var strValue: [*c]u8 = undefined;
3 strValue = strValue orelse "";
4}
5
6// error
7// backend=stage1
8// target=native
9//
10// tmp.zig:3:32: error: expected type '[*c]u8', found '*const [0:0]u8'
11// tmp.zig:3:32: note: cast discards const qualifier
test/cases/compile_errors/stage1/obj/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig deleted-24
......@@ -1,24 +0,0 @@
1comptime {
2 const c: [][]const u8 = &.{"hello", "world" };
3 _ = c;
4}
5comptime {
6 const c: *[2][]const u8 = &.{"hello", "world" };
7 _ = c;
8}
9const S = struct {a: u8 = 1, b: u32 = 2};
10comptime {
11 const c: *S = &.{};
12 _ = c;
13}
14
15// error
16// backend=stage1
17// target=native
18//
19// tmp.zig:2:31: error: cannot cast pointer to array literal to slice type '[][]const u8'
20// tmp.zig:2:31: note: cast discards const qualifier
21// tmp.zig:6:33: error: cannot cast pointer to array literal to '*[2][]const u8'
22// tmp.zig:6:33: note: cast discards const qualifier
23// tmp.zig:11:21: error: expected type '*S', found '*const struct:11:21'
24// tmp.zig:11:21: note: cast discards const qualifier