better error message when null termination does not match

master
Andrew Kelley 2019-11-19 23:24:33 -05:00
parent 47f06be369
commit cf2fe2536e
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
2 changed files with 33 additions and 7 deletions

View File

@ -63,7 +63,7 @@ pub extern "c" fn fclose(stream: *FILE) c_int;
pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
pub extern "c" fn printf(format: [*]const u8, ...) c_int;
pub extern "c" fn printf(format: [*]null const u8, ...) c_int;
pub extern "c" fn abort() noreturn;
pub extern "c" fn exit(code: c_int) noreturn;
pub extern "c" fn isatty(fd: fd_t) c_int;

View File

@ -68,6 +68,7 @@ enum ConstCastResultId {
ConstCastResultIdBadAllowsZero,
ConstCastResultIdArrayChild,
ConstCastResultIdBadNullTermArrays,
ConstCastResultIdPtrLens,
};
struct ConstCastOnly;
@ -92,6 +93,7 @@ struct ConstCastTypeMismatch;
struct ConstCastArrayMismatch;
struct ConstCastBadAllowsZero;
struct ConstCastBadNullTermArrays;
struct ConstCastBadPtrLens;
struct ConstCastOnly {
ConstCastResultId id;
@ -110,6 +112,7 @@ struct ConstCastOnly {
ConstCastArgNoAlias arg_no_alias;
ConstCastBadAllowsZero *bad_allows_zero;
ConstCastBadNullTermArrays *bad_null_term_arrays;
ConstCastBadPtrLens *bad_ptr_lens;
} data;
};
@ -169,6 +172,11 @@ struct ConstCastBadNullTermArrays {
ZigType *actual_type;
};
struct ConstCastBadPtrLens {
ZigType *wanted_type;
ZigType *actual_type;
};
static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
@ -9843,6 +9851,18 @@ 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 ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
bool ok_null_term_ptrs =
actual_ptr_type->data.pointer.ptr_len == PtrLenNull ||
wanted_ptr_type->data.pointer.ptr_len == PtrLenUnknown;
if (!(ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr || ok_null_term_ptrs)) {
result.id = ConstCastResultIdPtrLens;
result.data.bad_ptr_lens = allocate_nonzero<ConstCastBadPtrLens>(1);
result.data.bad_ptr_lens->wanted_type = wanted_type;
result.data.bad_ptr_lens->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)
@ -9881,12 +9901,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
result.id = ConstCastResultIdInvalid;
return result;
}
bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
bool ok_null_term_ptrs =
actual_ptr_type->data.pointer.ptr_len == PtrLenNull ||
wanted_ptr_type->data.pointer.ptr_len == PtrLenUnknown;
if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr || ok_null_term_ptrs) &&
type_has_bits(wanted_type) == type_has_bits(actual_type) &&
if (type_has_bits(wanted_type) == type_has_bits(actual_type) &&
(!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
(!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
@ -12569,6 +12584,17 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
}
break;
}
case ConstCastResultIdPtrLens: {
ZigType *wanted_type = cast_result->data.bad_ptr_lens->wanted_type;
ZigType *actual_type = cast_result->data.bad_ptr_lens->actual_type;
bool wanted_null_term = wanted_type->data.pointer.ptr_len == PtrLenNull;
bool actual_null_term = actual_type->data.pointer.ptr_len == PtrLenNull;
if (wanted_null_term && !actual_null_term) {
add_error_note(ira->codegen, parent_msg, source_node,
buf_sprintf("destination type requires null termination"));
}
break;
}
case ConstCastResultIdFnIsGeneric:
add_error_note(ira->codegen, parent_msg, source_node,
buf_sprintf("only one of the functions is generic"));