diff --git a/src/ir.cpp b/src/ir.cpp index dfbc36e02c..89528db185 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8683,16 +8683,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted bool actual_opt_or_ptr = actual_ptr_type != nullptr && (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional); if (wanted_opt_or_ptr && actual_opt_or_ptr) { - bool ok_allows_zero = (wanted_allows_zero && - (actual_allows_zero || wanted_ptr_type->data.pointer.is_const)) || - (!wanted_allows_zero && !actual_allows_zero); - if (!ok_allows_zero) { - result.id = ConstCastResultIdBadAllowsZero; - result.data.bad_allows_zero = allocate_nonzero(1); - result.data.bad_allows_zero->wanted_type = wanted_type; - result.data.bad_allows_zero->actual_type = actual_type; - return result; - } ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type, actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const); if (child.id == ConstCastResultIdInvalid) @@ -8705,6 +8695,16 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type; return result; } + bool ok_allows_zero = (wanted_allows_zero && + (actual_allows_zero || wanted_ptr_type->data.pointer.is_const)) || + (!wanted_allows_zero && !actual_allows_zero); + if (!ok_allows_zero) { + result.id = ConstCastResultIdBadAllowsZero; + result.data.bad_allows_zero = allocate_nonzero(1); + result.data.bad_allows_zero->wanted_type = wanted_type; + result.data.bad_allows_zero->actual_type = actual_type; + return result; + } if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { result.id = ConstCastResultIdInvalid; return result; @@ -10846,22 +10846,20 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa break; } case ConstCastResultIdBadAllowsZero: { - bool wanted_allows_zero = ptr_allows_addr_zero(cast_result->data.bad_allows_zero->wanted_type); - bool actual_allows_zero = ptr_allows_addr_zero(cast_result->data.bad_allows_zero->actual_type); - ZigType *wanted_ptr_type = get_src_ptr_type(cast_result->data.bad_allows_zero->wanted_type); - ZigType *actual_ptr_type = get_src_ptr_type(cast_result->data.bad_allows_zero->actual_type); - ZigType *wanted_elem_type = wanted_ptr_type->data.pointer.child_type; - ZigType *actual_elem_type = actual_ptr_type->data.pointer.child_type; + ZigType *wanted_type = cast_result->data.bad_allows_zero->wanted_type; + ZigType *actual_type = cast_result->data.bad_allows_zero->actual_type; + bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type); + bool actual_allows_zero = ptr_allows_addr_zero(actual_type); if (actual_allows_zero && !wanted_allows_zero) { add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("'%s' could have null values which are illegal in type '%s'", - buf_ptr(&actual_elem_type->name), - buf_ptr(&wanted_elem_type->name))); + buf_ptr(&actual_type->name), + buf_ptr(&wanted_type->name))); } else { add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("mutable '%s' allows illegal null values stored to type '%s'", - buf_ptr(&cast_result->data.bad_allows_zero->wanted_type->name), - buf_ptr(&cast_result->data.bad_allows_zero->actual_type->name))); + buf_ptr(&wanted_type->name), + buf_ptr(&actual_type->name))); } break; } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 71ee4901ff..630386aa4f 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,42 @@ const tests = @import("tests.zig"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.addTest( + "implicit cast between C pointer and Zig pointer - bad const/align/child", + \\export fn a() void { + \\ var x: [*c]u8 = undefined; + \\ var y: *align(4) u8 = x; + \\} + \\export fn b() void { + \\ var x: [*c]const u8 = undefined; + \\ var y: *u8 = x; + \\} + \\export fn c() void { + \\ var x: [*c]u8 = undefined; + \\ var y: *u32 = x; + \\} + \\export fn d() void { + \\ var y: *align(1) u32 = undefined; + \\ var x: [*c]u32 = y; + \\} + \\export fn e() void { + \\ var y: *const u8 = undefined; + \\ var x: [*c]u8 = y; + \\} + \\export fn f() void { + \\ var y: *u8 = undefined; + \\ var x: [*c]u32 = y; + \\} + , + ".tmp_source.zig:3:27: error: cast increases pointer alignment", + ".tmp_source.zig:7:18: error: cast discards const qualifier", + ".tmp_source.zig:11:19: error: expected type '*u32', found '[*c]u8'", + ".tmp_source.zig:11:19: note: pointer type child 'u8' cannot cast into pointer type child 'u32'", + ".tmp_source.zig:15:22: error: cast increases pointer alignment", + ".tmp_source.zig:19:21: error: cast discards const qualifier", + ".tmp_source.zig:23:22: error: expected type '[*c]u32', found '*u8'", + ); + cases.addTest( "implicit casting null c pointer to zig pointer", \\comptime { @@ -39,6 +75,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\} , ".tmp_source.zig:6:24: error: expected type '*const [*]const u8', found '[*c]const [*c]const u8'", + ".tmp_source.zig:6:24: note: pointer type child '[*c]const u8' cannot cast into pointer type child '[*]const u8'", ".tmp_source.zig:6:24: note: '[*c]const u8' could have null values which are illegal in type '[*]const u8'", ".tmp_source.zig:13:35: error: expected type '[*c]const [*c]u8', found '*[*]u8'", ".tmp_source.zig:13:35: note: pointer type child '[*]u8' cannot cast into pointer type child '[*c]u8'",