Merge pull request #12820 from ziglang/pointless-discard-error
introduce compile error for pointless discards
This commit is contained in:
@@ -404,7 +404,6 @@ fn callFn(comptime f: anytype, args: anytype) switch (Impl) {
|
||||
}
|
||||
|
||||
// pthreads don't support exit status, ignore value
|
||||
_ = status;
|
||||
return default_value;
|
||||
},
|
||||
.ErrorUnion => |info| {
|
||||
|
||||
@@ -582,8 +582,6 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
|
||||
old_align: u29,
|
||||
ret_addr: usize,
|
||||
) void {
|
||||
_ = old_align;
|
||||
|
||||
const entry = self.large_allocations.getEntry(@ptrToInt(old_mem.ptr)) orelse {
|
||||
if (config.safety) {
|
||||
@panic("Invalid free");
|
||||
|
||||
@@ -171,7 +171,6 @@ pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool {
|
||||
}
|
||||
|
||||
pub fn approxEq(comptime T: type, x: T, y: T, tolerance: T) bool {
|
||||
_ = T;
|
||||
_ = x;
|
||||
_ = y;
|
||||
_ = tolerance;
|
||||
|
||||
@@ -2685,11 +2685,7 @@ fn genDefers(
|
||||
}
|
||||
}
|
||||
|
||||
fn checkUsed(
|
||||
gz: *GenZir,
|
||||
outer_scope: *Scope,
|
||||
inner_scope: *Scope,
|
||||
) InnerError!void {
|
||||
fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!void {
|
||||
const astgen = gz.astgen;
|
||||
|
||||
var scope = inner_scope;
|
||||
@@ -2698,15 +2694,23 @@ fn checkUsed(
|
||||
.gen_zir => scope = scope.cast(GenZir).?.parent,
|
||||
.local_val => {
|
||||
const s = scope.cast(Scope.LocalVal).?;
|
||||
if (!s.used) {
|
||||
if (s.used == 0 and s.discarded == 0) {
|
||||
try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});
|
||||
} else if (s.used != 0 and s.discarded != 0) {
|
||||
try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{
|
||||
try gz.astgen.errNoteTok(s.used, "used here", .{}),
|
||||
});
|
||||
}
|
||||
scope = s.parent;
|
||||
},
|
||||
.local_ptr => {
|
||||
const s = scope.cast(Scope.LocalPtr).?;
|
||||
if (!s.used) {
|
||||
if (s.used == 0 and s.discarded == 0) {
|
||||
try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});
|
||||
} else if (s.used != 0 and s.discarded != 0) {
|
||||
try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{
|
||||
try gz.astgen.errNoteTok(s.used, "used here", .{}),
|
||||
});
|
||||
}
|
||||
scope = s.parent;
|
||||
},
|
||||
@@ -6848,11 +6852,10 @@ fn localVarRef(
|
||||
scope: *Scope,
|
||||
rl: ResultLoc,
|
||||
ident: Ast.Node.Index,
|
||||
ident_token: Ast.Node.Index,
|
||||
ident_token: Ast.TokenIndex,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const astgen = gz.astgen;
|
||||
const gpa = astgen.gpa;
|
||||
|
||||
const name_str_index = try astgen.identAsString(ident_token);
|
||||
var s = scope;
|
||||
var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already
|
||||
@@ -6865,7 +6868,11 @@ fn localVarRef(
|
||||
if (local_val.name == name_str_index) {
|
||||
// Locals cannot shadow anything, so we do not need to look for ambiguous
|
||||
// references in this case.
|
||||
local_val.used = true;
|
||||
if (rl == .discard) {
|
||||
local_val.discarded = ident_token;
|
||||
} else {
|
||||
local_val.used = ident_token;
|
||||
}
|
||||
|
||||
const value_inst = try tunnelThroughClosure(
|
||||
gz,
|
||||
@@ -6884,7 +6891,11 @@ fn localVarRef(
|
||||
.local_ptr => {
|
||||
const local_ptr = s.cast(Scope.LocalPtr).?;
|
||||
if (local_ptr.name == name_str_index) {
|
||||
local_ptr.used = true;
|
||||
if (rl == .discard) {
|
||||
local_ptr.discarded = ident_token;
|
||||
} else {
|
||||
local_ptr.used = ident_token;
|
||||
}
|
||||
|
||||
// Can't close over a runtime variable
|
||||
if (num_namespaces_out != 0 and !local_ptr.maybe_comptime) {
|
||||
@@ -7519,7 +7530,7 @@ fn builtinCall(
|
||||
.local_val => {
|
||||
const local_val = s.cast(Scope.LocalVal).?;
|
||||
if (local_val.name == decl_name) {
|
||||
local_val.used = true;
|
||||
local_val.used = ident_token;
|
||||
_ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{
|
||||
.operand = local_val.inst,
|
||||
.options = try comptimeExpr(gz, scope, .{ .coerced_ty = .export_options_type }, params[1]),
|
||||
@@ -7533,7 +7544,7 @@ fn builtinCall(
|
||||
if (local_ptr.name == decl_name) {
|
||||
if (!local_ptr.maybe_comptime)
|
||||
return astgen.failNode(params[0], "unable to export runtime-known value", .{});
|
||||
local_ptr.used = true;
|
||||
local_ptr.used = ident_token;
|
||||
const loaded = try gz.addUnNode(.load, local_ptr.ptr, node);
|
||||
_ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{
|
||||
.operand = loaded,
|
||||
@@ -10065,11 +10076,15 @@ const Scope = struct {
|
||||
inst: Zir.Inst.Ref,
|
||||
/// Source location of the corresponding variable declaration.
|
||||
token_src: Ast.TokenIndex,
|
||||
/// Track the first identifer where it is referenced.
|
||||
/// 0 means never referenced.
|
||||
used: Ast.TokenIndex = 0,
|
||||
/// Track the identifier where it is discarded, like this `_ = foo;`.
|
||||
/// 0 means never discarded.
|
||||
discarded: Ast.TokenIndex = 0,
|
||||
/// String table index.
|
||||
name: u32,
|
||||
id_cat: IdCat,
|
||||
/// Track whether the name has been referenced.
|
||||
used: bool = false,
|
||||
};
|
||||
|
||||
/// This could be a `const` or `var` local. It has a pointer instead of a value.
|
||||
@@ -10084,14 +10099,18 @@ const Scope = struct {
|
||||
ptr: Zir.Inst.Ref,
|
||||
/// Source location of the corresponding variable declaration.
|
||||
token_src: Ast.TokenIndex,
|
||||
/// Track the first identifer where it is referenced.
|
||||
/// 0 means never referenced.
|
||||
used: Ast.TokenIndex = 0,
|
||||
/// Track the identifier where it is discarded, like this `_ = foo;`.
|
||||
/// 0 means never discarded.
|
||||
discarded: Ast.TokenIndex = 0,
|
||||
/// String table index.
|
||||
name: u32,
|
||||
id_cat: IdCat,
|
||||
/// true means we find out during Sema whether the value is comptime.
|
||||
/// false means it is already known at AstGen the value is runtime-known.
|
||||
maybe_comptime: bool,
|
||||
/// Track whether the name has been referenced.
|
||||
used: bool = false,
|
||||
};
|
||||
|
||||
const Defer = struct {
|
||||
|
||||
@@ -2506,7 +2506,6 @@ fn walkInstruction(
|
||||
try self.srcLocInfo(file, sn, parent_src)
|
||||
else
|
||||
parent_src;
|
||||
_ = src_info;
|
||||
|
||||
const decls_len = if (small.has_decls_len) blk: {
|
||||
const decls_len = file.zir.extra[extra_index];
|
||||
@@ -2627,7 +2626,6 @@ fn walkInstruction(
|
||||
extra_index += 1;
|
||||
break :blk fields_len;
|
||||
} else 0;
|
||||
_ = fields_len;
|
||||
|
||||
const decls_len = if (small.has_decls_len) blk: {
|
||||
const decls_len = file.zir.extra[extra_index];
|
||||
@@ -2759,7 +2757,6 @@ fn walkInstruction(
|
||||
extra_index += 1;
|
||||
break :blk fields_len;
|
||||
} else 0;
|
||||
_ = fields_len;
|
||||
|
||||
const decls_len = if (small.has_decls_len) blk: {
|
||||
const decls_len = file.zir.extra[extra_index];
|
||||
@@ -2901,7 +2898,6 @@ fn walkInstruction(
|
||||
extra_index += 1;
|
||||
break :blk fields_len;
|
||||
} else 0;
|
||||
_ = fields_len;
|
||||
|
||||
const decls_len = if (small.has_decls_len) blk: {
|
||||
const decls_len = file.zir.extra[extra_index];
|
||||
|
||||
26
src/Sema.zig
26
src/Sema.zig
@@ -17575,30 +17575,30 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
const operand_coerced = try sema.coerce(block, Type.usize, operand_res, operand_src);
|
||||
|
||||
const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const type_res = try sema.resolveType(block, src, extra.lhs);
|
||||
try sema.checkPtrType(block, type_src, type_res);
|
||||
try sema.resolveTypeLayout(block, src, type_res.elemType2());
|
||||
const ptr_align = type_res.ptrAlignment(sema.mod.getTarget());
|
||||
const ptr_ty = try sema.resolveType(block, src, extra.lhs);
|
||||
const elem_ty = ptr_ty.elemType2();
|
||||
try sema.checkPtrType(block, type_src, ptr_ty);
|
||||
const target = sema.mod.getTarget();
|
||||
const ptr_align = try ptr_ty.ptrAlignmentAdvanced(target, sema.kit(block, src));
|
||||
|
||||
if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| {
|
||||
const addr = val.toUnsignedInt(target);
|
||||
if (!type_res.isAllowzeroPtr() and addr == 0)
|
||||
return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{type_res.fmt(sema.mod)});
|
||||
if (!ptr_ty.isAllowzeroPtr() and addr == 0)
|
||||
return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(sema.mod)});
|
||||
if (addr != 0 and addr % ptr_align != 0)
|
||||
return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{type_res.fmt(sema.mod)});
|
||||
return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)});
|
||||
|
||||
const val_payload = try sema.arena.create(Value.Payload.U64);
|
||||
val_payload.* = .{
|
||||
.base = .{ .tag = .int_u64 },
|
||||
.data = addr,
|
||||
};
|
||||
return sema.addConstant(type_res, Value.initPayload(&val_payload.base));
|
||||
return sema.addConstant(ptr_ty, Value.initPayload(&val_payload.base));
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, operand_src);
|
||||
if (block.wantSafety() and try sema.typeHasRuntimeBits(block, sema.src, type_res.elemType2())) {
|
||||
if (!type_res.isAllowzeroPtr()) {
|
||||
if (block.wantSafety() and try sema.typeHasRuntimeBits(block, sema.src, elem_ty)) {
|
||||
if (!ptr_ty.isAllowzeroPtr()) {
|
||||
const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
|
||||
try sema.addSafetyCheck(block, is_non_zero, .cast_to_null);
|
||||
}
|
||||
@@ -17618,7 +17618,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
try sema.addSafetyCheck(block, is_aligned, .incorrect_alignment);
|
||||
}
|
||||
}
|
||||
return block.addBitCast(type_res, operand_coerced);
|
||||
return block.addBitCast(ptr_ty, operand_coerced);
|
||||
}
|
||||
|
||||
fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
|
||||
@@ -19670,8 +19670,6 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
|
||||
if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |src_ptr_val| {
|
||||
if (!src_ptr_val.isComptimeMutablePtr()) break :rs src_src;
|
||||
if (try sema.resolveDefinedValue(block, len_src, len)) |len_val| {
|
||||
_ = dest_ptr_val;
|
||||
_ = src_ptr_val;
|
||||
_ = len_val;
|
||||
return sema.fail(block, src, "TODO: Sema.zirMemcpy at comptime", .{});
|
||||
} else break :rs len_src;
|
||||
@@ -19713,7 +19711,6 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
|
||||
if (!ptr_val.isComptimeMutablePtr()) break :rs dest_src;
|
||||
if (try sema.resolveDefinedValue(block, len_src, len)) |len_val| {
|
||||
if (try sema.resolveMaybeUndefVal(block, value_src, value)) |val| {
|
||||
_ = ptr_val;
|
||||
_ = len_val;
|
||||
_ = val;
|
||||
return sema.fail(block, src, "TODO: Sema.zirMemset at comptime", .{});
|
||||
@@ -19941,7 +19938,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
if (val.tag() == .generic_poison) {
|
||||
break :blk FuncLinkSection{ .generic = {} };
|
||||
}
|
||||
_ = val;
|
||||
return sema.fail(block, section_src, "TODO implement linksection on functions", .{});
|
||||
} else if (extra.data.bits.has_section_ref) blk: {
|
||||
const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
|
||||
|
||||
@@ -2581,7 +2581,6 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = inst;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst))
|
||||
.dead
|
||||
else
|
||||
@@ -3614,7 +3613,6 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ptr = try self.resolveInst(un_op);
|
||||
const ptr_ty = self.air.typeOf(un_op);
|
||||
const ret_ty = self.fn_type.fnReturnType();
|
||||
_ = ret_ty;
|
||||
|
||||
switch (self.ret_mcv) {
|
||||
.none => {},
|
||||
@@ -5099,7 +5097,6 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
|
||||
} else {
|
||||
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
|
||||
}
|
||||
_ = tv;
|
||||
}
|
||||
|
||||
fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
|
||||
|
||||
@@ -2111,7 +2111,6 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = inst;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst))
|
||||
.dead
|
||||
else
|
||||
@@ -3353,7 +3352,6 @@ fn divFloat(
|
||||
) InnerError!MCValue {
|
||||
_ = lhs_bind;
|
||||
_ = rhs_bind;
|
||||
_ = lhs_ty;
|
||||
_ = rhs_ty;
|
||||
_ = maybe_inst;
|
||||
|
||||
@@ -3420,7 +3418,6 @@ fn divExact(
|
||||
) InnerError!MCValue {
|
||||
_ = lhs_bind;
|
||||
_ = rhs_bind;
|
||||
_ = lhs_ty;
|
||||
_ = rhs_ty;
|
||||
_ = maybe_inst;
|
||||
|
||||
@@ -3506,7 +3503,6 @@ fn modulo(
|
||||
) InnerError!MCValue {
|
||||
_ = lhs_bind;
|
||||
_ = rhs_bind;
|
||||
_ = lhs_ty;
|
||||
_ = rhs_ty;
|
||||
_ = maybe_inst;
|
||||
|
||||
|
||||
@@ -1316,7 +1316,6 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = inst;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst))
|
||||
.dead
|
||||
else
|
||||
@@ -1598,7 +1597,6 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
|
||||
return self.structFieldPtr(ty_op.operand, ty_op.ty, index);
|
||||
}
|
||||
fn structFieldPtr(self: *Self, operand: Air.Inst.Ref, ty: Air.Inst.Ref, index: u32) !void {
|
||||
_ = self;
|
||||
_ = operand;
|
||||
_ = ty;
|
||||
_ = index;
|
||||
@@ -1615,7 +1613,6 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = self;
|
||||
_ = inst;
|
||||
return self.fail("TODO implement codegen airFieldParentPtr", .{});
|
||||
}
|
||||
|
||||
@@ -2084,9 +2084,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = self;
|
||||
_ = inst;
|
||||
|
||||
return self.fail("TODO implement switch for {}", .{self.target.cpu.arch});
|
||||
}
|
||||
|
||||
|
||||
@@ -1960,7 +1960,6 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = inst;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst))
|
||||
.dead
|
||||
else
|
||||
@@ -6590,7 +6589,6 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
_ = ty_pl;
|
||||
_ = extra;
|
||||
return self.fail("TODO implement x86 airCmpxchg", .{});
|
||||
// return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });
|
||||
|
||||
@@ -622,7 +622,6 @@ pub fn updateDeclExports(
|
||||
) !void {
|
||||
try self.seeDecl(decl_index);
|
||||
// we do all the things in flush
|
||||
_ = self;
|
||||
_ = module;
|
||||
_ = exports;
|
||||
}
|
||||
|
||||
@@ -324,7 +324,6 @@ const Writer = struct {
|
||||
fn writeNoOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
_ = w;
|
||||
_ = inst;
|
||||
_ = s;
|
||||
// no-op, no argument to write
|
||||
}
|
||||
|
||||
|
||||
@@ -1550,14 +1550,27 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
|
||||
.main_token = try c.addToken(.identifier, "_"),
|
||||
.data = undefined,
|
||||
});
|
||||
return c.addNode(.{
|
||||
.tag = .assign,
|
||||
.main_token = try c.addToken(.equal, "="),
|
||||
.data = .{
|
||||
.lhs = lhs,
|
||||
.rhs = try renderNode(c, payload.value),
|
||||
},
|
||||
});
|
||||
const main_token = try c.addToken(.equal, "=");
|
||||
if (payload.value.tag() == .identifier) {
|
||||
// Render as `_ = @TypeOf(foo);` to avoid tripping "pointless discard" error.
|
||||
return c.addNode(.{
|
||||
.tag = .assign,
|
||||
.main_token = main_token,
|
||||
.data = .{
|
||||
.lhs = lhs,
|
||||
.rhs = try renderBuiltinCall(c, "@TypeOf", &.{payload.value}),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return c.addNode(.{
|
||||
.tag = .assign,
|
||||
.main_token = main_token,
|
||||
.data = .{
|
||||
.lhs = lhs,
|
||||
.rhs = try renderNode(c, payload.value),
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
.@"while" => {
|
||||
const payload = node.castTag(.@"while").?.data;
|
||||
|
||||
25
src/type.zig
25
src/type.zig
@@ -2715,8 +2715,12 @@ pub const Type = extern union {
|
||||
}
|
||||
|
||||
/// Returns 0 if the pointer is naturally aligned and the element type is 0-bit.
|
||||
pub fn ptrAlignment(self: Type, target: Target) u32 {
|
||||
switch (self.tag()) {
|
||||
pub fn ptrAlignment(ty: Type, target: Target) u32 {
|
||||
return ptrAlignmentAdvanced(ty, target, null) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn ptrAlignmentAdvanced(ty: Type, target: Target, sema_kit: ?Module.WipAnalysis) !u32 {
|
||||
switch (ty.tag()) {
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@@ -2728,8 +2732,12 @@ pub const Type = extern union {
|
||||
.optional_single_const_pointer,
|
||||
.optional_single_mut_pointer,
|
||||
=> {
|
||||
const child_type = self.cast(Payload.ElemType).?.data;
|
||||
return child_type.abiAlignment(target);
|
||||
const child_type = ty.cast(Payload.ElemType).?.data;
|
||||
if (sema_kit) |sk| {
|
||||
const res = try child_type.abiAlignmentAdvanced(target, .{ .sema_kit = sk });
|
||||
return res.scalar;
|
||||
}
|
||||
return (child_type.abiAlignmentAdvanced(target, .eager) catch unreachable).scalar;
|
||||
},
|
||||
|
||||
.manyptr_u8,
|
||||
@@ -2740,14 +2748,17 @@ pub const Type = extern union {
|
||||
=> return 1,
|
||||
|
||||
.pointer => {
|
||||
const ptr_info = self.castTag(.pointer).?.data;
|
||||
const ptr_info = ty.castTag(.pointer).?.data;
|
||||
if (ptr_info.@"align" != 0) {
|
||||
return ptr_info.@"align";
|
||||
} else if (sema_kit) |sk| {
|
||||
const res = try ptr_info.pointee_type.abiAlignmentAdvanced(target, .{ .sema_kit = sk });
|
||||
return res.scalar;
|
||||
} else {
|
||||
return ptr_info.pointee_type.abiAlignment(target);
|
||||
return (ptr_info.pointee_type.abiAlignmentAdvanced(target, .eager) catch unreachable).scalar;
|
||||
}
|
||||
},
|
||||
.optional => return self.castTag(.optional).?.data.ptrAlignment(target),
|
||||
.optional => return ty.castTag(.optional).?.data.ptrAlignmentAdvanced(target, sema_kit),
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ test "bytes" {
|
||||
.a = undefined,
|
||||
.c = "12345".*, // this caused problems
|
||||
};
|
||||
_ = s_1;
|
||||
|
||||
var u_2 = U{ .s = s_1 };
|
||||
_ = u_2;
|
||||
@@ -35,7 +34,6 @@ test "aggregate" {
|
||||
.a = undefined,
|
||||
.c = c, // this caused problems
|
||||
};
|
||||
_ = s_1;
|
||||
|
||||
var u_2 = U{ .s = s_1 };
|
||||
_ = u_2;
|
||||
|
||||
@@ -486,7 +486,6 @@ test "Type.Union from Type.Enum" {
|
||||
.decls = &.{},
|
||||
},
|
||||
});
|
||||
_ = T;
|
||||
_ = @typeInfo(T).Union;
|
||||
}
|
||||
|
||||
@@ -505,7 +504,6 @@ test "Type.Union from regular enum" {
|
||||
.decls = &.{},
|
||||
},
|
||||
});
|
||||
_ = T;
|
||||
_ = @typeInfo(T).Union;
|
||||
}
|
||||
|
||||
|
||||
@@ -425,12 +425,8 @@ fn generic2(comptime T: type, param: T, param2: u8) void {
|
||||
_ = param;
|
||||
_ = param2;
|
||||
}
|
||||
fn generic3(param: anytype) @TypeOf(param) {
|
||||
_ = param;
|
||||
}
|
||||
fn generic4(comptime param: anytype) @TypeOf(param) {
|
||||
_ = param;
|
||||
}
|
||||
fn generic3(param: anytype) @TypeOf(param) {}
|
||||
fn generic4(comptime param: anytype) @TypeOf(param) {}
|
||||
|
||||
test "typeInfo with comptime parameter in struct fn def" {
|
||||
const S = struct {
|
||||
|
||||
@@ -6,7 +6,6 @@ export fn entry() void {
|
||||
}
|
||||
|
||||
fn makeLlamas(count: usize) [count]u8 {
|
||||
_ = count;
|
||||
}
|
||||
|
||||
// error
|
||||
|
||||
12
test/cases/compile_errors/pointless discard.zig
Normal file
12
test/cases/compile_errors/pointless discard.zig
Normal file
@@ -0,0 +1,12 @@
|
||||
export fn foo() void {
|
||||
var x: i32 = 1234;
|
||||
x += 1;
|
||||
_ = x;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:9: error: pointless discard of local variable
|
||||
// :3:5: note: used here
|
||||
@@ -1,6 +1,5 @@
|
||||
pub fn main() void {
|
||||
var x: usize = 0;
|
||||
_ = x;
|
||||
const z = @TypeOf(x, @as(u128, 5));
|
||||
assert(z == u128);
|
||||
}
|
||||
|
||||
@@ -116,10 +116,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub export fn foo() void {
|
||||
\\ while (true) if (true) {
|
||||
\\ var a: c_int = 1;
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\ } else {
|
||||
\\ var b: c_int = 2;
|
||||
\\ _ = b;
|
||||
\\ _ = @TypeOf(b);
|
||||
\\ };
|
||||
\\ if (true) if (true) {};
|
||||
\\}
|
||||
@@ -192,7 +192,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ .B = 0,
|
||||
\\ .C = 0,
|
||||
\\ };
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\ {
|
||||
\\ const struct_Foo_1 = extern struct {
|
||||
\\ A: c_int,
|
||||
@@ -204,7 +204,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ .B = 0,
|
||||
\\ .C = 0,
|
||||
\\ };
|
||||
\\ _ = a_2;
|
||||
\\ _ = @TypeOf(a_2);
|
||||
\\ }
|
||||
\\}
|
||||
});
|
||||
@@ -233,24 +233,24 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ B: c_int,
|
||||
\\ C: c_int,
|
||||
\\ };
|
||||
\\ _ = union_unnamed_1;
|
||||
\\ _ = @TypeOf(union_unnamed_1);
|
||||
\\ const Foo = union_unnamed_1;
|
||||
\\ var a: Foo = Foo{
|
||||
\\ .A = @as(c_int, 0),
|
||||
\\ };
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\ {
|
||||
\\ const union_unnamed_2 = extern union {
|
||||
\\ A: c_int,
|
||||
\\ B: c_int,
|
||||
\\ C: c_int,
|
||||
\\ };
|
||||
\\ _ = union_unnamed_2;
|
||||
\\ _ = @TypeOf(union_unnamed_2);
|
||||
\\ const Foo_1 = union_unnamed_2;
|
||||
\\ var a_2: Foo_1 = Foo_1{
|
||||
\\ .A = @as(c_int, 0),
|
||||
\\ };
|
||||
\\ _ = a_2;
|
||||
\\ _ = @TypeOf(a_2);
|
||||
\\ }
|
||||
\\}
|
||||
});
|
||||
@@ -318,7 +318,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ const bar_1 = struct {
|
||||
\\ threadlocal var static: c_int = 2;
|
||||
\\ };
|
||||
\\ _ = bar_1;
|
||||
\\ _ = @TypeOf(bar_1);
|
||||
\\ return 0;
|
||||
\\}
|
||||
});
|
||||
@@ -337,7 +337,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
\\pub export fn bar() c_int {
|
||||
\\ var a: c_int = 2;
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\ return 0;
|
||||
\\}
|
||||
\\pub export fn baz() c_int {
|
||||
@@ -352,7 +352,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
, &[_][]const u8{
|
||||
\\pub export fn main() void {
|
||||
\\ var a: c_int = @bitCast(c_int, @truncate(c_uint, @alignOf(c_int)));
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\}
|
||||
});
|
||||
|
||||
@@ -500,7 +500,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\#define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2))
|
||||
, &[_][]const u8{
|
||||
\\pub const foo = blk: {
|
||||
\\ _ = foo;
|
||||
\\ _ = @TypeOf(foo);
|
||||
\\ break :blk bar;
|
||||
\\};
|
||||
,
|
||||
@@ -724,7 +724,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub export fn function(arg_opaque_1: ?*struct_opaque) void {
|
||||
\\ var opaque_1 = arg_opaque_1;
|
||||
\\ var cast: ?*struct_opaque_2 = @ptrCast(?*struct_opaque_2, opaque_1);
|
||||
\\ _ = cast;
|
||||
\\ _ = @TypeOf(cast);
|
||||
\\}
|
||||
});
|
||||
|
||||
@@ -761,7 +761,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub export fn my_fn() align(128) void {}
|
||||
\\pub export fn other_fn() void {
|
||||
\\ var ARR: [16]u8 align(16) = undefined;
|
||||
\\ _ = ARR;
|
||||
\\ _ = @TypeOf(ARR);
|
||||
\\}
|
||||
});
|
||||
}
|
||||
@@ -798,17 +798,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\ var b: u8 = 123;
|
||||
\\ _ = b;
|
||||
\\ _ = @TypeOf(b);
|
||||
\\ const c: c_int = undefined;
|
||||
\\ _ = c;
|
||||
\\ _ = @TypeOf(c);
|
||||
\\ const d: c_uint = @bitCast(c_uint, @as(c_int, 440));
|
||||
\\ _ = d;
|
||||
\\ _ = @TypeOf(d);
|
||||
\\ var e: c_int = 10;
|
||||
\\ _ = e;
|
||||
\\ _ = @TypeOf(e);
|
||||
\\ var f: c_uint = 10;
|
||||
\\ _ = f;
|
||||
\\ _ = @TypeOf(f);
|
||||
\\}
|
||||
});
|
||||
|
||||
@@ -867,7 +867,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ const v2 = struct {
|
||||
\\ const static: [5:0]u8 = "2.2.2".*;
|
||||
\\ };
|
||||
\\ _ = v2;
|
||||
\\ _ = @TypeOf(v2);
|
||||
\\}
|
||||
});
|
||||
|
||||
@@ -911,7 +911,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub export fn bar() void {
|
||||
\\ var func_ptr: ?*anyopaque = @ptrCast(?*anyopaque, foo);
|
||||
\\ var typed_func_ptr: ?*const fn () callconv(.C) void = @intToPtr(?*const fn () callconv(.C) void, @intCast(c_ulong, @ptrToInt(func_ptr)));
|
||||
\\ _ = typed_func_ptr;
|
||||
\\ _ = @TypeOf(typed_func_ptr);
|
||||
\\}
|
||||
});
|
||||
}
|
||||
@@ -1353,7 +1353,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\}
|
||||
});
|
||||
|
||||
@@ -1524,23 +1524,23 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ var p: ?*anyopaque = undefined;
|
||||
\\ {
|
||||
\\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@import("std").meta.alignment([*c]u8), p));
|
||||
\\ _ = to_char;
|
||||
\\ _ = @TypeOf(to_char);
|
||||
\\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@import("std").meta.alignment([*c]c_short), p));
|
||||
\\ _ = to_short;
|
||||
\\ _ = @TypeOf(to_short);
|
||||
\\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@import("std").meta.alignment([*c]c_int), p));
|
||||
\\ _ = to_int;
|
||||
\\ _ = @TypeOf(to_int);
|
||||
\\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@import("std").meta.alignment([*c]c_longlong), p));
|
||||
\\ _ = to_longlong;
|
||||
\\ _ = @TypeOf(to_longlong);
|
||||
\\ }
|
||||
\\ {
|
||||
\\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@import("std").meta.alignment([*c]u8), p));
|
||||
\\ _ = to_char;
|
||||
\\ _ = @TypeOf(to_char);
|
||||
\\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@import("std").meta.alignment([*c]c_short), p));
|
||||
\\ _ = to_short;
|
||||
\\ _ = @TypeOf(to_short);
|
||||
\\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@import("std").meta.alignment([*c]c_int), p));
|
||||
\\ _ = to_int;
|
||||
\\ _ = @TypeOf(to_int);
|
||||
\\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@import("std").meta.alignment([*c]c_longlong), p));
|
||||
\\ _ = to_longlong;
|
||||
\\ _ = @TypeOf(to_longlong);
|
||||
\\ }
|
||||
\\}
|
||||
});
|
||||
@@ -1786,11 +1786,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ var arr: [10]u8 = [1]u8{
|
||||
\\ 1,
|
||||
\\ } ++ [1]u8{0} ** 9;
|
||||
\\ _ = arr;
|
||||
\\ _ = @TypeOf(arr);
|
||||
\\ var arr1: [10][*c]u8 = [1][*c]u8{
|
||||
\\ null,
|
||||
\\ } ++ [1][*c]u8{null} ** 9;
|
||||
\\ _ = arr1;
|
||||
\\ _ = @TypeOf(arr1);
|
||||
\\}
|
||||
});
|
||||
|
||||
@@ -2038,16 +2038,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub var c: c_int = 4;
|
||||
\\pub export fn foo(arg_c_1: u8) void {
|
||||
\\ var c_1 = arg_c_1;
|
||||
\\ _ = c_1;
|
||||
\\ _ = @TypeOf(c_1);
|
||||
\\ var a_2: c_int = undefined;
|
||||
\\ var b_3: u8 = 123;
|
||||
\\ b_3 = @bitCast(u8, @truncate(i8, a_2));
|
||||
\\ {
|
||||
\\ var d: c_int = 5;
|
||||
\\ _ = d;
|
||||
\\ _ = @TypeOf(d);
|
||||
\\ }
|
||||
\\ var d: c_uint = @bitCast(c_uint, @as(c_int, 440));
|
||||
\\ _ = d;
|
||||
\\ _ = @TypeOf(d);
|
||||
\\}
|
||||
});
|
||||
|
||||
@@ -2146,7 +2146,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ {
|
||||
\\ var i: c_int = 2;
|
||||
\\ var b: c_int = 4;
|
||||
\\ _ = b;
|
||||
\\ _ = @TypeOf(b);
|
||||
\\ while ((i + @as(c_int, 2)) != 0) : (i = 2) {
|
||||
\\ var a: c_int = 2;
|
||||
\\ _ = blk: {
|
||||
@@ -2159,7 +2159,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ }
|
||||
\\ }
|
||||
\\ var i: u8 = 2;
|
||||
\\ _ = i;
|
||||
\\ _ = @TypeOf(i);
|
||||
\\}
|
||||
});
|
||||
|
||||
@@ -2396,27 +2396,27 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
, &[_][]const u8{
|
||||
\\pub export fn escapes() [*c]const u8 {
|
||||
\\ var a: u8 = '\'';
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\ var b: u8 = '\\';
|
||||
\\ _ = b;
|
||||
\\ _ = @TypeOf(b);
|
||||
\\ var c: u8 = '\x07';
|
||||
\\ _ = c;
|
||||
\\ _ = @TypeOf(c);
|
||||
\\ var d: u8 = '\x08';
|
||||
\\ _ = d;
|
||||
\\ _ = @TypeOf(d);
|
||||
\\ var e: u8 = '\x0c';
|
||||
\\ _ = e;
|
||||
\\ _ = @TypeOf(e);
|
||||
\\ var f: u8 = '\n';
|
||||
\\ _ = f;
|
||||
\\ _ = @TypeOf(f);
|
||||
\\ var g: u8 = '\r';
|
||||
\\ _ = g;
|
||||
\\ _ = @TypeOf(g);
|
||||
\\ var h: u8 = '\t';
|
||||
\\ _ = h;
|
||||
\\ _ = @TypeOf(h);
|
||||
\\ var i: u8 = '\x0b';
|
||||
\\ _ = i;
|
||||
\\ _ = @TypeOf(i);
|
||||
\\ var j: u8 = '\x00';
|
||||
\\ _ = j;
|
||||
\\ _ = @TypeOf(j);
|
||||
\\ var k: u8 = '"';
|
||||
\\ _ = k;
|
||||
\\ _ = @TypeOf(k);
|
||||
\\ return "'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
|
||||
\\}
|
||||
});
|
||||
@@ -2612,7 +2612,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub export fn foo() c_int {
|
||||
\\ return blk: {
|
||||
\\ var a: c_int = 1;
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\ break :blk a;
|
||||
\\ };
|
||||
\\}
|
||||
@@ -2716,7 +2716,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\int bar(void) { return 0; }
|
||||
, &[_][]const u8{
|
||||
\\pub inline fn CALL(arg: anytype) @TypeOf(bar()) {
|
||||
\\ _ = arg;
|
||||
\\ _ = @TypeOf(arg);
|
||||
\\ return bar();
|
||||
\\}
|
||||
});
|
||||
@@ -2775,14 +2775,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub export fn foo() void {
|
||||
\\ if (true) {
|
||||
\\ var a: c_int = 2;
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\ }
|
||||
\\ if ((blk: {
|
||||
\\ _ = @as(c_int, 2);
|
||||
\\ break :blk @as(c_int, 5);
|
||||
\\ }) != 0) {
|
||||
\\ var a: c_int = 2;
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\ }
|
||||
\\}
|
||||
});
|
||||
@@ -3285,7 +3285,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\#define a 2
|
||||
, &[_][]const u8{
|
||||
\\pub inline fn FOO(bar: anytype) @TypeOf(baz(@import("std").zig.c_translation.cast(?*anyopaque, baz))) {
|
||||
\\ _ = bar;
|
||||
\\ _ = @TypeOf(bar);
|
||||
\\ return baz(@import("std").zig.c_translation.cast(?*anyopaque, baz));
|
||||
\\}
|
||||
,
|
||||
@@ -3425,7 +3425,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(arg_a: [*c]c_int) void {
|
||||
\\ var a = arg_a;
|
||||
\\ _ = a;
|
||||
\\ _ = @TypeOf(a);
|
||||
\\}
|
||||
\\pub export fn bar(arg_a: [*c]const c_int) void {
|
||||
\\ var a = arg_a;
|
||||
@@ -3785,12 +3785,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub export fn bar(arg_x: c_int, arg_y: c_int) c_int {
|
||||
\\ var x = arg_x;
|
||||
\\ var y = arg_y;
|
||||
\\ _ = y;
|
||||
\\ _ = @TypeOf(y);
|
||||
\\ return x;
|
||||
\\}
|
||||
,
|
||||
\\pub inline fn FOO(A: anytype, B: anytype) @TypeOf(A) {
|
||||
\\ _ = B;
|
||||
\\ _ = @TypeOf(B);
|
||||
\\ return A;
|
||||
\\}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user