From 57f9405a8fcaec6043d680fa47ae0e98709160c2 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 28 Jul 2022 15:00:40 +0300 Subject: Sema: validate bitcast operand type --- src/Sema.zig | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 5 deletions(-) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index a0829d6eb7..efdc0f8262 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8288,6 +8288,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); const operand = try sema.resolveInst(extra.rhs); + const operand_ty = sema.typeOf(operand); switch (dest_ty.zigTypeTag()) { .AnyFrame, .ComptimeFloat, @@ -8310,8 +8311,8 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air 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", .{}), + switch (operand_ty.zigTypeTag()) { + .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum to cast from '{}'", .{operand_ty.fmt(sema.mod)}), else => {}, } @@ -8320,9 +8321,20 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air 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), - }), + .Pointer => { + 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 (operand_ty.zigTypeTag()) { + .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToPtr to cast from '{}'", .{operand_ty.fmt(sema.mod)}), + .Pointer => try sema.errNote(block, dest_ty_src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(sema.mod)}), + else => {}, + } + + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + }, .Struct, .Union => if (dest_ty.containerLayout() == .Auto) { const container = switch (dest_ty.zigTypeTag()) { .Struct => "struct", @@ -8342,6 +8354,70 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .Vector, => {}, } + switch (operand_ty.zigTypeTag()) { + .AnyFrame, + .ComptimeFloat, + .ComptimeInt, + .EnumLiteral, + .ErrorSet, + .ErrorUnion, + .Fn, + .Frame, + .NoReturn, + .Null, + .Opaque, + .Optional, + .Type, + .Undefined, + .Void, + => return sema.fail(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}), + + .Enum => { + const msg = msg: { + const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}); + errdefer msg.destroy(sema.gpa); + switch (dest_ty.zigTypeTag()) { + .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @enumToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}), + else => {}, + } + + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + }, + .Pointer => { + const msg = msg: { + const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}); + errdefer msg.destroy(sema.gpa); + switch (dest_ty.zigTypeTag()) { + .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @ptrToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}), + .Pointer => try sema.errNote(block, operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(sema.mod)}), + else => {}, + } + + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + }, + .Struct, .Union => if (operand_ty.containerLayout() == .Auto) { + const container = switch (operand_ty.zigTypeTag()) { + .Struct => "struct", + .Union => "union", + else => unreachable, + }; + return sema.fail(block, operand_src, "cannot @bitCast from '{}', {s} does not have a guaranteed in-memory layout", .{ + operand_ty.fmt(sema.mod), container, + }); + }, + .BoundFn => @panic("TODO remove this type from the language and compiler"), + + .Array, + .Bool, + .Float, + .Int, + .Vector, + => {}, + } return sema.bitCast(block, dest_ty, operand, operand_src); } -- cgit v1.2.3 From f1768b40b2468d63355c8cf83d3614ae23a54317 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 28 Jul 2022 17:28:37 +0300 Subject: stage2: better source location for var decls --- src/AstGen.zig | 3 +- src/Module.zig | 107 ++++++++++++++++++--- src/Sema.zig | 22 ++--- src/Zir.zig | 6 ++ .../global_variable_alignment_non_power_of_2.zig | 8 ++ test/cases/compile_errors/src_outside_function.zig | 9 ++ .../global_variable_alignment_non_power_of_2.zig | 8 -- .../stage1/obj/src_outside_function.zig | 9 -- .../type_variables_must_be_constant.zig | 4 +- .../use_invalid_number_literal_as_array_index.zig | 4 +- .../usingnamespace_with_wrong_type.zig | 2 +- 11 files changed, 131 insertions(+), 51 deletions(-) create mode 100644 test/cases/compile_errors/global_variable_alignment_non_power_of_2.zig create mode 100644 test/cases/compile_errors/src_outside_function.zig delete mode 100644 test/cases/compile_errors/stage1/obj/global_variable_alignment_non_power_of_2.zig delete mode 100644 test/cases/compile_errors/stage1/obj/src_outside_function.zig (limited to 'src/Sema.zig') diff --git a/src/AstGen.zig b/src/AstGen.zig index b6a7450f3a..b2bbb27865 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -7424,7 +7424,8 @@ fn builtinCall( const token_starts = tree.tokens.items(.start); const node_start = token_starts[tree.firstToken(node)]; astgen.advanceSourceCursor(node_start); - const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.LineColumn{ + const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.Src{ + .node = gz.nodeIndexToRelative(node), .line = astgen.source_line, .column = astgen.source_column, }); diff --git a/src/Module.zig b/src/Module.zig index 4ac2775515..6122b417e4 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -2161,6 +2161,10 @@ pub const SrcLoc = struct { .local_var_decl => tree.localVarDecl(node), .simple_var_decl => tree.simpleVarDecl(node), .aligned_var_decl => tree.alignedVarDecl(node), + .@"usingnamespace" => { + const node_data = tree.nodes.items(.data); + return nodeToSpan(tree, node_data[node].lhs); + }, else => unreachable, }; if (full.ast.type_node != 0) { @@ -2171,6 +2175,58 @@ pub const SrcLoc = struct { const end = start + @intCast(u32, tree.tokenSlice(tok_index).len); return Span{ .start = start, .end = end, .main = start }; }, + .node_offset_var_decl_align => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node = src_loc.declRelativeToNodeIndex(node_off); + const node_tags = tree.nodes.items(.tag); + const full: Ast.full.VarDecl = switch (node_tags[node]) { + .global_var_decl => tree.globalVarDecl(node), + .local_var_decl => tree.localVarDecl(node), + .simple_var_decl => tree.simpleVarDecl(node), + .aligned_var_decl => tree.alignedVarDecl(node), + else => unreachable, + }; + return nodeToSpan(tree, full.ast.align_node); + }, + .node_offset_var_decl_section => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node = src_loc.declRelativeToNodeIndex(node_off); + const node_tags = tree.nodes.items(.tag); + const full: Ast.full.VarDecl = switch (node_tags[node]) { + .global_var_decl => tree.globalVarDecl(node), + .local_var_decl => tree.localVarDecl(node), + .simple_var_decl => tree.simpleVarDecl(node), + .aligned_var_decl => tree.alignedVarDecl(node), + else => unreachable, + }; + return nodeToSpan(tree, full.ast.section_node); + }, + .node_offset_var_decl_addrspace => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node = src_loc.declRelativeToNodeIndex(node_off); + const node_tags = tree.nodes.items(.tag); + const full: Ast.full.VarDecl = switch (node_tags[node]) { + .global_var_decl => tree.globalVarDecl(node), + .local_var_decl => tree.localVarDecl(node), + .simple_var_decl => tree.simpleVarDecl(node), + .aligned_var_decl => tree.alignedVarDecl(node), + else => unreachable, + }; + return nodeToSpan(tree, full.ast.addrspace_node); + }, + .node_offset_var_decl_init => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node = src_loc.declRelativeToNodeIndex(node_off); + const node_tags = tree.nodes.items(.tag); + const full: Ast.full.VarDecl = switch (node_tags[node]) { + .global_var_decl => tree.globalVarDecl(node), + .local_var_decl => tree.localVarDecl(node), + .simple_var_decl => tree.simpleVarDecl(node), + .aligned_var_decl => tree.alignedVarDecl(node), + else => unreachable, + }; + return nodeToSpan(tree, full.ast.init_node); + }, .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0), .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1), .node_offset_builtin_call_arg2 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 2), @@ -2857,6 +2913,18 @@ pub const LazySrcLoc = union(enum) { /// to the type expression. /// The Decl is determined contextually. node_offset_var_decl_ty: i32, + /// The source location points to the alignment expression of a var decl. + /// The Decl is determined contextually. + node_offset_var_decl_align: i32, + /// The source location points to the linksection expression of a var decl. + /// The Decl is determined contextually. + node_offset_var_decl_section: i32, + /// The source location points to the addrspace expression of a var decl. + /// The Decl is determined contextually. + node_offset_var_decl_addrspace: i32, + /// The source location points to the initializer of a var decl. + /// The Decl is determined contextually. + node_offset_var_decl_init: i32, /// The source location points to a for loop condition expression, /// found by taking this AST node index offset from the containing /// Decl AST node, which points to a for loop AST node. Next, navigate @@ -3098,6 +3166,10 @@ pub const LazySrcLoc = union(enum) { .node_offset, .node_offset_initializer, .node_offset_var_decl_ty, + .node_offset_var_decl_align, + .node_offset_var_decl_section, + .node_offset_var_decl_addrspace, + .node_offset_var_decl_init, .node_offset_for_cond, .node_offset_builtin_call_arg0, .node_offset_builtin_call_arg1, @@ -4414,17 +4486,26 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { const body = zir.extra[extra.end..][0..extra.data.body_len]; const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand; try wip_captures.finalize(); - const src = LazySrcLoc.nodeOffset(0); - const decl_tv = try sema.resolveInstValue(&block_scope, .unneeded, result_ref, undefined); + const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = 0 }; + const section_src: LazySrcLoc = .{ .node_offset_var_decl_section = 0 }; + const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 }; + const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 }; + const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 }; + const decl_tv = try sema.resolveInstValue(&block_scope, init_src, result_ref, undefined); const decl_align: u32 = blk: { const align_ref = decl.zirAlignRef(); if (align_ref == .none) break :blk 0; - break :blk try sema.resolveAlign(&block_scope, src, align_ref); + break :blk try sema.resolveAlign(&block_scope, align_src, align_ref); }; const decl_linksection: ?[*:0]const u8 = blk: { const linksection_ref = decl.zirLinksectionRef(); if (linksection_ref == .none) break :blk null; - const bytes = try sema.resolveConstString(&block_scope, src, linksection_ref, "linksection must be comptime known"); + const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, "linksection must be comptime known"); + if (mem.indexOfScalar(u8, bytes, 0) != null) { + return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{}); + } else if (bytes.len == 0) { + return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); + } break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr; }; const target = sema.mod.getTarget(); @@ -4442,27 +4523,27 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { .constant => target_util.defaultAddressSpace(target, .global_constant), else => unreachable, }, - else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, src, addrspace_ref, addrspace_ctx), + else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx), }; }; // Note this resolves the type of the Decl, not the value; if this Decl // is a struct, for example, this resolves `type` (which needs no resolution), // not the struct itself. - try sema.resolveTypeLayout(&block_scope, src, decl_tv.ty); + try sema.resolveTypeLayout(&block_scope, ty_src, decl_tv.ty); const decl_arena_state = try decl_arena_allocator.create(std.heap.ArenaAllocator.State); if (decl.is_usingnamespace) { if (!decl_tv.ty.eql(Type.type, mod)) { - return sema.fail(&block_scope, src, "expected type, found {}", .{ + return sema.fail(&block_scope, ty_src, "expected type, found {}", .{ decl_tv.ty.fmt(mod), }); } var buffer: Value.ToTypeBuffer = undefined; const ty = try decl_tv.val.toType(&buffer).copy(decl_arena_allocator); if (ty.getNamespace() == null) { - return sema.fail(&block_scope, src, "type {} has no namespace", .{ty.fmt(mod)}); + return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)}); } decl.ty = Type.type; @@ -4508,7 +4589,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { decl.analysis = .complete; decl.generation = mod.generation; - const has_runtime_bits = try sema.fnHasRuntimeBits(&block_scope, src, decl.ty); + const has_runtime_bits = try sema.fnHasRuntimeBits(&block_scope, ty_src, decl.ty); if (has_runtime_bits) { // We don't fully codegen the decl until later, but we do need to reserve a global @@ -4525,7 +4606,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { const is_inline = decl.ty.fnCallingConvention() == .Inline; if (decl.is_exported) { - const export_src = src; // TODO make this point at `export` token + const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) }; if (is_inline) { return sema.fail(&block_scope, export_src, "export of inline function", .{}); } @@ -4588,14 +4669,14 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { decl.generation = mod.generation; const has_runtime_bits = is_extern or - (queue_linker_work and try sema.typeHasRuntimeBits(&block_scope, src, decl.ty)); + (queue_linker_work and try sema.typeHasRuntimeBits(&block_scope, ty_src, decl.ty)); if (has_runtime_bits) { log.debug("queue linker work for {*} ({s})", .{ decl, decl.name }); // Needed for codegen_decl which will call updateDecl and then the // codegen backend wants full access to the Decl Type. - try sema.resolveTypeFully(&block_scope, src, decl.ty); + try sema.resolveTypeFully(&block_scope, ty_src, decl.ty); try mod.comp.bin_file.allocateDeclIndexes(decl_index); try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); @@ -4606,7 +4687,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { } if (decl.is_exported) { - const export_src = src; // TODO point to the export token + const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) }; // The scope needs to have the decl in it. const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) }; try sema.analyzeExport(&block_scope, export_src, options, decl_index); diff --git a/src/Sema.zig b/src/Sema.zig index efdc0f8262..22d0c572fc 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2971,7 +2971,7 @@ fn zirAllocExtended( const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand); const src = LazySrcLoc.nodeOffset(extra.data.src_node); const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = extra.data.src_node }; - const align_src = src; // TODO better source location + const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = extra.data.src_node }; const small = @bitCast(Zir.Inst.AllocExtended.Small, extended.small); var extra_index: usize = extra.end; @@ -8046,7 +8046,7 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai if (try sema.resolveMaybeUndefValIntable(block, ptr_src, ptr)) |ptr_val| { return sema.addConstant(Type.usize, ptr_val); } - try sema.requireRuntimeBlock(block, ptr_src, ptr_src); + try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); return block.addUnOp(.ptrtoint, ptr); } @@ -13174,8 +13174,8 @@ fn zirBuiltinSrc( const tracy = trace(@src()); defer tracy.end(); - const src = sema.src; // TODO better source location - const extra = sema.code.extraData(Zir.Inst.LineColumn, extended.operand).data; + const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data; + const src = LazySrcLoc.nodeOffset(extra.node); const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{}); const fn_owner_decl = sema.mod.declPtr(func.owner_decl); @@ -18959,10 +18959,8 @@ fn zirVarExtended( extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand); - const src = sema.src; - const ty_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at type - const name_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at the name token - const init_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at init expr + const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 }; + const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 }; const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); var extra_index: usize = extra.end; @@ -18976,12 +18974,6 @@ fn zirVarExtended( // ZIR supports encoding this information but it is not used; the information // is encoded via the Decl entry. assert(!small.has_align); - //const align_val: Value = if (small.has_align) blk: { - // const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); - // extra_index += 1; - // const align_tv = try sema.resolveInstConst(block, align_src, align_ref); - // break :blk align_tv.val; - //} else Value.@"null"; const uncasted_init: Air.Inst.Ref = if (small.has_init) blk: { const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); @@ -19005,7 +18997,7 @@ fn zirVarExtended( return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime known"); } else Value.initTag(.unreachable_value); - try sema.validateVarType(block, name_src, var_ty, small.is_extern); + try sema.validateVarType(block, ty_src, var_ty, small.is_extern); const new_var = try sema.gpa.create(Module.Var); errdefer sema.gpa.destroy(new_var); diff --git a/src/Zir.zig b/src/Zir.zig index ccd677df0b..3aa2378697 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -3548,6 +3548,12 @@ pub const Inst = struct { ty: Ref, init_count: u32, }; + + pub const Src = struct { + node: i32, + line: u32, + column: u32, + }; }; pub const SpecialProng = enum { none, @"else", under }; diff --git a/test/cases/compile_errors/global_variable_alignment_non_power_of_2.zig b/test/cases/compile_errors/global_variable_alignment_non_power_of_2.zig new file mode 100644 index 0000000000..b88d8aaf70 --- /dev/null +++ b/test/cases/compile_errors/global_variable_alignment_non_power_of_2.zig @@ -0,0 +1,8 @@ +const some_data: [100]u8 align(3) = undefined; +export fn entry() usize { return @sizeOf(@TypeOf(some_data)); } + +// error +// backend=stage2 +// target=native +// +// :1:32: error: alignment value '3' is not a power of two diff --git a/test/cases/compile_errors/src_outside_function.zig b/test/cases/compile_errors/src_outside_function.zig new file mode 100644 index 0000000000..8b66ba730b --- /dev/null +++ b/test/cases/compile_errors/src_outside_function.zig @@ -0,0 +1,9 @@ +comptime { + @src(); +} + +// error +// backend=stage2 +// target=native +// +// :2:5: error: @src outside function diff --git a/test/cases/compile_errors/stage1/obj/global_variable_alignment_non_power_of_2.zig b/test/cases/compile_errors/stage1/obj/global_variable_alignment_non_power_of_2.zig deleted file mode 100644 index f23f340b16..0000000000 --- a/test/cases/compile_errors/stage1/obj/global_variable_alignment_non_power_of_2.zig +++ /dev/null @@ -1,8 +0,0 @@ -const some_data: [100]u8 align(3) = undefined; -export fn entry() usize { return @sizeOf(@TypeOf(some_data)); } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:32: error: alignment value 3 is not a power of 2 diff --git a/test/cases/compile_errors/stage1/obj/src_outside_function.zig b/test/cases/compile_errors/stage1/obj/src_outside_function.zig deleted file mode 100644 index 7f8c7ae72f..0000000000 --- a/test/cases/compile_errors/stage1/obj/src_outside_function.zig +++ /dev/null @@ -1,9 +0,0 @@ -comptime { - @src(); -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:5: error: @src outside function diff --git a/test/cases/compile_errors/type_variables_must_be_constant.zig b/test/cases/compile_errors/type_variables_must_be_constant.zig index 35e94f3641..1dbddc126c 100644 --- a/test/cases/compile_errors/type_variables_must_be_constant.zig +++ b/test/cases/compile_errors/type_variables_must_be_constant.zig @@ -7,5 +7,5 @@ export fn entry() foo { // backend=stage2 // target=native // -// :1:1: error: variable of type 'type' must be const or comptime -// :1:1: note: types are not available at runtime +// :1:5: error: variable of type 'type' must be const or comptime +// :1:5: note: types are not available at runtime diff --git a/test/cases/compile_errors/use_invalid_number_literal_as_array_index.zig b/test/cases/compile_errors/use_invalid_number_literal_as_array_index.zig index 120ba5c588..c52f614657 100644 --- a/test/cases/compile_errors/use_invalid_number_literal_as_array_index.zig +++ b/test/cases/compile_errors/use_invalid_number_literal_as_array_index.zig @@ -8,5 +8,5 @@ export fn entry() void { // backend=stage2 // target=native // -// :1:1: error: variable of type 'comptime_int' must be const or comptime -// :1:1: note: to modify this variable at runtime, it must be given an explicit fixed-size number type +// :1:5: error: variable of type 'comptime_int' must be const or comptime +// :1:5: note: to modify this variable at runtime, it must be given an explicit fixed-size number type diff --git a/test/cases/compile_errors/usingnamespace_with_wrong_type.zig b/test/cases/compile_errors/usingnamespace_with_wrong_type.zig index 4ec4bf4838..294fd8c012 100644 --- a/test/cases/compile_errors/usingnamespace_with_wrong_type.zig +++ b/test/cases/compile_errors/usingnamespace_with_wrong_type.zig @@ -4,4 +4,4 @@ usingnamespace void; // backend=stage2 // target=native // -// :1:1: error: type void has no namespace +// :1:16: error: type void has no namespace -- cgit v1.2.3 From e47706f34454c46dd00fe10fdf9252657117a00d Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 28 Jul 2022 21:03:10 +0300 Subject: Sema: validate packed struct field types --- src/Sema.zig | 156 +++++++++++++++++---- test/behavior/packed-struct.zig | 28 +--- test/behavior/sizeof_and_typeof.zig | 2 + test/behavior/struct.zig | 6 +- ...ked_struct_with_fields_of_not_allowed_types.zig | 84 +++++++++++ ...ked_struct_with_fields_of_not_allowed_types.zig | 74 ---------- 6 files changed, 217 insertions(+), 133 deletions(-) create mode 100644 test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig delete mode 100644 test/cases/compile_errors/stage1/test/packed_struct_with_fields_of_not_allowed_types.zig (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index 22d0c572fc..71ab59d7f9 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5049,13 +5049,13 @@ pub fn analyzeExport( try mod.ensureDeclAnalyzed(exported_decl_index); const exported_decl = mod.declPtr(exported_decl_index); - if (!(try sema.validateExternType(exported_decl.ty, .other))) { + if (!sema.validateExternType(exported_decl.ty, .other)) { const msg = msg: { const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), exported_decl.ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), exported_decl.ty, .other); try sema.addDeclaredHereNote(msg, exported_decl.ty); break :msg msg; @@ -7634,7 +7634,7 @@ fn funcCommon( }; return sema.failWithOwnedErrorMsg(block, msg); } - if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !(try sema.validateExternType(return_type, .ret_ty))) { + if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) { const msg = msg: { const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{ return_type.fmt(sema.mod), @tagName(cc_workaround), @@ -7642,7 +7642,7 @@ fn funcCommon( errdefer msg.destroy(sema.gpa); const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(block, ret_ty_src, msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty); + try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty); try sema.addDeclaredHereNote(msg, return_type); break :msg msg; @@ -7830,7 +7830,7 @@ fn analyzeParameter( }; return sema.failWithOwnedErrorMsg(block, msg); } - if (!Type.fnCallingConventionAllowsZigTypes(cc) and !(try sema.validateExternType(param.ty, .param_ty))) { + if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) { const msg = msg: { const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ param.ty.fmt(sema.mod), @tagName(cc), @@ -7838,7 +7838,7 @@ fn analyzeParameter( errdefer msg.destroy(sema.gpa); const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(block, param_src, msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty); + try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty); try sema.addDeclaredHereNote(msg, param.ty); break :msg msg; @@ -14866,13 +14866,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) { return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{}); } else if (inst_data.size == .C) { - if (!(try sema.validateExternType(elem_ty, .other))) { + if (!sema.validateExternType(elem_ty, .other)) { const msg = msg: { const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(block, elem_ty_src, msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other); try sema.addDeclaredHereNote(msg, elem_ty); break :msg msg; @@ -15950,13 +15950,13 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) { return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); } else if (ptr_size == .C) { - if (!(try sema.validateExternType(elem_ty, .other))) { + if (!sema.validateExternType(elem_ty, .other)) { const msg = msg: { const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), elem_ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), elem_ty, .other); try sema.addDeclaredHereNote(msg, elem_ty); break :msg msg; @@ -19736,7 +19736,7 @@ const ExternPosition = enum { /// Returns true if `ty` is allowed in extern types. /// Does *NOT* require `ty` to be resolved in any way. -fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileError!bool { +fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool { switch (ty.zigTypeTag()) { .Type, .ComptimeFloat, @@ -19781,8 +19781,6 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileEr fn explainWhyTypeIsNotExtern( sema: *Sema, - block: *Block, - src: LazySrcLoc, msg: *Module.ErrorMsg, src_loc: Module.SrcLoc, ty: Type, @@ -19826,7 +19824,7 @@ fn explainWhyTypeIsNotExtern( var buf: Type.Payload.Bits = undefined; const tag_ty = ty.intTagType(&buf); try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)}); - try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, tag_ty, position); + try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); }, .Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}), .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}), @@ -19836,13 +19834,87 @@ fn explainWhyTypeIsNotExtern( } else if (position == .param_ty) { return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{}); } - try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position); + try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position); }, - .Vector => try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position), + .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position), .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}), } } +/// Returns true if `ty` is allowed in packed types. +/// Does *NOT* require `ty` to be resolved in any way. +fn validatePackedType(ty: Type) bool { + switch (ty.zigTypeTag()) { + .Type, + .ComptimeFloat, + .ComptimeInt, + .EnumLiteral, + .Undefined, + .Null, + .ErrorUnion, + .ErrorSet, + .BoundFn, + .Frame, + .NoReturn, + .Opaque, + .AnyFrame, + .Fn, + .Array, + .Optional, + => return false, + .Void, + .Bool, + .Float, + .Pointer, + .Int, + .Vector, + .Enum, + => return true, + .Struct, .Union => return ty.containerLayout() == .Packed, + } +} + +fn explainWhyTypeIsNotPacked( + sema: *Sema, + msg: *Module.ErrorMsg, + src_loc: Module.SrcLoc, + ty: Type, +) CompileError!void { + const mod = sema.mod; + switch (ty.zigTypeTag()) { + .Void, + .Bool, + .Float, + .Pointer, + .Int, + .Vector, + .Enum, + => return, + .Type, + .ComptimeFloat, + .ComptimeInt, + .EnumLiteral, + .Undefined, + .Null, + .BoundFn, + .Frame, + .NoReturn, + .Opaque, + .ErrorUnion, + .ErrorSet, + .AnyFrame, + .Optional, + .Array, + => try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}), + .Fn => { + try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}); + try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{}); + }, + .Struct => try mod.errNoteNonLazy(src_loc, msg, "only packed structs layout are allowed in packed types", .{}), + .Union => try mod.errNoteNonLazy(src_loc, msg, "only packed unions layout are allowed in packed types", .{}), + } +} + pub const PanicId = enum { unreach, unwrap_null, @@ -26919,28 +26991,41 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void const field = &struct_obj.fields.values()[i]; field.ty = try field_ty.copy(decl_arena_allocator); - if (struct_obj.layout == .Extern and !(try sema.validateExternType(field.ty, .other))) { + if (field_ty.zigTypeTag() == .Opaque) { + const msg = msg: { + const tree = try sema.getAstTree(&block_scope); + const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i); + const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); + errdefer msg.destroy(sema.gpa); + + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(&block_scope, msg); + } + if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) { const msg = msg: { const tree = try sema.getAstTree(&block_scope); const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i); const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsNotExtern(&block_scope, fields_src, msg, fields_src.toSrcLoc(decl), field.ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .other); try sema.addDeclaredHereNote(msg, field.ty); break :msg msg; }; return sema.failWithOwnedErrorMsg(&block_scope, msg); - } - if (field_ty.zigTypeTag() == .Opaque) { + } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) { const msg = msg: { const tree = try sema.getAstTree(&block_scope); - const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i); - const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); + const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i); + const msg = try sema.errMsg(&block_scope, fields_src, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, field_ty); + try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field.ty); + + try sema.addDeclaredHereNote(msg, field.ty); break :msg msg; }; return sema.failWithOwnedErrorMsg(&block_scope, msg); @@ -27243,27 +27328,40 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { } } - if (union_obj.layout == .Extern and !(try sema.validateExternType(field_ty, .union_field))) { + if (field_ty.zigTypeTag() == .Opaque) { const msg = msg: { const tree = try sema.getAstTree(&block_scope); const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i); - const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); + const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsNotExtern(&block_scope, field_src, msg, field_src.toSrcLoc(decl), field_ty, .union_field); - try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }; return sema.failWithOwnedErrorMsg(&block_scope, msg); } - if (field_ty.zigTypeTag() == .Opaque) { + if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field)) { const msg = msg: { const tree = try sema.getAstTree(&block_scope); const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i); - const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); + const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); + try sema.explainWhyTypeIsNotExtern(msg, field_src.toSrcLoc(decl), field_ty, .union_field); + + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(&block_scope, msg); + } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) { + const msg = msg: { + const tree = try sema.getAstTree(&block_scope); + const fields_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i); + const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); + errdefer msg.destroy(sema.gpa); + + try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field_ty); + try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }; diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 2dea485bf5..8c34f5741b 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -6,6 +6,8 @@ const expectEqual = std.testing.expectEqual; const native_endian = builtin.cpu.arch.endian(); test "correct size of packed structs" { + // Stage2 has different packed struct semantics. + if (builtin.zig_backend != .stage1) return error.SkipZigTest; const T1 = packed struct { one: u8, three: [3]u8 }; try expectEqual(4, @sizeOf(T1)); @@ -118,18 +120,6 @@ test "flags in packed structs" { try expectEqual(32, @bitSizeOf(Flags3)); } -test "arrays in packed structs" { - if (builtin.zig_backend == .stage1) return error.SkipZigTest; - - const T1 = packed struct { array: [3][3]u8 }; - const T2 = packed struct { array: [9]u8 }; - - try expectEqual(@sizeOf(u72), @sizeOf(T1)); - try expectEqual(72, @bitSizeOf(T1)); - try expectEqual(@sizeOf(u72), @sizeOf(T2)); - try expectEqual(72, @bitSizeOf(T2)); -} - test "consistent size of packed structs" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; @@ -145,23 +135,15 @@ test "consistent size of packed structs" { try expectEqual(register_size_bits, @bitSizeOf(TxData2)); try expectEqual(register_size_bytes, @sizeOf(TxData2)); - const TxData3 = packed struct { a: u32, b: [3]u8 }; const TxData4 = packed struct { a: u32, b: u24 }; - const TxData5 = packed struct { a: [3]u8, b: u32 }; const TxData6 = packed struct { a: u24, b: u32 }; const expectedBitSize = 56; const expectedByteSize = @sizeOf(u56); - try expectEqual(expectedBitSize, @bitSizeOf(TxData3)); - try expectEqual(expectedByteSize, @sizeOf(TxData3)); - try expectEqual(expectedBitSize, @bitSizeOf(TxData4)); try expectEqual(expectedByteSize, @sizeOf(TxData4)); - try expectEqual(expectedBitSize, @bitSizeOf(TxData5)); - try expectEqual(expectedByteSize, @sizeOf(TxData5)); - try expectEqual(expectedBitSize, @bitSizeOf(TxData6)); try expectEqual(expectedByteSize, @sizeOf(TxData6)); } @@ -234,12 +216,6 @@ test "correct sizeOf and offsets in packed structs" { try expectEqual(@as(u7, 0b1111010), s2.y); try expectEqual(@as(u24, 0xd5c71f), s2.z); } - - const S = packed struct { a: u32, pad: [3]u32, b: u32 }; - - try expectEqual(16, @offsetOf(S, "b")); - try expectEqual(128, @bitOffsetOf(S, "b")); - try expectEqual(@sizeOf(u160), @sizeOf(S)); } test "nested packed structs" { diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig index 6c7e16b502..83c5d977be 100644 --- a/test/behavior/sizeof_and_typeof.zig +++ b/test/behavior/sizeof_and_typeof.zig @@ -105,6 +105,8 @@ test "@offsetOf" { } test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" { + // Stage2 has different packed struct semantics. + if (builtin.zig_backend != .stage1) return error.SkipZigTest; const p3a_len = 3; const P3 = packed struct { a: [p3a_len]u8, diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 8fac5697ec..377cbb56f4 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -704,10 +704,8 @@ const FooArray24Bits = packed struct { }; test "aligned array of packed struct" { - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + // Stage2 has different packed struct semantics. + if (builtin.zig_backend != .stage1) return error.SkipZigTest; comptime { try expect(@sizeOf(FooStructAligned) == 2); diff --git a/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig b/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig new file mode 100644 index 0000000000..8fcd300629 --- /dev/null +++ b/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig @@ -0,0 +1,84 @@ +export fn entry1() void { + _ = @sizeOf(packed struct { + x: anyerror, + }); +} +export fn entry2() void { + _ = @sizeOf(packed struct { + x: [2]u24, + }); +} +export fn entry3() void { + _ = @sizeOf(packed struct { + x: anyerror!u32, + }); +} +export fn entry4() void { + _ = @sizeOf(packed struct { + x: S, + }); +} +export fn entry5() void { + _ = @sizeOf(packed struct { + x: U, + }); +} +export fn entry6() void { + _ = @sizeOf(packed struct { + x: ?anyerror, + }); +} +export fn entry7() void { + _ = @sizeOf(packed struct { + x: enum { A, B }, + }); +} +export fn entry8() void { + _ = @sizeOf(packed struct { + x: fn () void, + }); +} +export fn entry9() void { + _ = @sizeOf(packed struct { + x: *const fn () void, + }); +} +export fn entry10() void { + _ = @sizeOf(packed struct { + x: packed struct { x: i32 }, + }); +} +export fn entry11() void { + _ = @sizeOf(packed struct { + x: packed union { A: i32, B: u32 }, + }); +} +const S = struct { + x: i32, +}; +const U = extern union { + A: i32, + B: u32, +}; + +// error +// backend=llvm +// target=native +// +// :3:9: error: packed structs cannot contain fields of type 'anyerror' +// :3:9: note: type has no guaranteed in-memory representation +// :8:9: error: packed structs cannot contain fields of type '[2]u24' +// :8:9: note: type has no guaranteed in-memory representation +// :13:9: error: packed structs cannot contain fields of type 'anyerror!u32' +// :13:9: note: type has no guaranteed in-memory representation +// :18:9: error: packed structs cannot contain fields of type 'tmp.S' +// :18:9: note: only packed structs layout are allowed in packed types +// :56:11: note: struct declared here +// :23:9: error: packed structs cannot contain fields of type 'tmp.U' +// :23:9: note: only packed unions layout are allowed in packed types +// :59:18: note: union declared here +// :28:9: error: packed structs cannot contain fields of type '?anyerror' +// :28:9: note: type has no guaranteed in-memory representation +// :38:9: error: packed structs cannot contain fields of type 'fn() void' +// :38:9: note: type has no guaranteed in-memory representation +// :38:9: note: use '*const ' to make a function pointer type diff --git a/test/cases/compile_errors/stage1/test/packed_struct_with_fields_of_not_allowed_types.zig b/test/cases/compile_errors/stage1/test/packed_struct_with_fields_of_not_allowed_types.zig deleted file mode 100644 index 2951d26c52..0000000000 --- a/test/cases/compile_errors/stage1/test/packed_struct_with_fields_of_not_allowed_types.zig +++ /dev/null @@ -1,74 +0,0 @@ -const A = packed struct { - x: anyerror, -}; -const B = packed struct { - x: [2]u24, -}; -const C = packed struct { - x: [1]anyerror, -}; -const D = packed struct { - x: [1]S, -}; -const E = packed struct { - x: [1]U, -}; -const F = packed struct { - x: ?anyerror, -}; -const G = packed struct { - x: Enum, -}; -export fn entry1() void { - var a: A = undefined; - _ = a; -} -export fn entry2() void { - var b: B = undefined; - _ = b; -} -export fn entry3() void { - var r: C = undefined; - _ = r; -} -export fn entry4() void { - var d: D = undefined; - _ = d; -} -export fn entry5() void { - var e: E = undefined; - _ = e; -} -export fn entry6() void { - var f: F = undefined; - _ = f; -} -export fn entry7() void { - var g: G = undefined; - _ = g; -} -const S = struct { - x: i32, -}; -const U = struct { - A: i32, - B: u32, -}; -const Enum = enum { - A, - B, -}; - -// error -// backend=stage1 -// target=native -// is_test=1 -// -// tmp.zig:2:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation -// tmp.zig:5:5: error: array of 'u24' not allowed in packed struct due to padding bits (must be padded from 48 to 64 bits) -// tmp.zig:8:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation -// tmp.zig:11:5: error: non-packed, non-extern struct 'S' not allowed in packed struct; no guaranteed in-memory representation -// tmp.zig:14:5: error: non-packed, non-extern struct 'U' not allowed in packed struct; no guaranteed in-memory representation -// tmp.zig:17:5: error: type '?anyerror' not allowed in packed struct; no guaranteed in-memory representation -// tmp.zig:20:5: error: type 'Enum' not allowed in packed struct; no guaranteed in-memory representation -// tmp.zig:57:14: note: enum declaration does not specify an integer tag type -- cgit v1.2.3