aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compiler/std-docs.zig20
-rw-r--r--lib/std/packed_int_array.zig96
-rw-r--r--src/Compilation.zig25
-rw-r--r--src/Sema.zig39
-rw-r--r--src/codegen.zig2
-rw-r--r--src/link/Dwarf.zig62
-rw-r--r--test/behavior/error.zig15
-rw-r--r--test/cases.zig1
-rw-r--r--test/cases/compile_errors/@errorCast_with_bad_type.zig31
-rw-r--r--test/cases/compile_errors/error_union_field_default_init.zig13
-rw-r--r--test/cases/compile_errors/type_error_union_field_type.zig16
-rw-r--r--test/cases/translate_c/align() attribute.c17
-rw-r--r--test/cbe.zig953
-rw-r--r--test/translate_c.zig21
14 files changed, 245 insertions, 1066 deletions
diff --git a/lib/compiler/std-docs.zig b/lib/compiler/std-docs.zig
index 93a04a28e5..d86be67702 100644
--- a/lib/compiler/std-docs.zig
+++ b/lib/compiler/std-docs.zig
@@ -177,6 +177,26 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void {
try w.writeFile(file);
try w.writeByteNTimes(0, padding);
}
+
+ {
+ // Since this command is JIT compiled, the builtin module available in
+ // this source file corresponds to the user's host system.
+ const builtin_zig = @embedFile("builtin");
+
+ var file_header = std.tar.output.Header.init();
+ file_header.typeflag = .regular;
+ try file_header.setPath("builtin", "builtin.zig");
+ try file_header.setSize(builtin_zig.len);
+ try file_header.updateChecksum();
+ try w.writeAll(std.mem.asBytes(&file_header));
+ try w.writeAll(builtin_zig);
+ const padding = p: {
+ const remainder = builtin_zig.len % 512;
+ break :p if (remainder > 0) 512 - remainder else 0;
+ };
+ try w.writeByteNTimes(0, padding);
+ }
+
// intentionally omitting the pointless trailer
//try w.writeByteNTimes(0, 512 * 2);
try response.end();
diff --git a/lib/std/packed_int_array.zig b/lib/std/packed_int_array.zig
index 7264fed599..02c721e7cf 100644
--- a/lib/std/packed_int_array.zig
+++ b/lib/std/packed_int_array.zig
@@ -66,32 +66,31 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: Endian) type {
fn getBits(bytes: []const u8, comptime Container: type, bit_index: usize) Int {
const container_bits = @bitSizeOf(Container);
- const Shift = std.math.Log2Int(Container);
const start_byte = bit_index / 8;
const head_keep_bits = bit_index - (start_byte * 8);
const tail_keep_bits = container_bits - (int_bits + head_keep_bits);
//read bytes as container
- const value_ptr = @as(*align(1) const Container, @ptrCast(&bytes[start_byte]));
+ const value_ptr: *align(1) const Container = @ptrCast(&bytes[start_byte]);
var value = value_ptr.*;
if (endian != native_endian) value = @byteSwap(value);
switch (endian) {
.big => {
- value <<= @as(Shift, @intCast(head_keep_bits));
- value >>= @as(Shift, @intCast(head_keep_bits));
- value >>= @as(Shift, @intCast(tail_keep_bits));
+ value <<= @intCast(head_keep_bits);
+ value >>= @intCast(head_keep_bits);
+ value >>= @intCast(tail_keep_bits);
},
.little => {
- value <<= @as(Shift, @intCast(tail_keep_bits));
- value >>= @as(Shift, @intCast(tail_keep_bits));
- value >>= @as(Shift, @intCast(head_keep_bits));
+ value <<= @intCast(tail_keep_bits);
+ value >>= @intCast(tail_keep_bits);
+ value >>= @intCast(head_keep_bits);
},
}
- return @as(Int, @bitCast(@as(UnInt, @truncate(value))));
+ return @bitCast(@as(UnInt, @truncate(value)));
}
/// Sets the integer at `index` to `val` within the packed data beginning
@@ -114,16 +113,16 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: Endian) type {
const start_byte = bit_index / 8;
const head_keep_bits = bit_index - (start_byte * 8);
const tail_keep_bits = container_bits - (int_bits + head_keep_bits);
- const keep_shift = switch (endian) {
- .big => @as(Shift, @intCast(tail_keep_bits)),
- .little => @as(Shift, @intCast(head_keep_bits)),
+ const keep_shift: Shift = switch (endian) {
+ .big => @intCast(tail_keep_bits),
+ .little => @intCast(head_keep_bits),
};
//position the bits where they need to be in the container
const value = @as(Container, @intCast(@as(UnInt, @bitCast(int)))) << keep_shift;
//read existing bytes
- const target_ptr = @as(*align(1) Container, @ptrCast(&bytes[start_byte]));
+ const target_ptr: *align(1) Container = @ptrCast(&bytes[start_byte]);
var target = target_ptr.*;
if (endian != native_endian) target = @byteSwap(target);
@@ -156,7 +155,7 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: Endian) type {
if (length == 0) return PackedIntSliceEndian(Int, endian).init(new_bytes[0..0], 0);
var new_slice = PackedIntSliceEndian(Int, endian).init(new_bytes, length);
- new_slice.bit_offset = @as(u3, @intCast((bit_index - (start_byte * 8))));
+ new_slice.bit_offset = @intCast((bit_index - (start_byte * 8)));
return new_slice;
}
@@ -214,15 +213,14 @@ pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: Endian, comptim
/// Initialize a packed array using an unpacked array
/// or, more likely, an array literal.
pub fn init(ints: [int_count]Int) Self {
- var self = @as(Self, undefined);
+ var self: Self = undefined;
for (ints, 0..) |int, i| self.set(i, int);
return self;
}
/// Initialize all entries of a packed array to the same value.
pub fn initAllTo(int: Int) Self {
- // TODO: use `var self = @as(Self, undefined);` https://github.com/ziglang/zig/issues/7635
- var self = Self{ .bytes = [_]u8{0} ** total_bytes, .len = int_count };
+ var self: Self = undefined;
self.setAll(int);
return self;
}
@@ -365,11 +363,11 @@ test "PackedIntArray" {
const expected_bytes = ((bits * int_count) + 7) / 8;
try testing.expect(@sizeOf(PackedArray) == expected_bytes);
- var data = @as(PackedArray, undefined);
+ var data: PackedArray = undefined;
//write values, counting up
- var i = @as(usize, 0);
- var count = @as(I, 0);
+ var i: usize = 0;
+ var count: I = 0;
while (i < data.len) : (i += 1) {
data.set(i, count);
if (bits > 0) count +%= 1;
@@ -395,17 +393,29 @@ test "PackedIntIo" {
}
test "PackedIntArray init" {
- const PackedArray = PackedIntArray(u3, 8);
- var packed_array = PackedArray.init([_]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
- var i = @as(usize, 0);
- while (i < packed_array.len) : (i += 1) try testing.expectEqual(@as(u3, @intCast(i)), packed_array.get(i));
+ const S = struct {
+ fn doTheTest() !void {
+ const PackedArray = PackedIntArray(u3, 8);
+ var packed_array = PackedArray.init([_]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
+ var i: usize = 0;
+ while (i < packed_array.len) : (i += 1) try testing.expectEqual(@as(u3, @intCast(i)), packed_array.get(i));
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
}
test "PackedIntArray initAllTo" {
- const PackedArray = PackedIntArray(u3, 8);
- var packed_array = PackedArray.initAllTo(5);
- var i = @as(usize, 0);
- while (i < packed_array.len) : (i += 1) try testing.expectEqual(@as(u3, 5), packed_array.get(i));
+ const S = struct {
+ fn doTheTest() !void {
+ const PackedArray = PackedIntArray(u3, 8);
+ var packed_array = PackedArray.initAllTo(5);
+ var i: usize = 0;
+ while (i < packed_array.len) : (i += 1) try testing.expectEqual(@as(u3, 5), packed_array.get(i));
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
}
test "PackedIntSlice" {
@@ -433,8 +443,8 @@ test "PackedIntSlice" {
var data = P.init(&buffer, int_count);
//write values, counting up
- var i = @as(usize, 0);
- var count = @as(I, 0);
+ var i: usize = 0;
+ var count: I = 0;
while (i < data.len) : (i += 1) {
data.set(i, count);
if (bits > 0) count +%= 1;
@@ -463,13 +473,13 @@ test "PackedIntSlice of PackedInt(Array/Slice)" {
const Int = std.meta.Int(.unsigned, bits);
const PackedArray = PackedIntArray(Int, int_count);
- var packed_array = @as(PackedArray, undefined);
+ var packed_array: PackedArray = undefined;
const limit = (1 << bits);
- var i = @as(usize, 0);
+ var i: usize = 0;
while (i < packed_array.len) : (i += 1) {
- packed_array.set(i, @as(Int, @intCast(i % limit)));
+ packed_array.set(i, @intCast(i % limit));
}
//slice of array
@@ -524,20 +534,20 @@ test "PackedIntSlice accumulating bit offsets" {
// anything
{
const PackedArray = PackedIntArray(u3, 16);
- var packed_array = @as(PackedArray, undefined);
+ var packed_array: PackedArray = undefined;
var packed_slice = packed_array.slice(0, packed_array.len);
- var i = @as(usize, 0);
+ var i: usize = 0;
while (i < packed_array.len - 1) : (i += 1) {
packed_slice = packed_slice.slice(1, packed_slice.len);
}
}
{
const PackedArray = PackedIntArray(u11, 88);
- var packed_array = @as(PackedArray, undefined);
+ var packed_array: PackedArray = undefined;
var packed_slice = packed_array.slice(0, packed_array.len);
- var i = @as(usize, 0);
+ var i: usize = 0;
while (i < packed_array.len - 1) : (i += 1) {
packed_slice = packed_slice.slice(1, packed_slice.len);
}
@@ -552,7 +562,7 @@ test "PackedInt(Array/Slice) sliceCast" {
var packed_slice_cast_9 = packed_array.slice(0, (packed_array.len / 9) * 9).sliceCast(u9);
const packed_slice_cast_3 = packed_slice_cast_9.sliceCast(u3);
- var i = @as(usize, 0);
+ var i: usize = 0;
while (i < packed_slice_cast_2.len) : (i += 1) {
const val = switch (native_endian) {
.big => 0b01,
@@ -576,9 +586,9 @@ test "PackedInt(Array/Slice) sliceCast" {
}
i = 0;
while (i < packed_slice_cast_3.len) : (i += 1) {
- const val = switch (native_endian) {
- .big => if (i % 2 == 0) @as(u3, 0b111) else @as(u3, 0b000),
- .little => if (i % 2 == 0) @as(u3, 0b111) else @as(u3, 0b000),
+ const val: u3 = switch (native_endian) {
+ .big => if (i % 2 == 0) 0b111 else 0b000,
+ .little => if (i % 2 == 0) 0b111 else 0b000,
};
try testing.expect(packed_slice_cast_3.get(i) == val);
}
@@ -591,7 +601,7 @@ test "PackedInt(Array/Slice)Endian" {
try testing.expect(packed_array_be.bytes[0] == 0b00000001);
try testing.expect(packed_array_be.bytes[1] == 0b00100011);
- var i = @as(usize, 0);
+ var i: usize = 0;
while (i < packed_array_be.len) : (i += 1) {
try testing.expect(packed_array_be.get(i) == i);
}
@@ -620,7 +630,7 @@ test "PackedInt(Array/Slice)Endian" {
try testing.expect(packed_array_be.bytes[3] == 0b00000001);
try testing.expect(packed_array_be.bytes[4] == 0b00000000);
- var i = @as(usize, 0);
+ var i: usize = 0;
while (i < packed_array_be.len) : (i += 1) {
try testing.expect(packed_array_be.get(i) == i);
}
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 003ecb8e28..5a6e02d400 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -3696,6 +3696,9 @@ fn workerDocsCopy(comp: *Compilation, wg: *WaitGroup) void {
}
fn docsCopyFallible(comp: *Compilation) anyerror!void {
+ const zcu = comp.module orelse
+ return comp.lockAndSetMiscFailure(.docs_copy, "no Zig code to document", .{});
+
const emit = comp.docs_emit.?;
var out_dir = emit.directory.handle.makeOpenPath(emit.sub_path, .{}) catch |err| {
return comp.lockAndSetMiscFailure(
@@ -3726,7 +3729,25 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
};
defer tar_file.close();
- const root = comp.root_mod.root;
+ var seen_table: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .{};
+ defer seen_table.deinit(comp.gpa);
+
+ try seen_table.put(comp.gpa, zcu.main_mod, {});
+ try seen_table.put(comp.gpa, zcu.std_mod, {});
+
+ var i: usize = 0;
+ while (i < seen_table.count()) : (i += 1) {
+ const mod = seen_table.keys()[i];
+ try comp.docsCopyModule(mod, tar_file);
+
+ const deps = mod.deps.values();
+ try seen_table.ensureUnusedCapacity(comp.gpa, deps.len);
+ for (deps) |dep| seen_table.putAssumeCapacity(dep, {});
+ }
+}
+
+fn docsCopyModule(comp: *Compilation, module: *Package.Module, tar_file: std.fs.File) !void {
+ const root = module.root;
const sub_path = if (root.sub_path.len == 0) "." else root.sub_path;
var mod_dir = root.root_dir.handle.openDir(sub_path, .{ .iterate = true }) catch |err| {
return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{}': {s}", .{
@@ -3765,7 +3786,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
var file_header = std.tar.output.Header.init();
file_header.typeflag = .regular;
- try file_header.setPath(comp.root_name, entry.path);
+ try file_header.setPath(module.fully_qualified_name, entry.path);
try file_header.setSize(stat.size);
try file_header.updateChecksum();
diff --git a/src/Sema.zig b/src/Sema.zig
index d21fed6910..4541d02f66 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -22626,20 +22626,33 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
const base_operand_ty = sema.typeOf(operand);
const dest_tag = base_dest_ty.zigTypeTag(mod);
const operand_tag = base_operand_ty.zigTypeTag(mod);
- if (dest_tag != operand_tag) {
- return sema.fail(block, src, "expected source and destination types to match, found '{s}' and '{s}'", .{
- @tagName(operand_tag), @tagName(dest_tag),
- });
- } else if (dest_tag != .ErrorSet and dest_tag != .ErrorUnion) {
+
+ if (dest_tag != .ErrorSet and dest_tag != .ErrorUnion) {
return sema.fail(block, src, "expected error set or error union type, found '{s}'", .{@tagName(dest_tag)});
}
- const dest_ty, const operand_ty = if (dest_tag == .ErrorUnion) .{
- base_dest_ty.errorUnionSet(mod),
- base_operand_ty.errorUnionSet(mod),
- } else .{
- base_dest_ty,
- base_operand_ty,
- };
+ if (operand_tag != .ErrorSet and operand_tag != .ErrorUnion) {
+ return sema.fail(block, src, "expected error set or error union type, found '{s}'", .{@tagName(operand_tag)});
+ }
+ if (dest_tag == .ErrorSet and operand_tag == .ErrorUnion) {
+ return sema.fail(block, src, "cannot cast an error union type to error set", .{});
+ }
+ if (dest_tag == .ErrorUnion and operand_tag == .ErrorUnion and
+ base_dest_ty.errorUnionPayload(mod).toIntern() != base_operand_ty.errorUnionPayload(mod).toIntern())
+ {
+ return sema.failWithOwnedErrorMsg(block, msg: {
+ const msg = try sema.errMsg(block, src, "payload types of error unions must match", .{});
+ errdefer msg.destroy(sema.gpa);
+ const dest_ty = base_dest_ty.errorUnionPayload(mod);
+ const operand_ty = base_operand_ty.errorUnionPayload(mod);
+ try sema.errNote(block, src, msg, "destination payload is '{}'", .{dest_ty.fmt(mod)});
+ try sema.errNote(block, src, msg, "operand payload is '{}'", .{operand_ty.fmt(mod)});
+ try addDeclaredHereNote(sema, msg, dest_ty);
+ try addDeclaredHereNote(sema, msg, operand_ty);
+ break :msg msg;
+ });
+ }
+ const dest_ty = if (dest_tag == .ErrorUnion) base_dest_ty.errorUnionSet(mod) else base_dest_ty;
+ const operand_ty = if (operand_tag == .ErrorUnion) base_operand_ty.errorUnionSet(mod) else base_operand_ty;
// operand must be defined since it can be an invalid error value
const maybe_operand_val = try sema.resolveDefinedValue(block, operand_src, operand);
@@ -22681,7 +22694,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
if (!dest_ty.isAnyError(mod)) check: {
const operand_val = mod.intern_pool.indexToKey(val.toIntern());
var error_name: InternPool.NullTerminatedString = undefined;
- if (dest_tag == .ErrorUnion) {
+ if (operand_tag == .ErrorUnion) {
if (operand_val.error_union.val != .err_name) break :check;
error_name = operand_val.error_union.val.err_name;
} else {
diff --git a/src/codegen.zig b/src/codegen.zig
index c5da0ebcb7..004cf7a7be 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -486,7 +486,7 @@ pub fn generateSymbol(
const abi_size = math.cast(usize, ty.abiSize(mod)) orelse
return error.Overflow;
const current_pos = code.items.len;
- try code.resize(current_pos + abi_size);
+ try code.appendNTimes(0, abi_size);
var bits: u16 = 0;
for (struct_type.field_types.get(ip), 0..) |field_ty, index| {
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig
index e2d4669156..6a41bb3793 100644
--- a/src/link/Dwarf.zig
+++ b/src/link/Dwarf.zig
@@ -187,17 +187,16 @@ pub const DeclState = struct {
// DW.AT.name, DW.FORM.string
try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
// DW.AT.member
- try dbg_info_buffer.ensureUnusedCapacity(7);
+ try dbg_info_buffer.ensureUnusedCapacity(21);
dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
// DW.AT.name, DW.FORM.string
dbg_info_buffer.appendSliceAssumeCapacity("maybe");
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.type, DW.FORM.ref4
var index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocGlobal(atom_index, Type.bool, @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
- try dbg_info_buffer.ensureUnusedCapacity(6);
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.member
dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
@@ -206,7 +205,7 @@ pub const DeclState = struct {
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.type, DW.FORM.ref4
index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
const offset = abi_size - payload_ty.abiSize(mod);
@@ -228,18 +227,17 @@ pub const DeclState = struct {
// DW.AT.name, DW.FORM.string
try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
// DW.AT.member
- try dbg_info_buffer.ensureUnusedCapacity(5);
+ try dbg_info_buffer.ensureUnusedCapacity(21);
dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
// DW.AT.name, DW.FORM.string
dbg_info_buffer.appendSliceAssumeCapacity("ptr");
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.type, DW.FORM.ref4
var index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
const ptr_ty = ty.slicePtrFieldType(mod);
try self.addTypeRelocGlobal(atom_index, ptr_ty, @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
- try dbg_info_buffer.ensureUnusedCapacity(6);
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.member
dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
@@ -248,19 +246,18 @@ pub const DeclState = struct {
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.type, DW.FORM.ref4
index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocGlobal(atom_index, Type.usize, @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
- try dbg_info_buffer.ensureUnusedCapacity(2);
dbg_info_buffer.appendAssumeCapacity(ptr_bytes);
// DW.AT.structure_type delimit children
dbg_info_buffer.appendAssumeCapacity(0);
} else {
- try dbg_info_buffer.ensureUnusedCapacity(5);
+ try dbg_info_buffer.ensureUnusedCapacity(9);
dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.ptr_type));
// DW.AT.type, DW.FORM.ref4
const index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocGlobal(atom_index, ty.childType(mod), @intCast(index));
}
},
@@ -271,13 +268,14 @@ pub const DeclState = struct {
try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
// DW.AT.type, DW.FORM.ref4
var index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ try dbg_info_buffer.ensureUnusedCapacity(9);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocGlobal(atom_index, ty.childType(mod), @intCast(index));
// DW.AT.subrange_type
- try dbg_info_buffer.append(@intFromEnum(AbbrevCode.array_dim));
+ dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.array_dim));
// DW.AT.type, DW.FORM.ref4
index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocGlobal(atom_index, Type.usize, @intCast(index));
// DW.AT.count, DW.FORM.udata
const len = ty.arrayLenIncludingSentinel(mod);
@@ -304,7 +302,7 @@ pub const DeclState = struct {
try dbg_info_buffer.writer().print("{d}\x00", .{field_index});
// DW.AT.type, DW.FORM.ref4
const index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ try dbg_info_buffer.appendNTimes(0, 4);
try self.addTypeRelocGlobal(atom_index, Type.fromInterned(field_ty), @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
const field_off = ty.structFieldOffset(field_index, mod);
@@ -331,7 +329,7 @@ pub const DeclState = struct {
try dbg_info_buffer.writer().print("{d}\x00", .{field_index});
// DW.AT.type, DW.FORM.ref4
const index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ try dbg_info_buffer.appendNTimes(0, 4);
try self.addTypeRelocGlobal(atom_index, Type.fromInterned(field_ty), @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
@@ -352,7 +350,7 @@ pub const DeclState = struct {
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.type, DW.FORM.ref4
const index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ try dbg_info_buffer.appendNTimes(0, 4);
try self.addTypeRelocGlobal(atom_index, Type.fromInterned(field_ty), @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
@@ -418,14 +416,14 @@ pub const DeclState = struct {
try dbg_info_buffer.append(0);
// DW.AT.member
- try dbg_info_buffer.ensureUnusedCapacity(9);
+ try dbg_info_buffer.ensureUnusedCapacity(13);
dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
// DW.AT.name, DW.FORM.string
dbg_info_buffer.appendSliceAssumeCapacity("payload");
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.type, DW.FORM.ref4
const inner_union_index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(inner_union_index + 4);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocLocal(atom_index, @intCast(inner_union_index), 5);
// DW.AT.data_member_location, DW.FORM.udata
try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset);
@@ -452,7 +450,7 @@ pub const DeclState = struct {
try dbg_info_buffer.append(0);
// DW.AT.type, DW.FORM.ref4
const index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ try dbg_info_buffer.appendNTimes(0, 4);
try self.addTypeRelocGlobal(atom_index, Type.fromInterned(field_ty), @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
try dbg_info_buffer.append(0);
@@ -462,14 +460,14 @@ pub const DeclState = struct {
if (is_tagged) {
// DW.AT.member
- try dbg_info_buffer.ensureUnusedCapacity(5);
+ try dbg_info_buffer.ensureUnusedCapacity(9);
dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
// DW.AT.name, DW.FORM.string
dbg_info_buffer.appendSliceAssumeCapacity("tag");
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.type, DW.FORM.ref4
const index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocGlobal(atom_index, Type.fromInterned(union_obj.enum_tag_ty), @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset);
@@ -498,14 +496,14 @@ pub const DeclState = struct {
if (!payload_ty.isNoReturn(mod)) {
// DW.AT.member
- try dbg_info_buffer.ensureUnusedCapacity(7);
+ try dbg_info_buffer.ensureUnusedCapacity(11);
dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
// DW.AT.name, DW.FORM.string
dbg_info_buffer.appendSliceAssumeCapacity("value");
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.type, DW.FORM.ref4
const index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off);
@@ -513,14 +511,14 @@ pub const DeclState = struct {
{
// DW.AT.member
- try dbg_info_buffer.ensureUnusedCapacity(5);
+ try dbg_info_buffer.ensureUnusedCapacity(9);
dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
// DW.AT.name, DW.FORM.string
dbg_info_buffer.appendSliceAssumeCapacity("err");
dbg_info_buffer.appendAssumeCapacity(0);
// DW.AT.type, DW.FORM.ref4
const index = dbg_info_buffer.items.len;
- try dbg_info_buffer.resize(index + 4);
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocGlobal(atom_index, error_ty, @intCast(index));
// DW.AT.data_member_location, DW.FORM.udata
try leb128.writeULEB128(dbg_info_buffer.writer(), error_off);
@@ -661,7 +659,7 @@ pub const DeclState = struct {
try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
const index = dbg_info.items.len;
- try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4
+ dbg_info.appendNTimesAssumeCapacity(0, 4);
try self.addTypeRelocGlobal(atom_index, ty, @intCast(index)); // DW.AT.type, DW.FORM.ref4
dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
}
@@ -877,7 +875,7 @@ pub const DeclState = struct {
try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
const index = dbg_info.items.len;
- try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4
+ dbg_info.appendNTimesAssumeCapacity(0, 4); // dw.at.type, dw.form.ref4
try self.addTypeRelocGlobal(atom_index, child_ty, @intCast(index));
dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
}
@@ -1133,7 +1131,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde
});
// This is the "relocatable" vaddr, corresponding to `code_buffer` index `0`.
assert(dbg_line_vaddr_reloc_index == dbg_line_buffer.items.len);
- dbg_line_buffer.items.len += ptr_width_bytes;
+ dbg_line_buffer.appendNTimesAssumeCapacity(0, ptr_width_bytes);
dbg_line_buffer.appendAssumeCapacity(DW.LNS.advance_line);
// This is the "relocatable" relative line offset from the previous function's end curly
@@ -1171,12 +1169,12 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde
// "relocations" and have to be in this fixed place so that functions can be
// moved in virtual address space.
assert(dbg_info_low_pc_reloc_index == dbg_info_buffer.items.len);
- dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, ptr_width_bytes); // DW.AT.low_pc, DW.FORM.addr
assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len);
- dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4); // DW.AT.high_pc, DW.FORM.data4
if (fn_ret_has_bits) {
try decl_state.addTypeRelocGlobal(di_atom_index, fn_ret_type, @intCast(dbg_info_buffer.items.len));
- dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4
+ dbg_info_buffer.appendNTimesAssumeCapacity(0, 4); // DW.AT.type, DW.FORM.ref4
}
dbg_info_buffer.appendSliceAssumeCapacity(
decl_name_slice[0 .. decl_name_slice.len + 1],
diff --git a/test/behavior/error.zig b/test/behavior/error.zig
index 8e4dd2c091..8380c89619 100644
--- a/test/behavior/error.zig
+++ b/test/behavior/error.zig
@@ -930,6 +930,16 @@ test "optional error set return type" {
try expect(E.A == S.foo(false).?);
}
+test "optional error set function parameter" {
+ const S = struct {
+ fn doTheTest(a: ?anyerror) !void {
+ try std.testing.expect(a.? == error.OutOfMemory);
+ }
+ };
+ try S.doTheTest(error.OutOfMemory);
+ try comptime S.doTheTest(error.OutOfMemory);
+}
+
test "returning an error union containing a type with no runtime bits" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
@@ -1039,3 +1049,8 @@ test "errorCast to adhoc inferred error set" {
};
try std.testing.expect((try S.baz()) == 1234);
}
+
+test "errorCast from error sets to error unions" {
+ const err_union: Set1!void = @errorCast(error.A);
+ try expectError(error.A, err_union);
+}
diff --git a/test/cases.zig b/test/cases.zig
index 9bbdde4777..2c51078abd 100644
--- a/test/cases.zig
+++ b/test/cases.zig
@@ -11,7 +11,6 @@ pub const BuildOptions = struct {
pub fn addCases(cases: *Cases, build_options: BuildOptions, b: *std.Build) !void {
try @import("compile_errors.zig").addCases(cases, b);
- try @import("cbe.zig").addCases(cases, b);
try @import("llvm_targets.zig").addCases(cases, build_options, b);
try @import("nvptx.zig").addCases(cases, b);
}
diff --git a/test/cases/compile_errors/@errorCast_with_bad_type.zig b/test/cases/compile_errors/@errorCast_with_bad_type.zig
new file mode 100644
index 0000000000..6fc42f79f3
--- /dev/null
+++ b/test/cases/compile_errors/@errorCast_with_bad_type.zig
@@ -0,0 +1,31 @@
+const err = error.Foo;
+
+export fn entry1() void {
+ const a: anyerror = @errorCast(1);
+ _ = a;
+}
+export fn entry2() void {
+ const a: i32 = @errorCast(err);
+ _ = a;
+}
+export fn entry3() void {
+ const e: anyerror!void = err;
+ const a: anyerror = @errorCast(e);
+ _ = a;
+}
+pub export fn entry4() void {
+ const a: anyerror!u32 = 123;
+ const b: anyerror!f32 = @errorCast(a);
+ _ = b;
+}
+
+// error
+// backend=stage2
+// target=x86_64-linux
+//
+// :4:25: error: expected error set or error union type, found 'ComptimeInt'
+// :8:20: error: expected error set or error union type, found 'Int'
+// :13:25: error: cannot cast an error union type to error set
+// :18:29: error: payload types of error unions must match
+// :18:29: note: destination payload is 'f32'
+// :18:29: note: operand payload is 'u32'
diff --git a/test/cases/compile_errors/error_union_field_default_init.zig b/test/cases/compile_errors/error_union_field_default_init.zig
new file mode 100644
index 0000000000..c3d9a62389
--- /dev/null
+++ b/test/cases/compile_errors/error_union_field_default_init.zig
@@ -0,0 +1,13 @@
+const Input = struct {
+ value: u32 = @as(error{}!u32, 0),
+};
+export fn foo() void {
+ var x: Input = Input{};
+ _ = &x;
+}
+
+// error
+//
+//:2:18: error: expected type 'u32', found 'error{}!u32'
+//:2:18: note: cannot convert error union to payload type
+//:2:18: note: consider using 'try', 'catch', or 'if'
diff --git a/test/cases/compile_errors/type_error_union_field_type.zig b/test/cases/compile_errors/type_error_union_field_type.zig
new file mode 100644
index 0000000000..74aa93bc6a
--- /dev/null
+++ b/test/cases/compile_errors/type_error_union_field_type.zig
@@ -0,0 +1,16 @@
+fn CreateType() !type {
+ return struct {};
+}
+const MyType = CreateType();
+const TestType = struct {
+ my_type: MyType,
+};
+comptime {
+ _ = @sizeOf(TestType) + 1;
+}
+
+// error
+//
+//:6:14: error: expected type 'type', found 'error{}!type'
+//:6:14: note: cannot convert error union to payload type
+//:6:14: note: consider using 'try', 'catch', or 'if'
diff --git a/test/cases/translate_c/align() attribute.c b/test/cases/translate_c/align() attribute.c
new file mode 100644
index 0000000000..600e8251fb
--- /dev/null
+++ b/test/cases/translate_c/align() attribute.c
@@ -0,0 +1,17 @@
+__attribute__ ((aligned(128)))
+extern char my_array[16];
+__attribute__ ((aligned(128)))
+void my_fn(void) { }
+void other_fn(void) {
+ char ARR[16] __attribute__ ((aligned (16)));
+}
+
+// translate-c
+// c_frontend=clang
+//
+// pub extern var my_array: [16]u8 align(128);
+// pub export fn my_fn() align(128) void {}
+// pub export fn other_fn() void {
+// var ARR: [16]u8 align(16) = undefined;
+// _ = &ARR;
+// }
diff --git a/test/cbe.zig b/test/cbe.zig
deleted file mode 100644
index 35c2d8e8f9..0000000000
--- a/test/cbe.zig
+++ /dev/null
@@ -1,953 +0,0 @@
-const std = @import("std");
-const Cases = @import("src/Cases.zig");
-const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n";
-
-pub fn addCases(ctx: *Cases, b: *std.Build) !void {
- // These tests should work with all platforms, but we're using linux_x64 for
- // now for consistency. Will be expanded eventually.
- const linux_x64: std.Target.Query = .{
- .cpu_arch = .x86_64,
- .os_tag = .linux,
- };
-
- {
- var case = ctx.exeFromCompiledC("hello world with updates", .{}, b);
-
- // Regular old hello world
- case.addCompareOutput(
- \\extern fn puts(s: [*:0]const u8) c_int;
- \\pub export fn main() c_int {
- \\ _ = puts("hello world!");
- \\ return 0;
- \\}
- , "hello world!" ++ nl);
-
- // Now change the message only
- case.addCompareOutput(
- \\extern fn puts(s: [*:0]const u8) c_int;
- \\pub export fn main() c_int {
- \\ _ = puts("yo");
- \\ return 0;
- \\}
- , "yo" ++ nl);
-
- // Add an unused Decl
- case.addCompareOutput(
- \\extern fn puts(s: [*:0]const u8) c_int;
- \\pub export fn main() c_int {
- \\ _ = puts("yo!");
- \\ return 0;
- \\}
- \\fn unused() void {}
- , "yo!" ++ nl);
-
- // Comptime return type and calling convention expected.
- case.addError(
- \\var x: i32 = 1234;
- \\pub export fn main() x {
- \\ return 0;
- \\}
- \\export fn foo() callconv(y) c_int {
- \\ return 0;
- \\}
- \\var y: @import("std").builtin.CallingConvention = .C;
- , &.{
- ":2:22: error: expected type 'type', found 'i32'",
- ":5:26: error: unable to resolve comptime value",
- ":5:26: note: calling convention must be comptime-known",
- });
- }
-
- {
- var case = ctx.exeFromCompiledC("var args", .{}, b);
-
- case.addCompareOutput(
- \\extern fn printf(format: [*:0]const u8, ...) c_int;
- \\
- \\pub export fn main() c_int {
- \\ _ = printf("Hello, %s!\n", "world");
- \\ return 0;
- \\}
- , "Hello, world!" ++ nl);
- }
-
- {
- var case = ctx.exeFromCompiledC("errorFromInt", .{}, b);
-
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ // comptime checks
- \\ const a = error.A;
- \\ const b = error.B;
- \\ const c = @errorFromInt(2);
- \\ const d = @errorFromInt(1);
- \\ if (!(c == b)) unreachable;
- \\ if (!(a == d)) unreachable;
- \\ // runtime checks
- \\ var x = error.A;
- \\ var y = error.B;
- \\ var z = @errorFromInt(2);
- \\ var f = @errorFromInt(1);
- \\ if (!(y == z)) unreachable;
- \\ if (!(x == f)) unreachable;
- \\ return 0;
- \\}
- , "");
- case.addError(
- \\pub export fn main() c_int {
- \\ _ = @errorFromInt(0);
- \\ return 0;
- \\}
- , &.{":2:21: error: integer value '0' represents no error"});
- case.addError(
- \\pub export fn main() c_int {
- \\ _ = @errorFromInt(3);
- \\ return 0;
- \\}
- , &.{":2:21: error: integer value '3' represents no error"});
- }
-
- {
- var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64, b);
-
- // Exit with 0
- case.addCompareOutput(
- \\fn exitGood() noreturn {
- \\ asm volatile ("syscall"
- \\ :
- \\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (0)
- \\ );
- \\ unreachable;
- \\}
- \\
- \\pub export fn main() c_int {
- \\ exitGood();
- \\}
- , "");
-
- // Pass a usize parameter to exit
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ exit(0);
- \\}
- \\
- \\fn exit(code: usize) noreturn {
- \\ asm volatile ("syscall"
- \\ :
- \\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (code)
- \\ );
- \\ unreachable;
- \\}
- , "");
-
- // Change the parameter to u8
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ exit(0);
- \\}
- \\
- \\fn exit(code: u8) noreturn {
- \\ asm volatile ("syscall"
- \\ :
- \\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (code)
- \\ );
- \\ unreachable;
- \\}
- , "");
-
- // Do some arithmetic at the exit callsite
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ exitMath(1);
- \\}
- \\
- \\fn exitMath(a: u8) noreturn {
- \\ exit(0 + a - a);
- \\}
- \\
- \\fn exit(code: u8) noreturn {
- \\ asm volatile ("syscall"
- \\ :
- \\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (code)
- \\ );
- \\ unreachable;
- \\}
- \\
- , "");
-
- // Invert the arithmetic
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ exitMath(1);
- \\}
- \\
- \\fn exitMath(a: u8) noreturn {
- \\ exit(a + 0 - a);
- \\}
- \\
- \\fn exit(code: u8) noreturn {
- \\ asm volatile ("syscall"
- \\ :
- \\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (code)
- \\ );
- \\ unreachable;
- \\}
- \\
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("alloc and retptr", .{}, b);
-
- case.addCompareOutput(
- \\fn add(a: i32, b: i32) i32 {
- \\ return a + b;
- \\}
- \\
- \\fn addIndirect(a: i32, b: i32) i32 {
- \\ return add(a, b);
- \\}
- \\
- \\pub export fn main() c_int {
- \\ return addIndirect(1, 2) - 3;
- \\}
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("inferred local const and var", .{}, b);
-
- case.addCompareOutput(
- \\fn add(a: i32, b: i32) i32 {
- \\ return a + b;
- \\}
- \\
- \\pub export fn main() c_int {
- \\ const x = add(1, 2);
- \\ var y = add(3, 0);
- \\ y -= x;
- \\ return y;
- \\}
- , "");
- }
- {
- var case = ctx.exeFromCompiledC("control flow", .{}, b);
-
- // Simple while loop
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var a: c_int = 0;
- \\ while (a < 5) : (a+=1) {}
- \\ return a - 5;
- \\}
- , "");
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var a = true;
- \\ while (!a) {}
- \\ return 0;
- \\}
- , "");
-
- // If expression
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ var a: c_int = @as(c_int, if (cond == 0)
- \\ 2
- \\ else
- \\ 3) + 9;
- \\ return a - 11;
- \\}
- , "");
-
- // If expression with breakpoint that does not get hit
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var x: i32 = 1;
- \\ if (x != 1) @breakpoint();
- \\ return 0;
- \\}
- , "");
-
- // Switch expression
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ var a: c_int = switch (cond) {
- \\ 1 => 1,
- \\ 2 => 2,
- \\ 99...300, 12 => 3,
- \\ 0 => 4,
- \\ else => 5,
- \\ };
- \\ return a - 4;
- \\}
- , "");
-
- // Switch expression missing else case.
- case.addError(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ const a: c_int = switch (cond) {
- \\ 1 => 1,
- \\ 2 => 2,
- \\ 3 => 3,
- \\ 4 => 4,
- \\ };
- \\ return a - 4;
- \\}
- , &.{":3:22: error: switch must handle all possibilities"});
-
- // Switch expression, has an unreachable prong.
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ const a: c_int = switch (cond) {
- \\ 1 => 1,
- \\ 2 => 2,
- \\ 99...300, 12 => 3,
- \\ 0 => 4,
- \\ 13 => unreachable,
- \\ else => 5,
- \\ };
- \\ return a - 4;
- \\}
- , "");
-
- // Switch expression, has an unreachable prong and prongs write
- // to result locations.
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ var a: c_int = switch (cond) {
- \\ 1 => 1,
- \\ 2 => 2,
- \\ 99...300, 12 => 3,
- \\ 0 => 4,
- \\ 13 => unreachable,
- \\ else => 5,
- \\ };
- \\ return a - 4;
- \\}
- , "");
-
- // Integer switch expression has duplicate case value.
- case.addError(
- \\pub export fn main() c_int {
- \\ var cond: c_int = 0;
- \\ const a: c_int = switch (cond) {
- \\ 1 => 1,
- \\ 2 => 2,
- \\ 96, 11...13, 97 => 3,
- \\ 0 => 4,
- \\ 90, 12 => 100,
- \\ else => 5,
- \\ };
- \\ return a - 4;
- \\}
- , &.{
- ":8:13: error: duplicate switch value",
- ":6:15: note: previous value here",
- });
-
- // Boolean switch expression has duplicate case value.
- case.addError(
- \\pub export fn main() c_int {
- \\ var a: bool = false;
- \\ const b: c_int = switch (a) {
- \\ false => 1,
- \\ true => 2,
- \\ false => 3,
- \\ };
- \\ _ = b;
- \\}
- , &.{
- ":6:9: error: duplicate switch value",
- });
-
- // Sparse (no range capable) switch expression has duplicate case value.
- case.addError(
- \\pub export fn main() c_int {
- \\ const A: type = i32;
- \\ const b: c_int = switch (A) {
- \\ i32 => 1,
- \\ bool => 2,
- \\ f64, i32 => 3,
- \\ else => 4,
- \\ };
- \\ _ = b;
- \\}
- , &.{
- ":6:14: error: duplicate switch value",
- ":4:9: note: previous value here",
- });
-
- // Ranges not allowed for some kinds of switches.
- case.addError(
- \\pub export fn main() c_int {
- \\ const A: type = i32;
- \\ const b: c_int = switch (A) {
- \\ i32 => 1,
- \\ bool => 2,
- \\ f16...f64 => 3,
- \\ else => 4,
- \\ };
- \\ _ = b;
- \\}
- , &.{
- ":3:30: error: ranges not allowed when switching on type 'type'",
- ":6:12: note: range here",
- });
-
- // Switch expression has unreachable else prong.
- case.addError(
- \\pub export fn main() c_int {
- \\ var a: u2 = 0;
- \\ const b: i32 = switch (a) {
- \\ 0 => 10,
- \\ 1 => 20,
- \\ 2 => 30,
- \\ 3 => 40,
- \\ else => 50,
- \\ };
- \\ _ = b;
- \\}
- , &.{
- ":8:14: error: unreachable else prong; all cases already handled",
- });
- }
- //{
- // var case = ctx.exeFromCompiledC("optionals", .{}, b);
-
- // // Simple while loop
- // case.addCompareOutput(
- // \\pub export fn main() c_int {
- // \\ var count: c_int = 0;
- // \\ var opt_ptr: ?*c_int = &count;
- // \\ while (opt_ptr) |_| : (count += 1) {
- // \\ if (count == 4) opt_ptr = null;
- // \\ }
- // \\ return count - 5;
- // \\}
- // , "");
-
- // // Same with non pointer optionals
- // case.addCompareOutput(
- // \\pub export fn main() c_int {
- // \\ var count: c_int = 0;
- // \\ var opt_ptr: ?c_int = count;
- // \\ while (opt_ptr) |_| : (count += 1) {
- // \\ if (count == 4) opt_ptr = null;
- // \\ }
- // \\ return count - 5;
- // \\}
- // , "");
- //}
-
- {
- var case = ctx.exeFromCompiledC("errors", .{}, b);
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var e1 = error.Foo;
- \\ var e2 = error.Bar;
- \\ assert(e1 != e2);
- \\ assert(e1 == error.Foo);
- \\ assert(e2 == error.Bar);
- \\ return 0;
- \\}
- \\fn assert(b: bool) void {
- \\ if (!b) unreachable;
- \\}
- , "");
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var e: anyerror!c_int = 0;
- \\ const i = e catch 69;
- \\ return i;
- \\}
- , "");
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var e: anyerror!c_int = error.Foo;
- \\ const i = e catch 69;
- \\ return 69 - i;
- \\}
- , "");
- case.addCompareOutput(
- \\const E = error{e};
- \\const S = struct { x: u32 };
- \\fn f() E!u32 {
- \\ const x = (try @as(E!S, S{ .x = 1 })).x;
- \\ return x;
- \\}
- \\pub export fn main() c_int {
- \\ const x = f() catch @as(u32, 0);
- \\ if (x != 1) unreachable;
- \\ return 0;
- \\}
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("structs", .{}, b);
- case.addError(
- \\const Point = struct { x: i32, y: i32 };
- \\pub export fn main() c_int {
- \\ var p: Point = .{
- \\ .y = 24,
- \\ .x = 12,
- \\ .y = 24,
- \\ };
- \\ return p.y - p.x - p.x;
- \\}
- , &.{
- ":4:10: error: duplicate struct field name",
- ":6:10: note: duplicate name here",
- ":3:21: note: struct declared here",
- });
- case.addError(
- \\const Point = struct { x: i32, y: i32 };
- \\pub export fn main() c_int {
- \\ var p: Point = .{
- \\ .y = 24,
- \\ };
- \\ return p.y - p.x - p.x;
- \\}
- , &.{
- ":3:21: error: missing struct field: x",
- ":1:15: note: struct 'tmp.Point' declared here",
- });
- case.addError(
- \\const Point = struct { x: i32, y: i32 };
- \\pub export fn main() c_int {
- \\ var p: Point = .{
- \\ .x = 12,
- \\ .y = 24,
- \\ .z = 48,
- \\ };
- \\ return p.y - p.x - p.x;
- \\}
- , &.{
- ":6:10: error: no field named 'z' in struct 'tmp.Point'",
- ":1:15: note: struct declared here",
- });
- case.addCompareOutput(
- \\const Point = struct { x: i32, y: i32 };
- \\pub export fn main() c_int {
- \\ var p: Point = .{
- \\ .x = 12,
- \\ .y = 24,
- \\ };
- \\ return p.y - p.x - p.x;
- \\}
- , "");
- case.addCompareOutput(
- \\const Point = struct { x: i32, y: i32, z: i32, a: i32, b: i32 };
- \\pub export fn main() c_int {
- \\ var p: Point = .{
- \\ .x = 18,
- \\ .y = 24,
- \\ .z = 1,
- \\ .a = 2,
- \\ .b = 3,
- \\ };
- \\ return p.y - p.x - p.z - p.a - p.b;
- \\}
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("unions", .{}, b);
-
- case.addError(
- \\const U = union {
- \\ a: u32,
- \\ b
- \\};
- , &.{
- ":3:5: error: union field missing type",
- });
-
- case.addError(
- \\const E = enum { a, b };
- \\const U = union(E) {
- \\ a: u32 = 1,
- \\ b: f32 = 2,
- \\};
- , &.{
- ":2:11: error: explicitly valued tagged union requires inferred enum tag type",
- ":3:14: note: tag value specified here",
- });
-
- case.addError(
- \\const U = union(enum) {
- \\ a: u32 = 1,
- \\ b: f32 = 2,
- \\};
- , &.{
- ":1:11: error: explicitly valued tagged union missing integer tag type",
- ":2:14: note: tag value specified here",
- });
- }
-
- {
- var case = ctx.exeFromCompiledC("enums", .{}, b);
-
- case.addError(
- \\const E1 = packed enum { a, b, c };
- \\const E2 = extern enum { a, b, c };
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- \\export fn bar() void {
- \\ _ = E2.a;
- \\}
- , &.{
- ":1:12: error: enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type",
- ":2:12: error: enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type",
- });
-
- // comptime and types are caught in AstGen.
- case.addError(
- \\const E1 = enum {
- \\ a,
- \\ comptime b,
- \\ c,
- \\};
- \\const E2 = enum {
- \\ a,
- \\ b: i32,
- \\ c,
- \\};
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- \\export fn bar() void {
- \\ _ = E2.a;
- \\}
- , &.{
- ":3:5: error: enum fields cannot be marked comptime",
- ":8:8: error: enum fields do not have types",
- ":6:12: note: consider 'union(enum)' here to make it a tagged union",
- });
-
- // @intFromEnum, @enumFromInt, enum literal coercion, field access syntax, comparison, switch
- case.addCompareOutput(
- \\const Number = enum { One, Two, Three };
- \\
- \\pub export fn main() c_int {
- \\ var number1 = Number.One;
- \\ var number2: Number = .Two;
- \\ const number3: Number = @enumFromInt(2);
- \\ if (number1 == number2) return 1;
- \\ if (number2 == number3) return 1;
- \\ if (@intFromEnum(number1) != 0) return 1;
- \\ if (@intFromEnum(number2) != 1) return 1;
- \\ if (@intFromEnum(number3) != 2) return 1;
- \\ var x: Number = .Two;
- \\ if (number2 != x) return 1;
- \\ switch (x) {
- \\ .One => return 1,
- \\ .Two => return 0,
- \\ number3 => return 2,
- \\ }
- \\}
- , "");
-
- // Specifying alignment is a parse error.
- // This also tests going from a successful build to a parse error.
- case.addError(
- \\const E1 = enum {
- \\ a,
- \\ b align(4),
- \\ c,
- \\};
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- , &.{
- ":3:13: error: enum fields cannot be aligned",
- });
-
- // Redundant non-exhaustive enum mark.
- // This also tests going from a parse error to an AstGen error.
- case.addError(
- \\const E1 = enum {
- \\ a,
- \\ _,
- \\ b,
- \\ c,
- \\ _,
- \\};
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- , &.{
- ":6:5: error: redundant non-exhaustive enum mark",
- ":3:5: note: other mark here",
- });
-
- case.addError(
- \\const E1 = enum {
- \\ a,
- \\ b,
- \\ c,
- \\ _ = 10,
- \\};
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- , &.{
- ":5:9: error: '_' is used to mark an enum as non-exhaustive and cannot be assigned a value",
- });
-
- case.addError(
- \\const E1 = enum { a, b, _ };
- \\export fn foo() void {
- \\ _ = E1.a;
- \\}
- , &.{
- ":1:12: error: non-exhaustive enum missing integer tag type",
- ":1:25: note: marked non-exhaustive here",
- });
-
- case.addError(
- \\const E1 = enum { a, b, c, b, d };
- \\pub export fn main() c_int {
- \\ _ = E1.a;
- \\}
- , &.{
- ":1:22: error: duplicate enum field name",
- ":1:28: note: duplicate field here",
- ":1:12: note: enum declared here",
- });
-
- case.addError(
- \\pub export fn main() c_int {
- \\ const a = true;
- \\ _ = @intFromEnum(a);
- \\}
- , &.{
- ":3:20: error: expected enum or tagged union, found 'bool'",
- });
-
- case.addError(
- \\pub export fn main() c_int {
- \\ const a = 1;
- \\ _ = @as(bool, @enumFromInt(a));
- \\}
- , &.{
- ":3:19: error: expected enum, found 'bool'",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ _ = @as(E, @enumFromInt(3));
- \\}
- , &.{
- ":3:16: error: enum 'tmp.E' has no tag with value '3'",
- ":1:11: note: enum declared here",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ var x: E = .a;
- \\ switch (x) {
- \\ .a => {},
- \\ .c => {},
- \\ }
- \\}
- , &.{
- ":4:5: error: switch must handle all possibilities",
- ":1:21: note: unhandled enumeration value: 'b'",
- ":1:11: note: enum 'tmp.E' declared here",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ var x: E = .a;
- \\ switch (x) {
- \\ .a => {},
- \\ .b => {},
- \\ .b => {},
- \\ .c => {},
- \\ }
- \\}
- , &.{
- ":7:10: error: duplicate switch value",
- ":6:10: note: previous value here",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ var x: E = .a;
- \\ switch (x) {
- \\ .a => {},
- \\ .b => {},
- \\ .c => {},
- \\ else => {},
- \\ }
- \\}
- , &.{
- ":8:14: error: unreachable else prong; all cases already handled",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ var x: E = .a;
- \\ switch (x) {
- \\ .a => {},
- \\ .b => {},
- \\ _ => {},
- \\ }
- \\}
- , &.{
- ":4:5: error: '_' prong only allowed when switching on non-exhaustive enums",
- ":7:11: note: '_' prong here",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ _ = E.d;
- \\}
- , &.{
- ":3:11: error: enum 'tmp.E' has no member named 'd'",
- ":1:11: note: enum declared here",
- });
-
- case.addError(
- \\const E = enum { a, b, c };
- \\pub export fn main() c_int {
- \\ var x: E = .d;
- \\ _ = x;
- \\}
- , &.{
- ":3:17: error: no field named 'd' in enum 'tmp.E'",
- ":1:11: note: enum declared here",
- });
- }
-
- {
- var case = ctx.exeFromCompiledC("shift right and left", .{}, b);
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var i: u32 = 16;
- \\ assert(i >> 1, 8);
- \\ return 0;
- \\}
- \\fn assert(a: u32, b: u32) void {
- \\ if (a != b) unreachable;
- \\}
- , "");
-
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ var i: u32 = 16;
- \\ assert(i << 1, 32);
- \\ return 0;
- \\}
- \\fn assert(a: u32, b: u32) void {
- \\ if (a != b) unreachable;
- \\}
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("inferred error sets", .{}, b);
-
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ if (foo()) |_| {
- \\ @panic("test fail");
- \\ } else |err| {
- \\ if (err != error.ItBroke) {
- \\ @panic("test fail");
- \\ }
- \\ }
- \\ return 0;
- \\}
- \\fn foo() !void {
- \\ return error.ItBroke;
- \\}
- , "");
- }
-
- {
- // TODO: add u64 tests, ran into issues with the literal generated for std.math.maxInt(u64)
- var case = ctx.exeFromCompiledC("add and sub wrapping operations", .{}, b);
- case.addCompareOutput(
- \\pub export fn main() c_int {
- \\ // Addition
- \\ if (!add_u3(1, 1, 2)) return 1;
- \\ if (!add_u3(7, 1, 0)) return 1;
- \\ if (!add_i3(1, 1, 2)) return 1;
- \\ if (!add_i3(3, 2, -3)) return 1;
- \\ if (!add_i3(-3, -2, 3)) return 1;
- \\ if (!add_c_int(1, 1, 2)) return 1;
- \\ // TODO enable these when stage2 supports std.math.maxInt
- \\ //if (!add_c_int(maxInt(c_int), 2, minInt(c_int) + 1)) return 1;
- \\ //if (!add_c_int(maxInt(c_int) + 1, -2, maxInt(c_int))) return 1;
- \\
- \\ // Subtraction
- \\ if (!sub_u3(2, 1, 1)) return 1;
- \\ if (!sub_u3(0, 1, 7)) return 1;
- \\ if (!sub_i3(2, 1, 1)) return 1;
- \\ if (!sub_i3(3, -2, -3)) return 1;
- \\ if (!sub_i3(-3, 2, 3)) return 1;
- \\ if (!sub_c_int(2, 1, 1)) return 1;
- \\ // TODO enable these when stage2 supports std.math.maxInt
- \\ //if (!sub_c_int(maxInt(c_int), -2, minInt(c_int) + 1)) return 1;
- \\ //if (!sub_c_int(minInt(c_int) + 1, 2, maxInt(c_int))) return 1;
- \\
- \\ return 0;
- \\}
- \\fn add_u3(lhs: u3, rhs: u3, expected: u3) bool {
- \\ return expected == lhs +% rhs;
- \\}
- \\fn add_i3(lhs: i3, rhs: i3, expected: i3) bool {
- \\ return expected == lhs +% rhs;
- \\}
- \\fn add_c_int(lhs: c_int, rhs: c_int, expected: c_int) bool {
- \\ return expected == lhs +% rhs;
- \\}
- \\fn sub_u3(lhs: u3, rhs: u3, expected: u3) bool {
- \\ return expected == lhs -% rhs;
- \\}
- \\fn sub_i3(lhs: i3, rhs: i3, expected: i3) bool {
- \\ return expected == lhs -% rhs;
- \\}
- \\fn sub_c_int(lhs: c_int, rhs: c_int, expected: c_int) bool {
- \\ return expected == lhs -% rhs;
- \\}
- , "");
- }
-
- {
- var case = ctx.exeFromCompiledC("rem", linux_x64, b);
- case.addCompareOutput(
- \\fn assert(ok: bool) void {
- \\ if (!ok) unreachable;
- \\}
- \\fn rem(lhs: i32, rhs: i32, expected: i32) bool {
- \\ return @rem(lhs, rhs) == expected;
- \\}
- \\pub export fn main() c_int {
- \\ assert(rem(-5, 3, -2));
- \\ assert(rem(5, 3, 2));
- \\ return 0;
- \\}
- , "");
- }
-}
diff --git a/test/translate_c.zig b/test/translate_c.zig
index a390810830..3b201e2c11 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -764,27 +764,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
});
- // Test case temporarily disabled:
- // https://github.com/ziglang/zig/issues/12055
- if (false) {
- cases.add("align() attribute",
- \\__attribute__ ((aligned(128)))
- \\extern char my_array[16];
- \\__attribute__ ((aligned(128)))
- \\void my_fn(void) { }
- \\void other_fn(void) {
- \\ char ARR[16] __attribute__ ((aligned (16)));
- \\}
- , &[_][]const u8{
- \\pub extern var my_array: [16]u8 align(128);
- \\pub export fn my_fn() align(128) void {}
- \\pub export fn other_fn() void {
- \\ var ARR: [16]u8 align(16) = undefined;
- \\ _ = &ARR;
- \\}
- });
- }
-
cases.add("linksection() attribute",
\\// Use the "segment,section" format to make this test pass when
\\// targeting the mach-o binary format