mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
parent
b47e54ed3f
commit
562ac8be48
@ -2289,6 +2289,14 @@ fn lowerParentPtr(self: *Self, ptr_val: Value, ptr_child_ty: Type) InnerError!WV
|
||||
const offset = @intCast(u32, std.mem.alignForwardGeneric(u64, layout.tag_size, layout.tag_align));
|
||||
break :blk offset;
|
||||
},
|
||||
.Pointer => switch (parent_ty.ptrSize()) {
|
||||
.Slice => switch (field_ptr.field_index) {
|
||||
0 => 0,
|
||||
1 => self.ptrSize(),
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
|
||||
@ -363,11 +363,21 @@ pub fn generateSymbol(
|
||||
const mod = bin_file.options.module.?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const addend = blk: {
|
||||
switch (decl.ty.tag()) {
|
||||
.@"struct" => {
|
||||
switch (decl.ty.zigTypeTag()) {
|
||||
.Struct => {
|
||||
const addend = decl.ty.structFieldOffset(field_ptr.field_index, target);
|
||||
break :blk @intCast(u32, addend);
|
||||
},
|
||||
.Pointer => {
|
||||
assert(decl.ty.isSlice());
|
||||
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
|
||||
const addend = switch (field_ptr.field_index) {
|
||||
0 => 0,
|
||||
1 => decl.ty.slicePtrFieldType(&buf).abiSize(target),
|
||||
else => unreachable,
|
||||
};
|
||||
break :blk @intCast(u32, addend);
|
||||
},
|
||||
else => return Result{
|
||||
.fail = try ErrorMsg.create(
|
||||
bin_file.allocator,
|
||||
|
||||
@ -485,14 +485,24 @@ pub const DeclGen = struct {
|
||||
const field_ptr = ptr_val.castTag(.field_ptr).?.data;
|
||||
const container_ty = field_ptr.container_ty;
|
||||
const index = field_ptr.field_index;
|
||||
const field_name = switch (container_ty.zigTypeTag()) {
|
||||
.Struct => container_ty.structFields().keys()[index],
|
||||
.Union => container_ty.unionFields().keys()[index],
|
||||
else => unreachable,
|
||||
};
|
||||
const field_ty = switch (container_ty.zigTypeTag()) {
|
||||
.Struct => container_ty.structFields().values()[index].ty,
|
||||
.Union => container_ty.unionFields().values()[index].ty,
|
||||
const FieldInfo = struct { name: []const u8, ty: Type };
|
||||
const field_info: FieldInfo = switch (container_ty.zigTypeTag()) {
|
||||
.Struct => .{
|
||||
.name = container_ty.structFields().keys()[index],
|
||||
.ty = container_ty.structFields().values()[index].ty,
|
||||
},
|
||||
.Union => .{
|
||||
.name = container_ty.unionFields().keys()[index],
|
||||
.ty = container_ty.unionFields().values()[index].ty,
|
||||
},
|
||||
.Pointer => switch (container_ty.ptrSize()) {
|
||||
.Slice => switch (index) {
|
||||
0 => FieldInfo{ .name = "ptr", .ty = container_ty.childType() },
|
||||
1 => FieldInfo{ .name = "len", .ty = Type.usize },
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
var container_ptr_ty_pl: Type.Payload.ElemType = .{
|
||||
@ -501,16 +511,16 @@ pub const DeclGen = struct {
|
||||
};
|
||||
const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base);
|
||||
|
||||
if (field_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
if (field_info.ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
try writer.writeAll("&(");
|
||||
try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
|
||||
if (field_ptr.container_ty.tag() == .union_tagged or field_ptr.container_ty.tag() == .union_safety_tagged) {
|
||||
try writer.print(")->payload.{ }", .{fmtIdent(field_name)});
|
||||
try writer.print(")->payload.{ }", .{fmtIdent(field_info.name)});
|
||||
} else {
|
||||
try writer.print(")->{ }", .{fmtIdent(field_name)});
|
||||
try writer.print(")->{ }", .{fmtIdent(field_info.name)});
|
||||
}
|
||||
} else {
|
||||
try dg.renderParentPtr(writer, field_ptr.container_ptr, field_ty);
|
||||
try dg.renderParentPtr(writer, field_ptr.container_ptr, field_info.ty);
|
||||
}
|
||||
},
|
||||
.elem_ptr => {
|
||||
|
||||
@ -3938,6 +3938,15 @@ pub const DeclGen = struct {
|
||||
const parent_llvm_ty = try dg.lowerType(parent_ty);
|
||||
break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
|
||||
},
|
||||
.Pointer => {
|
||||
assert(parent_ty.isSlice());
|
||||
const indices: [2]*llvm.Value = .{
|
||||
llvm_u32.constInt(0, .False),
|
||||
llvm_u32.constInt(field_index, .False),
|
||||
};
|
||||
const parent_llvm_ty = try dg.lowerType(parent_ty);
|
||||
break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
|
||||
@ -100,6 +100,7 @@ test {
|
||||
_ = @import("behavior/bugs/12928.zig");
|
||||
_ = @import("behavior/bugs/12945.zig");
|
||||
_ = @import("behavior/bugs/12984.zig");
|
||||
_ = @import("behavior/bugs/13068.zig");
|
||||
_ = @import("behavior/bugs/13128.zig");
|
||||
_ = @import("behavior/byteswap.zig");
|
||||
_ = @import("behavior/byval_arg_var.zig");
|
||||
|
||||
15
test/behavior/bugs/13068.zig
Normal file
15
test/behavior/bugs/13068.zig
Normal file
@ -0,0 +1,15 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub const allocator = std.heap.page_allocator;
|
||||
var list = std.ArrayList(u32).init(allocator);
|
||||
|
||||
test {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
list.items.len = 0;
|
||||
}
|
||||
@ -2,6 +2,7 @@ const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqualSlices = std.testing.expectEqualSlices;
|
||||
const expectEqualStrings = std.testing.expectEqualStrings;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const mem = std.mem;
|
||||
|
||||
@ -686,8 +687,6 @@ test "slice len modification at comptime" {
|
||||
}
|
||||
|
||||
test "slice field ptr const" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
const const_slice: []const u8 = "string";
|
||||
|
||||
const const_ptr_const_slice = &const_slice;
|
||||
@ -700,8 +699,6 @@ test "slice field ptr const" {
|
||||
}
|
||||
|
||||
test "slice field ptr var" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
var var_slice: []const u8 = "string";
|
||||
|
||||
var var_ptr_var_slice = &var_slice;
|
||||
@ -712,3 +709,18 @@ test "slice field ptr var" {
|
||||
try expectEqual(*[]const u8, @TypeOf(&const_ptr_var_slice.*));
|
||||
try expectEqual(*[*]const u8, @TypeOf(&const_ptr_var_slice.ptr));
|
||||
}
|
||||
|
||||
test "global slice field access" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
var slice: []const u8 = undefined;
|
||||
};
|
||||
S.slice = "string";
|
||||
S.slice.ptr += 1;
|
||||
S.slice.len -= 2;
|
||||
try expectEqualStrings("trin", S.slice);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user