| author | |
| committer | |
| log | 4831c1c65f51ccfdb48c8d16bdf77435e0256070 |
| tree | 62ed249f1b2ce780c511b7aa6304104c4cd5bc90 |
| parent | 2375658da9f8e73d3e4b6d14d88c02cc765ae579 |
| parent | e47706f34454c46dd00fe10fdf9252657117a00d |
| signature |
Stage2: validate packed struct field types22 files changed, 459 insertions(+), 233 deletions(-)
src/AstGen.zig+2-1| ... | ... | @@ -7424,7 +7424,8 @@ fn builtinCall( |
| 7424 | 7424 | const token_starts = tree.tokens.items(.start); |
| 7425 | 7425 | const node_start = token_starts[tree.firstToken(node)]; |
| 7426 | 7426 | astgen.advanceSourceCursor(node_start); |
| 7427 | const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.LineColumn{ | |
| 7427 | const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.Src{ | |
| 7428 | .node = gz.nodeIndexToRelative(node), | |
| 7428 | 7429 | .line = astgen.source_line, |
| 7429 | 7430 | .column = astgen.source_column, |
| 7430 | 7431 | }); |
src/Module.zig+94-13| ... | ... | @@ -2161,6 +2161,10 @@ pub const SrcLoc = struct { |
| 2161 | 2161 | .local_var_decl => tree.localVarDecl(node), |
| 2162 | 2162 | .simple_var_decl => tree.simpleVarDecl(node), |
| 2163 | 2163 | .aligned_var_decl => tree.alignedVarDecl(node), |
| 2164 | .@"usingnamespace" => { | |
| 2165 | const node_data = tree.nodes.items(.data); | |
| 2166 | return nodeToSpan(tree, node_data[node].lhs); | |
| 2167 | }, | |
| 2164 | 2168 | else => unreachable, |
| 2165 | 2169 | }; |
| 2166 | 2170 | if (full.ast.type_node != 0) { |
| ... | ... | @@ -2171,6 +2175,58 @@ pub const SrcLoc = struct { |
| 2171 | 2175 | const end = start + @intCast(u32, tree.tokenSlice(tok_index).len); |
| 2172 | 2176 | return Span{ .start = start, .end = end, .main = start }; |
| 2173 | 2177 | }, |
| 2178 | .node_offset_var_decl_align => |node_off| { | |
| 2179 | const tree = try src_loc.file_scope.getTree(gpa); | |
| 2180 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 2181 | const node_tags = tree.nodes.items(.tag); | |
| 2182 | const full: Ast.full.VarDecl = switch (node_tags[node]) { | |
| 2183 | .global_var_decl => tree.globalVarDecl(node), | |
| 2184 | .local_var_decl => tree.localVarDecl(node), | |
| 2185 | .simple_var_decl => tree.simpleVarDecl(node), | |
| 2186 | .aligned_var_decl => tree.alignedVarDecl(node), | |
| 2187 | else => unreachable, | |
| 2188 | }; | |
| 2189 | return nodeToSpan(tree, full.ast.align_node); | |
| 2190 | }, | |
| 2191 | .node_offset_var_decl_section => |node_off| { | |
| 2192 | const tree = try src_loc.file_scope.getTree(gpa); | |
| 2193 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 2194 | const node_tags = tree.nodes.items(.tag); | |
| 2195 | const full: Ast.full.VarDecl = switch (node_tags[node]) { | |
| 2196 | .global_var_decl => tree.globalVarDecl(node), | |
| 2197 | .local_var_decl => tree.localVarDecl(node), | |
| 2198 | .simple_var_decl => tree.simpleVarDecl(node), | |
| 2199 | .aligned_var_decl => tree.alignedVarDecl(node), | |
| 2200 | else => unreachable, | |
| 2201 | }; | |
| 2202 | return nodeToSpan(tree, full.ast.section_node); | |
| 2203 | }, | |
| 2204 | .node_offset_var_decl_addrspace => |node_off| { | |
| 2205 | const tree = try src_loc.file_scope.getTree(gpa); | |
| 2206 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 2207 | const node_tags = tree.nodes.items(.tag); | |
| 2208 | const full: Ast.full.VarDecl = switch (node_tags[node]) { | |
| 2209 | .global_var_decl => tree.globalVarDecl(node), | |
| 2210 | .local_var_decl => tree.localVarDecl(node), | |
| 2211 | .simple_var_decl => tree.simpleVarDecl(node), | |
| 2212 | .aligned_var_decl => tree.alignedVarDecl(node), | |
| 2213 | else => unreachable, | |
| 2214 | }; | |
| 2215 | return nodeToSpan(tree, full.ast.addrspace_node); | |
| 2216 | }, | |
| 2217 | .node_offset_var_decl_init => |node_off| { | |
| 2218 | const tree = try src_loc.file_scope.getTree(gpa); | |
| 2219 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 2220 | const node_tags = tree.nodes.items(.tag); | |
| 2221 | const full: Ast.full.VarDecl = switch (node_tags[node]) { | |
| 2222 | .global_var_decl => tree.globalVarDecl(node), | |
| 2223 | .local_var_decl => tree.localVarDecl(node), | |
| 2224 | .simple_var_decl => tree.simpleVarDecl(node), | |
| 2225 | .aligned_var_decl => tree.alignedVarDecl(node), | |
| 2226 | else => unreachable, | |
| 2227 | }; | |
| 2228 | return nodeToSpan(tree, full.ast.init_node); | |
| 2229 | }, | |
| 2174 | 2230 | .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0), |
| 2175 | 2231 | .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1), |
| 2176 | 2232 | .node_offset_builtin_call_arg2 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 2), |
| ... | ... | @@ -2857,6 +2913,18 @@ pub const LazySrcLoc = union(enum) { |
| 2857 | 2913 | /// to the type expression. |
| 2858 | 2914 | /// The Decl is determined contextually. |
| 2859 | 2915 | node_offset_var_decl_ty: i32, |
| 2916 | /// The source location points to the alignment expression of a var decl. | |
| 2917 | /// The Decl is determined contextually. | |
| 2918 | node_offset_var_decl_align: i32, | |
| 2919 | /// The source location points to the linksection expression of a var decl. | |
| 2920 | /// The Decl is determined contextually. | |
| 2921 | node_offset_var_decl_section: i32, | |
| 2922 | /// The source location points to the addrspace expression of a var decl. | |
| 2923 | /// The Decl is determined contextually. | |
| 2924 | node_offset_var_decl_addrspace: i32, | |
| 2925 | /// The source location points to the initializer of a var decl. | |
| 2926 | /// The Decl is determined contextually. | |
| 2927 | node_offset_var_decl_init: i32, | |
| 2860 | 2928 | /// The source location points to a for loop condition expression, |
| 2861 | 2929 | /// found by taking this AST node index offset from the containing |
| 2862 | 2930 | /// Decl AST node, which points to a for loop AST node. Next, navigate |
| ... | ... | @@ -3098,6 +3166,10 @@ pub const LazySrcLoc = union(enum) { |
| 3098 | 3166 | .node_offset, |
| 3099 | 3167 | .node_offset_initializer, |
| 3100 | 3168 | .node_offset_var_decl_ty, |
| 3169 | .node_offset_var_decl_align, | |
| 3170 | .node_offset_var_decl_section, | |
| 3171 | .node_offset_var_decl_addrspace, | |
| 3172 | .node_offset_var_decl_init, | |
| 3101 | 3173 | .node_offset_for_cond, |
| 3102 | 3174 | .node_offset_builtin_call_arg0, |
| 3103 | 3175 | .node_offset_builtin_call_arg1, |
| ... | ... | @@ -4414,17 +4486,26 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4414 | 4486 | const body = zir.extra[extra.end..][0..extra.data.body_len]; |
| 4415 | 4487 | const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand; |
| 4416 | 4488 | try wip_captures.finalize(); |
| 4417 | const src = LazySrcLoc.nodeOffset(0); | |
| 4418 | const decl_tv = try sema.resolveInstValue(&block_scope, .unneeded, result_ref, undefined); | |
| 4489 | const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = 0 }; | |
| 4490 | const section_src: LazySrcLoc = .{ .node_offset_var_decl_section = 0 }; | |
| 4491 | const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 }; | |
| 4492 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 }; | |
| 4493 | const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 }; | |
| 4494 | const decl_tv = try sema.resolveInstValue(&block_scope, init_src, result_ref, undefined); | |
| 4419 | 4495 | const decl_align: u32 = blk: { |
| 4420 | 4496 | const align_ref = decl.zirAlignRef(); |
| 4421 | 4497 | if (align_ref == .none) break :blk 0; |
| 4422 | break :blk try sema.resolveAlign(&block_scope, src, align_ref); | |
| 4498 | break :blk try sema.resolveAlign(&block_scope, align_src, align_ref); | |
| 4423 | 4499 | }; |
| 4424 | 4500 | const decl_linksection: ?[*:0]const u8 = blk: { |
| 4425 | 4501 | const linksection_ref = decl.zirLinksectionRef(); |
| 4426 | 4502 | if (linksection_ref == .none) break :blk null; |
| 4427 | const bytes = try sema.resolveConstString(&block_scope, src, linksection_ref, "linksection must be comptime known"); | |
| 4503 | const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, "linksection must be comptime known"); | |
| 4504 | if (mem.indexOfScalar(u8, bytes, 0) != null) { | |
| 4505 | return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{}); | |
| 4506 | } else if (bytes.len == 0) { | |
| 4507 | return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); | |
| 4508 | } | |
| 4428 | 4509 | break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr; |
| 4429 | 4510 | }; |
| 4430 | 4511 | const target = sema.mod.getTarget(); |
| ... | ... | @@ -4442,27 +4523,27 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4442 | 4523 | .constant => target_util.defaultAddressSpace(target, .global_constant), |
| 4443 | 4524 | else => unreachable, |
| 4444 | 4525 | }, |
| 4445 | else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, src, addrspace_ref, addrspace_ctx), | |
| 4526 | else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx), | |
| 4446 | 4527 | }; |
| 4447 | 4528 | }; |
| 4448 | 4529 | |
| 4449 | 4530 | // Note this resolves the type of the Decl, not the value; if this Decl |
| 4450 | 4531 | // is a struct, for example, this resolves `type` (which needs no resolution), |
| 4451 | 4532 | // not the struct itself. |
| 4452 | try sema.resolveTypeLayout(&block_scope, src, decl_tv.ty); | |
| 4533 | try sema.resolveTypeLayout(&block_scope, ty_src, decl_tv.ty); | |
| 4453 | 4534 | |
| 4454 | 4535 | const decl_arena_state = try decl_arena_allocator.create(std.heap.ArenaAllocator.State); |
| 4455 | 4536 | |
| 4456 | 4537 | if (decl.is_usingnamespace) { |
| 4457 | 4538 | if (!decl_tv.ty.eql(Type.type, mod)) { |
| 4458 | return sema.fail(&block_scope, src, "expected type, found {}", .{ | |
| 4539 | return sema.fail(&block_scope, ty_src, "expected type, found {}", .{ | |
| 4459 | 4540 | decl_tv.ty.fmt(mod), |
| 4460 | 4541 | }); |
| 4461 | 4542 | } |
| 4462 | 4543 | var buffer: Value.ToTypeBuffer = undefined; |
| 4463 | 4544 | const ty = try decl_tv.val.toType(&buffer).copy(decl_arena_allocator); |
| 4464 | 4545 | if (ty.getNamespace() == null) { |
| 4465 | return sema.fail(&block_scope, src, "type {} has no namespace", .{ty.fmt(mod)}); | |
| 4546 | return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)}); | |
| 4466 | 4547 | } |
| 4467 | 4548 | |
| 4468 | 4549 | decl.ty = Type.type; |
| ... | ... | @@ -4508,7 +4589,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4508 | 4589 | decl.analysis = .complete; |
| 4509 | 4590 | decl.generation = mod.generation; |
| 4510 | 4591 | |
| 4511 | const has_runtime_bits = try sema.fnHasRuntimeBits(&block_scope, src, decl.ty); | |
| 4592 | const has_runtime_bits = try sema.fnHasRuntimeBits(&block_scope, ty_src, decl.ty); | |
| 4512 | 4593 | |
| 4513 | 4594 | if (has_runtime_bits) { |
| 4514 | 4595 | // 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 { |
| 4525 | 4606 | |
| 4526 | 4607 | const is_inline = decl.ty.fnCallingConvention() == .Inline; |
| 4527 | 4608 | if (decl.is_exported) { |
| 4528 | const export_src = src; // TODO make this point at `export` token | |
| 4609 | const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) }; | |
| 4529 | 4610 | if (is_inline) { |
| 4530 | 4611 | return sema.fail(&block_scope, export_src, "export of inline function", .{}); |
| 4531 | 4612 | } |
| ... | ... | @@ -4588,14 +4669,14 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4588 | 4669 | decl.generation = mod.generation; |
| 4589 | 4670 | |
| 4590 | 4671 | const has_runtime_bits = is_extern or |
| 4591 | (queue_linker_work and try sema.typeHasRuntimeBits(&block_scope, src, decl.ty)); | |
| 4672 | (queue_linker_work and try sema.typeHasRuntimeBits(&block_scope, ty_src, decl.ty)); | |
| 4592 | 4673 | |
| 4593 | 4674 | if (has_runtime_bits) { |
| 4594 | 4675 | log.debug("queue linker work for {*} ({s})", .{ decl, decl.name }); |
| 4595 | 4676 | |
| 4596 | 4677 | // Needed for codegen_decl which will call updateDecl and then the |
| 4597 | 4678 | // codegen backend wants full access to the Decl Type. |
| 4598 | try sema.resolveTypeFully(&block_scope, src, decl.ty); | |
| 4679 | try sema.resolveTypeFully(&block_scope, ty_src, decl.ty); | |
| 4599 | 4680 | |
| 4600 | 4681 | try mod.comp.bin_file.allocateDeclIndexes(decl_index); |
| 4601 | 4682 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); |
| ... | ... | @@ -4606,7 +4687,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4606 | 4687 | } |
| 4607 | 4688 | |
| 4608 | 4689 | if (decl.is_exported) { |
| 4609 | const export_src = src; // TODO point to the export token | |
| 4690 | const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) }; | |
| 4610 | 4691 | // The scope needs to have the decl in it. |
| 4611 | 4692 | const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) }; |
| 4612 | 4693 | try sema.analyzeExport(&block_scope, export_src, options, decl_index); |
src/Sema.zig+215-49| ... | ... | @@ -2971,7 +2971,7 @@ fn zirAllocExtended( |
| 2971 | 2971 | const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand); |
| 2972 | 2972 | const src = LazySrcLoc.nodeOffset(extra.data.src_node); |
| 2973 | 2973 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = extra.data.src_node }; |
| 2974 | const align_src = src; // TODO better source location | |
| 2974 | const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = extra.data.src_node }; | |
| 2975 | 2975 | const small = @bitCast(Zir.Inst.AllocExtended.Small, extended.small); |
| 2976 | 2976 | |
| 2977 | 2977 | var extra_index: usize = extra.end; |
| ... | ... | @@ -5049,13 +5049,13 @@ pub fn analyzeExport( |
| 5049 | 5049 | try mod.ensureDeclAnalyzed(exported_decl_index); |
| 5050 | 5050 | const exported_decl = mod.declPtr(exported_decl_index); |
| 5051 | 5051 | |
| 5052 | if (!(try sema.validateExternType(exported_decl.ty, .other))) { | |
| 5052 | if (!sema.validateExternType(exported_decl.ty, .other)) { | |
| 5053 | 5053 | const msg = msg: { |
| 5054 | 5054 | const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)}); |
| 5055 | 5055 | errdefer msg.destroy(sema.gpa); |
| 5056 | 5056 | |
| 5057 | 5057 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 5058 | try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), exported_decl.ty, .other); | |
| 5058 | try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), exported_decl.ty, .other); | |
| 5059 | 5059 | |
| 5060 | 5060 | try sema.addDeclaredHereNote(msg, exported_decl.ty); |
| 5061 | 5061 | break :msg msg; |
| ... | ... | @@ -7634,7 +7634,7 @@ fn funcCommon( |
| 7634 | 7634 | }; |
| 7635 | 7635 | return sema.failWithOwnedErrorMsg(block, msg); |
| 7636 | 7636 | } |
| 7637 | if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !(try sema.validateExternType(return_type, .ret_ty))) { | |
| 7637 | if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) { | |
| 7638 | 7638 | const msg = msg: { |
| 7639 | 7639 | const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{ |
| 7640 | 7640 | return_type.fmt(sema.mod), @tagName(cc_workaround), |
| ... | ... | @@ -7642,7 +7642,7 @@ fn funcCommon( |
| 7642 | 7642 | errdefer msg.destroy(sema.gpa); |
| 7643 | 7643 | |
| 7644 | 7644 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 7645 | try sema.explainWhyTypeIsNotExtern(block, ret_ty_src, msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty); | |
| 7645 | try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty); | |
| 7646 | 7646 | |
| 7647 | 7647 | try sema.addDeclaredHereNote(msg, return_type); |
| 7648 | 7648 | break :msg msg; |
| ... | ... | @@ -7830,7 +7830,7 @@ fn analyzeParameter( |
| 7830 | 7830 | }; |
| 7831 | 7831 | return sema.failWithOwnedErrorMsg(block, msg); |
| 7832 | 7832 | } |
| 7833 | if (!Type.fnCallingConventionAllowsZigTypes(cc) and !(try sema.validateExternType(param.ty, .param_ty))) { | |
| 7833 | if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) { | |
| 7834 | 7834 | const msg = msg: { |
| 7835 | 7835 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ |
| 7836 | 7836 | param.ty.fmt(sema.mod), @tagName(cc), |
| ... | ... | @@ -7838,7 +7838,7 @@ fn analyzeParameter( |
| 7838 | 7838 | errdefer msg.destroy(sema.gpa); |
| 7839 | 7839 | |
| 7840 | 7840 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 7841 | try sema.explainWhyTypeIsNotExtern(block, param_src, msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty); | |
| 7841 | try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty); | |
| 7842 | 7842 | |
| 7843 | 7843 | try sema.addDeclaredHereNote(msg, param.ty); |
| 7844 | 7844 | break :msg msg; |
| ... | ... | @@ -8046,7 +8046,7 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 8046 | 8046 | if (try sema.resolveMaybeUndefValIntable(block, ptr_src, ptr)) |ptr_val| { |
| 8047 | 8047 | return sema.addConstant(Type.usize, ptr_val); |
| 8048 | 8048 | } |
| 8049 | try sema.requireRuntimeBlock(block, ptr_src, ptr_src); | |
| 8049 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); | |
| 8050 | 8050 | return block.addUnOp(.ptrtoint, ptr); |
| 8051 | 8051 | } |
| 8052 | 8052 | |
| ... | ... | @@ -8288,6 +8288,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 8288 | 8288 | |
| 8289 | 8289 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 8290 | 8290 | const operand = try sema.resolveInst(extra.rhs); |
| 8291 | const operand_ty = sema.typeOf(operand); | |
| 8291 | 8292 | switch (dest_ty.zigTypeTag()) { |
| 8292 | 8293 | .AnyFrame, |
| 8293 | 8294 | .ComptimeFloat, |
| ... | ... | @@ -8310,8 +8311,8 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 8310 | 8311 | const msg = msg: { |
| 8311 | 8312 | const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)}); |
| 8312 | 8313 | errdefer msg.destroy(sema.gpa); |
| 8313 | switch (sema.typeOf(operand).zigTypeTag()) { | |
| 8314 | .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum for type coercion", .{}), | |
| 8314 | switch (operand_ty.zigTypeTag()) { | |
| 8315 | .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum to cast from '{}'", .{operand_ty.fmt(sema.mod)}), | |
| 8315 | 8316 | else => {}, |
| 8316 | 8317 | } |
| 8317 | 8318 | |
| ... | ... | @@ -8320,9 +8321,20 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 8320 | 8321 | return sema.failWithOwnedErrorMsg(block, msg); |
| 8321 | 8322 | }, |
| 8322 | 8323 | |
| 8323 | .Pointer => return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}', use @ptrCast to cast to a pointer", .{ | |
| 8324 | dest_ty.fmt(sema.mod), | |
| 8325 | }), | |
| 8324 | .Pointer => { | |
| 8325 | const msg = msg: { | |
| 8326 | const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)}); | |
| 8327 | errdefer msg.destroy(sema.gpa); | |
| 8328 | switch (operand_ty.zigTypeTag()) { | |
| 8329 | .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToPtr to cast from '{}'", .{operand_ty.fmt(sema.mod)}), | |
| 8330 | .Pointer => try sema.errNote(block, dest_ty_src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(sema.mod)}), | |
| 8331 | else => {}, | |
| 8332 | } | |
| 8333 | ||
| 8334 | break :msg msg; | |
| 8335 | }; | |
| 8336 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 8337 | }, | |
| 8326 | 8338 | .Struct, .Union => if (dest_ty.containerLayout() == .Auto) { |
| 8327 | 8339 | const container = switch (dest_ty.zigTypeTag()) { |
| 8328 | 8340 | .Struct => "struct", |
| ... | ... | @@ -8342,6 +8354,70 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 8342 | 8354 | .Vector, |
| 8343 | 8355 | => {}, |
| 8344 | 8356 | } |
| 8357 | switch (operand_ty.zigTypeTag()) { | |
| 8358 | .AnyFrame, | |
| 8359 | .ComptimeFloat, | |
| 8360 | .ComptimeInt, | |
| 8361 | .EnumLiteral, | |
| 8362 | .ErrorSet, | |
| 8363 | .ErrorUnion, | |
| 8364 | .Fn, | |
| 8365 | .Frame, | |
| 8366 | .NoReturn, | |
| 8367 | .Null, | |
| 8368 | .Opaque, | |
| 8369 | .Optional, | |
| 8370 | .Type, | |
| 8371 | .Undefined, | |
| 8372 | .Void, | |
| 8373 | => return sema.fail(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}), | |
| 8374 | ||
| 8375 | .Enum => { | |
| 8376 | const msg = msg: { | |
| 8377 | const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}); | |
| 8378 | errdefer msg.destroy(sema.gpa); | |
| 8379 | switch (dest_ty.zigTypeTag()) { | |
| 8380 | .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @enumToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}), | |
| 8381 | else => {}, | |
| 8382 | } | |
| 8383 | ||
| 8384 | break :msg msg; | |
| 8385 | }; | |
| 8386 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 8387 | }, | |
| 8388 | .Pointer => { | |
| 8389 | const msg = msg: { | |
| 8390 | const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}); | |
| 8391 | errdefer msg.destroy(sema.gpa); | |
| 8392 | switch (dest_ty.zigTypeTag()) { | |
| 8393 | .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @ptrToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}), | |
| 8394 | .Pointer => try sema.errNote(block, operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(sema.mod)}), | |
| 8395 | else => {}, | |
| 8396 | } | |
| 8397 | ||
| 8398 | break :msg msg; | |
| 8399 | }; | |
| 8400 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 8401 | }, | |
| 8402 | .Struct, .Union => if (operand_ty.containerLayout() == .Auto) { | |
| 8403 | const container = switch (operand_ty.zigTypeTag()) { | |
| 8404 | .Struct => "struct", | |
| 8405 | .Union => "union", | |
| 8406 | else => unreachable, | |
| 8407 | }; | |
| 8408 | return sema.fail(block, operand_src, "cannot @bitCast from '{}', {s} does not have a guaranteed in-memory layout", .{ | |
| 8409 | operand_ty.fmt(sema.mod), container, | |
| 8410 | }); | |
| 8411 | }, | |
| 8412 | .BoundFn => @panic("TODO remove this type from the language and compiler"), | |
| 8413 | ||
| 8414 | .Array, | |
| 8415 | .Bool, | |
| 8416 | .Float, | |
| 8417 | .Int, | |
| 8418 | .Vector, | |
| 8419 | => {}, | |
| 8420 | } | |
| 8345 | 8421 | return sema.bitCast(block, dest_ty, operand, operand_src); |
| 8346 | 8422 | } |
| 8347 | 8423 | |
| ... | ... | @@ -13098,8 +13174,8 @@ fn zirBuiltinSrc( |
| 13098 | 13174 | const tracy = trace(@src()); |
| 13099 | 13175 | defer tracy.end(); |
| 13100 | 13176 | |
| 13101 | const src = sema.src; // TODO better source location | |
| 13102 | const extra = sema.code.extraData(Zir.Inst.LineColumn, extended.operand).data; | |
| 13177 | const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data; | |
| 13178 | const src = LazySrcLoc.nodeOffset(extra.node); | |
| 13103 | 13179 | const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{}); |
| 13104 | 13180 | const fn_owner_decl = sema.mod.declPtr(func.owner_decl); |
| 13105 | 13181 | |
| ... | ... | @@ -14790,13 +14866,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 14790 | 14866 | } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) { |
| 14791 | 14867 | return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{}); |
| 14792 | 14868 | } else if (inst_data.size == .C) { |
| 14793 | if (!(try sema.validateExternType(elem_ty, .other))) { | |
| 14869 | if (!sema.validateExternType(elem_ty, .other)) { | |
| 14794 | 14870 | const msg = msg: { |
| 14795 | 14871 | const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); |
| 14796 | 14872 | errdefer msg.destroy(sema.gpa); |
| 14797 | 14873 | |
| 14798 | 14874 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 14799 | try sema.explainWhyTypeIsNotExtern(block, elem_ty_src, msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other); | |
| 14875 | try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other); | |
| 14800 | 14876 | |
| 14801 | 14877 | try sema.addDeclaredHereNote(msg, elem_ty); |
| 14802 | 14878 | break :msg msg; |
| ... | ... | @@ -15874,13 +15950,13 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 15874 | 15950 | } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) { |
| 15875 | 15951 | return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); |
| 15876 | 15952 | } else if (ptr_size == .C) { |
| 15877 | if (!(try sema.validateExternType(elem_ty, .other))) { | |
| 15953 | if (!sema.validateExternType(elem_ty, .other)) { | |
| 15878 | 15954 | const msg = msg: { |
| 15879 | 15955 | const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); |
| 15880 | 15956 | errdefer msg.destroy(sema.gpa); |
| 15881 | 15957 | |
| 15882 | 15958 | const src_decl = sema.mod.declPtr(block.src_decl); |
| 15883 | try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), elem_ty, .other); | |
| 15959 | try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), elem_ty, .other); | |
| 15884 | 15960 | |
| 15885 | 15961 | try sema.addDeclaredHereNote(msg, elem_ty); |
| 15886 | 15962 | break :msg msg; |
| ... | ... | @@ -18883,10 +18959,8 @@ fn zirVarExtended( |
| 18883 | 18959 | extended: Zir.Inst.Extended.InstData, |
| 18884 | 18960 | ) CompileError!Air.Inst.Ref { |
| 18885 | 18961 | const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand); |
| 18886 | const src = sema.src; | |
| 18887 | const ty_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at type | |
| 18888 | const name_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at the name token | |
| 18889 | const init_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at init expr | |
| 18962 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 }; | |
| 18963 | const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 }; | |
| 18890 | 18964 | const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); |
| 18891 | 18965 | |
| 18892 | 18966 | var extra_index: usize = extra.end; |
| ... | ... | @@ -18900,12 +18974,6 @@ fn zirVarExtended( |
| 18900 | 18974 | // ZIR supports encoding this information but it is not used; the information |
| 18901 | 18975 | // is encoded via the Decl entry. |
| 18902 | 18976 | assert(!small.has_align); |
| 18903 | //const align_val: Value = if (small.has_align) blk: { | |
| 18904 | // const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | |
| 18905 | // extra_index += 1; | |
| 18906 | // const align_tv = try sema.resolveInstConst(block, align_src, align_ref); | |
| 18907 | // break :blk align_tv.val; | |
| 18908 | //} else Value.@"null"; | |
| 18909 | 18977 | |
| 18910 | 18978 | const uncasted_init: Air.Inst.Ref = if (small.has_init) blk: { |
| 18911 | 18979 | const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| ... | ... | @@ -18929,7 +18997,7 @@ fn zirVarExtended( |
| 18929 | 18997 | return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime known"); |
| 18930 | 18998 | } else Value.initTag(.unreachable_value); |
| 18931 | 18999 | |
| 18932 | try sema.validateVarType(block, name_src, var_ty, small.is_extern); | |
| 19000 | try sema.validateVarType(block, ty_src, var_ty, small.is_extern); | |
| 18933 | 19001 | |
| 18934 | 19002 | const new_var = try sema.gpa.create(Module.Var); |
| 18935 | 19003 | errdefer sema.gpa.destroy(new_var); |
| ... | ... | @@ -19668,7 +19736,7 @@ const ExternPosition = enum { |
| 19668 | 19736 | |
| 19669 | 19737 | /// Returns true if `ty` is allowed in extern types. |
| 19670 | 19738 | /// Does *NOT* require `ty` to be resolved in any way. |
| 19671 | fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileError!bool { | |
| 19739 | fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool { | |
| 19672 | 19740 | switch (ty.zigTypeTag()) { |
| 19673 | 19741 | .Type, |
| 19674 | 19742 | .ComptimeFloat, |
| ... | ... | @@ -19713,8 +19781,6 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileEr |
| 19713 | 19781 | |
| 19714 | 19782 | fn explainWhyTypeIsNotExtern( |
| 19715 | 19783 | sema: *Sema, |
| 19716 | block: *Block, | |
| 19717 | src: LazySrcLoc, | |
| 19718 | 19784 | msg: *Module.ErrorMsg, |
| 19719 | 19785 | src_loc: Module.SrcLoc, |
| 19720 | 19786 | ty: Type, |
| ... | ... | @@ -19758,7 +19824,7 @@ fn explainWhyTypeIsNotExtern( |
| 19758 | 19824 | var buf: Type.Payload.Bits = undefined; |
| 19759 | 19825 | const tag_ty = ty.intTagType(&buf); |
| 19760 | 19826 | try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)}); |
| 19761 | try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, tag_ty, position); | |
| 19827 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); | |
| 19762 | 19828 | }, |
| 19763 | 19829 | .Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}), |
| 19764 | 19830 | .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}), |
| ... | ... | @@ -19768,13 +19834,87 @@ fn explainWhyTypeIsNotExtern( |
| 19768 | 19834 | } else if (position == .param_ty) { |
| 19769 | 19835 | return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{}); |
| 19770 | 19836 | } |
| 19771 | try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position); | |
| 19837 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position); | |
| 19772 | 19838 | }, |
| 19773 | .Vector => try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position), | |
| 19839 | .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position), | |
| 19774 | 19840 | .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}), |
| 19775 | 19841 | } |
| 19776 | 19842 | } |
| 19777 | 19843 | |
| 19844 | /// Returns true if `ty` is allowed in packed types. | |
| 19845 | /// Does *NOT* require `ty` to be resolved in any way. | |
| 19846 | fn validatePackedType(ty: Type) bool { | |
| 19847 | switch (ty.zigTypeTag()) { | |
| 19848 | .Type, | |
| 19849 | .ComptimeFloat, | |
| 19850 | .ComptimeInt, | |
| 19851 | .EnumLiteral, | |
| 19852 | .Undefined, | |
| 19853 | .Null, | |
| 19854 | .ErrorUnion, | |
| 19855 | .ErrorSet, | |
| 19856 | .BoundFn, | |
| 19857 | .Frame, | |
| 19858 | .NoReturn, | |
| 19859 | .Opaque, | |
| 19860 | .AnyFrame, | |
| 19861 | .Fn, | |
| 19862 | .Array, | |
| 19863 | .Optional, | |
| 19864 | => return false, | |
| 19865 | .Void, | |
| 19866 | .Bool, | |
| 19867 | .Float, | |
| 19868 | .Pointer, | |
| 19869 | .Int, | |
| 19870 | .Vector, | |
| 19871 | .Enum, | |
| 19872 | => return true, | |
| 19873 | .Struct, .Union => return ty.containerLayout() == .Packed, | |
| 19874 | } | |
| 19875 | } | |
| 19876 | ||
| 19877 | fn explainWhyTypeIsNotPacked( | |
| 19878 | sema: *Sema, | |
| 19879 | msg: *Module.ErrorMsg, | |
| 19880 | src_loc: Module.SrcLoc, | |
| 19881 | ty: Type, | |
| 19882 | ) CompileError!void { | |
| 19883 | const mod = sema.mod; | |
| 19884 | switch (ty.zigTypeTag()) { | |
| 19885 | .Void, | |
| 19886 | .Bool, | |
| 19887 | .Float, | |
| 19888 | .Pointer, | |
| 19889 | .Int, | |
| 19890 | .Vector, | |
| 19891 | .Enum, | |
| 19892 | => return, | |
| 19893 | .Type, | |
| 19894 | .ComptimeFloat, | |
| 19895 | .ComptimeInt, | |
| 19896 | .EnumLiteral, | |
| 19897 | .Undefined, | |
| 19898 | .Null, | |
| 19899 | .BoundFn, | |
| 19900 | .Frame, | |
| 19901 | .NoReturn, | |
| 19902 | .Opaque, | |
| 19903 | .ErrorUnion, | |
| 19904 | .ErrorSet, | |
| 19905 | .AnyFrame, | |
| 19906 | .Optional, | |
| 19907 | .Array, | |
| 19908 | => try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}), | |
| 19909 | .Fn => { | |
| 19910 | try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}); | |
| 19911 | try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{}); | |
| 19912 | }, | |
| 19913 | .Struct => try mod.errNoteNonLazy(src_loc, msg, "only packed structs layout are allowed in packed types", .{}), | |
| 19914 | .Union => try mod.errNoteNonLazy(src_loc, msg, "only packed unions layout are allowed in packed types", .{}), | |
| 19915 | } | |
| 19916 | } | |
| 19917 | ||
| 19778 | 19918 | pub const PanicId = enum { |
| 19779 | 19919 | unreach, |
| 19780 | 19920 | unwrap_null, |
| ... | ... | @@ -26851,28 +26991,41 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 26851 | 26991 | const field = &struct_obj.fields.values()[i]; |
| 26852 | 26992 | field.ty = try field_ty.copy(decl_arena_allocator); |
| 26853 | 26993 | |
| 26854 | if (struct_obj.layout == .Extern and !(try sema.validateExternType(field.ty, .other))) { | |
| 26994 | if (field_ty.zigTypeTag() == .Opaque) { | |
| 26995 | const msg = msg: { | |
| 26996 | const tree = try sema.getAstTree(&block_scope); | |
| 26997 | const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i); | |
| 26998 | const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); | |
| 26999 | errdefer msg.destroy(sema.gpa); | |
| 27000 | ||
| 27001 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 27002 | break :msg msg; | |
| 27003 | }; | |
| 27004 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 27005 | } | |
| 27006 | if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) { | |
| 26855 | 27007 | const msg = msg: { |
| 26856 | 27008 | const tree = try sema.getAstTree(&block_scope); |
| 26857 | 27009 | const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i); |
| 26858 | 27010 | const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)}); |
| 26859 | 27011 | errdefer msg.destroy(sema.gpa); |
| 26860 | 27012 | |
| 26861 | try sema.explainWhyTypeIsNotExtern(&block_scope, fields_src, msg, fields_src.toSrcLoc(decl), field.ty, .other); | |
| 27013 | try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .other); | |
| 26862 | 27014 | |
| 26863 | 27015 | try sema.addDeclaredHereNote(msg, field.ty); |
| 26864 | 27016 | break :msg msg; |
| 26865 | 27017 | }; |
| 26866 | 27018 | return sema.failWithOwnedErrorMsg(&block_scope, msg); |
| 26867 | } | |
| 26868 | if (field_ty.zigTypeTag() == .Opaque) { | |
| 27019 | } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) { | |
| 26869 | 27020 | const msg = msg: { |
| 26870 | 27021 | const tree = try sema.getAstTree(&block_scope); |
| 26871 | const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i); | |
| 26872 | const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); | |
| 27022 | const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i); | |
| 27023 | const msg = try sema.errMsg(&block_scope, fields_src, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)}); | |
| 26873 | 27024 | errdefer msg.destroy(sema.gpa); |
| 26874 | 27025 | |
| 26875 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 27026 | try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field.ty); | |
| 27027 | ||
| 27028 | try sema.addDeclaredHereNote(msg, field.ty); | |
| 26876 | 27029 | break :msg msg; |
| 26877 | 27030 | }; |
| 26878 | 27031 | return sema.failWithOwnedErrorMsg(&block_scope, msg); |
| ... | ... | @@ -27175,27 +27328,40 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 27175 | 27328 | } |
| 27176 | 27329 | } |
| 27177 | 27330 | |
| 27178 | if (union_obj.layout == .Extern and !(try sema.validateExternType(field_ty, .union_field))) { | |
| 27331 | if (field_ty.zigTypeTag() == .Opaque) { | |
| 27179 | 27332 | const msg = msg: { |
| 27180 | 27333 | const tree = try sema.getAstTree(&block_scope); |
| 27181 | 27334 | const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i); |
| 27182 | const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); | |
| 27335 | const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); | |
| 27183 | 27336 | errdefer msg.destroy(sema.gpa); |
| 27184 | 27337 | |
| 27185 | try sema.explainWhyTypeIsNotExtern(&block_scope, field_src, msg, field_src.toSrcLoc(decl), field_ty, .union_field); | |
| 27186 | ||
| 27187 | 27338 | try sema.addDeclaredHereNote(msg, field_ty); |
| 27188 | 27339 | break :msg msg; |
| 27189 | 27340 | }; |
| 27190 | 27341 | return sema.failWithOwnedErrorMsg(&block_scope, msg); |
| 27191 | 27342 | } |
| 27192 | if (field_ty.zigTypeTag() == .Opaque) { | |
| 27343 | if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field)) { | |
| 27193 | 27344 | const msg = msg: { |
| 27194 | 27345 | const tree = try sema.getAstTree(&block_scope); |
| 27195 | 27346 | const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i); |
| 27196 | const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); | |
| 27347 | const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); | |
| 27197 | 27348 | errdefer msg.destroy(sema.gpa); |
| 27198 | 27349 | |
| 27350 | try sema.explainWhyTypeIsNotExtern(msg, field_src.toSrcLoc(decl), field_ty, .union_field); | |
| 27351 | ||
| 27352 | try sema.addDeclaredHereNote(msg, field_ty); | |
| 27353 | break :msg msg; | |
| 27354 | }; | |
| 27355 | return sema.failWithOwnedErrorMsg(&block_scope, msg); | |
| 27356 | } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) { | |
| 27357 | const msg = msg: { | |
| 27358 | const tree = try sema.getAstTree(&block_scope); | |
| 27359 | const fields_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i); | |
| 27360 | const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)}); | |
| 27361 | errdefer msg.destroy(sema.gpa); | |
| 27362 | ||
| 27363 | try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field_ty); | |
| 27364 | ||
| 27199 | 27365 | try sema.addDeclaredHereNote(msg, field_ty); |
| 27200 | 27366 | break :msg msg; |
| 27201 | 27367 | }; |
src/Zir.zig+6| ... | ... | @@ -3548,6 +3548,12 @@ pub const Inst = struct { |
| 3548 | 3548 | ty: Ref, |
| 3549 | 3549 | init_count: u32, |
| 3550 | 3550 | }; |
| 3551 | ||
| 3552 | pub const Src = struct { | |
| 3553 | node: i32, | |
| 3554 | line: u32, | |
| 3555 | column: u32, | |
| 3556 | }; | |
| 3551 | 3557 | }; |
| 3552 | 3558 | |
| 3553 | 3559 | pub const SpecialProng = enum { none, @"else", under }; |
test/behavior/bitcast.zig-16| ... | ... | @@ -90,22 +90,6 @@ test "nested bitcast" { |
| 90 | 90 | comptime try S.foo(42); |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | test "@bitCast enum to its integer type" { | |
| 94 | const SOCK = enum(c_int) { | |
| 95 | A, | |
| 96 | B, | |
| 97 | ||
| 98 | fn testBitCastExternEnum() !void { | |
| 99 | var SOCK_DGRAM = @This().B; | |
| 100 | var sock_dgram = @bitCast(c_int, SOCK_DGRAM); | |
| 101 | try expect(sock_dgram == 1); | |
| 102 | } | |
| 103 | }; | |
| 104 | ||
| 105 | try SOCK.testBitCastExternEnum(); | |
| 106 | comptime try SOCK.testBitCastExternEnum(); | |
| 107 | } | |
| 108 | ||
| 109 | 93 | // issue #3010: compiler segfault |
| 110 | 94 | test "bitcast literal [4]u8 param to u32" { |
| 111 | 95 | const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 }); |
test/behavior/packed-struct.zig+2-26| ... | ... | @@ -6,6 +6,8 @@ const expectEqual = std.testing.expectEqual; |
| 6 | 6 | const native_endian = builtin.cpu.arch.endian(); |
| 7 | 7 | |
| 8 | 8 | test "correct size of packed structs" { |
| 9 | // Stage2 has different packed struct semantics. | |
| 10 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 9 | 11 | const T1 = packed struct { one: u8, three: [3]u8 }; |
| 10 | 12 | |
| 11 | 13 | try expectEqual(4, @sizeOf(T1)); |
| ... | ... | @@ -118,18 +120,6 @@ test "flags in packed structs" { |
| 118 | 120 | try expectEqual(32, @bitSizeOf(Flags3)); |
| 119 | 121 | } |
| 120 | 122 | |
| 121 | test "arrays in packed structs" { | |
| 122 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 123 | ||
| 124 | const T1 = packed struct { array: [3][3]u8 }; | |
| 125 | const T2 = packed struct { array: [9]u8 }; | |
| 126 | ||
| 127 | try expectEqual(@sizeOf(u72), @sizeOf(T1)); | |
| 128 | try expectEqual(72, @bitSizeOf(T1)); | |
| 129 | try expectEqual(@sizeOf(u72), @sizeOf(T2)); | |
| 130 | try expectEqual(72, @bitSizeOf(T2)); | |
| 131 | } | |
| 132 | ||
| 133 | 123 | test "consistent size of packed structs" { |
| 134 | 124 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 135 | 125 | |
| ... | ... | @@ -145,23 +135,15 @@ test "consistent size of packed structs" { |
| 145 | 135 | try expectEqual(register_size_bits, @bitSizeOf(TxData2)); |
| 146 | 136 | try expectEqual(register_size_bytes, @sizeOf(TxData2)); |
| 147 | 137 | |
| 148 | const TxData3 = packed struct { a: u32, b: [3]u8 }; | |
| 149 | 138 | const TxData4 = packed struct { a: u32, b: u24 }; |
| 150 | const TxData5 = packed struct { a: [3]u8, b: u32 }; | |
| 151 | 139 | const TxData6 = packed struct { a: u24, b: u32 }; |
| 152 | 140 | |
| 153 | 141 | const expectedBitSize = 56; |
| 154 | 142 | const expectedByteSize = @sizeOf(u56); |
| 155 | 143 | |
| 156 | try expectEqual(expectedBitSize, @bitSizeOf(TxData3)); | |
| 157 | try expectEqual(expectedByteSize, @sizeOf(TxData3)); | |
| 158 | ||
| 159 | 144 | try expectEqual(expectedBitSize, @bitSizeOf(TxData4)); |
| 160 | 145 | try expectEqual(expectedByteSize, @sizeOf(TxData4)); |
| 161 | 146 | |
| 162 | try expectEqual(expectedBitSize, @bitSizeOf(TxData5)); | |
| 163 | try expectEqual(expectedByteSize, @sizeOf(TxData5)); | |
| 164 | ||
| 165 | 147 | try expectEqual(expectedBitSize, @bitSizeOf(TxData6)); |
| 166 | 148 | try expectEqual(expectedByteSize, @sizeOf(TxData6)); |
| 167 | 149 | } |
| ... | ... | @@ -234,12 +216,6 @@ test "correct sizeOf and offsets in packed structs" { |
| 234 | 216 | try expectEqual(@as(u7, 0b1111010), s2.y); |
| 235 | 217 | try expectEqual(@as(u24, 0xd5c71f), s2.z); |
| 236 | 218 | } |
| 237 | ||
| 238 | const S = packed struct { a: u32, pad: [3]u32, b: u32 }; | |
| 239 | ||
| 240 | try expectEqual(16, @offsetOf(S, "b")); | |
| 241 | try expectEqual(128, @bitOffsetOf(S, "b")); | |
| 242 | try expectEqual(@sizeOf(u160), @sizeOf(S)); | |
| 243 | 219 | } |
| 244 | 220 | |
| 245 | 221 | test "nested packed structs" { |
test/behavior/sizeof_and_typeof.zig+2| ... | ... | @@ -105,6 +105,8 @@ test "@offsetOf" { |
| 105 | 105 | } |
| 106 | 106 | |
| 107 | 107 | test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" { |
| 108 | // Stage2 has different packed struct semantics. | |
| 109 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 108 | 110 | const p3a_len = 3; |
| 109 | 111 | const P3 = packed struct { |
| 110 | 112 | a: [p3a_len]u8, |
test/behavior/struct.zig+2-4| ... | ... | @@ -704,10 +704,8 @@ const FooArray24Bits = packed struct { |
| 704 | 704 | }; |
| 705 | 705 | |
| 706 | 706 | test "aligned array of packed struct" { |
| 707 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 708 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 709 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 710 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 707 | // Stage2 has different packed struct semantics. | |
| 708 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | |
| 711 | 709 | |
| 712 | 710 | comptime { |
| 713 | 711 | try expect(@sizeOf(FooStructAligned) == 2); |
test/cases/compile_errors/bitCast_to_enum_type.zig+1-1| ... | ... | @@ -9,4 +9,4 @@ export fn entry() void { |
| 9 | 9 | // target=native |
| 10 | 10 | // |
| 11 | 11 | // :3:24: error: cannot @bitCast to 'tmp.entry.E' |
| 12 | // :3:24: note: use @intToEnum for type coercion | |
| 12 | // :3:24: note: use @intToEnum to cast from 'u32' |
test/cases/compile_errors/global_variable_alignment_non_power_of_2.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | const some_data: [100]u8 align(3) = undefined; | |
| 2 | export fn entry() usize { return @sizeOf(@TypeOf(some_data)); } | |
| 3 | ||
| 4 | // error | |
| 5 | // backend=stage2 | |
| 6 | // target=native | |
| 7 | // | |
| 8 | // :1:32: error: alignment value '3' is not a power of two |
test/cases/compile_errors/intToPtr_with_misaligned_address.zig created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | pub export fn entry() void { | |
| 2 | var y = @intToPtr([*]align(4) u8, 5); | |
| 3 | _ = y; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage2 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // :2:39: error: pointer type '[*]align(4) u8' requires aligned address |
test/cases/compile_errors/issue_3818_bitcast_from_parray-slice_to_u16.zig created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | export fn foo1() void { | |
| 2 | var bytes = [_]u8{1, 2}; | |
| 3 | const word: u16 = @bitCast(u16, bytes[0..]); | |
| 4 | _ = word; | |
| 5 | } | |
| 6 | export fn foo2() void { | |
| 7 | var bytes: []const u8 = &[_]u8{1, 2}; | |
| 8 | const word: u16 = @bitCast(u16, bytes); | |
| 9 | _ = word; | |
| 10 | } | |
| 11 | ||
| 12 | // error | |
| 13 | // backend=stage2 | |
| 14 | // target=native | |
| 15 | // | |
| 16 | // :3:42: error: cannot @bitCast from '*[2]u8' | |
| 17 | // :3:42: note: use @ptrToInt to cast to 'u16' | |
| 18 | // :8:37: error: cannot @bitCast from '[]const u8' | |
| 19 | // :8:37: note: use @ptrToInt to cast to 'u16' |
test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig created+84| ... | ... | @@ -0,0 +1,84 @@ |
| 1 | export fn entry1() void { | |
| 2 | _ = @sizeOf(packed struct { | |
| 3 | x: anyerror, | |
| 4 | }); | |
| 5 | } | |
| 6 | export fn entry2() void { | |
| 7 | _ = @sizeOf(packed struct { | |
| 8 | x: [2]u24, | |
| 9 | }); | |
| 10 | } | |
| 11 | export fn entry3() void { | |
| 12 | _ = @sizeOf(packed struct { | |
| 13 | x: anyerror!u32, | |
| 14 | }); | |
| 15 | } | |
| 16 | export fn entry4() void { | |
| 17 | _ = @sizeOf(packed struct { | |
| 18 | x: S, | |
| 19 | }); | |
| 20 | } | |
| 21 | export fn entry5() void { | |
| 22 | _ = @sizeOf(packed struct { | |
| 23 | x: U, | |
| 24 | }); | |
| 25 | } | |
| 26 | export fn entry6() void { | |
| 27 | _ = @sizeOf(packed struct { | |
| 28 | x: ?anyerror, | |
| 29 | }); | |
| 30 | } | |
| 31 | export fn entry7() void { | |
| 32 | _ = @sizeOf(packed struct { | |
| 33 | x: enum { A, B }, | |
| 34 | }); | |
| 35 | } | |
| 36 | export fn entry8() void { | |
| 37 | _ = @sizeOf(packed struct { | |
| 38 | x: fn () void, | |
| 39 | }); | |
| 40 | } | |
| 41 | export fn entry9() void { | |
| 42 | _ = @sizeOf(packed struct { | |
| 43 | x: *const fn () void, | |
| 44 | }); | |
| 45 | } | |
| 46 | export fn entry10() void { | |
| 47 | _ = @sizeOf(packed struct { | |
| 48 | x: packed struct { x: i32 }, | |
| 49 | }); | |
| 50 | } | |
| 51 | export fn entry11() void { | |
| 52 | _ = @sizeOf(packed struct { | |
| 53 | x: packed union { A: i32, B: u32 }, | |
| 54 | }); | |
| 55 | } | |
| 56 | const S = struct { | |
| 57 | x: i32, | |
| 58 | }; | |
| 59 | const U = extern union { | |
| 60 | A: i32, | |
| 61 | B: u32, | |
| 62 | }; | |
| 63 | ||
| 64 | // error | |
| 65 | // backend=llvm | |
| 66 | // target=native | |
| 67 | // | |
| 68 | // :3:9: error: packed structs cannot contain fields of type 'anyerror' | |
| 69 | // :3:9: note: type has no guaranteed in-memory representation | |
| 70 | // :8:9: error: packed structs cannot contain fields of type '[2]u24' | |
| 71 | // :8:9: note: type has no guaranteed in-memory representation | |
| 72 | // :13:9: error: packed structs cannot contain fields of type 'anyerror!u32' | |
| 73 | // :13:9: note: type has no guaranteed in-memory representation | |
| 74 | // :18:9: error: packed structs cannot contain fields of type 'tmp.S' | |
| 75 | // :18:9: note: only packed structs layout are allowed in packed types | |
| 76 | // :56:11: note: struct declared here | |
| 77 | // :23:9: error: packed structs cannot contain fields of type 'tmp.U' | |
| 78 | // :23:9: note: only packed unions layout are allowed in packed types | |
| 79 | // :59:18: note: union declared here | |
| 80 | // :28:9: error: packed structs cannot contain fields of type '?anyerror' | |
| 81 | // :28:9: note: type has no guaranteed in-memory representation | |
| 82 | // :38:9: error: packed structs cannot contain fields of type 'fn() void' | |
| 83 | // :38:9: note: type has no guaranteed in-memory representation | |
| 84 | // :38:9: note: use '*const ' to make a function pointer type |
test/cases/compile_errors/src_outside_function.zig created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | comptime { | |
| 2 | @src(); | |
| 3 | } | |
| 4 | ||
| 5 | // error | |
| 6 | // backend=stage2 | |
| 7 | // target=native | |
| 8 | // | |
| 9 | // :2:5: error: @src outside function |
test/cases/compile_errors/stage1/obj/global_variable_alignment_non_power_of_2.zig deleted-8| ... | ... | @@ -1,8 +0,0 @@ |
| 1 | const some_data: [100]u8 align(3) = undefined; | |
| 2 | export fn entry() usize { return @sizeOf(@TypeOf(some_data)); } | |
| 3 | ||
| 4 | // error | |
| 5 | // backend=stage1 | |
| 6 | // target=native | |
| 7 | // | |
| 8 | // tmp.zig:1:32: error: alignment value 3 is not a power of 2 |
test/cases/compile_errors/stage1/obj/intToPtr_with_misaligned_address.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | pub fn main() void { | |
| 2 | var y = @intToPtr([*]align(4) u8, 5); | |
| 3 | _ = y; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage1 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address |
test/cases/compile_errors/stage1/obj/issue_3818_bitcast_from_parray-slice_to_u16.zig deleted-17| ... | ... | @@ -1,17 +0,0 @@ |
| 1 | export fn foo1() void { | |
| 2 | var bytes = [_]u8{1, 2}; | |
| 3 | const word: u16 = @bitCast(u16, bytes[0..]); | |
| 4 | _ = word; | |
| 5 | } | |
| 6 | export fn foo2() void { | |
| 7 | var bytes: []const u8 = &[_]u8{1, 2}; | |
| 8 | const word: u16 = @bitCast(u16, bytes); | |
| 9 | _ = word; | |
| 10 | } | |
| 11 | ||
| 12 | // error | |
| 13 | // backend=stage1 | |
| 14 | // target=native | |
| 15 | // | |
| 16 | // tmp.zig:3:42: error: unable to @bitCast from pointer type '*[2]u8' | |
| 17 | // tmp.zig:8:32: error: destination type 'u16' has size 2 but source type '[]const u8' has size 16 |
test/cases/compile_errors/stage1/obj/src_outside_function.zig deleted-9| ... | ... | @@ -1,9 +0,0 @@ |
| 1 | comptime { | |
| 2 | @src(); | |
| 3 | } | |
| 4 | ||
| 5 | // error | |
| 6 | // backend=stage1 | |
| 7 | // target=native | |
| 8 | // | |
| 9 | // tmp.zig:2:5: error: @src outside function |
test/cases/compile_errors/stage1/test/packed_struct_with_fields_of_not_allowed_types.zig deleted-74| ... | ... | @@ -1,74 +0,0 @@ |
| 1 | const A = packed struct { | |
| 2 | x: anyerror, | |
| 3 | }; | |
| 4 | const B = packed struct { | |
| 5 | x: [2]u24, | |
| 6 | }; | |
| 7 | const C = packed struct { | |
| 8 | x: [1]anyerror, | |
| 9 | }; | |
| 10 | const D = packed struct { | |
| 11 | x: [1]S, | |
| 12 | }; | |
| 13 | const E = packed struct { | |
| 14 | x: [1]U, | |
| 15 | }; | |
| 16 | const F = packed struct { | |
| 17 | x: ?anyerror, | |
| 18 | }; | |
| 19 | const G = packed struct { | |
| 20 | x: Enum, | |
| 21 | }; | |
| 22 | export fn entry1() void { | |
| 23 | var a: A = undefined; | |
| 24 | _ = a; | |
| 25 | } | |
| 26 | export fn entry2() void { | |
| 27 | var b: B = undefined; | |
| 28 | _ = b; | |
| 29 | } | |
| 30 | export fn entry3() void { | |
| 31 | var r: C = undefined; | |
| 32 | _ = r; | |
| 33 | } | |
| 34 | export fn entry4() void { | |
| 35 | var d: D = undefined; | |
| 36 | _ = d; | |
| 37 | } | |
| 38 | export fn entry5() void { | |
| 39 | var e: E = undefined; | |
| 40 | _ = e; | |
| 41 | } | |
| 42 | export fn entry6() void { | |
| 43 | var f: F = undefined; | |
| 44 | _ = f; | |
| 45 | } | |
| 46 | export fn entry7() void { | |
| 47 | var g: G = undefined; | |
| 48 | _ = g; | |
| 49 | } | |
| 50 | const S = struct { | |
| 51 | x: i32, | |
| 52 | }; | |
| 53 | const U = struct { | |
| 54 | A: i32, | |
| 55 | B: u32, | |
| 56 | }; | |
| 57 | const Enum = enum { | |
| 58 | A, | |
| 59 | B, | |
| 60 | }; | |
| 61 | ||
| 62 | // error | |
| 63 | // backend=stage1 | |
| 64 | // target=native | |
| 65 | // is_test=1 | |
| 66 | // | |
| 67 | // tmp.zig:2:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation | |
| 68 | // 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) | |
| 69 | // tmp.zig:8:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation | |
| 70 | // tmp.zig:11:5: error: non-packed, non-extern struct 'S' not allowed in packed struct; no guaranteed in-memory representation | |
| 71 | // tmp.zig:14:5: error: non-packed, non-extern struct 'U' not allowed in packed struct; no guaranteed in-memory representation | |
| 72 | // tmp.zig:17:5: error: type '?anyerror' not allowed in packed struct; no guaranteed in-memory representation | |
| 73 | // tmp.zig:20:5: error: type 'Enum' not allowed in packed struct; no guaranteed in-memory representation | |
| 74 | // tmp.zig:57:14: note: enum declaration does not specify an integer tag type |
test/cases/compile_errors/type_variables_must_be_constant.zig+2-2| ... | ... | @@ -7,5 +7,5 @@ export fn entry() foo { |
| 7 | 7 | // backend=stage2 |
| 8 | 8 | // target=native |
| 9 | 9 | // |
| 10 | // :1:1: error: variable of type 'type' must be const or comptime | |
| 11 | // :1:1: note: types are not available at runtime | |
| 10 | // :1:5: error: variable of type 'type' must be const or comptime | |
| 11 | // :1:5: note: types are not available at runtime |
test/cases/compile_errors/use_invalid_number_literal_as_array_index.zig+2-2| ... | ... | @@ -8,5 +8,5 @@ export fn entry() void { |
| 8 | 8 | // backend=stage2 |
| 9 | 9 | // target=native |
| 10 | 10 | // |
| 11 | // :1:1: error: variable of type 'comptime_int' must be const or comptime | |
| 12 | // :1:1: note: to modify this variable at runtime, it must be given an explicit fixed-size number type | |
| 11 | // :1:5: error: variable of type 'comptime_int' must be const or comptime | |
| 12 | // :1:5: note: to modify this variable at runtime, it must be given an explicit fixed-size number type |
test/cases/compile_errors/usingnamespace_with_wrong_type.zig+1-1| ... | ... | @@ -4,4 +4,4 @@ usingnamespace void; |
| 4 | 4 | // backend=stage2 |
| 5 | 5 | // target=native |
| 6 | 6 | // |
| 7 | // :1:1: error: type void has no namespace | |
| 7 | // :1:16: error: type void has no namespace |