authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-24 17:02:56-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-24 17:02:56-05:00
logc96d565166a4e63487b43d6d50797b1037c9603c
treed639f53cd61bb26cb9a3c055e2162393d1a287ef
parent4018034708beea63086a34d361ffb400979a1189
signaturelock-open Commit is signed but in an unrecognized format.

add compile error for incompatible pointer sentinels


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

src/ir.cpp+19-9
...@@ -183,6 +183,7 @@ struct ConstCastBadCV {...@@ -183,6 +183,7 @@ struct ConstCastBadCV {
183183
184struct ConstCastPtrSentinel {184struct ConstCastPtrSentinel {
185 ZigType *wanted_type;185 ZigType *wanted_type;
186 ZigType *actual_type;
186};187};
187188
188static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);189static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
...@@ -9898,7 +9899,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9898,7 +9899,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9898 if (!ok_null_term_ptrs) {9899 if (!ok_null_term_ptrs) {
9899 result.id = ConstCastResultIdPtrSentinel;9900 result.id = ConstCastResultIdPtrSentinel;
9900 result.data.bad_ptr_sentinel = allocate_nonzero<ConstCastPtrSentinel>(1);9901 result.data.bad_ptr_sentinel = allocate_nonzero<ConstCastPtrSentinel>(1);
9901 result.data.bad_ptr_sentinel->wanted_type = wanted_type;9902 result.data.bad_ptr_sentinel->wanted_type = wanted_ptr_type;
9903 result.data.bad_ptr_sentinel->actual_type = actual_ptr_type;
9902 return result;9904 return result;
9903 }9905 }
9904 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;9906 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
...@@ -12653,19 +12655,27 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -12653,19 +12655,27 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
12653 break;12655 break;
12654 }12656 }
12655 case ConstCastResultIdPtrSentinel: {12657 case ConstCastResultIdPtrSentinel: {
12658 ZigType *actual_type = cast_result->data.bad_ptr_sentinel->actual_type;
12656 ZigType *wanted_type = cast_result->data.bad_ptr_sentinel->wanted_type;12659 ZigType *wanted_type = cast_result->data.bad_ptr_sentinel->wanted_type;
12657 Buf *msg = buf_sprintf("destination pointer requires a terminating '");12660 {
12658 render_const_value(ira->codegen, msg, wanted_type->data.pointer.sentinel);12661 Buf *txt_msg = buf_sprintf("destination pointer requires a terminating '");
12659 buf_appendf(msg, "' sentinel value");12662 render_const_value(ira->codegen, txt_msg, wanted_type->data.pointer.sentinel);
12660 add_error_note(ira->codegen, parent_msg, source_node, msg);12663 buf_appendf(txt_msg, "' sentinel value");
12664 if (actual_type->data.pointer.sentinel != nullptr) {
12665 buf_appendf(txt_msg, ", but source pointer has a terminating '");
12666 render_const_value(ira->codegen, txt_msg, actual_type->data.pointer.sentinel);
12667 buf_appendf(txt_msg, "' sentinel value");
12668 }
12669 add_error_note(ira->codegen, parent_msg, source_node, txt_msg);
12670 }
12661 break;12671 break;
12662 }12672 }
12663 case ConstCastResultIdSentinelArrays: {12673 case ConstCastResultIdSentinelArrays: {
12664 ZigType *wanted_type = cast_result->data.sentinel_arrays->wanted_type;12674 ZigType *wanted_type = cast_result->data.sentinel_arrays->wanted_type;
12665 Buf *msg = buf_sprintf("destination array requires a terminating '");12675 Buf *txt_msg = buf_sprintf("destination array requires a terminating '");
12666 render_const_value(ira->codegen, msg, wanted_type->data.pointer.sentinel);12676 render_const_value(ira->codegen, txt_msg, wanted_type->data.pointer.sentinel);
12667 buf_appendf(msg, "' sentinel value");12677 buf_appendf(txt_msg, "' sentinel value");
12668 add_error_note(ira->codegen, parent_msg, source_node, msg);12678 add_error_note(ira->codegen, parent_msg, source_node, txt_msg);
12669 break;12679 break;
12670 }12680 }
12671 case ConstCastResultIdCV: {12681 case ConstCastResultIdCV: {
test/compile_errors.zig+15
...@@ -2,6 +2,21 @@ const tests = @import("tests.zig");...@@ -2,6 +2,21 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "incompatible pointer sentinels",
7 \\export fn entry1(ptr: [*:255]u8) [*:0]u8 {
8 \\ return ptr;
9 \\}
10 \\export fn entry2(ptr: [*]u8) [*:0]u8 {
11 \\ return ptr;
12 \\}
13 ,
14 "tmp.zig:2:5: error: expected type '[*:0]u8', found '[*:255]u8'",
15 "tmp.zig:2:5: note: destination pointer requires a terminating '0' sentinel value, but source pointer has a terminating '255' sentinel value",
16 "tmp.zig:5:5: error: expected type '[*:0]u8', found '[*]u8'",
17 "tmp.zig:5:5: note: destination pointer requires a terminating '0' sentinel value",
18 );
19
5 cases.add(20 cases.add(
6 "regression test #2980: base type u32 is not type checked properly when assigning a value within a struct",21 "regression test #2980: base type u32 is not type checked properly when assigning a value within a struct",
7 \\const Foo = struct {22 \\const Foo = struct {