From 6d24c40b6e79176b05ec735adcecfd346b03f059 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 30 Jun 2022 16:10:15 +0300 Subject: [PATCH 1/7] Sema: improve bitcast to enum error --- src/Sema.zig | 20 +++++++++++++++---- .../compile_errors/bitCast_to_enum_type.zig | 12 +++++++++++ .../stage1/obj/bitCast_to_enum_type.zig | 10 ---------- 3 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 test/cases/compile_errors/bitCast_to_enum_type.zig delete mode 100644 test/cases/compile_errors/stage1/obj/bitCast_to_enum_type.zig diff --git a/src/Sema.zig b/src/Sema.zig index 862d5cbf48..08372bf7b3 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7617,11 +7617,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); + const operand = try sema.resolveInst(extra.rhs); switch (dest_ty.zigTypeTag()) { .AnyFrame, .ComptimeFloat, .ComptimeInt, - .Enum, .EnumLiteral, .ErrorSet, .ErrorUnion, @@ -7634,7 +7634,21 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .Type, .Undefined, .Void, - => return sema.fail(block, dest_ty_src, "invalid type '{}' for @bitCast", .{dest_ty.fmt(sema.mod)}), + => return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)}), + + .Enum => { + const msg = msg: { + const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)}); + errdefer msg.destroy(sema.gpa); + switch (sema.typeOf(operand).zigTypeTag()) { + .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum for type coercion", .{}), + else => {}, + } + + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + }, .Pointer => return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}', use @ptrCast to cast to a pointer", .{ dest_ty.fmt(sema.mod), @@ -7658,8 +7672,6 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .Vector, => {}, } - - const operand = try sema.resolveInst(extra.rhs); return sema.bitCast(block, dest_ty, operand, operand_src); } diff --git a/test/cases/compile_errors/bitCast_to_enum_type.zig b/test/cases/compile_errors/bitCast_to_enum_type.zig new file mode 100644 index 0000000000..add531627f --- /dev/null +++ b/test/cases/compile_errors/bitCast_to_enum_type.zig @@ -0,0 +1,12 @@ +export fn entry() void { + const E = enum(u32) { a, b }; + const y = @bitCast(E, @as(u32, 3)); + _ = y; +} + +// error +// backend=stage2 +// target=native +// +// :3:24: error: cannot @bitCast to 'tmp.entry.E' +// :3:24: note: use @intToEnum for type coercion diff --git a/test/cases/compile_errors/stage1/obj/bitCast_to_enum_type.zig b/test/cases/compile_errors/stage1/obj/bitCast_to_enum_type.zig deleted file mode 100644 index 4d63ab9e01..0000000000 --- a/test/cases/compile_errors/stage1/obj/bitCast_to_enum_type.zig +++ /dev/null @@ -1,10 +0,0 @@ -export fn entry() void { - const y = @bitCast(enum(u32) { a, b }, @as(u32, 3)); - _ = y; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:24: error: cannot cast a value of type 'y' From 3014a0d5f1dcbcfdcec3852ffd54f3c589fe3e83 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 30 Jun 2022 16:39:54 +0300 Subject: [PATCH 2/7] Sema: validate callconv --- src/Sema.zig | 40 +++++++++++++++++++ .../{stage1/obj => }/bogus_compile_var.zig | 4 +- ...aapcs_aapcsvfp_on_unsupported_platform.zig | 11 +++++ ...conv_interrupt_on_unsupported_platform.zig | 7 ++++ ...allconv_signal_on_unsupported_platform.zig | 7 ++++ ...call_thiscall_on_unsupported_platform.zig} | 8 ++-- ...onv_vectorcall_on_unsupported_platform.zig | 7 ++++ ...aapcs_aapcsvfp_on_unsupported_platform.zig | 11 ----- ...conv_interrupt_on_unsupported_platform.zig | 7 ---- ...allconv_signal_on_unsupported_platform.zig | 7 ---- ...all_thiscall_on_unsupported_platform-1.zig | 11 ----- ...onv_vectorcall_on_unsupported_platform.zig | 7 ---- 12 files changed, 78 insertions(+), 49 deletions(-) rename test/cases/compile_errors/{stage1/obj => }/bogus_compile_var.zig (57%) create mode 100644 test/cases/compile_errors/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig create mode 100644 test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig create mode 100644 test/cases/compile_errors/callconv_signal_on_unsupported_platform.zig rename test/cases/compile_errors/{stage1/obj/callconv_stdcall_fastcall_thiscall_on_unsupported_platform-0.zig => callconv_stdcall_fastcall_thiscall_on_unsupported_platform.zig} (58%) create mode 100644 test/cases/compile_errors/callconv_vectorcall_on_unsupported_platform.zig delete mode 100644 test/cases/compile_errors/stage1/obj/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig delete mode 100644 test/cases/compile_errors/stage1/obj/callconv_interrupt_on_unsupported_platform.zig delete mode 100644 test/cases/compile_errors/stage1/obj/callconv_signal_on_unsupported_platform.zig delete mode 100644 test/cases/compile_errors/stage1/obj/callconv_stdcall_fastcall_thiscall_on_unsupported_platform-1.zig delete mode 100644 test/cases/compile_errors/stage1/obj/callconv_vectorcall_on_unsupported_platform.zig diff --git a/src/Sema.zig b/src/Sema.zig index 08372bf7b3..0d568f8b38 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7007,6 +7007,7 @@ fn funcCommon( noalias_bits: u32, ) CompileError!Air.Inst.Ref { const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; + const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset }; var is_generic = bare_return_type.tag() == .generic_poison or alignment == null or @@ -7109,6 +7110,45 @@ fn funcCommon( const cc_workaround = cc orelse .Unspecified; const align_workaround = alignment orelse 0; + const arch = sema.mod.getTarget().cpu.arch; + if (switch (cc_workaround) { + .Unspecified, .C, .Naked, .Async, .Inline => null, + .Interrupt => switch (arch) { + .i386, .x86_64, .avr, .msp430 => null, + else => @as([]const u8, "i386, x86_64, AVR, and MSP430"), + }, + .Signal => switch (arch) { + .avr => null, + else => @as([]const u8, "AVR"), + }, + .Stdcall, .Fastcall, .Thiscall => switch (arch) { + .i386 => null, + else => @as([]const u8, "i386"), + }, + .Vectorcall => switch (arch) { + .i386, .aarch64, .aarch64_be, .aarch64_32 => null, + else => @as([]const u8, "i386 and AArch64"), + }, + .APCS, .AAPCS, .AAPCSVFP => switch (arch) { + .arm, .armeb, .aarch64, .aarch64_be, .aarch64_32 => null, + else => @as([]const u8, "ARM"), + }, + .SysV, .Win64 => switch (arch) { + .x86_64 => null, + else => @as([]const u8, "x86_64"), + }, + .PtxKernel => switch (arch) { + .nvptx, .nvptx64 => null, + else => @as([]const u8, "nvptx and nvptx64"), + }, + }) |allowed_platform| { + return sema.fail(block, cc_src, "callconv '{s}' is only available on {s}, not {s}", .{ + @tagName(cc_workaround), + allowed_platform, + @tagName(arch), + }); + } + break :fn_ty try Type.Tag.function.create(sema.arena, .{ .param_types = param_types, .comptime_params = comptime_params.ptr, diff --git a/test/cases/compile_errors/stage1/obj/bogus_compile_var.zig b/test/cases/compile_errors/bogus_compile_var.zig similarity index 57% rename from test/cases/compile_errors/stage1/obj/bogus_compile_var.zig rename to test/cases/compile_errors/bogus_compile_var.zig index 845d943c7d..28d8b1dba5 100644 --- a/test/cases/compile_errors/stage1/obj/bogus_compile_var.zig +++ b/test/cases/compile_errors/bogus_compile_var.zig @@ -2,7 +2,7 @@ const x = @import("builtin").bogus; export fn entry() usize { return @sizeOf(@TypeOf(x)); } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:1:29: error: container 'builtin' has no member called 'bogus' +// :1:29: error: struct 'builtin.builtin' has no member named 'bogus' diff --git a/test/cases/compile_errors/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig b/test/cases/compile_errors/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig new file mode 100644 index 0000000000..cc6fc59a1a --- /dev/null +++ b/test/cases/compile_errors/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig @@ -0,0 +1,11 @@ +export fn entry1() callconv(.APCS) void {} +export fn entry2() callconv(.AAPCS) void {} +export fn entry3() callconv(.AAPCSVFP) void {} + +// error +// backend=stage2 +// target=x86_64-linux-none +// +// :1:30: error: callconv 'APCS' is only available on ARM, not x86_64 +// :2:30: error: callconv 'AAPCS' is only available on ARM, not x86_64 +// :3:30: error: callconv 'AAPCSVFP' is only available on ARM, not x86_64 diff --git a/test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig b/test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig new file mode 100644 index 0000000000..5f11fdcfa8 --- /dev/null +++ b/test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig @@ -0,0 +1,7 @@ +export fn entry() callconv(.Interrupt) void {} + +// error +// backend=stage2 +// target=aarch64-linux-none +// +// :1:29: error: callconv 'Interrupt' is only available on i386, x86_64, AVR, and MSP430, not aarch64 diff --git a/test/cases/compile_errors/callconv_signal_on_unsupported_platform.zig b/test/cases/compile_errors/callconv_signal_on_unsupported_platform.zig new file mode 100644 index 0000000000..9233655e35 --- /dev/null +++ b/test/cases/compile_errors/callconv_signal_on_unsupported_platform.zig @@ -0,0 +1,7 @@ +export fn entry() callconv(.Signal) void {} + +// error +// backend=stage2 +// target=x86_64-linux-none +// +// :1:29: error: callconv 'Signal' is only available on AVR, not x86_64 diff --git a/test/cases/compile_errors/stage1/obj/callconv_stdcall_fastcall_thiscall_on_unsupported_platform-0.zig b/test/cases/compile_errors/callconv_stdcall_fastcall_thiscall_on_unsupported_platform.zig similarity index 58% rename from test/cases/compile_errors/stage1/obj/callconv_stdcall_fastcall_thiscall_on_unsupported_platform-0.zig rename to test/cases/compile_errors/callconv_stdcall_fastcall_thiscall_on_unsupported_platform.zig index f4994107cd..d22fd13e8a 100644 --- a/test/cases/compile_errors/stage1/obj/callconv_stdcall_fastcall_thiscall_on_unsupported_platform-0.zig +++ b/test/cases/compile_errors/callconv_stdcall_fastcall_thiscall_on_unsupported_platform.zig @@ -15,9 +15,9 @@ export fn entry3() void { } // error -// backend=stage1 +// backend=stage2 // target=x86_64-linux-none // -// tmp.zig:1:27: error: callconv 'Stdcall' is only available on x86, not x86_64 -// tmp.zig:2:27: error: callconv 'Fastcall' is only available on x86, not x86_64 -// tmp.zig:3:27: error: callconv 'Thiscall' is only available on x86, not x86_64 +// :1:28: error: callconv 'Stdcall' is only available on i386, not x86_64 +// :2:28: error: callconv 'Fastcall' is only available on i386, not x86_64 +// :3:28: error: callconv 'Thiscall' is only available on i386, not x86_64 diff --git a/test/cases/compile_errors/callconv_vectorcall_on_unsupported_platform.zig b/test/cases/compile_errors/callconv_vectorcall_on_unsupported_platform.zig new file mode 100644 index 0000000000..9c231a6ea8 --- /dev/null +++ b/test/cases/compile_errors/callconv_vectorcall_on_unsupported_platform.zig @@ -0,0 +1,7 @@ +export fn entry() callconv(.Vectorcall) void {} + +// error +// backend=stage2 +// target=x86_64-linux-none +// +// :1:29: error: callconv 'Vectorcall' is only available on i386 and AArch64, not x86_64 diff --git a/test/cases/compile_errors/stage1/obj/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig b/test/cases/compile_errors/stage1/obj/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig deleted file mode 100644 index fa06287803..0000000000 --- a/test/cases/compile_errors/stage1/obj/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig +++ /dev/null @@ -1,11 +0,0 @@ -export fn entry1() callconv(.APCS) void {} -export fn entry2() callconv(.AAPCS) void {} -export fn entry3() callconv(.AAPCSVFP) void {} - -// error -// backend=stage1 -// target=x86_64-linux-none -// -// tmp.zig:1:29: error: callconv 'APCS' is only available on ARM, not x86_64 -// tmp.zig:2:29: error: callconv 'AAPCS' is only available on ARM, not x86_64 -// tmp.zig:3:29: error: callconv 'AAPCSVFP' is only available on ARM, not x86_64 diff --git a/test/cases/compile_errors/stage1/obj/callconv_interrupt_on_unsupported_platform.zig b/test/cases/compile_errors/stage1/obj/callconv_interrupt_on_unsupported_platform.zig deleted file mode 100644 index 8304fb90c1..0000000000 --- a/test/cases/compile_errors/stage1/obj/callconv_interrupt_on_unsupported_platform.zig +++ /dev/null @@ -1,7 +0,0 @@ -export fn entry() callconv(.Interrupt) void {} - -// error -// backend=stage1 -// target=aarch64-linux-none -// -// tmp.zig:1:28: error: callconv 'Interrupt' is only available on x86, x86_64, AVR, and MSP430, not aarch64 diff --git a/test/cases/compile_errors/stage1/obj/callconv_signal_on_unsupported_platform.zig b/test/cases/compile_errors/stage1/obj/callconv_signal_on_unsupported_platform.zig deleted file mode 100644 index 4b19b188fd..0000000000 --- a/test/cases/compile_errors/stage1/obj/callconv_signal_on_unsupported_platform.zig +++ /dev/null @@ -1,7 +0,0 @@ -export fn entry() callconv(.Signal) void {} - -// error -// backend=stage1 -// target=x86_64-linux-none -// -// tmp.zig:1:28: error: callconv 'Signal' is only available on AVR, not x86_64 diff --git a/test/cases/compile_errors/stage1/obj/callconv_stdcall_fastcall_thiscall_on_unsupported_platform-1.zig b/test/cases/compile_errors/stage1/obj/callconv_stdcall_fastcall_thiscall_on_unsupported_platform-1.zig deleted file mode 100644 index aa23f9ae51..0000000000 --- a/test/cases/compile_errors/stage1/obj/callconv_stdcall_fastcall_thiscall_on_unsupported_platform-1.zig +++ /dev/null @@ -1,11 +0,0 @@ -export fn entry1() callconv(.Stdcall) void {} -export fn entry2() callconv(.Fastcall) void {} -export fn entry3() callconv(.Thiscall) void {} - -// error -// backend=stage1 -// target=x86_64-linux-none -// -// tmp.zig:1:29: error: callconv 'Stdcall' is only available on x86, not x86_64 -// tmp.zig:2:29: error: callconv 'Fastcall' is only available on x86, not x86_64 -// tmp.zig:3:29: error: callconv 'Thiscall' is only available on x86, not x86_64 diff --git a/test/cases/compile_errors/stage1/obj/callconv_vectorcall_on_unsupported_platform.zig b/test/cases/compile_errors/stage1/obj/callconv_vectorcall_on_unsupported_platform.zig deleted file mode 100644 index e60e6ab42c..0000000000 --- a/test/cases/compile_errors/stage1/obj/callconv_vectorcall_on_unsupported_platform.zig +++ /dev/null @@ -1,7 +0,0 @@ -export fn entry() callconv(.Vectorcall) void {} - -// error -// backend=stage1 -// target=x86_64-linux-none -// -// tmp.zig:1:28: error: callconv 'Vectorcall' is only available on x86 and AArch64, not x86_64 From 3c73f711771e41e9176e973c64484f0ce5e0eeed Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 30 Jun 2022 16:58:46 +0300 Subject: [PATCH 3/7] Sema: prefer func.onwer_decl for compilelog src --- src/Sema.zig | 3 ++- .../{stage1/obj => }/compile-time_division_by_zero.zig | 4 ++-- .../obj => }/compile-time_remainder_division_by_zero.zig | 4 ++-- .../compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig | 6 +++--- test/cases/compile_errors/{stage1/obj => }/compile_log.zig | 6 ++---- ...ent_inside_function_which_must_be_comptime_evaluated.zig | 4 ++-- .../{stage1/obj => }/compile_time_division_by_zero.zig | 5 +++-- 7 files changed, 16 insertions(+), 16 deletions(-) rename test/cases/compile_errors/{stage1/obj => }/compile-time_division_by_zero.zig (58%) rename test/cases/compile_errors/{stage1/obj => }/compile-time_remainder_division_by_zero.zig (58%) rename test/cases/compile_errors/{stage1/obj => }/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig (66%) rename test/cases/compile_errors/{stage1/obj => }/compile_log.zig (54%) rename test/cases/compile_errors/{stage1/obj => }/compile_log_statement_inside_function_which_must_be_comptime_evaluated.zig (72%) rename test/cases/compile_errors/{stage1/obj => }/compile_time_division_by_zero.zig (56%) diff --git a/src/Sema.zig b/src/Sema.zig index 0d568f8b38..30cebe18b3 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4272,7 +4272,8 @@ fn zirCompileLog( } try writer.print("\n", .{}); - const gop = try sema.mod.compile_log_decls.getOrPut(sema.gpa, sema.owner_decl_index); + const decl_index = if (sema.func) |some| some.owner_decl else sema.owner_decl_index; + const gop = try sema.mod.compile_log_decls.getOrPut(sema.gpa, decl_index); if (!gop.found_existing) { gop.value_ptr.* = src_node; } diff --git a/test/cases/compile_errors/stage1/obj/compile-time_division_by_zero.zig b/test/cases/compile_errors/compile-time_division_by_zero.zig similarity index 58% rename from test/cases/compile_errors/stage1/obj/compile-time_division_by_zero.zig rename to test/cases/compile_errors/compile-time_division_by_zero.zig index e16f5f8cf4..969598e500 100644 --- a/test/cases/compile_errors/stage1/obj/compile-time_division_by_zero.zig +++ b/test/cases/compile_errors/compile-time_division_by_zero.zig @@ -6,7 +6,7 @@ comptime { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:4:17: error: division by zero +// :4:19: error: division by zero here causes undefined behavior diff --git a/test/cases/compile_errors/stage1/obj/compile-time_remainder_division_by_zero.zig b/test/cases/compile_errors/compile-time_remainder_division_by_zero.zig similarity index 58% rename from test/cases/compile_errors/stage1/obj/compile-time_remainder_division_by_zero.zig rename to test/cases/compile_errors/compile-time_remainder_division_by_zero.zig index 63f0def52c..301fad6a68 100644 --- a/test/cases/compile_errors/stage1/obj/compile-time_remainder_division_by_zero.zig +++ b/test/cases/compile_errors/compile-time_remainder_division_by_zero.zig @@ -6,7 +6,7 @@ comptime { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:4:17: error: division by zero +// :4:19: error: division by zero here causes undefined behavior diff --git a/test/cases/compile_errors/stage1/obj/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig b/test/cases/compile_errors/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig similarity index 66% rename from test/cases/compile_errors/stage1/obj/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig rename to test/cases/compile_errors/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig index 36e1ee1118..9189eeb48d 100644 --- a/test/cases/compile_errors/stage1/obj/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig +++ b/test/cases/compile_errors/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig @@ -6,12 +6,12 @@ fn testCompileLog(x: Bar) void { @compileLog(x); } -pub fn main () void { +pub export fn entry() void { comptime testCompileLog(Bar{.X = 123}); } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:6:5: error: found compile log statement +// :6:5: error: found compile log statement diff --git a/test/cases/compile_errors/stage1/obj/compile_log.zig b/test/cases/compile_errors/compile_log.zig similarity index 54% rename from test/cases/compile_errors/stage1/obj/compile_log.zig rename to test/cases/compile_errors/compile_log.zig index 7f5d522407..281f8747d2 100644 --- a/test/cases/compile_errors/stage1/obj/compile_log.zig +++ b/test/cases/compile_errors/compile_log.zig @@ -8,9 +8,7 @@ fn bar(a: i32, b: []const u8) void { } // error -// backend=stage1 +// backend=llvm // target=native // -// tmp.zig:5:5: error: found compile log statement -// tmp.zig:6:5: error: found compile log statement -// tmp.zig:7:5: error: found compile log statement +// :5:5: error: found compile log statement diff --git a/test/cases/compile_errors/stage1/obj/compile_log_statement_inside_function_which_must_be_comptime_evaluated.zig b/test/cases/compile_errors/compile_log_statement_inside_function_which_must_be_comptime_evaluated.zig similarity index 72% rename from test/cases/compile_errors/stage1/obj/compile_log_statement_inside_function_which_must_be_comptime_evaluated.zig rename to test/cases/compile_errors/compile_log_statement_inside_function_which_must_be_comptime_evaluated.zig index 19b96048cb..0bc45eae0a 100644 --- a/test/cases/compile_errors/stage1/obj/compile_log_statement_inside_function_which_must_be_comptime_evaluated.zig +++ b/test/cases/compile_errors/compile_log_statement_inside_function_which_must_be_comptime_evaluated.zig @@ -8,7 +8,7 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:5: error: found compile log statement +// :2:5: error: found compile log statement diff --git a/test/cases/compile_errors/stage1/obj/compile_time_division_by_zero.zig b/test/cases/compile_errors/compile_time_division_by_zero.zig similarity index 56% rename from test/cases/compile_errors/stage1/obj/compile_time_division_by_zero.zig rename to test/cases/compile_errors/compile_time_division_by_zero.zig index 7f7e168f02..281ccf28a1 100644 --- a/test/cases/compile_errors/stage1/obj/compile_time_division_by_zero.zig +++ b/test/cases/compile_errors/compile_time_division_by_zero.zig @@ -6,7 +6,8 @@ fn foo(x: u32) u32 { export fn entry() usize { return @sizeOf(@TypeOf(y)); } // error -// backend=stage1 +// backend=llvm // target=native // -// tmp.zig:3:14: error: division by zero +// :3:16: error: division by zero here causes undefined behavior +// :1:14: note: called from here From ae7b32eb62cb00a09fe2e0e30b307eb83e9f0a86 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 30 Jun 2022 17:22:16 +0300 Subject: [PATCH 4/7] Sema: validate deref operator type and value --- lib/c.zig | 2 +- lib/std/os.zig | 2 +- lib/std/process.zig | 2 +- src/AstGen.zig | 2 ++ src/Sema.zig | 27 +++++++++++++++++++ src/Zir.zig | 6 +++++ src/print_zir.zig | 1 + .../assign_to_invalid_dereference.zig | 9 +++++++ .../{stage1 => }/deref_on_undefined_value.zig | 4 +-- .../deref_slice_and_get_len_field.zig | 4 +-- .../{stage1/obj => }/dereference_an_array.zig | 6 ++--- .../compile_errors/dereference_slice.zig | 12 +++++++++ .../dereference_unknown_length_pointer.zig | 9 +++++++ .../invalid_deref_on_switch_target.zig | 4 +-- .../invalid_multiple_dereferences.zig | 6 ++--- .../comptime_ptrcast_of_zero-sized_type.zig | 0 .../obj/assign_to_invalid_dereference.zig | 9 ------- .../dereference_unknown_length_pointer.zig | 9 ------- .../obj/take_slice_of_invalid_dereference.zig | 10 ------- .../take_slice_of_invalid_dereference.zig | 10 +++++++ 20 files changed, 91 insertions(+), 43 deletions(-) create mode 100644 test/cases/compile_errors/assign_to_invalid_dereference.zig rename test/cases/compile_errors/{stage1 => }/deref_on_undefined_value.zig (51%) rename test/cases/compile_errors/{stage1/obj => }/deref_slice_and_get_len_field.zig (53%) rename test/cases/compile_errors/{stage1/obj => }/dereference_an_array.zig (52%) create mode 100644 test/cases/compile_errors/dereference_slice.zig create mode 100644 test/cases/compile_errors/dereference_unknown_length_pointer.zig rename test/cases/compile_errors/{stage1/obj => }/invalid_deref_on_switch_target.zig (68%) rename test/cases/compile_errors/{stage1/obj => }/invalid_multiple_dereferences.zig (61%) rename test/cases/compile_errors/stage1/{obj => }/comptime_ptrcast_of_zero-sized_type.zig (100%) delete mode 100644 test/cases/compile_errors/stage1/obj/assign_to_invalid_dereference.zig delete mode 100644 test/cases/compile_errors/stage1/obj/dereference_unknown_length_pointer.zig delete mode 100644 test/cases/compile_errors/stage1/obj/take_slice_of_invalid_dereference.zig create mode 100644 test/cases/compile_errors/take_slice_of_invalid_dereference.zig diff --git a/lib/c.zig b/lib/c.zig index 30c6e0cd76..9df1b3fb01 100644 --- a/lib/c.zig +++ b/lib/c.zig @@ -82,7 +82,7 @@ fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 { var d = dest.?; var n = len; while (true) { - d.* = c; + d[0] = c; n -= 1; if (n == 0) break; d += 1; diff --git a/lib/std/os.zig b/lib/std/os.zig index 578a8ddcbc..02ed710dd3 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1868,7 +1868,7 @@ pub fn getenv(key: []const u8) ?[]const u8 { } // Search the entire `environ` because we don't have a null terminated pointer. var ptr = std.c.environ; - while (ptr.*) |line| : (ptr += 1) { + while (ptr[0]) |line| : (ptr += 1) { var line_i: usize = 0; while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} const this_key = line[0..line_i]; diff --git a/lib/std/process.zig b/lib/std/process.zig index 0b64b5910d..dffd6b1701 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -313,7 +313,7 @@ pub fn getEnvMap(allocator: Allocator) !EnvMap { return result; } else if (builtin.link_libc) { var ptr = std.c.environ; - while (ptr.*) |line| : (ptr += 1) { + while (ptr[0]) |line| : (ptr += 1) { var line_i: usize = 0; while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} const key = line[0..line_i]; diff --git a/src/AstGen.zig b/src/AstGen.zig index c9abb1859b..8707728313 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -812,6 +812,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr .deref => { const lhs = try expr(gz, scope, .none, node_datas[node].lhs); + _ = try gz.addUnTok(.validate_deref, lhs, main_tokens[node]); switch (rl) { .ref => return lhs, else => { @@ -2500,6 +2501,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner .memset, .validate_array_init_ty, .validate_struct_init_ty, + .validate_deref, => break :b true, } } else switch (maybe_unused_result) { diff --git a/src/Sema.zig b/src/Sema.zig index 30cebe18b3..0e7188a6c9 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1080,6 +1080,11 @@ fn analyzeBodyInner( i += 1; continue; }, + .validate_deref => { + try sema.zirValidateDeref(block, inst); + i += 1; + continue; + }, .@"export" => { try sema.zirExport(block, inst); i += 1; @@ -3849,6 +3854,28 @@ fn zirValidateArrayInit( } } +fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { + const inst_data = sema.code.instructions.items(.data)[inst].un_tok; + const src = inst_data.src(); + const operand_src: LazySrcLoc = .{ .token_offset = inst_data.src_tok + 1 }; + const operand = try sema.resolveInst(inst_data.operand); + const operand_ty = sema.typeOf(operand); + + if (operand_ty.zigTypeTag() != .Pointer) { + return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(sema.mod)}); + } else switch (operand_ty.ptrSize()) { + .One, .C => {}, + .Many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{}'", .{operand_ty.fmt(sema.mod)}), + .Slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(sema.mod)}), + } + + if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { + if (val.isUndef()) { + return sema.fail(block, src, "cannot dereference undefined value", .{}); + } + } +} + fn failWithBadMemberAccess( sema: *Sema, block: *Block, diff --git a/src/Zir.zig b/src/Zir.zig index e6acfe8ed2..26bb09860d 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -729,6 +729,9 @@ pub const Inst = struct { /// Same as `validate_array_init` but additionally communicates that the /// resulting array initialization value is within a comptime scope. validate_array_init_comptime, + /// Check that operand type supports the dereference operand (.*). + /// Uses the `un_tok` field. + validate_deref, /// A struct literal with a specified type, with no fields. /// Uses the `un_node` field. struct_init_empty, @@ -1156,6 +1159,7 @@ pub const Inst = struct { .validate_struct_init_comptime, .validate_array_init, .validate_array_init_comptime, + .validate_deref, .struct_init_empty, .struct_init, .struct_init_ref, @@ -1309,6 +1313,7 @@ pub const Inst = struct { .validate_struct_init_comptime, .validate_array_init, .validate_array_init_comptime, + .validate_deref, .@"export", .export_value, .set_cold, @@ -1709,6 +1714,7 @@ pub const Inst = struct { .validate_struct_init_comptime = .pl_node, .validate_array_init = .pl_node, .validate_array_init_comptime = .pl_node, + .validate_deref = .un_tok, .struct_init_empty = .un_node, .field_type = .pl_node, .field_type_ref = .pl_node, diff --git a/src/print_zir.zig b/src/print_zir.zig index 480a3e2a4f..fe8446b34a 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -242,6 +242,7 @@ const Writer = struct { .ret_tok, .ensure_err_payload_void, .closure_capture, + .validate_deref, => try self.writeUnTok(stream, inst), .bool_br_and, diff --git a/test/cases/compile_errors/assign_to_invalid_dereference.zig b/test/cases/compile_errors/assign_to_invalid_dereference.zig new file mode 100644 index 0000000000..cb35004034 --- /dev/null +++ b/test/cases/compile_errors/assign_to_invalid_dereference.zig @@ -0,0 +1,9 @@ +export fn entry() void { + 'a'.* = 1; +} + +// error +// backend=stage2 +// target=native +// +// :2:8: error: cannot dereference non-pointer type 'comptime_int' diff --git a/test/cases/compile_errors/stage1/deref_on_undefined_value.zig b/test/cases/compile_errors/deref_on_undefined_value.zig similarity index 51% rename from test/cases/compile_errors/stage1/deref_on_undefined_value.zig rename to test/cases/compile_errors/deref_on_undefined_value.zig index f64d567a26..fa12e2824c 100644 --- a/test/cases/compile_errors/stage1/deref_on_undefined_value.zig +++ b/test/cases/compile_errors/deref_on_undefined_value.zig @@ -4,7 +4,7 @@ comptime { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:3:9: error: attempt to dereference undefined value +// :3:10: error: cannot dereference undefined value diff --git a/test/cases/compile_errors/stage1/obj/deref_slice_and_get_len_field.zig b/test/cases/compile_errors/deref_slice_and_get_len_field.zig similarity index 53% rename from test/cases/compile_errors/stage1/obj/deref_slice_and_get_len_field.zig rename to test/cases/compile_errors/deref_slice_and_get_len_field.zig index 98097597cc..1ba03c6d50 100644 --- a/test/cases/compile_errors/stage1/obj/deref_slice_and_get_len_field.zig +++ b/test/cases/compile_errors/deref_slice_and_get_len_field.zig @@ -4,7 +4,7 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:3:10: error: attempt to dereference non-pointer type '[]u8' +// :3:10: error: index syntax required for slice type '[]u8' diff --git a/test/cases/compile_errors/stage1/obj/dereference_an_array.zig b/test/cases/compile_errors/dereference_an_array.zig similarity index 52% rename from test/cases/compile_errors/stage1/obj/dereference_an_array.zig rename to test/cases/compile_errors/dereference_an_array.zig index 0dd91f70e5..f5aabf081c 100644 --- a/test/cases/compile_errors/stage1/obj/dereference_an_array.zig +++ b/test/cases/compile_errors/dereference_an_array.zig @@ -5,10 +5,10 @@ pub fn pass(in: []u8) []u8 { return out.*[0..1]; } -export fn entry() usize { return @sizeOf(@TypeOf(pass)); } +export fn entry() usize { return @sizeOf(@TypeOf(&pass)); } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:4:10: error: attempt to dereference non-pointer type '[10]u8' +// :4:10: error: cannot dereference non-pointer type '[10]u8' diff --git a/test/cases/compile_errors/dereference_slice.zig b/test/cases/compile_errors/dereference_slice.zig new file mode 100644 index 0000000000..7dba3b55d8 --- /dev/null +++ b/test/cases/compile_errors/dereference_slice.zig @@ -0,0 +1,12 @@ +fn entry(x: []i32) i32 { + return x.*; +} +comptime { + _ = entry; +} + +// error +// backend=stage2 +// target=native +// +// :2:13: error: index syntax required for slice type '[]i32' diff --git a/test/cases/compile_errors/dereference_unknown_length_pointer.zig b/test/cases/compile_errors/dereference_unknown_length_pointer.zig new file mode 100644 index 0000000000..353f94b8d9 --- /dev/null +++ b/test/cases/compile_errors/dereference_unknown_length_pointer.zig @@ -0,0 +1,9 @@ +export fn entry(x: [*]i32) i32 { + return x.*; +} + +// error +// backend=stage2 +// target=native +// +// :2:13: error: index syntax required for unknown-length pointer type '[*]i32' diff --git a/test/cases/compile_errors/stage1/obj/invalid_deref_on_switch_target.zig b/test/cases/compile_errors/invalid_deref_on_switch_target.zig similarity index 68% rename from test/cases/compile_errors/stage1/obj/invalid_deref_on_switch_target.zig rename to test/cases/compile_errors/invalid_deref_on_switch_target.zig index 966a881543..a880b16fca 100644 --- a/test/cases/compile_errors/stage1/obj/invalid_deref_on_switch_target.zig +++ b/test/cases/compile_errors/invalid_deref_on_switch_target.zig @@ -11,7 +11,7 @@ const Tile = enum { }; // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:3:17: error: attempt to dereference non-pointer type 'Tile' +// :3:17: error: cannot dereference non-pointer type 'tmp.Tile' diff --git a/test/cases/compile_errors/stage1/obj/invalid_multiple_dereferences.zig b/test/cases/compile_errors/invalid_multiple_dereferences.zig similarity index 61% rename from test/cases/compile_errors/stage1/obj/invalid_multiple_dereferences.zig rename to test/cases/compile_errors/invalid_multiple_dereferences.zig index f8a0b8013f..3edebf7b1f 100644 --- a/test/cases/compile_errors/stage1/obj/invalid_multiple_dereferences.zig +++ b/test/cases/compile_errors/invalid_multiple_dereferences.zig @@ -12,8 +12,8 @@ pub const Box = struct { }; // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:3:8: error: attempt to dereference non-pointer type 'Box' -// tmp.zig:8:13: error: attempt to dereference non-pointer type 'Box' +// :3:8: error: cannot dereference non-pointer type 'tmp.Box' +// :8:13: error: cannot dereference non-pointer type 'tmp.Box' diff --git a/test/cases/compile_errors/stage1/obj/comptime_ptrcast_of_zero-sized_type.zig b/test/cases/compile_errors/stage1/comptime_ptrcast_of_zero-sized_type.zig similarity index 100% rename from test/cases/compile_errors/stage1/obj/comptime_ptrcast_of_zero-sized_type.zig rename to test/cases/compile_errors/stage1/comptime_ptrcast_of_zero-sized_type.zig diff --git a/test/cases/compile_errors/stage1/obj/assign_to_invalid_dereference.zig b/test/cases/compile_errors/stage1/obj/assign_to_invalid_dereference.zig deleted file mode 100644 index 7fef5db83c..0000000000 --- a/test/cases/compile_errors/stage1/obj/assign_to_invalid_dereference.zig +++ /dev/null @@ -1,9 +0,0 @@ -export fn entry() void { - 'a'.* = 1; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:8: error: attempt to dereference non-pointer type 'comptime_int' diff --git a/test/cases/compile_errors/stage1/obj/dereference_unknown_length_pointer.zig b/test/cases/compile_errors/stage1/obj/dereference_unknown_length_pointer.zig deleted file mode 100644 index c305e4bc98..0000000000 --- a/test/cases/compile_errors/stage1/obj/dereference_unknown_length_pointer.zig +++ /dev/null @@ -1,9 +0,0 @@ -export fn entry(x: [*]i32) i32 { - return x.*; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:13: error: index syntax required for unknown-length pointer type '[*]i32' diff --git a/test/cases/compile_errors/stage1/obj/take_slice_of_invalid_dereference.zig b/test/cases/compile_errors/stage1/obj/take_slice_of_invalid_dereference.zig deleted file mode 100644 index c039be3737..0000000000 --- a/test/cases/compile_errors/stage1/obj/take_slice_of_invalid_dereference.zig +++ /dev/null @@ -1,10 +0,0 @@ -export fn entry() void { - const x = 'a'.*[0..]; - _ = x; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:18: error: attempt to dereference non-pointer type 'comptime_int' diff --git a/test/cases/compile_errors/take_slice_of_invalid_dereference.zig b/test/cases/compile_errors/take_slice_of_invalid_dereference.zig new file mode 100644 index 0000000000..35c1b2de0d --- /dev/null +++ b/test/cases/compile_errors/take_slice_of_invalid_dereference.zig @@ -0,0 +1,10 @@ +export fn entry() void { + const x = 'a'.*[0..]; + _ = x; +} + +// error +// backend=stage2 +// target=native +// +// :2:18: error: cannot dereference non-pointer type 'comptime_int' From e6ebf56dd6cf2e2c23af952d2e9e327703c9cd02 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 30 Jun 2022 17:38:04 +0300 Subject: [PATCH 5/7] Sema: validate `@intToEnum` int operand type --- src/Sema.zig | 7 ++++--- .../{stage1/obj => }/discarding_error_value.zig | 4 ++-- .../{stage1/obj => }/duplicate_enum_field.zig | 6 +++--- .../{stage1/obj => }/duplicate_error_in_switch.zig | 6 +++--- .../obj => }/explicitly_casting_non_tag_type_to_enum.zig | 4 ++-- test/stage2/cbe.zig | 4 ++-- 6 files changed, 16 insertions(+), 15 deletions(-) rename test/cases/compile_errors/{stage1/obj => }/discarding_error_value.zig (54%) rename test/cases/compile_errors/{stage1/obj => }/duplicate_enum_field.zig (56%) rename test/cases/compile_errors/{stage1/obj => }/duplicate_error_in_switch.zig (65%) rename test/cases/compile_errors/{stage1/obj => }/explicitly_casting_non_tag_type_to_enum.zig (71%) diff --git a/src/Sema.zig b/src/Sema.zig index 0e7188a6c9..64db6a9bed 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2439,9 +2439,9 @@ fn zirEnumDecl( const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i); const other_tag_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, gop.index); const msg = msg: { - const msg = try sema.errMsg(block, field_src, "duplicate enum tag", .{}); + const msg = try sema.errMsg(block, field_src, "duplicate enum field '{s}'", .{field_name}); errdefer msg.destroy(gpa); - try sema.errNote(block, other_tag_src, msg, "other tag here", .{}); + try sema.errNote(block, other_tag_src, msg, "other field here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -2751,7 +2751,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com const src = inst_data.src(); const operand_ty = sema.typeOf(operand); switch (operand_ty.zigTypeTag()) { - .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is discarded", .{}), + .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is discardederror is discarded. consider using `try`, `catch`, or `if`", .{}), else => return, } } @@ -6444,6 +6444,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A if (dest_ty.zigTypeTag() != .Enum) { return sema.fail(block, dest_ty_src, "expected enum, found '{}'", .{dest_ty.fmt(sema.mod)}); } + _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand)); if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |int_val| { if (dest_ty.isNonexhaustiveEnum()) { diff --git a/test/cases/compile_errors/stage1/obj/discarding_error_value.zig b/test/cases/compile_errors/discarding_error_value.zig similarity index 54% rename from test/cases/compile_errors/stage1/obj/discarding_error_value.zig rename to test/cases/compile_errors/discarding_error_value.zig index dcfa22e8cb..f74fc4ea29 100644 --- a/test/cases/compile_errors/stage1/obj/discarding_error_value.zig +++ b/test/cases/compile_errors/discarding_error_value.zig @@ -6,7 +6,7 @@ fn foo() !void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:12: error: error is discarded. consider using `try`, `catch`, or `if` +// :2:12: error: error is discarded. consider using `try`, `catch`, or `if` diff --git a/test/cases/compile_errors/stage1/obj/duplicate_enum_field.zig b/test/cases/compile_errors/duplicate_enum_field.zig similarity index 56% rename from test/cases/compile_errors/stage1/obj/duplicate_enum_field.zig rename to test/cases/compile_errors/duplicate_enum_field.zig index cd024270bd..ebf01f99a7 100644 --- a/test/cases/compile_errors/stage1/obj/duplicate_enum_field.zig +++ b/test/cases/compile_errors/duplicate_enum_field.zig @@ -9,8 +9,8 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:3:5: error: duplicate enum field: 'Bar' -// tmp.zig:2:5: note: other field here +// :3:5: error: duplicate enum field 'Bar' +// :2:5: note: other field here diff --git a/test/cases/compile_errors/stage1/obj/duplicate_error_in_switch.zig b/test/cases/compile_errors/duplicate_error_in_switch.zig similarity index 65% rename from test/cases/compile_errors/stage1/obj/duplicate_error_in_switch.zig rename to test/cases/compile_errors/duplicate_error_in_switch.zig index 140a14ec81..6e9b1e9099 100644 --- a/test/cases/compile_errors/stage1/obj/duplicate_error_in_switch.zig +++ b/test/cases/compile_errors/duplicate_error_in_switch.zig @@ -15,8 +15,8 @@ fn foo(x: i32) !void { } // error -// backend=stage1 +// backend=llvm // target=native // -// tmp.zig:5:14: error: duplicate switch value: '@typeInfo(@typeInfo(@TypeOf(foo)).Fn.return_type.?).ErrorUnion.error_set.Foo' -// tmp.zig:3:14: note: other value here +// :5:9: error: duplicate switch value +// :3:9: note: other value here diff --git a/test/cases/compile_errors/stage1/obj/explicitly_casting_non_tag_type_to_enum.zig b/test/cases/compile_errors/explicitly_casting_non_tag_type_to_enum.zig similarity index 71% rename from test/cases/compile_errors/stage1/obj/explicitly_casting_non_tag_type_to_enum.zig rename to test/cases/compile_errors/explicitly_casting_non_tag_type_to_enum.zig index 1999fd70a7..aac876e614 100644 --- a/test/cases/compile_errors/stage1/obj/explicitly_casting_non_tag_type_to_enum.zig +++ b/test/cases/compile_errors/explicitly_casting_non_tag_type_to_enum.zig @@ -12,7 +12,7 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:10:31: error: expected integer type, found 'f32' +// :10:31: error: expected integer type, found 'f32' diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig index f602c49885..4817f0502f 100644 --- a/test/stage2/cbe.zig +++ b/test/stage2/cbe.zig @@ -729,8 +729,8 @@ pub fn addCases(ctx: *TestContext) !void { \\ _ = E1.a; \\} , &.{ - ":1:28: error: duplicate enum tag", - ":1:22: note: other tag here", + ":1:28: error: duplicate enum field 'b'", + ":1:22: note: other field here", }); case.addError( From a6bf8c2593ae6e60d4c4804d4e9fd87fe29885ed Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 30 Jun 2022 22:57:20 +0300 Subject: [PATCH 6/7] Sema: add more validation to zirFieldParentPtr --- src/Sema.zig | 52 ++++++++++++++----- .../{stage1/obj => }/division_by_zero.zig | 11 ++-- .../obj => }/error_not_handled_in_switch.zig | 7 +-- ...comptime_field_ptr_not_based_on_struct.zig | 4 +- ...ldParentPtr-comptime_wrong_field_index.zig | 5 +- ...ParentPtr-field_pointer_is_not_pointer.zig | 4 +- .../obj => }/field_access_of_opaque_type.zig | 4 +- .../obj => }/field_access_of_slices.zig | 5 +- ...field_access_of_unknown_length_pointer.zig | 4 +- ...uality_but_sets_have_no_common_members.zig | 0 10 files changed, 61 insertions(+), 35 deletions(-) rename test/cases/compile_errors/{stage1/obj => }/division_by_zero.zig (55%) rename test/cases/compile_errors/{stage1/obj => }/error_not_handled_in_switch.zig (64%) rename test/cases/compile_errors/{stage1/obj => }/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig (76%) rename test/cases/compile_errors/{stage1/obj => }/fieldParentPtr-comptime_wrong_field_index.zig (59%) rename test/cases/compile_errors/{stage1/obj => }/fieldParentPtr-field_pointer_is_not_pointer.zig (66%) rename test/cases/compile_errors/{stage1/obj => }/field_access_of_opaque_type.zig (68%) rename test/cases/compile_errors/{stage1/obj => }/field_access_of_slices.zig (54%) rename test/cases/compile_errors/{stage1/obj => }/field_access_of_unknown_length_pointer.zig (60%) rename test/cases/compile_errors/stage1/{obj => }/error_equality_but_sets_have_no_common_members.zig (100%) diff --git a/src/Sema.zig b/src/Sema.zig index 64db6a9bed..5010d86c9a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8378,19 +8378,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError block, src, msg, - "unhandled error value: error.{s}", + "unhandled error value: 'error.{s}'", .{error_name}, ); } } if (maybe_msg) |msg| { - try sema.mod.errNoteNonLazy( - operand_ty.declSrcLoc(sema.mod), - msg, - "error set '{}' declared here", - .{operand_ty.fmt(sema.mod)}, - ); + maybe_msg = null; + try sema.addDeclaredHereNote(msg, operand_ty); return sema.failWithOwnedErrorMsg(block, msg); } @@ -17143,9 +17139,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr const field_index = struct_obj.fields.getIndex(field_name) orelse return sema.failWithBadStructFieldAccess(block, struct_obj, name_src, field_name); - if (field_ptr_ty.zigTypeTag() != .Pointer) { - return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{field_ptr_ty.fmt(sema.mod)}); - } + try sema.checkPtrOperand(block, ptr_src, field_ptr_ty); const field = struct_obj.fields.values()[field_index]; const field_ptr_ty_info = field_ptr_ty.ptrInfo().data; @@ -17168,8 +17162,29 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data); if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| { - const payload = field_ptr_val.castTag(.field_ptr).?.data; - return sema.addConstant(result_ptr, payload.container_ptr); + const payload = field_ptr_val.castTag(.field_ptr) orelse { + return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{}); + }; + if (payload.data.field_index != field_index) { + const msg = msg: { + const msg = try sema.errMsg( + block, + src, + "field '{s}' has index '{d}' but pointer value is index '{d}' of struct '{}'", + .{ + field_name, + field_index, + payload.data.field_index, + struct_ty.fmt(sema.mod), + }, + ); + errdefer msg.destroy(sema.gpa); + try sema.addDeclaredHereNote(msg, struct_ty); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + } + return sema.addConstant(result_ptr, payload.data.container_ptr); } try sema.requireRuntimeBlock(block, src); @@ -18515,7 +18530,16 @@ fn fieldVal( kw_name, child_type.fmt(sema.mod), field_name, }); }, - else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}), + else => { + const msg = msg: { + const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}); + errdefer msg.destroy(sema.gpa); + if (child_type.isSlice()) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{}); + if (child_type.zigTypeTag() == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{}); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + }, } }, .Struct => if (is_pointer_to) { @@ -18739,7 +18763,7 @@ fn fieldPtr( }, else => {}, } - return sema.fail(block, src, "type '{}' does not support field access (fieldPtr, {}.{s})", .{ object_ty.fmt(sema.mod), object_ptr_ty.fmt(sema.mod), field_name }); + return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); } fn fieldCallBind( diff --git a/test/cases/compile_errors/stage1/obj/division_by_zero.zig b/test/cases/compile_errors/division_by_zero.zig similarity index 55% rename from test/cases/compile_errors/stage1/obj/division_by_zero.zig rename to test/cases/compile_errors/division_by_zero.zig index 3023f0c6f3..2e2f7e2be2 100644 --- a/test/cases/compile_errors/stage1/obj/division_by_zero.zig +++ b/test/cases/compile_errors/division_by_zero.zig @@ -6,13 +6,12 @@ const float_x = @as(f32, 1.0) / @as(f32, 0.0); export fn entry1() usize { return @sizeOf(@TypeOf(lit_int_x)); } export fn entry2() usize { return @sizeOf(@TypeOf(lit_float_x)); } export fn entry3() usize { return @sizeOf(@TypeOf(int_x)); } -export fn entry4() usize { return @sizeOf(@TypeOf(float_x)); } +export fn entry4() usize { return @sizeOf(@TypeOf(float_x)); } // no error on purpose // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:1:21: error: division by zero -// tmp.zig:2:25: error: division by zero -// tmp.zig:3:27: error: division by zero -// tmp.zig:4:31: error: division by zero +// :1:23: error: division by zero here causes undefined behavior +// :2:27: error: division by zero here causes undefined behavior +// :3:29: error: division by zero here causes undefined behavior diff --git a/test/cases/compile_errors/stage1/obj/error_not_handled_in_switch.zig b/test/cases/compile_errors/error_not_handled_in_switch.zig similarity index 64% rename from test/cases/compile_errors/stage1/obj/error_not_handled_in_switch.zig rename to test/cases/compile_errors/error_not_handled_in_switch.zig index 12ee35daef..8f0d26a4a9 100644 --- a/test/cases/compile_errors/stage1/obj/error_not_handled_in_switch.zig +++ b/test/cases/compile_errors/error_not_handled_in_switch.zig @@ -13,8 +13,9 @@ fn foo(x: i32) !void { } // error -// backend=stage1 +// backend=llvm // target=native // -// tmp.zig:2:26: error: error.Baz not handled in switch -// tmp.zig:2:26: error: error.Bar not handled in switch +// :2:26: error: switch must handle all possibilities +// :2:26: note: unhandled error value: 'error.Bar' +// :2:26: note: unhandled error value: 'error.Baz' diff --git a/test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig b/test/cases/compile_errors/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig similarity index 76% rename from test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig rename to test/cases/compile_errors/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig index 9375f4639a..7f57268f06 100644 --- a/test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig +++ b/test/cases/compile_errors/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig @@ -11,7 +11,7 @@ comptime { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:9:55: error: pointer value not based on parent struct +// :9:55: error: pointer value not based on parent struct diff --git a/test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_wrong_field_index.zig b/test/cases/compile_errors/fieldParentPtr-comptime_wrong_field_index.zig similarity index 59% rename from test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_wrong_field_index.zig rename to test/cases/compile_errors/fieldParentPtr-comptime_wrong_field_index.zig index c322543dc0..a73409aea3 100644 --- a/test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_wrong_field_index.zig +++ b/test/cases/compile_errors/fieldParentPtr-comptime_wrong_field_index.zig @@ -10,7 +10,8 @@ comptime { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:8:29: error: field 'b' has index 1 but pointer value is index 0 of struct 'Foo' +// :8:29: error: field 'b' has index '1' but pointer value is index '0' of struct 'tmp.Foo' +// :1:13: note: struct declared here diff --git a/test/cases/compile_errors/stage1/obj/fieldParentPtr-field_pointer_is_not_pointer.zig b/test/cases/compile_errors/fieldParentPtr-field_pointer_is_not_pointer.zig similarity index 66% rename from test/cases/compile_errors/stage1/obj/fieldParentPtr-field_pointer_is_not_pointer.zig rename to test/cases/compile_errors/fieldParentPtr-field_pointer_is_not_pointer.zig index 71360e5681..8a57d08c3b 100644 --- a/test/cases/compile_errors/stage1/obj/fieldParentPtr-field_pointer_is_not_pointer.zig +++ b/test/cases/compile_errors/fieldParentPtr-field_pointer_is_not_pointer.zig @@ -6,7 +6,7 @@ export fn foo(a: i32) *Foo { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:5:38: error: expected pointer, found 'i32' +// :5:38: error: expected pointer type, found 'i32' diff --git a/test/cases/compile_errors/stage1/obj/field_access_of_opaque_type.zig b/test/cases/compile_errors/field_access_of_opaque_type.zig similarity index 68% rename from test/cases/compile_errors/stage1/obj/field_access_of_opaque_type.zig rename to test/cases/compile_errors/field_access_of_opaque_type.zig index 963c89dafe..f9ec483305 100644 --- a/test/cases/compile_errors/stage1/obj/field_access_of_opaque_type.zig +++ b/test/cases/compile_errors/field_access_of_opaque_type.zig @@ -10,7 +10,7 @@ fn bar(x: *MyType) bool { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:9:13: error: no member named 'blah' in opaque type 'MyType' +// :9:13: error: type '*tmp.MyType' does not support field access diff --git a/test/cases/compile_errors/stage1/obj/field_access_of_slices.zig b/test/cases/compile_errors/field_access_of_slices.zig similarity index 54% rename from test/cases/compile_errors/stage1/obj/field_access_of_slices.zig rename to test/cases/compile_errors/field_access_of_slices.zig index 45ca711367..1fbfda9646 100644 --- a/test/cases/compile_errors/stage1/obj/field_access_of_slices.zig +++ b/test/cases/compile_errors/field_access_of_slices.zig @@ -5,7 +5,8 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:3:32: error: type 'type' does not support field access +// :3:32: error: type '[]i32' has no members +// :3:32: note: slice values have 'len' and 'ptr' members diff --git a/test/cases/compile_errors/stage1/obj/field_access_of_unknown_length_pointer.zig b/test/cases/compile_errors/field_access_of_unknown_length_pointer.zig similarity index 60% rename from test/cases/compile_errors/stage1/obj/field_access_of_unknown_length_pointer.zig rename to test/cases/compile_errors/field_access_of_unknown_length_pointer.zig index f9a37cabcc..2f526277fe 100644 --- a/test/cases/compile_errors/stage1/obj/field_access_of_unknown_length_pointer.zig +++ b/test/cases/compile_errors/field_access_of_unknown_length_pointer.zig @@ -7,7 +7,7 @@ export fn entry(foo: [*]Foo) void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:6:8: error: type '[*]Foo' does not support field access +// :6:8: error: type '[*]tmp.Foo' does not support field access diff --git a/test/cases/compile_errors/stage1/obj/error_equality_but_sets_have_no_common_members.zig b/test/cases/compile_errors/stage1/error_equality_but_sets_have_no_common_members.zig similarity index 100% rename from test/cases/compile_errors/stage1/obj/error_equality_but_sets_have_no_common_members.zig rename to test/cases/compile_errors/stage1/error_equality_but_sets_have_no_common_members.zig From 2029601cb2ad4a6e9c8b260eec68de881d46735b Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 30 Jun 2022 23:59:39 +0300 Subject: [PATCH 7/7] AstGen: use elem_{ptr,val}_node for array access syntax --- src/AstGen.zig | 25 ++++++------ src/Sema.zig | 39 ++++++++++--------- src/Zir.zig | 19 +++++---- src/print_zir.zig | 4 +- src/type.zig | 2 +- .../ignored_deferred_function_call.zig | 4 +- ...nored_expression_in_while_continuation.zig | 8 ++-- .../illegal_comparison_of_types.zig | 20 ++++++++++ .../implicitly_casting_enum_to_tag_type.zig | 4 +- .../obj => }/incorrect_return_type.zig | 4 +- .../indexing_an_array_of_size_zero.zig | 4 +- ..._array_of_size_zero_with_runtime_index.zig | 4 +- .../obj => }/indexing_single-item_pointer.zig | 4 +- ...nvalid_cast_from_integral_type_to_enum.zig | 4 +- .../runtime_indexing_comptime_array.zig | 12 +++--- .../implicit_cast_from_f64_to_f32.zig | 0 .../stage1/{obj => }/int_to_ptr_of_0_bits.zig | 0 .../obj/illegal_comparison_of_types.zig | 20 ---------- 18 files changed, 90 insertions(+), 87 deletions(-) rename test/cases/compile_errors/{stage1/obj => }/ignored_deferred_function_call.zig (52%) rename test/cases/compile_errors/{stage1/obj => }/ignored_expression_in_while_continuation.zig (54%) create mode 100644 test/cases/compile_errors/illegal_comparison_of_types.zig rename test/cases/compile_errors/{stage1/obj => }/implicitly_casting_enum_to_tag_type.zig (68%) rename test/cases/compile_errors/{stage1/obj => }/incorrect_return_type.zig (75%) rename test/cases/compile_errors/{stage1/obj => }/indexing_an_array_of_size_zero.zig (59%) rename test/cases/compile_errors/{stage1/obj => }/indexing_an_array_of_size_zero_with_runtime_index.zig (64%) rename test/cases/compile_errors/{stage1/obj => }/indexing_single-item_pointer.zig (51%) rename test/cases/compile_errors/{stage1/obj => }/invalid_cast_from_integral_type_to_enum.zig (70%) rename test/cases/compile_errors/stage1/{obj => }/implicit_cast_from_f64_to_f32.zig (100%) rename test/cases/compile_errors/stage1/{obj => }/int_to_ptr_of_0_bits.zig (100%) delete mode 100644 test/cases/compile_errors/stage1/obj/illegal_comparison_of_types.zig diff --git a/src/AstGen.zig b/src/AstGen.zig index 8707728313..a0ff7a0e6e 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -5154,16 +5154,14 @@ fn arrayAccess( const tree = astgen.tree; const node_datas = tree.nodes.items(.data); switch (rl) { - .ref => return gz.addBin( - .elem_ptr, - try expr(gz, scope, .ref, node_datas[node].lhs), - try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs), - ), - else => return rvalue(gz, rl, try gz.addBin( - .elem_val, - try expr(gz, scope, .none, node_datas[node].lhs), - try expr(gz, scope, .{ .coerced_ty = .usize_type }, node_datas[node].rhs), - ), node), + .ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ + .lhs = try expr(gz, scope, .ref, node_datas[node].lhs), + .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs), + }), + else => return rvalue(gz, rl, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ + .lhs = try expr(gz, scope, .none, node_datas[node].lhs), + .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs), + }), node), } } @@ -5685,7 +5683,7 @@ fn whileExpr( try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst); } if (while_full.ast.cont_expr != 0) { - _ = try expr(&loop_scope, then_sub_scope, .{ .ty = .void_type }, while_full.ast.cont_expr); + _ = try unusedResultExpr(&loop_scope, then_sub_scope, while_full.ast.cont_expr); } try then_scope.addDbgBlockEnd(); const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat; @@ -5890,7 +5888,10 @@ fn forExpr( if (!mem.eql(u8, value_name, "_")) { const name_str_index = try astgen.identAsString(ident); const tag: Zir.Inst.Tag = if (is_ptr) .elem_ptr else .elem_val; - const payload_inst = try then_scope.addBin(tag, array_ptr, index); + const payload_inst = try then_scope.addPlNode(tag, for_full.ast.cond_expr, Zir.Inst.Bin{ + .lhs = array_ptr, + .rhs = index, + }); try astgen.detectLocalShadowing(&then_scope.base, name_str_index, ident, value_name); payload_val_scope = .{ .parent = &then_scope.base, diff --git a/src/Sema.zig b/src/Sema.zig index 5010d86c9a..b946e29057 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2738,6 +2738,7 @@ fn ensureResultUsed( const operand_ty = sema.typeOf(operand); switch (operand_ty.zigTypeTag()) { .Void, .NoReturn => return, + .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is ignored. consider using `try`, `catch`, or `if`", .{}), else => return sema.fail(block, src, "expression value is ignored", .{}), } } @@ -2751,7 +2752,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com const src = inst_data.src(); const operand_ty = sema.typeOf(operand); switch (operand_ty.zigTypeTag()) { - .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is discardederror is discarded. consider using `try`, `catch`, or `if`", .{}), + .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is discarded. consider using `try`, `catch`, or `if`", .{}), else => return, } } @@ -7092,7 +7093,7 @@ fn funcCommon( const param_types = try sema.arena.alloc(Type, block.params.items.len); const comptime_params = try sema.arena.alloc(bool, block.params.items.len); for (block.params.items) |param, i| { - const param_src = LazySrcLoc.nodeOffset(src_node_offset); // TODO better src + const param_src = LazySrcLoc.nodeOffset(src_node_offset); // TODO better soruce location param_types[i] = param.ty; comptime_params[i] = param.is_comptime or try sema.typeRequiresComptime(block, param_src, param.ty); @@ -7798,12 +7799,12 @@ fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const tracy = trace(@src()); defer tracy.end(); - const bin_inst = sema.code.instructions.items(.data)[inst].bin; - const src = sema.src; // TODO better source location - const elem_index_src = sema.src; // TODO better source location - const array = try sema.resolveInst(bin_inst.lhs); - const elem_index = try sema.resolveInst(bin_inst.rhs); - return sema.elemVal(block, src, array, elem_index, elem_index_src); + const inst_data = sema.code.instructions.items(.data)[inst].pl_node; + const src = inst_data.src(); + const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; + const array = try sema.resolveInst(extra.lhs); + const elem_index = try sema.resolveInst(extra.rhs); + return sema.elemVal(block, src, array, elem_index, src); } fn zirElemValNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -7823,10 +7824,12 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const tracy = trace(@src()); defer tracy.end(); - const bin_inst = sema.code.instructions.items(.data)[inst].bin; - const array_ptr = try sema.resolveInst(bin_inst.lhs); - const elem_index = try sema.resolveInst(bin_inst.rhs); - return sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src, false); + const inst_data = sema.code.instructions.items(.data)[inst].pl_node; + const src = inst_data.src(); + const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; + const array_ptr = try sema.resolveInst(extra.lhs); + const elem_index = try sema.resolveInst(extra.rhs); + return sema.elemPtr(block, src, array_ptr, elem_index, src, false); } fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -19454,7 +19457,7 @@ fn tupleFieldPtr( const tuple_fields = tuple_ty.tupleFields(); if (tuple_fields.types.len == 0) { - return sema.fail(block, field_index_src, "indexing into empty tuple", .{}); + return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{}); } if (field_index >= tuple_fields.types.len) { @@ -19497,7 +19500,7 @@ fn tupleField( const tuple_fields = tuple_ty.tupleFields(); if (tuple_fields.types.len == 0) { - return sema.fail(block, field_index_src, "indexing into empty tuple", .{}); + return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{}); } if (field_index >= tuple_fields.types.len) { @@ -19538,7 +19541,7 @@ fn elemValArray( const elem_ty = array_ty.childType(); if (array_len_s == 0) { - return sema.fail(block, elem_index_src, "indexing into empty array", .{}); + return sema.fail(block, array_src, "indexing into empty array is not allowed", .{}); } const maybe_undef_array_val = try sema.resolveMaybeUndefVal(block, array_src, array); @@ -19618,7 +19621,7 @@ fn elemPtrArray( const array_len_s = array_len + @boolToInt(array_sent); if (array_len_s == 0) { - return sema.fail(block, elem_index_src, "indexing into empty array", .{}); + return sema.fail(block, array_ptr_src, "indexing into empty array is not allowed", .{}); } const maybe_undef_array_ptr_val = try sema.resolveMaybeUndefVal(block, array_ptr_src, array_ptr); @@ -19700,7 +19703,7 @@ fn elemValSlice( const slice_len = slice_val.sliceLen(sema.mod); const slice_len_s = slice_len + @boolToInt(slice_sent); if (slice_len_s == 0) { - return sema.fail(block, elem_index_src, "indexing into empty slice", .{}); + return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); } if (maybe_index_val) |index_val| { const index = @intCast(usize, index_val.toUnsignedInt(target)); @@ -19757,7 +19760,7 @@ fn elemPtrSlice( const slice_len = slice_val.sliceLen(sema.mod); const slice_len_s = slice_len + @boolToInt(slice_sent); if (slice_len_s == 0) { - return sema.fail(block, elem_index_src, "indexing into empty slice", .{}); + return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); } if (offset) |index| { if (index >= slice_len_s) { diff --git a/src/Zir.zig b/src/Zir.zig index 26bb09860d..98cdd490b8 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -370,24 +370,23 @@ pub const Inst = struct { /// Uses the `pl_node` union field. Payload is `Bin`. div, /// Given a pointer to an array, slice, or pointer, returns a pointer to the element at - /// the provided index. Uses the `bin` union field. Source location is implied - /// to be the same as the previous instruction. - elem_ptr, - /// Same as `elem_ptr` except also stores a source location node. + /// the provided index. /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`. elem_ptr_node, + /// Same as `elem_ptr_node` but used only for for loop. + /// Uses the `pl_node` union field. AST node is the condition of a for loop. Payload is `Bin`. + elem_ptr, /// Same as `elem_ptr_node` except the index is stored immediately rather than /// as a reference to another ZIR instruction. /// Uses the `pl_node` union field. AST node is an element inside array initialization /// syntax. Payload is `ElemPtrImm`. elem_ptr_imm, /// Given an array, slice, or pointer, returns the element at the provided index. - /// Uses the `bin` union field. Source location is implied to be the same - /// as the previous instruction. - elem_val, - /// Same as `elem_val` except also stores a source location node. /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`. elem_val_node, + /// Same as `elem_val_node` but used only for for loop. + /// Uses the `pl_node` union field. AST node is the condition of a for loop. Payload is `Bin`. + elem_val, /// Emits a compile error if the operand is not `void`. /// Uses the `un_node` field. ensure_result_used, @@ -1627,10 +1626,10 @@ pub const Inst = struct { .decl_val = .str_tok, .load = .un_node, .div = .pl_node, - .elem_ptr = .bin, + .elem_ptr = .pl_node, .elem_ptr_node = .pl_node, .elem_ptr_imm = .pl_node, - .elem_val = .bin, + .elem_val = .pl_node, .elem_val_node = .pl_node, .ensure_result_used = .un_node, .ensure_result_non_error = .un_node, diff --git a/src/print_zir.zig b/src/print_zir.zig index fe8446b34a..b19076a7f0 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -144,8 +144,6 @@ const Writer = struct { switch (tag) { .array_type, .as, - .elem_ptr, - .elem_val, .store, .store_to_block_ptr, .store_to_inferred_ptr, @@ -355,6 +353,8 @@ const Writer = struct { .minimum, .elem_ptr_node, .elem_val_node, + .elem_ptr, + .elem_val, .coerce_result_ptr, => try self.writePlNodeBin(stream, inst), diff --git a/src/type.zig b/src/type.zig index 0ca7ba83c5..50302dca6c 100644 --- a/src/type.zig +++ b/src/type.zig @@ -189,7 +189,7 @@ pub const Type = extern union { .Frame, => false, - .Pointer => is_equality_cmp or ty.isCPtr(), + .Pointer => !ty.isSlice() and (is_equality_cmp or ty.isCPtr()), .Optional => { if (!is_equality_cmp) return false; var buf: Payload.ElemType = undefined; diff --git a/test/cases/compile_errors/stage1/obj/ignored_deferred_function_call.zig b/test/cases/compile_errors/ignored_deferred_function_call.zig similarity index 52% rename from test/cases/compile_errors/stage1/obj/ignored_deferred_function_call.zig rename to test/cases/compile_errors/ignored_deferred_function_call.zig index 41812bfda9..69df8b0498 100644 --- a/test/cases/compile_errors/stage1/obj/ignored_deferred_function_call.zig +++ b/test/cases/compile_errors/ignored_deferred_function_call.zig @@ -4,7 +4,7 @@ export fn foo() void { fn bar() anyerror!i32 { return 0; } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:14: error: error is ignored. consider using `try`, `catch`, or `if` +// :2:14: error: error is ignored. consider using `try`, `catch`, or `if` diff --git a/test/cases/compile_errors/stage1/obj/ignored_expression_in_while_continuation.zig b/test/cases/compile_errors/ignored_expression_in_while_continuation.zig similarity index 54% rename from test/cases/compile_errors/stage1/obj/ignored_expression_in_while_continuation.zig rename to test/cases/compile_errors/ignored_expression_in_while_continuation.zig index 43f3713fc6..d295d476ab 100644 --- a/test/cases/compile_errors/stage1/obj/ignored_expression_in_while_continuation.zig +++ b/test/cases/compile_errors/ignored_expression_in_while_continuation.zig @@ -14,9 +14,9 @@ fn bad() anyerror!void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:24: error: error is ignored. consider using `try`, `catch`, or `if` -// tmp.zig:6:25: error: error is ignored. consider using `try`, `catch`, or `if` -// tmp.zig:10:25: error: error is ignored. consider using `try`, `catch`, or `if` +// :2:24: error: error is ignored. consider using `try`, `catch`, or `if` +// :6:25: error: error is ignored. consider using `try`, `catch`, or `if` +// :10:25: error: error is ignored. consider using `try`, `catch`, or `if` diff --git a/test/cases/compile_errors/illegal_comparison_of_types.zig b/test/cases/compile_errors/illegal_comparison_of_types.zig new file mode 100644 index 0000000000..69d7a28fa4 --- /dev/null +++ b/test/cases/compile_errors/illegal_comparison_of_types.zig @@ -0,0 +1,20 @@ +fn bad_eql_1(a: []u8, b: []u8) bool { + return a == b; +} +const EnumWithData = union(enum) { + One: void, + Two: i32, +}; +fn bad_eql_2(a: *const EnumWithData, b: *const EnumWithData) bool { + return a.* == b.*; +} + +export fn entry1() usize { return @sizeOf(@TypeOf(&bad_eql_1)); } +export fn entry2() usize { return @sizeOf(@TypeOf(&bad_eql_2)); } + +// error +// backend=stage2 +// target=native +// +// :2:14: error: operator == not allowed for type '[]u8' +// :9:16: error: operator == not allowed for type 'tmp.EnumWithData' diff --git a/test/cases/compile_errors/stage1/obj/implicitly_casting_enum_to_tag_type.zig b/test/cases/compile_errors/implicitly_casting_enum_to_tag_type.zig similarity index 68% rename from test/cases/compile_errors/stage1/obj/implicitly_casting_enum_to_tag_type.zig rename to test/cases/compile_errors/implicitly_casting_enum_to_tag_type.zig index a40615f99b..b1930cb548 100644 --- a/test/cases/compile_errors/stage1/obj/implicitly_casting_enum_to_tag_type.zig +++ b/test/cases/compile_errors/implicitly_casting_enum_to_tag_type.zig @@ -11,7 +11,7 @@ export fn entry() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:9:22: error: expected type 'u2', found 'Small' +// :9:22: error: expected type 'u2', found 'tmp.Small' diff --git a/test/cases/compile_errors/stage1/obj/incorrect_return_type.zig b/test/cases/compile_errors/incorrect_return_type.zig similarity index 75% rename from test/cases/compile_errors/stage1/obj/incorrect_return_type.zig rename to test/cases/compile_errors/incorrect_return_type.zig index b25e2a8ea4..b37cbebc7f 100644 --- a/test/cases/compile_errors/stage1/obj/incorrect_return_type.zig +++ b/test/cases/compile_errors/incorrect_return_type.zig @@ -15,7 +15,7 @@ } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:8:16: error: expected type 'A', found 'B' +// :8:16: error: expected type 'tmp.A', found 'tmp.B' diff --git a/test/cases/compile_errors/stage1/obj/indexing_an_array_of_size_zero.zig b/test/cases/compile_errors/indexing_an_array_of_size_zero.zig similarity index 59% rename from test/cases/compile_errors/stage1/obj/indexing_an_array_of_size_zero.zig rename to test/cases/compile_errors/indexing_an_array_of_size_zero.zig index dfb2e7c1c3..d2a54046de 100644 --- a/test/cases/compile_errors/stage1/obj/indexing_an_array_of_size_zero.zig +++ b/test/cases/compile_errors/indexing_an_array_of_size_zero.zig @@ -5,7 +5,7 @@ export fn foo() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:3:27: error: accessing a zero length array is not allowed +// :3:27: error: indexing into empty array is not allowed diff --git a/test/cases/compile_errors/stage1/obj/indexing_an_array_of_size_zero_with_runtime_index.zig b/test/cases/compile_errors/indexing_an_array_of_size_zero_with_runtime_index.zig similarity index 64% rename from test/cases/compile_errors/stage1/obj/indexing_an_array_of_size_zero_with_runtime_index.zig rename to test/cases/compile_errors/indexing_an_array_of_size_zero_with_runtime_index.zig index f50931312e..eceb5db50e 100644 --- a/test/cases/compile_errors/stage1/obj/indexing_an_array_of_size_zero_with_runtime_index.zig +++ b/test/cases/compile_errors/indexing_an_array_of_size_zero_with_runtime_index.zig @@ -6,7 +6,7 @@ export fn foo() void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:4:27: error: accessing a zero length array is not allowed +// :4:27: error: indexing into empty array is not allowed diff --git a/test/cases/compile_errors/stage1/obj/indexing_single-item_pointer.zig b/test/cases/compile_errors/indexing_single-item_pointer.zig similarity index 51% rename from test/cases/compile_errors/stage1/obj/indexing_single-item_pointer.zig rename to test/cases/compile_errors/indexing_single-item_pointer.zig index bc7951ec96..efd063817c 100644 --- a/test/cases/compile_errors/stage1/obj/indexing_single-item_pointer.zig +++ b/test/cases/compile_errors/indexing_single-item_pointer.zig @@ -3,7 +3,7 @@ export fn entry(ptr: *i32) i32 { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:2:15: error: index of single-item pointer +// :2:15: error: element access of non-indexable type '*i32' diff --git a/test/cases/compile_errors/stage1/obj/invalid_cast_from_integral_type_to_enum.zig b/test/cases/compile_errors/invalid_cast_from_integral_type_to_enum.zig similarity index 70% rename from test/cases/compile_errors/stage1/obj/invalid_cast_from_integral_type_to_enum.zig rename to test/cases/compile_errors/invalid_cast_from_integral_type_to_enum.zig index 81dbd88e3b..ce2f64169b 100644 --- a/test/cases/compile_errors/stage1/obj/invalid_cast_from_integral_type_to_enum.zig +++ b/test/cases/compile_errors/invalid_cast_from_integral_type_to_enum.zig @@ -11,7 +11,7 @@ fn foo(x: usize) void { } // error -// backend=stage1 +// backend=stage2 // target=native // -// tmp.zig:9:10: error: expected type 'usize', found 'E' +// :9:10: error: expected type 'usize', found 'tmp.E' diff --git a/test/cases/compile_errors/runtime_indexing_comptime_array.zig b/test/cases/compile_errors/runtime_indexing_comptime_array.zig index 16f7305f63..b83e977b3f 100644 --- a/test/cases/compile_errors/runtime_indexing_comptime_array.zig +++ b/test/cases/compile_errors/runtime_indexing_comptime_array.zig @@ -24,9 +24,9 @@ pub export fn entry3() void { // target=native // backend=stage2 // -// :6:5: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known -// :6:5: note: use '*const fn() void' for a function pointer type -// :13:5: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known -// :13:5: note: use '*const fn() void' for a function pointer type -// :19:5: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known -// :19:5: note: use '*const fn() void' for a function pointer type +// :7:10: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known +// :7:10: note: use '*const fn() void' for a function pointer type +// :15:18: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known +// :15:17: note: use '*const fn() void' for a function pointer type +// :21:19: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known +// :21:18: note: use '*const fn() void' for a function pointer type diff --git a/test/cases/compile_errors/stage1/obj/implicit_cast_from_f64_to_f32.zig b/test/cases/compile_errors/stage1/implicit_cast_from_f64_to_f32.zig similarity index 100% rename from test/cases/compile_errors/stage1/obj/implicit_cast_from_f64_to_f32.zig rename to test/cases/compile_errors/stage1/implicit_cast_from_f64_to_f32.zig diff --git a/test/cases/compile_errors/stage1/obj/int_to_ptr_of_0_bits.zig b/test/cases/compile_errors/stage1/int_to_ptr_of_0_bits.zig similarity index 100% rename from test/cases/compile_errors/stage1/obj/int_to_ptr_of_0_bits.zig rename to test/cases/compile_errors/stage1/int_to_ptr_of_0_bits.zig diff --git a/test/cases/compile_errors/stage1/obj/illegal_comparison_of_types.zig b/test/cases/compile_errors/stage1/obj/illegal_comparison_of_types.zig deleted file mode 100644 index d04eaec3b5..0000000000 --- a/test/cases/compile_errors/stage1/obj/illegal_comparison_of_types.zig +++ /dev/null @@ -1,20 +0,0 @@ -fn bad_eql_1(a: []u8, b: []u8) bool { - return a == b; -} -const EnumWithData = union(enum) { - One: void, - Two: i32, -}; -fn bad_eql_2(a: *const EnumWithData, b: *const EnumWithData) bool { - return a.* == b.*; -} - -export fn entry1() usize { return @sizeOf(@TypeOf(bad_eql_1)); } -export fn entry2() usize { return @sizeOf(@TypeOf(bad_eql_2)); } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:14: error: operator not allowed for type '[]u8' -// tmp.zig:9:16: error: operator not allowed for type 'EnumWithData'