mirror of
https://github.com/ziglang/zig.git
synced 2026-01-09 08:55:36 +00:00
Merge pull request #12277 from Vexu/stage2-compile-errors
Stage2: validate packed struct field types
This commit is contained in:
commit
4831c1c65f
@ -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,
|
||||
});
|
||||
|
||||
107
src/Module.zig
107
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);
|
||||
|
||||
294
src/Sema.zig
294
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;
|
||||
@ -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;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -13098,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);
|
||||
|
||||
@ -14790,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;
|
||||
@ -15874,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;
|
||||
@ -18883,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;
|
||||
@ -18900,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]);
|
||||
@ -18929,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);
|
||||
@ -19668,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,
|
||||
@ -19713,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,
|
||||
@ -19758,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", .{}),
|
||||
@ -19768,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,
|
||||
@ -26851,20 +26991,6 @@ 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))) {
|
||||
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.addDeclaredHereNote(msg, field.ty);
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(&block_scope, msg);
|
||||
}
|
||||
if (field_ty.zigTypeTag() == .Opaque) {
|
||||
const msg = msg: {
|
||||
const tree = try sema.getAstTree(&block_scope);
|
||||
@ -26877,6 +27003,33 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
|
||||
};
|
||||
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(msg, fields_src.toSrcLoc(decl), field.ty, .other);
|
||||
|
||||
try sema.addDeclaredHereNote(msg, field.ty);
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(&block_scope, msg);
|
||||
} else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {
|
||||
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, "packed structs 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;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(&block_scope, msg);
|
||||
}
|
||||
|
||||
if (zir_field.align_body_len > 0) {
|
||||
const body = zir.extra[extra_index..][0..zir_field.align_body_len];
|
||||
@ -27175,20 +27328,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
|
||||
}
|
||||
}
|
||||
|
||||
if (union_obj.layout == .Extern and !(try 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, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
|
||||
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) {
|
||||
const msg = msg: {
|
||||
const tree = try sema.getAstTree(&block_scope);
|
||||
@ -27201,6 +27340,33 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(&block_scope, msg);
|
||||
}
|
||||
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, "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;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(&block_scope, msg);
|
||||
}
|
||||
|
||||
gop.value_ptr.* = .{
|
||||
.ty = try field_ty.copy(decl_arena_allocator),
|
||||
|
||||
@ -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 };
|
||||
|
||||
@ -90,22 +90,6 @@ test "nested bitcast" {
|
||||
comptime try S.foo(42);
|
||||
}
|
||||
|
||||
test "@bitCast enum to its integer type" {
|
||||
const SOCK = enum(c_int) {
|
||||
A,
|
||||
B,
|
||||
|
||||
fn testBitCastExternEnum() !void {
|
||||
var SOCK_DGRAM = @This().B;
|
||||
var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
|
||||
try expect(sock_dgram == 1);
|
||||
}
|
||||
};
|
||||
|
||||
try SOCK.testBitCastExternEnum();
|
||||
comptime try SOCK.testBitCastExternEnum();
|
||||
}
|
||||
|
||||
// issue #3010: compiler segfault
|
||||
test "bitcast literal [4]u8 param to u32" {
|
||||
const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
|
||||
|
||||
@ -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" {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -9,4 +9,4 @@ export fn entry() void {
|
||||
// target=native
|
||||
//
|
||||
// :3:24: error: cannot @bitCast to 'tmp.entry.E'
|
||||
// :3:24: note: use @intToEnum for type coercion
|
||||
// :3:24: note: use @intToEnum to cast from 'u32'
|
||||
|
||||
@ -2,7 +2,7 @@ const some_data: [100]u8 align(3) = undefined;
|
||||
export fn entry() usize { return @sizeOf(@TypeOf(some_data)); }
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:32: error: alignment value 3 is not a power of 2
|
||||
// :1:32: error: alignment value '3' is not a power of two
|
||||
@ -0,0 +1,10 @@
|
||||
pub export fn entry() void {
|
||||
var y = @intToPtr([*]align(4) u8, 5);
|
||||
_ = y;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:39: error: pointer type '[*]align(4) u8' requires aligned address
|
||||
@ -10,8 +10,10 @@ export fn foo2() void {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:42: error: unable to @bitCast from pointer type '*[2]u8'
|
||||
// tmp.zig:8:32: error: destination type 'u16' has size 2 but source type '[]const u8' has size 16
|
||||
// :3:42: error: cannot @bitCast from '*[2]u8'
|
||||
// :3:42: note: use @ptrToInt to cast to 'u16'
|
||||
// :8:37: error: cannot @bitCast from '[]const u8'
|
||||
// :8:37: note: use @ptrToInt to cast to 'u16'
|
||||
@ -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
|
||||
9
test/cases/compile_errors/src_outside_function.zig
Normal file
9
test/cases/compile_errors/src_outside_function.zig
Normal file
@ -0,0 +1,9 @@
|
||||
comptime {
|
||||
@src();
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:5: error: @src outside function
|
||||
@ -1,10 +0,0 @@
|
||||
pub fn main() void {
|
||||
var y = @intToPtr([*]align(4) u8, 5);
|
||||
_ = y;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address
|
||||
@ -1,9 +0,0 @@
|
||||
comptime {
|
||||
@src();
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:2:5: error: @src outside function
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user