mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 00:08:56 +00:00
parent
270933b1e9
commit
5699ab5e77
@ -691,15 +691,17 @@ struct AstNodePointerType {
|
||||
AstNode *align_expr;
|
||||
BigInt *bit_offset_start;
|
||||
BigInt *host_int_bytes;
|
||||
AstNode *op_expr;
|
||||
Token *allow_zero_token;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
AstNode *op_expr;
|
||||
};
|
||||
|
||||
struct AstNodeArrayType {
|
||||
AstNode *size;
|
||||
AstNode *child_type;
|
||||
AstNode *align_expr;
|
||||
Token *allow_zero_token;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
};
|
||||
@ -1050,6 +1052,7 @@ struct ZigTypePointer {
|
||||
uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
bool allow_zero;
|
||||
};
|
||||
|
||||
struct ZigTypeInt {
|
||||
@ -1499,11 +1502,12 @@ struct TypeId {
|
||||
struct {
|
||||
ZigType *child_type;
|
||||
PtrLen ptr_len;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
uint32_t alignment;
|
||||
uint32_t bit_offset_in_host;
|
||||
uint32_t host_int_bytes;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
bool allow_zero;
|
||||
} pointer;
|
||||
struct {
|
||||
ZigType *child_type;
|
||||
@ -2592,6 +2596,7 @@ struct IrInstructionPtrType {
|
||||
PtrLen ptr_len;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
bool allow_zero;
|
||||
};
|
||||
|
||||
struct IrInstructionPromiseType {
|
||||
@ -2607,6 +2612,7 @@ struct IrInstructionSliceType {
|
||||
IrInstruction *child_type;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
bool allow_zero;
|
||||
};
|
||||
|
||||
struct IrInstructionAsm {
|
||||
|
||||
@ -433,6 +433,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
|
||||
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
|
||||
uint32_t bit_offset_in_host, uint32_t host_int_bytes)
|
||||
{
|
||||
// TODO when implementing https://github.com/ziglang/zig/issues/1953
|
||||
// move this to a parameter
|
||||
bool allow_zero = (ptr_len == PtrLenC);
|
||||
assert(!type_is_invalid(child_type));
|
||||
assert(ptr_len != PtrLenUnknown || child_type->id != ZigTypeIdOpaque);
|
||||
|
||||
@ -452,7 +455,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
|
||||
|
||||
TypeId type_id = {};
|
||||
ZigType **parent_pointer = nullptr;
|
||||
if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
|
||||
if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) {
|
||||
type_id.id = ZigTypeIdPointer;
|
||||
type_id.data.pointer.child_type = child_type;
|
||||
type_id.data.pointer.is_const = is_const;
|
||||
@ -461,6 +464,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
|
||||
type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
|
||||
type_id.data.pointer.host_int_bytes = host_int_bytes;
|
||||
type_id.data.pointer.ptr_len = ptr_len;
|
||||
type_id.data.pointer.allow_zero = allow_zero;
|
||||
|
||||
auto existing_entry = g->type_table.maybe_get(type_id);
|
||||
if (existing_entry)
|
||||
@ -481,18 +485,28 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
|
||||
const char *star_str = ptr_len_to_star_str(ptr_len);
|
||||
const char *const_str = is_const ? "const " : "";
|
||||
const char *volatile_str = is_volatile ? "volatile " : "";
|
||||
const char *allow_zero_str;
|
||||
if (ptr_len == PtrLenC) {
|
||||
assert(allow_zero);
|
||||
allow_zero_str = "";
|
||||
} else {
|
||||
allow_zero_str = allow_zero ? "allowzero " : "";
|
||||
}
|
||||
buf_resize(&entry->name, 0);
|
||||
if (host_int_bytes == 0 && byte_alignment == 0) {
|
||||
buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
buf_appendf(&entry->name, "%s%s%s%s%s",
|
||||
star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
|
||||
} else if (host_int_bytes == 0) {
|
||||
buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
|
||||
const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
|
||||
const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
|
||||
} else if (byte_alignment == 0) {
|
||||
buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
|
||||
bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,
|
||||
bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
|
||||
buf_ptr(&child_type->name));
|
||||
} else {
|
||||
buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
|
||||
bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
|
||||
bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
|
||||
buf_ptr(&child_type->name));
|
||||
}
|
||||
|
||||
assert(child_type->id != ZigTypeIdInvalid);
|
||||
@ -500,7 +514,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
|
||||
entry->zero_bits = !type_has_bits(child_type);
|
||||
|
||||
if (!entry->zero_bits) {
|
||||
if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || bit_offset_in_host != 0) {
|
||||
if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
|
||||
bit_offset_in_host != 0 || allow_zero)
|
||||
{
|
||||
ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
|
||||
PtrLenSingle, 0, 0, host_int_bytes);
|
||||
entry->type_ref = peer_type->type_ref;
|
||||
@ -534,6 +550,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
|
||||
entry->data.pointer.explicit_alignment = byte_alignment;
|
||||
entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
|
||||
entry->data.pointer.host_int_bytes = host_int_bytes;
|
||||
entry->data.pointer.allow_zero = allow_zero;
|
||||
|
||||
if (parent_pointer) {
|
||||
*parent_pointer = entry;
|
||||
@ -850,7 +867,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
|
||||
|
||||
ZigType *child_type = ptr_type->data.pointer.child_type;
|
||||
if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
|
||||
ptr_type->data.pointer.explicit_alignment != 0)
|
||||
ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
|
||||
{
|
||||
ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
|
||||
PtrLenUnknown, 0, 0, 0);
|
||||
@ -873,7 +890,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
|
||||
ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
assert(child_ptr_type->id == ZigTypeIdPointer);
|
||||
if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
|
||||
child_ptr_type->data.pointer.explicit_alignment != 0)
|
||||
child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero)
|
||||
{
|
||||
ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
|
||||
ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
|
||||
@ -4053,7 +4070,9 @@ ZigType *get_src_ptr_type(ZigType *type) {
|
||||
if (type->id == ZigTypeIdFn) return type;
|
||||
if (type->id == ZigTypeIdPromise) return type;
|
||||
if (type->id == ZigTypeIdOptional) {
|
||||
if (type->data.maybe.child_type->id == ZigTypeIdPointer) return type->data.maybe.child_type;
|
||||
if (type->data.maybe.child_type->id == ZigTypeIdPointer) {
|
||||
return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type;
|
||||
}
|
||||
if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
|
||||
if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;
|
||||
}
|
||||
@ -6289,6 +6308,7 @@ uint32_t type_id_hash(TypeId x) {
|
||||
((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
|
||||
(x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
|
||||
(x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
|
||||
(x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
|
||||
(((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
|
||||
(((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
|
||||
(((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
|
||||
@ -6339,6 +6359,7 @@ bool type_id_eql(TypeId a, TypeId b) {
|
||||
a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
|
||||
a.data.pointer.is_const == b.data.pointer.is_const &&
|
||||
a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
|
||||
a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
|
||||
a.data.pointer.alignment == b.data.pointer.alignment &&
|
||||
a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
|
||||
a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
|
||||
|
||||
99
src/ir.cpp
99
src/ir.cpp
@ -61,7 +61,7 @@ enum ConstCastResultId {
|
||||
ConstCastResultIdType,
|
||||
ConstCastResultIdUnresolvedInferredErrSet,
|
||||
ConstCastResultIdAsyncAllocatorType,
|
||||
ConstCastResultIdNullWrapPtr
|
||||
ConstCastResultIdBadAllowsZero,
|
||||
};
|
||||
|
||||
struct ConstCastOnly;
|
||||
@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;
|
||||
struct ConstCastErrUnionPayloadMismatch;
|
||||
struct ConstCastErrSetMismatch;
|
||||
struct ConstCastTypeMismatch;
|
||||
struct ConstCastBadAllowsZero;
|
||||
|
||||
struct ConstCastOnly {
|
||||
ConstCastResultId id;
|
||||
@ -99,6 +100,7 @@ struct ConstCastOnly {
|
||||
ConstCastOnly *null_wrap_ptr_child;
|
||||
ConstCastArg fn_arg;
|
||||
ConstCastArgNoAlias arg_no_alias;
|
||||
ConstCastBadAllowsZero *bad_allows_zero;
|
||||
} data;
|
||||
};
|
||||
|
||||
@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {
|
||||
ZigList<ErrorTableEntry *> missing_errors;
|
||||
};
|
||||
|
||||
struct ConstCastBadAllowsZero {
|
||||
ZigType *wanted_type;
|
||||
ZigType *actual_type;
|
||||
};
|
||||
|
||||
|
||||
enum UndefAllowed {
|
||||
UndefOk,
|
||||
UndefBad,
|
||||
@ -8636,6 +8644,14 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
|
||||
return err_set_type;
|
||||
}
|
||||
|
||||
static bool ptr_allows_addr_zero(ZigType *ptr_type) {
|
||||
if (ptr_type->id == ZigTypeIdPointer) {
|
||||
return ptr_type->data.pointer.allow_zero;
|
||||
} else if (ptr_type->id == ZigTypeIdOptional) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
|
||||
ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)
|
||||
@ -8649,34 +8665,35 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
|
||||
if (wanted_type == actual_type)
|
||||
return result;
|
||||
|
||||
// *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively
|
||||
// but not if we want a mutable pointer
|
||||
// and not if the actual pointer has zero bits
|
||||
if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional &&
|
||||
wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&
|
||||
actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type))
|
||||
{
|
||||
ConstCastOnly child = types_match_const_cast_only(ira,
|
||||
wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);
|
||||
if (child.id == ConstCastResultIdInvalid)
|
||||
return child;
|
||||
if (child.id != ConstCastResultIdOk) {
|
||||
result.id = ConstCastResultIdNullWrapPtr;
|
||||
result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1);
|
||||
*result.data.null_wrap_ptr_child = child;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// pointer const
|
||||
// If pointers have the same representation in memory, they can be "const-casted".
|
||||
// `const` attribute can be gained
|
||||
// `volatile` attribute can be gained
|
||||
// `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer)
|
||||
// but only if !wanted_is_mutable
|
||||
// alignment can be decreased
|
||||
// bit offset attributes must match exactly
|
||||
// PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
|
||||
ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
|
||||
ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
|
||||
bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
|
||||
bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
|
||||
bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
|
||||
bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
|
||||
if ((wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) ||
|
||||
(wanted_ptr_type != nullptr && actual_is_c_ptr) ||
|
||||
(actual_ptr_type != nullptr && wanted_is_c_ptr))
|
||||
{
|
||||
bool wanted_opt_or_ptr = wanted_ptr_type != nullptr &&
|
||||
(wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional);
|
||||
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<ConstCastBadAllowsZero>(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)
|
||||
@ -8699,6 +8716,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
|
||||
}
|
||||
bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
|
||||
if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
|
||||
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 &&
|
||||
@ -9922,7 +9940,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
|
||||
if (undef_allowed == UndefOk) {
|
||||
return &value->value;
|
||||
} else {
|
||||
ir_add_error(ira, value, buf_sprintf("use of undefined value"));
|
||||
ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior"));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -10828,6 +10846,26 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
|
||||
report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
|
||||
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;
|
||||
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)));
|
||||
} 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)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ConstCastResultIdFnAlign: // TODO
|
||||
case ConstCastResultIdFnCC: // TODO
|
||||
case ConstCastResultIdFnVarArgs: // TODO
|
||||
@ -10838,7 +10876,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
|
||||
case ConstCastResultIdFnArgNoAlias: // TODO
|
||||
case ConstCastResultIdUnresolvedInferredErrSet: // TODO
|
||||
case ConstCastResultIdAsyncAllocatorType: // TODO
|
||||
case ConstCastResultIdNullWrapPtr: // TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -20589,12 +20626,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
|
||||
// We have a check for zero bits later so we use get_src_ptr_type to
|
||||
// validate src_type and dest_type.
|
||||
|
||||
if (get_src_ptr_type(src_type) == nullptr) {
|
||||
ZigType *src_ptr_type = get_src_ptr_type(src_type);
|
||||
if (src_ptr_type == nullptr) {
|
||||
ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
if (get_src_ptr_type(dest_type) == nullptr) {
|
||||
ZigType *dest_ptr_type = get_src_ptr_type(dest_type);
|
||||
if (dest_ptr_type == nullptr) {
|
||||
ir_add_error(ira, dest_type_src,
|
||||
buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
@ -20606,6 +20645,8 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
|
||||
}
|
||||
|
||||
if (instr_is_comptime(ptr)) {
|
||||
// Undefined is OK here; @ptrCast is defined to reinterpret the bit pattern
|
||||
// of the pointer as the new pointer type.
|
||||
ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk);
|
||||
if (!val)
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
@ -1,6 +1,30 @@
|
||||
const tests = @import("tests.zig");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.addTest(
|
||||
"implicit casting C pointers which would mess up null semantics",
|
||||
\\export fn entry() void {
|
||||
\\ var slice: []const u8 = "aoeu";
|
||||
\\ const opt_many_ptr: [*]const u8 = slice.ptr;
|
||||
\\ var ptr_opt_many_ptr = &opt_many_ptr;
|
||||
\\ var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
|
||||
\\ ptr_opt_many_ptr = c_ptr;
|
||||
\\}
|
||||
\\export fn entry2() void {
|
||||
\\ var buf: [4]u8 = "aoeu";
|
||||
\\ var slice: []u8 = &buf;
|
||||
\\ var opt_many_ptr: [*]u8 = slice.ptr;
|
||||
\\ var ptr_opt_many_ptr = &opt_many_ptr;
|
||||
\\ var c_ptr: [*c]const [*c]u8 = ptr_opt_many_ptr;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:24: error: expected type '*const [*]const u8', found '[*c]const [*c]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'",
|
||||
".tmp_source.zig:13:35: note: mutable '[*c]u8' allows illegal null values stored to type '[*]u8'",
|
||||
);
|
||||
|
||||
cases.addTest(
|
||||
"implicit casting too big integers to C pointers",
|
||||
\\export fn a() void {
|
||||
@ -31,7 +55,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ var z = @truncate(u8, u16(undefined));
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:30: error: use of undefined value",
|
||||
".tmp_source.zig:2:30: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.addTest(
|
||||
@ -392,7 +416,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ f(i32);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:4:5: error: use of undefined value",
|
||||
".tmp_source.zig:4:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -792,7 +816,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ command.exec();
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:12: error: use of undefined value",
|
||||
".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -805,7 +829,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ command.exec();
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:12: error: use of undefined value",
|
||||
".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2776,7 +2800,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\
|
||||
\\export fn entry() usize { return @sizeOf(@typeOf(x)); }
|
||||
,
|
||||
".tmp_source.zig:1:15: error: use of undefined value",
|
||||
".tmp_source.zig:1:15: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2786,7 +2810,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a / a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2796,7 +2820,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a /= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2806,7 +2830,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a % a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2816,7 +2840,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a %= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2826,7 +2850,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a + a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2836,7 +2860,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a += a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2846,7 +2870,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a +% a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2856,7 +2880,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a +%= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2866,7 +2890,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a - a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2876,7 +2900,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a -= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2886,7 +2910,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a -% a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2896,7 +2920,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a -%= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2906,7 +2930,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a * a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2916,7 +2940,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a *= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2926,7 +2950,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a *% a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2936,7 +2960,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a *%= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2946,7 +2970,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a << 2;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2956,7 +2980,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a <<= 2;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2966,7 +2990,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a >> 2;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2976,7 +3000,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a >>= 2;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2986,7 +3010,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a & a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2996,7 +3020,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a &= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3006,7 +3030,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a | a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3016,7 +3040,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a |= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3026,7 +3050,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a ^ a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3036,7 +3060,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ a ^= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:5: error: use of undefined value",
|
||||
".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3046,7 +3070,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a == a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3056,7 +3080,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a != a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3066,7 +3090,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a > a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3076,7 +3100,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a >= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3086,7 +3110,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a < a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3096,7 +3120,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a <= a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3106,7 +3130,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a and a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3116,7 +3140,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a or a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:9: error: use of undefined value",
|
||||
".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3126,7 +3150,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = -a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:10: error: use of undefined value",
|
||||
".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3136,7 +3160,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = -%a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:11: error: use of undefined value",
|
||||
".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3146,7 +3170,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = ~a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:10: error: use of undefined value",
|
||||
".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3156,7 +3180,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = !a;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:10: error: use of undefined value",
|
||||
".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3166,7 +3190,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a orelse false;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:11: error: use of undefined value",
|
||||
".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3176,7 +3200,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _ = a catch |err| false;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:3:11: error: use of undefined value",
|
||||
".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user