diff --git a/src/all_types.hpp b/src/all_types.hpp index 3e0296c0d6..7d9e0003e9 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -117,6 +117,9 @@ enum ConstPtrSpecial { // emit a binary with a compile time known address. // In this case index is the numeric address value. ConstPtrSpecialHardCodedAddr, + // This means that the pointer represents memory of assigning to _. + // That is, storing discards the data, and loading is invalid. + ConstPtrSpecialDiscard, }; enum ConstPtrMut { diff --git a/src/analyze.cpp b/src/analyze.cpp index 6b864a7947..842ddbdf48 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3091,6 +3091,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { hash_val += 4048518294; hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr); return hash_val; + case ConstPtrSpecialDiscard: + hash_val += 2010123162; + return hash_val; } zig_unreachable(); } @@ -3601,6 +3604,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr) return false; return true; + case ConstPtrSpecialDiscard: + return true; } zig_unreachable(); case TypeTableEntryIdArray: @@ -3785,6 +3790,9 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) { buf_appendf(buf, "(&%s)(%" PRIx64 ")", buf_ptr(&canon_type->data.pointer.child_type->name), const_val->data.x_ptr.data.hard_coded_addr.addr); return; + case ConstPtrSpecialDiscard: + buf_append_str(buf, "&_"); + return; } zig_unreachable(); case TypeTableEntryIdFn: diff --git a/src/codegen.cpp b/src/codegen.cpp index 8fec6a4c51..99e095ffbc 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2928,6 +2928,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { render_const_val_global(g, const_val, ""); switch (const_val->data.x_ptr.special) { case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: zig_unreachable(); case ConstPtrSpecialRef: { diff --git a/src/ir.cpp b/src/ir.cpp index 43040fd7a2..77631f0666 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -77,6 +77,8 @@ ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) { const_val->data.x_ptr.data.base_struct.field_index]; case ConstPtrSpecialHardCodedAddr: zig_unreachable(); + case ConstPtrSpecialDiscard: + zig_unreachable(); } zig_unreachable(); } @@ -3656,6 +3658,15 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, Buf *variable_name = node->data.symbol_expr.symbol; + if (buf_eql_str(variable_name, "_") && lval.is_ptr) { + IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, node); + const_instruction->base.value.type = get_pointer_to_type(irb->codegen, + irb->codegen->builtin_types.entry_void, false); + const_instruction->base.value.special = ConstValSpecialStatic; + const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialDiscard; + return &const_instruction->base; + } + auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); if (primitive_table_entry) { IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value); @@ -8927,6 +8938,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc size_t old_size; switch (array_ptr_val->data.x_ptr.special) { case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: zig_unreachable(); case ConstPtrSpecialRef: mem_size = 1; @@ -8977,6 +8989,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc out_val->data.x_ptr.mut = ptr_field->data.x_ptr.mut; switch (ptr_field->data.x_ptr.special) { case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: zig_unreachable(); case ConstPtrSpecialRef: out_val->data.x_ptr.special = ConstPtrSpecialRef; @@ -9384,6 +9397,10 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru return value->value.type; assert(ptr->value.type->id == TypeTableEntryIdPointer); + if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) { + return ir_analyze_void(ira, &store_ptr_instruction->base); + } + if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) { ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant")); return ira->codegen->builtin_types.entry_invalid; @@ -11365,6 +11382,7 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi size_t bound_end; switch (dest_ptr_val->data.x_ptr.special) { case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: zig_unreachable(); case ConstPtrSpecialRef: dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee; @@ -11455,6 +11473,7 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi size_t dest_end; switch (dest_ptr_val->data.x_ptr.special) { case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: zig_unreachable(); case ConstPtrSpecialRef: dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee; @@ -11487,6 +11506,7 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi switch (src_ptr_val->data.x_ptr.special) { case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: zig_unreachable(); case ConstPtrSpecialRef: src_elements = src_ptr_val->data.x_ptr.data.ref.pointee; @@ -11595,6 +11615,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio parent_ptr = const_ptr_pointee(&ptr_ptr->value); switch (parent_ptr->data.x_ptr.special) { case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: zig_unreachable(); case ConstPtrSpecialRef: array_val = nullptr; @@ -11619,6 +11640,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio switch (parent_ptr->data.x_ptr.special) { case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: zig_unreachable(); case ConstPtrSpecialRef: array_val = nullptr; @@ -11676,6 +11698,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio } else { switch (parent_ptr->data.x_ptr.special) { case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: zig_unreachable(); case ConstPtrSpecialRef: init_const_ptr_ref(ira->codegen, ptr_val, @@ -12302,6 +12325,14 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins instruction_type->id == TypeTableEntryIdUnreachable); instruction->other = instruction; } + if (instruction_type->id != TypeTableEntryIdInvalid && + instruction_type->id != TypeTableEntryIdVoid && + instruction_type->id != TypeTableEntryIdUnreachable && + instruction->ref_count == 0) + { + ir_add_error(ira, instruction, buf_sprintf("return value ignored")); + } + return instruction_type; } diff --git a/std/compiler_rt.zig b/std/compiler_rt.zig index aa6217b493..2e05de9125 100644 --- a/std/compiler_rt.zig +++ b/std/compiler_rt.zig @@ -218,7 +218,7 @@ export fn __umoddi3(a: du_int, b: du_int) -> du_int { @setDebugSafety(this, false); var r: du_int = undefined; - __udivmoddi4(a, b, &r); + _ = __udivmoddi4(a, b, &r); return r; } diff --git a/std/io.zig b/std/io.zig index 8fc2092fcf..73736f0adb 100644 --- a/std/io.zig +++ b/std/io.zig @@ -170,7 +170,7 @@ pub const OutStream = struct { }, State.Integer => switch (c) { '}' => { - self.printInt(args[next_arg], radix, uppercase, width); + %return self.printInt(args[next_arg], radix, uppercase, width); next_arg += 1; state = State.Start; start_index = i + 1; @@ -184,7 +184,7 @@ pub const OutStream = struct { State.IntegerWidth => switch (c) { '}' => { width = comptime %%parseUnsigned(usize, format[width_start...i], 10); - self.printInt(args[next_arg], radix, uppercase, width); + %return self.printInt(args[next_arg], radix, uppercase, width); next_arg += 1; state = State.Start; start_index = i + 1; @@ -194,7 +194,7 @@ pub const OutStream = struct { }, State.Character => switch (c) { '}' => { - self.printAsciiChar(args[next_arg]); + %return self.printAsciiChar(args[next_arg]); next_arg += 1; state = State.Start; start_index = i + 1; diff --git a/std/linux.zig b/std/linux.zig index 4dcd341c3a..5ace0d257d 100644 --- a/std/linux.zig +++ b/std/linux.zig @@ -298,7 +298,7 @@ pub fn lseek(fd: i32, offset: usize, ref_pos: usize) -> usize { } pub fn exit(status: i32) -> unreachable { - arch.syscall1(arch.SYS_exit, usize(status)); + _ = arch.syscall1(arch.SYS_exit, usize(status)); @unreachable() } @@ -325,15 +325,15 @@ pub fn raise(sig: i32) -> i32 { } fn blockAllSignals(set: &sigset_t) { - arch.syscall4(arch.SYS_rt_sigprocmask, SIG_BLOCK, usize(&all_mask), usize(set), NSIG/8); + _ = arch.syscall4(arch.SYS_rt_sigprocmask, SIG_BLOCK, usize(&all_mask), usize(set), NSIG/8); } fn blockAppSignals(set: &sigset_t) { - arch.syscall4(arch.SYS_rt_sigprocmask, SIG_BLOCK, usize(&app_mask), usize(set), NSIG/8); + _ = arch.syscall4(arch.SYS_rt_sigprocmask, SIG_BLOCK, usize(&app_mask), usize(set), NSIG/8); } fn restoreSignals(set: &sigset_t) { - arch.syscall4(arch.SYS_rt_sigprocmask, SIG_SETMASK, usize(set), 0, NSIG/8); + _ = arch.syscall4(arch.SYS_rt_sigprocmask, SIG_SETMASK, usize(set), 0, NSIG/8); } @@ -432,8 +432,8 @@ pub fn shutdown(fd: i32, how: i32) -> usize { arch.syscall2(arch.SYS_shutdown, usize(fd), usize(how)) } -pub fn bind(fd: i32, addr: &const sockaddr, len: socklen_t) { - arch.syscall3(arch.SYS_bind, usize(fd), usize(addr), usize(len)); +pub fn bind(fd: i32, addr: &const sockaddr, len: socklen_t) -> usize { + arch.syscall3(arch.SYS_bind, usize(fd), usize(addr), usize(len)) } pub fn listen(fd: i32, backlog: i32) -> usize { diff --git a/std/os.zig b/std/os.zig index da1b93c3f1..bfb8daecb3 100644 --- a/std/os.zig +++ b/std/os.zig @@ -30,8 +30,8 @@ pub fn getRandomBytes(buf: []u8) -> %void { pub coldcc fn abort() -> unreachable { switch (@compileVar("os")) { Os.linux, Os.darwin => { - system.raise(system.SIGABRT); - system.raise(system.SIGKILL); + _ = system.raise(system.SIGABRT); + _ = system.raise(system.SIGKILL); while (true) {} }, else => @compileError("unsupported os"), diff --git a/test/cases/struct.zig b/test/cases/struct.zig index 8baba81926..9bcd9fd9f6 100644 --- a/test/cases/struct.zig +++ b/test/cases/struct.zig @@ -193,7 +193,7 @@ const EmptyStruct = struct { fn returnEmptyStructFromFn() { @setFnTest(this); - testReturnEmptyStructFromFn(); + _ = testReturnEmptyStructFromFn(); } const EmptyStruct2 = struct {}; fn testReturnEmptyStructFromFn() -> EmptyStruct2 { diff --git a/test/run_tests.cpp b/test/run_tests.cpp index a160abbd9f..418ed4f8d0 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -230,7 +230,7 @@ static void add_compiling_test_cases(void) { add_simple_case_libc("hello world with libc", R"SOURCE( const c = @cImport(@cInclude("stdio.h")); export fn main(argc: c_int, argv: &&u8) -> c_int { - c.puts(c"Hello, world!"); + _ = c.puts(c"Hello, world!"); return 0; } )SOURCE", "Hello, world!" NL); @@ -344,84 +344,84 @@ pub fn main(args: [][]u8) -> %void { const c = @cImport(@cInclude("stdio.h")); export fn main(argc: c_int, argv: &&u8) -> c_int { - c.printf(c"\n"); + _ = c.printf(c"\n"); - c.printf(c"0: %llu\n", + _ = c.printf(c"0: %llu\n", u64(0)); - c.printf(c"320402575052271: %llu\n", + _ = c.printf(c"320402575052271: %llu\n", u64(320402575052271)); - c.printf(c"0x01236789abcdef: %llu\n", + _ = c.printf(c"0x01236789abcdef: %llu\n", u64(0x01236789abcdef)); - c.printf(c"0xffffffffffffffff: %llu\n", + _ = c.printf(c"0xffffffffffffffff: %llu\n", u64(0xffffffffffffffff)); - c.printf(c"0x000000ffffffffffffffff: %llu\n", + _ = c.printf(c"0x000000ffffffffffffffff: %llu\n", u64(0x000000ffffffffffffffff)); - c.printf(c"0o1777777777777777777777: %llu\n", + _ = c.printf(c"0o1777777777777777777777: %llu\n", u64(0o1777777777777777777777)); - c.printf(c"0o0000001777777777777777777777: %llu\n", + _ = c.printf(c"0o0000001777777777777777777777: %llu\n", u64(0o0000001777777777777777777777)); - c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n", + _ = c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n", u64(0b1111111111111111111111111111111111111111111111111111111111111111)); - c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n", + _ = c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n", u64(0b0000001111111111111111111111111111111111111111111111111111111111111111)); - c.printf(c"\n"); + _ = c.printf(c"\n"); - c.printf(c"0.0: %a\n", + _ = c.printf(c"0.0: %a\n", f64(0.0)); - c.printf(c"0e0: %a\n", + _ = c.printf(c"0e0: %a\n", f64(0e0)); - c.printf(c"0.0e0: %a\n", + _ = c.printf(c"0.0e0: %a\n", f64(0.0e0)); - c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n", + _ = c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n", f64(000000000000000000000000000000000000000000000000000000000.0e0)); - c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n", + _ = c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n", f64(0.000000000000000000000000000000000000000000000000000000000e0)); - c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n", + _ = c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n", f64(0.0e000000000000000000000000000000000000000000000000000000000)); - c.printf(c"1.0: %a\n", + _ = c.printf(c"1.0: %a\n", f64(1.0)); - c.printf(c"10.0: %a\n", + _ = c.printf(c"10.0: %a\n", f64(10.0)); - c.printf(c"10.5: %a\n", + _ = c.printf(c"10.5: %a\n", f64(10.5)); - c.printf(c"10.5e5: %a\n", + _ = c.printf(c"10.5e5: %a\n", f64(10.5e5)); - c.printf(c"10.5e+5: %a\n", + _ = c.printf(c"10.5e+5: %a\n", f64(10.5e+5)); - c.printf(c"50.0e-2: %a\n", + _ = c.printf(c"50.0e-2: %a\n", f64(50.0e-2)); - c.printf(c"50e-2: %a\n", + _ = c.printf(c"50e-2: %a\n", f64(50e-2)); - c.printf(c"\n"); + _ = c.printf(c"\n"); - c.printf(c"0x1.0: %a\n", + _ = c.printf(c"0x1.0: %a\n", f64(0x1.0)); - c.printf(c"0x10.0: %a\n", + _ = c.printf(c"0x10.0: %a\n", f64(0x10.0)); - c.printf(c"0x100.0: %a\n", + _ = c.printf(c"0x100.0: %a\n", f64(0x100.0)); - c.printf(c"0x103.0: %a\n", + _ = c.printf(c"0x103.0: %a\n", f64(0x103.0)); - c.printf(c"0x103.7: %a\n", + _ = c.printf(c"0x103.7: %a\n", f64(0x103.7)); - c.printf(c"0x103.70: %a\n", + _ = c.printf(c"0x103.70: %a\n", f64(0x103.70)); - c.printf(c"0x103.70p4: %a\n", + _ = c.printf(c"0x103.70p4: %a\n", f64(0x103.70p4)); - c.printf(c"0x103.70p5: %a\n", + _ = c.printf(c"0x103.70p5: %a\n", f64(0x103.70p5)); - c.printf(c"0x103.70p+5: %a\n", + _ = c.printf(c"0x103.70p+5: %a\n", f64(0x103.70p+5)); - c.printf(c"0x103.70p-5: %a\n", + _ = c.printf(c"0x103.70p-5: %a\n", f64(0x103.70p-5)); - c.printf(c"\n"); + _ = c.printf(c"\n"); - c.printf(c"0b10100.00010e0: %a\n", + _ = c.printf(c"0b10100.00010e0: %a\n", f64(0b10100.00010e0)); - c.printf(c"0o10700.00010e0: %a\n", + _ = c.printf(c"0o10700.00010e0: %a\n", f64(0o10700.00010e0)); return 0; @@ -520,7 +520,7 @@ export fn main(argc: c_int, argv: &&u8) -> c_int { const x: f64 = small; const y = i32(x); const z = f64(y); - c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, f64(-0.4)); + _ = c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, f64(-0.4)); return 0; } )SOURCE", "3.25\n3\n3.00\n-0.40\n"); @@ -1691,6 +1691,12 @@ fn bar() { } ".tmp_source.zig:4:5: error: control flow attempts to use compile-time variable at runtime", ".tmp_source.zig:4:21: note: compile-time variable assigned here"); + add_compile_fail_case("ignored return value", R"SOURCE( +fn foo() { + bar(); +} +fn bar() -> i32 { 0 } + )SOURCE", 1, ".tmp_source.zig:3:8: error: return value ignored"); } //////////////////////////////////////////////////////////////////////////////