mirror of
https://github.com/ziglang/zig.git
synced 2024-12-12 22:25:21 +00:00
stage2: fix unwrap function call with optional pointer return value
This commit is contained in:
parent
a130eac785
commit
b560f46c87
@ -3464,11 +3464,16 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
|
||||
queue_linker_work = true;
|
||||
}
|
||||
},
|
||||
.array, .@"struct", .@"union" => {
|
||||
|
||||
.generic_poison => unreachable,
|
||||
.unreachable_value => unreachable,
|
||||
|
||||
.function => {},
|
||||
|
||||
else => {
|
||||
log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name });
|
||||
queue_linker_work = true;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
decl.ty = try decl_tv.ty.copy(&decl_arena.allocator);
|
||||
|
@ -4800,8 +4800,10 @@ fn zirOptionalPayload(
|
||||
if (val.isNull()) {
|
||||
return sema.fail(block, src, "unable to unwrap null", .{});
|
||||
}
|
||||
const sub_val = val.castTag(.opt_payload).?.data;
|
||||
return sema.addConstant(result_ty, sub_val);
|
||||
if (val.castTag(.opt_payload)) |payload| {
|
||||
return sema.addConstant(result_ty, payload.data);
|
||||
}
|
||||
return sema.addConstant(result_ty, val);
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src);
|
||||
|
@ -848,6 +848,11 @@ pub fn gen(self: *Self, ty: Type, val: Value) InnerError!Result {
|
||||
try self.emitConstant(val, ty);
|
||||
return Result.appended;
|
||||
},
|
||||
.Bool => {
|
||||
const int_byte: u8 = @boolToInt(val.toBool());
|
||||
try self.code.append(int_byte);
|
||||
return Result.appended;
|
||||
},
|
||||
.Struct => {
|
||||
// TODO write the fields for real
|
||||
const abi_size = try std.math.cast(usize, ty.abiSize(self.target));
|
||||
|
@ -286,6 +286,62 @@ pub fn generateSymbol(
|
||||
}
|
||||
return Result{ .appended = {} };
|
||||
},
|
||||
.Enum => {
|
||||
// TODO populate .debug_info for the enum
|
||||
var int_buffer: Value.Payload.U64 = undefined;
|
||||
const int_val = typed_value.enumToInt(&int_buffer);
|
||||
|
||||
const target = bin_file.options.target;
|
||||
const info = typed_value.ty.intInfo(target);
|
||||
if (info.bits <= 8) {
|
||||
const x = @intCast(u8, int_val.toUnsignedInt());
|
||||
try code.append(x);
|
||||
return Result{ .appended = {} };
|
||||
}
|
||||
if (info.bits > 64) {
|
||||
return Result{
|
||||
.fail = try ErrorMsg.create(
|
||||
bin_file.allocator,
|
||||
src_loc,
|
||||
"TODO implement generateSymbol for big int enums ('{}')",
|
||||
.{typed_value.ty},
|
||||
),
|
||||
};
|
||||
}
|
||||
const endian = target.cpu.arch.endian();
|
||||
switch (info.signedness) {
|
||||
.unsigned => {
|
||||
if (info.bits <= 16) {
|
||||
const x = @intCast(u16, int_val.toUnsignedInt());
|
||||
mem.writeInt(u16, try code.addManyAsArray(2), x, endian);
|
||||
} else if (info.bits <= 32) {
|
||||
const x = @intCast(u32, int_val.toUnsignedInt());
|
||||
mem.writeInt(u32, try code.addManyAsArray(4), x, endian);
|
||||
} else {
|
||||
const x = int_val.toUnsignedInt();
|
||||
mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
|
||||
}
|
||||
},
|
||||
.signed => {
|
||||
if (info.bits <= 16) {
|
||||
const x = @intCast(i16, int_val.toSignedInt());
|
||||
mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
|
||||
} else if (info.bits <= 32) {
|
||||
const x = @intCast(i32, int_val.toSignedInt());
|
||||
mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
|
||||
} else {
|
||||
const x = int_val.toSignedInt();
|
||||
mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
|
||||
}
|
||||
},
|
||||
}
|
||||
return Result{ .appended = {} };
|
||||
},
|
||||
.Bool => {
|
||||
const x: u8 = @boolToInt(typed_value.val.toBool());
|
||||
try code.append(x);
|
||||
return Result{ .appended = {} };
|
||||
},
|
||||
.Struct => {
|
||||
const field_vals = typed_value.val.castTag(.@"struct").?.data;
|
||||
_ = field_vals; // TODO write the fields for real
|
||||
|
@ -772,10 +772,7 @@ pub const DeclGen = struct {
|
||||
const target = dg.module.getTarget();
|
||||
|
||||
switch (t.zigTypeTag()) {
|
||||
.NoReturn => {
|
||||
try w.writeAll("zig_noreturn void");
|
||||
},
|
||||
.Void => try w.writeAll("void"),
|
||||
.NoReturn, .Void => try w.writeAll("void"),
|
||||
.Bool => try w.writeAll("bool"),
|
||||
.Int => {
|
||||
switch (t.tag()) {
|
||||
|
@ -118,3 +118,21 @@ fn test_cmp_optional_non_optional() !void {
|
||||
break :blk2 @as(?f64, 5.0);
|
||||
};
|
||||
}
|
||||
|
||||
test "unwrap function call with optional pointer return value" {
|
||||
const S = struct {
|
||||
fn entry() !void {
|
||||
try expect(foo().?.* == 1234);
|
||||
try expect(bar() == null);
|
||||
}
|
||||
const global: i32 = 1234;
|
||||
fn foo() ?*const i32 {
|
||||
return &global;
|
||||
}
|
||||
fn bar() ?*i32 {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
try S.entry();
|
||||
comptime try S.entry();
|
||||
}
|
||||
|
@ -3,24 +3,6 @@ const testing = std.testing;
|
||||
const expect = testing.expect;
|
||||
const expectEqual = testing.expectEqual;
|
||||
|
||||
test "unwrap function call with optional pointer return value" {
|
||||
const S = struct {
|
||||
fn entry() !void {
|
||||
try expect(foo().?.* == 1234);
|
||||
try expect(bar() == null);
|
||||
}
|
||||
const global: i32 = 1234;
|
||||
fn foo() ?*const i32 {
|
||||
return &global;
|
||||
}
|
||||
fn bar() ?*i32 {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
try S.entry();
|
||||
comptime try S.entry();
|
||||
}
|
||||
|
||||
test "nested orelse" {
|
||||
const S = struct {
|
||||
fn entry() !void {
|
||||
|
Loading…
Reference in New Issue
Block a user