authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-14 00:40:39-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-14 00:40:39-05:00
logd4d2718bca9e23ceec029bb505c0ea1b91c875b6
treec2b7b61f36fff694f5ff030fde50846b23c690cd
parent5699ab5e77f8d13cac1e34775e6e51358119965c
signaturelock-open Commit is signed but in an unrecognized format.

comptime detection of casting null to pointer

See #1059

2 files changed, 34 insertions(+), 3 deletions(-)

src/ir.cpp+14-3
...@@ -20645,12 +20645,23 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20645,12 +20645,23 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20645 }20645 }
2064620646
20647 if (instr_is_comptime(ptr)) {20647 if (instr_is_comptime(ptr)) {
20648 // Undefined is OK here; @ptrCast is defined to reinterpret the bit pattern20648 bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type);
20649 // of the pointer as the new pointer type.20649 UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad;
20650 ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk);20650 ConstExprValue *val = ir_resolve_const(ira, ptr, is_undef_allowed);
20651 if (!val)20651 if (!val)
20652 return ira->codegen->invalid_instruction;20652 return ira->codegen->invalid_instruction;
2065320653
20654 if (val->special == ConstValSpecialStatic) {
20655 bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull ||
20656 (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
20657 val->data.x_ptr.data.hard_coded_addr.addr == 0);
20658 if (is_addr_zero && !dest_allows_addr_zero) {
20659 ir_add_error(ira, source_instr,
20660 buf_sprintf("null pointer casted to type '%s'", buf_ptr(&dest_type->name)));
20661 return ira->codegen->invalid_instruction;
20662 }
20663 }
20664
20654 IrInstruction *result = ir_const(ira, source_instr, dest_type);20665 IrInstruction *result = ir_const(ira, source_instr, dest_type);
20655 copy_const_val(&result->value, val, false);20666 copy_const_val(&result->value, val, false);
20656 result->value.type = dest_type;20667 result->value.type = dest_type;
test/compile_errors.zig+20
...@@ -1,6 +1,26 @@...@@ -1,6 +1,26 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompileErrorContext) void {3pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.addTest(
5 "implicit casting null c pointer to zig pointer",
6 \\comptime {
7 \\ var c_ptr: [*c]u8 = 0;
8 \\ var zig_ptr: *u8 = c_ptr;
9 \\}
10 ,
11 ".tmp_source.zig:3:24: error: null pointer casted to type '*u8'",
12 );
13
14 cases.addTest(
15 "implicit casting undefined c pointer to zig pointer",
16 \\comptime {
17 \\ var c_ptr: [*c]u8 = undefined;
18 \\ var zig_ptr: *u8 = c_ptr;
19 \\}
20 ,
21 ".tmp_source.zig:3:24: error: use of undefined value here causes undefined behavior",
22 );
23
4 cases.addTest(24 cases.addTest(
5 "implicit casting C pointers which would mess up null semantics",25 "implicit casting C pointers which would mess up null semantics",
6 \\export fn entry() void {26 \\export fn entry() void {