stage1 compile error instead of crashing for unsupported comptime ptr cast

See #955
This commit is contained in:
Andrew Kelley 2018-09-05 15:53:36 -04:00
parent ba7836ea48
commit c87a576cb5
No known key found for this signature in database
GPG Key ID: 4E7CD66038A4D47C
3 changed files with 279 additions and 138 deletions

View File

@ -1587,7 +1587,7 @@ test "pointer casting" {
// operation that Zig cannot protect you against. Use @ptrCast only when other
// conversions are not possible.
const bytes align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12 };
const u32_ptr = @ptrCast(*const u32, &bytes[0]);
const u32_ptr = @ptrCast(*const u32, &bytes);
assert(u32_ptr.* == 0x12121212);
// Even this example is contrived - there are better ways to do the above than

View File

@ -150,8 +150,10 @@ static TypeTableEntry *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruct
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
static TypeTableEntry *adjust_ptr_align(CodeGen *g, TypeTableEntry *ptr_type, uint32_t new_align);
static TypeTableEntry *adjust_slice_align(CodeGen *g, TypeTableEntry *slice_type, uint32_t new_align);
static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_codegen_ptr_type(const_val->type) != nullptr);
assert(const_val->special == ConstValSpecialStatic);
ConstExprValue *result;
@ -181,6 +183,27 @@ ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
return result;
}
static bool types_have_same_zig_comptime_repr(TypeTableEntry *a, TypeTableEntry *b) {
if (a == b)
return true;
if (a->id == b->id)
return true;
if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
return true;
return false;
}
ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
ConstExprValue *result = const_ptr_pointee_unchecked(g, const_val);
if (const_val->type->id == TypeTableEntryIdPointer) {
assert(types_have_same_zig_comptime_repr(const_val->type->data.pointer.child_type, result->type));
}
return result;
}
static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
if (exec->is_inline)
return true;
@ -7602,6 +7625,19 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction,
return ir_add_error_node(ira, source_instruction->source_node, msg);
}
static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) {
ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val);
assert(val != nullptr);
assert(const_val->type->id == TypeTableEntryIdPointer);
TypeTableEntry *expected_type = const_val->type->data.pointer.child_type;
if (!types_have_same_zig_comptime_repr(val->type, expected_type)) {
ir_add_error_node(ira, source_node,
buf_sprintf("TODO handle comptime reinterpreted pointer. See https://github.com/ziglang/zig/issues/955"));
return nullptr;
}
return val;
}
static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
IrBasicBlock *bb = exec->basic_block_list.at(0);
for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
@ -9461,7 +9497,9 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
wanted_type = adjust_ptr_align(ira->codegen, wanted_type, value->value.type->data.pointer.alignment);
if (instr_is_comptime(value)) {
ConstExprValue *pointee = const_ptr_pointee(ira->codegen, &value->value);
ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);
if (pointee == nullptr)
return ira->codegen->invalid_instruction;
if (pointee->special != ConstValSpecialRuntime) {
IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
source_instr->source_node, wanted_type);
@ -9487,7 +9525,9 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
wanted_type = adjust_slice_align(ira->codegen, wanted_type, value->value.type->data.pointer.alignment);
if (instr_is_comptime(value)) {
ConstExprValue *pointee = const_ptr_pointee(ira->codegen, &value->value);
ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);
if (pointee == nullptr)
return ira->codegen->invalid_instruction;
if (pointee->special != ConstValSpecialRuntime) {
assert(value->value.type->id == TypeTableEntryIdPointer);
TypeTableEntry *array_type = value->value.type->data.pointer.child_type;
@ -10458,7 +10498,9 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
return ira->codegen->invalid_instruction;
assert(val->type->id == TypeTableEntryIdPointer);
ConstExprValue *pointee = const_ptr_pointee(ira->codegen, val);
ConstExprValue *pointee = ir_const_ptr_pointee(ira, val, source_instr->source_node);
if (pointee == nullptr)
return ira->codegen->invalid_instruction;
if (pointee->special != ConstValSpecialRuntime) {
ConstExprValue *array_val = create_const_vals(1);
array_val->special = ConstValSpecialStatic;
@ -10773,6 +10815,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
!wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_child_type);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);
}
}
@ -11045,7 +11089,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||
ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
{
ConstExprValue *pointee = const_ptr_pointee(ira->codegen, &ptr->value);
ConstExprValue *pointee = ir_const_ptr_pointee(ira, &ptr->value, source_instruction->source_node);
if (pointee == nullptr)
return ira->codegen->invalid_instruction;
if (pointee->special != ConstValSpecialRuntime) {
IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
source_instruction->source_node, child_type);
@ -13716,7 +13762,39 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
}
}
// out_val->type must be the type to read the pointer as
// if the type is different than the actual type then it does a comptime byte reinterpretation
static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
ConstExprValue *out_val, ConstExprValue *ptr_val)
{
assert(out_val->type != nullptr);
ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr_val);
size_t src_size = type_size(ira->codegen, pointee->type);
size_t dst_size = type_size(ira->codegen, out_val->type);
if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
return ErrorNone;
}
if (dst_size > src_size) {
ir_add_error_node(ira, source_node,
buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
dst_size, buf_ptr(&pointee->type->name), src_size));
return ErrorSemanticAnalyzeFail;
}
Buf buf = BUF_INIT;
buf_resize(&buf, src_size);
buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
return ErrorNone;
}
static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
Error err;
IrInstruction *value = un_op_instruction->value->other;
TypeTableEntry *ptr_type = value->value.type;
@ -13746,12 +13824,11 @@ static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp
if (comptime_value == nullptr)
return ira->codegen->builtin_types.entry_invalid;
ConstExprValue *pointee = const_ptr_pointee(ira->codegen, comptime_value);
if (pointee->type == child_type) {
ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
copy_const_val(out_val, pointee, value->value.data.x_ptr.mut == ConstPtrMutComptimeConst);
return child_type;
}
ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
out_val->type = child_type;
if ((err = ir_read_const_ptr(ira, un_op_instruction->base.source_node, out_val, comptime_value)))
return ira->codegen->builtin_types.entry_invalid;
return child_type;
}
ir_build_load_ptr_from(&ira->new_irb, &un_op_instruction->base, value);
@ -14152,7 +14229,10 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
array_type = array_type->data.pointer.child_type;
ptr_type = ptr_type->data.pointer.child_type;
if (orig_array_ptr_val->special != ConstValSpecialRuntime) {
orig_array_ptr_val = const_ptr_pointee(ira->codegen, orig_array_ptr_val);
orig_array_ptr_val = ir_const_ptr_pointee(ira, orig_array_ptr_val,
elem_ptr_instruction->base.source_node);
if (orig_array_ptr_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
}
}
if (array_type->data.array.len == 0) {
@ -14193,7 +14273,9 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
if (!ptr_val)
return ira->codegen->builtin_types.entry_invalid;
ConstExprValue *args_val = const_ptr_pointee(ira->codegen, ptr_val);
ConstExprValue *args_val = ir_const_ptr_pointee(ira, ptr_val, elem_ptr_instruction->base.source_node);
if (args_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
size_t start = args_val->data.x_arg_tuple.start_index;
size_t end = args_val->data.x_arg_tuple.end_index;
uint64_t elem_index_val;
@ -14269,120 +14351,126 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align);
}
ConstExprValue *array_ptr_val;
if (orig_array_ptr_val->special != ConstValSpecialRuntime &&
(orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == TypeTableEntryIdArray) &&
(array_ptr_val = const_ptr_pointee(ira->codegen, orig_array_ptr_val)) &&
array_ptr_val->special != ConstValSpecialRuntime &&
(array_type->id != TypeTableEntryIdPointer ||
array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
(orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar ||
array_type->id == TypeTableEntryIdArray))
{
if (array_type->id == TypeTableEntryIdPointer) {
ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
out_val->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
size_t new_index;
size_t mem_size;
size_t old_size;
switch (array_ptr_val->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
case ConstPtrSpecialDiscard:
zig_unreachable();
case ConstPtrSpecialRef:
mem_size = 1;
old_size = 1;
new_index = index;
ConstExprValue *array_ptr_val = ir_const_ptr_pointee(ira, orig_array_ptr_val,
elem_ptr_instruction->base.source_node);
if (array_ptr_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.data.ref.pointee = array_ptr_val->data.x_ptr.data.ref.pointee;
break;
case ConstPtrSpecialBaseArray:
{
size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
new_index = offset + index;
mem_size = array_ptr_val->data.x_ptr.data.base_array.array_val->type->data.array.len;
old_size = mem_size - offset;
assert(array_ptr_val->data.x_ptr.data.base_array.array_val);
out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
out_val->data.x_ptr.data.base_array.array_val =
array_ptr_val->data.x_ptr.data.base_array.array_val;
out_val->data.x_ptr.data.base_array.elem_index = new_index;
out_val->data.x_ptr.data.base_array.is_cstr =
array_ptr_val->data.x_ptr.data.base_array.is_cstr;
if (array_ptr_val->special != ConstValSpecialRuntime &&
(array_type->id != TypeTableEntryIdPointer ||
array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
{
if (array_type->id == TypeTableEntryIdPointer) {
ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
out_val->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
size_t new_index;
size_t mem_size;
size_t old_size;
switch (array_ptr_val->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
case ConstPtrSpecialDiscard:
zig_unreachable();
case ConstPtrSpecialRef:
mem_size = 1;
old_size = 1;
new_index = index;
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.data.ref.pointee = array_ptr_val->data.x_ptr.data.ref.pointee;
break;
}
case ConstPtrSpecialBaseStruct:
zig_panic("TODO elem ptr on a const inner struct");
case ConstPtrSpecialHardCodedAddr:
zig_unreachable();
case ConstPtrSpecialFunction:
zig_panic("TODO element ptr of a function casted to a ptr");
}
if (new_index >= mem_size) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index %" ZIG_PRI_u64 " outside pointer of size %" ZIG_PRI_usize "", index, old_size));
return ira->codegen->builtin_types.entry_invalid;
}
return return_type;
} else if (is_slice(array_type)) {
ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];
if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node,
array_ptr, casted_elem_index, false, elem_ptr_instruction->ptr_len);
result->value.type = return_type;
ir_link_new_instruction(result, &elem_ptr_instruction->base);
case ConstPtrSpecialBaseArray:
{
size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
new_index = offset + index;
mem_size = array_ptr_val->data.x_ptr.data.base_array.array_val->type->data.array.len;
old_size = mem_size - offset;
assert(array_ptr_val->data.x_ptr.data.base_array.array_val);
out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
out_val->data.x_ptr.data.base_array.array_val =
array_ptr_val->data.x_ptr.data.base_array.array_val;
out_val->data.x_ptr.data.base_array.elem_index = new_index;
out_val->data.x_ptr.data.base_array.is_cstr =
array_ptr_val->data.x_ptr.data.base_array.is_cstr;
break;
}
case ConstPtrSpecialBaseStruct:
zig_panic("TODO elem ptr on a const inner struct");
case ConstPtrSpecialHardCodedAddr:
zig_unreachable();
case ConstPtrSpecialFunction:
zig_panic("TODO element ptr of a function casted to a ptr");
}
if (new_index >= mem_size) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index %" ZIG_PRI_u64 " outside pointer of size %" ZIG_PRI_usize "", index, old_size));
return ira->codegen->builtin_types.entry_invalid;
}
return return_type;
}
ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];
ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
uint64_t slice_len = bigint_as_unsigned(&len_field->data.x_bigint);
if (index >= slice_len) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,
index, slice_len));
return ira->codegen->builtin_types.entry_invalid;
}
out_val->data.x_ptr.mut = ptr_field->data.x_ptr.mut;
switch (ptr_field->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
case ConstPtrSpecialDiscard:
zig_unreachable();
case ConstPtrSpecialRef:
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee;
break;
case ConstPtrSpecialBaseArray:
{
size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
uint64_t new_index = offset + index;
assert(new_index < ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len);
out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
out_val->data.x_ptr.data.base_array.array_val =
ptr_field->data.x_ptr.data.base_array.array_val;
out_val->data.x_ptr.data.base_array.elem_index = new_index;
out_val->data.x_ptr.data.base_array.is_cstr =
ptr_field->data.x_ptr.data.base_array.is_cstr;
} else if (is_slice(array_type)) {
ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];
if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node,
array_ptr, casted_elem_index, false, elem_ptr_instruction->ptr_len);
result->value.type = return_type;
ir_link_new_instruction(result, &elem_ptr_instruction->base);
return return_type;
}
ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];
ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
uint64_t slice_len = bigint_as_unsigned(&len_field->data.x_bigint);
if (index >= slice_len) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,
index, slice_len));
return ira->codegen->builtin_types.entry_invalid;
}
out_val->data.x_ptr.mut = ptr_field->data.x_ptr.mut;
switch (ptr_field->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
case ConstPtrSpecialDiscard:
zig_unreachable();
case ConstPtrSpecialRef:
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee;
break;
}
case ConstPtrSpecialBaseStruct:
zig_panic("TODO elem ptr on a slice backed by const inner struct");
case ConstPtrSpecialHardCodedAddr:
zig_unreachable();
case ConstPtrSpecialFunction:
zig_panic("TODO elem ptr on a slice that was ptrcast from a function");
case ConstPtrSpecialBaseArray:
{
size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
uint64_t new_index = offset + index;
assert(new_index < ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len);
out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
out_val->data.x_ptr.data.base_array.array_val =
ptr_field->data.x_ptr.data.base_array.array_val;
out_val->data.x_ptr.data.base_array.elem_index = new_index;
out_val->data.x_ptr.data.base_array.is_cstr =
ptr_field->data.x_ptr.data.base_array.is_cstr;
break;
}
case ConstPtrSpecialBaseStruct:
zig_panic("TODO elem ptr on a slice backed by const inner struct");
case ConstPtrSpecialHardCodedAddr:
zig_unreachable();
case ConstPtrSpecialFunction:
zig_panic("TODO elem ptr on a slice that was ptrcast from a function");
}
return return_type;
} else if (array_type->id == TypeTableEntryIdArray) {
ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut;
out_val->data.x_ptr.data.base_array.array_val = array_ptr_val;
out_val->data.x_ptr.data.base_array.elem_index = index;
return return_type;
} else {
zig_unreachable();
}
return return_type;
} else if (array_type->id == TypeTableEntryIdArray) {
ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut;
out_val->data.x_ptr.data.base_array.array_val = array_ptr_val;
out_val->data.x_ptr.data.base_array.elem_index = index;
return return_type;
} else {
zig_unreachable();
}
}
@ -14474,7 +14562,9 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
return ira->codegen->invalid_instruction;
if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
ConstExprValue *struct_val = const_ptr_pointee(ira->codegen, ptr_val);
ConstExprValue *struct_val = ir_const_ptr_pointee(ira, ptr_val, source_instr->source_node);
if (struct_val == nullptr)
return ira->codegen->invalid_instruction;
if (type_is_invalid(struct_val->type))
return ira->codegen->invalid_instruction;
ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];
@ -14516,7 +14606,9 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
return ira->codegen->invalid_instruction;
if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
ConstExprValue *union_val = const_ptr_pointee(ira->codegen, ptr_val);
ConstExprValue *union_val = ir_const_ptr_pointee(ira, ptr_val, source_instr->source_node);
if (union_val == nullptr)
return ira->codegen->invalid_instruction;
if (type_is_invalid(union_val->type))
return ira->codegen->invalid_instruction;
@ -14711,7 +14803,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
return ira->codegen->builtin_types.entry_invalid;
assert(container_ptr->value.type->id == TypeTableEntryIdPointer);
ConstExprValue *child_val = const_ptr_pointee(ira->codegen, container_ptr_val);
ConstExprValue *child_val = ir_const_ptr_pointee(ira, container_ptr_val, source_node);
if (child_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
if (buf_eql_str(field_name, "len")) {
ConstExprValue *len_val = create_const_vals(1);
@ -14735,7 +14829,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
return ira->codegen->builtin_types.entry_invalid;
assert(container_ptr->value.type->id == TypeTableEntryIdPointer);
ConstExprValue *child_val = const_ptr_pointee(ira->codegen, container_ptr_val);
ConstExprValue *child_val = ir_const_ptr_pointee(ira, container_ptr_val, source_node);
if (child_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
TypeTableEntry *child_type = child_val->data.x_type;
if (type_is_invalid(child_type)) {
@ -15003,7 +15099,10 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
if (!container_ptr_val)
return ira->codegen->builtin_types.entry_invalid;
ConstExprValue *namespace_val = const_ptr_pointee(ira->codegen, container_ptr_val);
ConstExprValue *namespace_val = ir_const_ptr_pointee(ira, container_ptr_val,
field_ptr_instruction->base.source_node);
if (namespace_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
assert(namespace_val->special == ConstValSpecialStatic);
ImportTableEntry *namespace_import = namespace_val->data.x_import;
@ -15079,7 +15178,9 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
}
if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
if (instr_is_comptime(casted_value)) {
ConstExprValue *dest_val = const_ptr_pointee(ira->codegen, &ptr->value);
ConstExprValue *dest_val = ir_const_ptr_pointee(ira, &ptr->value, store_ptr_instruction->base.source_node);
if (dest_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
if (dest_val->special != ConstValSpecialRuntime) {
*dest_val = casted_value->value;
if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
@ -15090,7 +15191,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
}
ir_add_error(ira, &store_ptr_instruction->base,
buf_sprintf("cannot store runtime value in compile time variable"));
ConstExprValue *dest_val = const_ptr_pointee(ira->codegen, &ptr->value);
ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
dest_val->type = ira->codegen->builtin_types.entry_invalid;
return ira->codegen->builtin_types.entry_invalid;
@ -15656,7 +15757,9 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
if (!val)
return ira->codegen->builtin_types.entry_invalid;
ConstExprValue *maybe_val = const_ptr_pointee(ira->codegen, val);
ConstExprValue *maybe_val = ir_const_ptr_pointee(ira, val, unwrap_maybe_instruction->base.source_node);
if (maybe_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
if (optional_value_is_null(maybe_val)) {
@ -15947,7 +16050,10 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
TypeTableEntry *target_type = target_value_ptr->value.type->data.pointer.child_type;
ConstExprValue *pointee_val = nullptr;
if (instr_is_comptime(target_value_ptr)) {
pointee_val = const_ptr_pointee(ira->codegen, &target_value_ptr->value);
pointee_val = ir_const_ptr_pointee(ira, &target_value_ptr->value, target_value_ptr->source_node);
if (pointee_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
if (pointee_val->special == ConstValSpecialRuntime)
pointee_val = nullptr;
}
@ -16078,7 +16184,10 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
if (!target_value_ptr)
return ira->codegen->builtin_types.entry_invalid;
ConstExprValue *pointee_val = const_ptr_pointee(ira->codegen, target_val_ptr);
ConstExprValue *pointee_val = ir_const_ptr_pointee(ira, target_val_ptr, instruction->base.source_node);
if (pointee_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.mut = target_val_ptr->data.x_ptr.mut;
@ -18815,19 +18924,30 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
if (array_type->id == TypeTableEntryIdPointer) {
TypeTableEntry *child_array_type = array_type->data.pointer.child_type;
assert(child_array_type->id == TypeTableEntryIdArray);
parent_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value);
array_val = const_ptr_pointee(ira->codegen, parent_ptr);
parent_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
if (parent_ptr == nullptr)
return ira->codegen->builtin_types.entry_invalid;
array_val = ir_const_ptr_pointee(ira, parent_ptr, instruction->base.source_node);
if (array_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
rel_end = child_array_type->data.array.len;
abs_offset = 0;
} else {
array_val = const_ptr_pointee(ira->codegen, &ptr_ptr->value);
array_val = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
if (array_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
rel_end = array_type->data.array.len;
parent_ptr = nullptr;
abs_offset = 0;
}
} else if (array_type->id == TypeTableEntryIdPointer) {
assert(array_type->data.pointer.ptr_len == PtrLenUnknown);
parent_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value);
parent_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
if (parent_ptr == nullptr)
return ira->codegen->builtin_types.entry_invalid;
if (parent_ptr->special == ConstValSpecialUndef) {
array_val = nullptr;
abs_offset = 0;
@ -18858,7 +18978,10 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
zig_panic("TODO slice of ptr cast from function");
}
} else if (is_slice(array_type)) {
ConstExprValue *slice_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value);
ConstExprValue *slice_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
if (slice_ptr == nullptr)
return ira->codegen->builtin_types.entry_invalid;
parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index];
ConstExprValue *len_val = &slice_ptr->data.x_struct.fields[slice_len_index];
@ -19258,7 +19381,9 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
BigInt *op1_bigint = &casted_op1->value.data.x_bigint;
BigInt *op2_bigint = &casted_op2->value.data.x_bigint;
ConstExprValue *pointee_val = const_ptr_pointee(ira->codegen, &casted_result_ptr->value);
ConstExprValue *pointee_val = ir_const_ptr_pointee(ira, &casted_result_ptr->value, casted_result_ptr->source_node);
if (pointee_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
BigInt *dest_bigint = &pointee_val->data.x_bigint;
switch (instruction->op) {
case IrOverflowOpAdd:
@ -19358,7 +19483,9 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
if (!ptr_val)
return ira->codegen->builtin_types.entry_invalid;
ConstExprValue *err_union_val = const_ptr_pointee(ira->codegen, ptr_val);
ConstExprValue *err_union_val = ir_const_ptr_pointee(ira, ptr_val, instruction->base.source_node);
if (err_union_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
if (err_union_val->special != ConstValSpecialRuntime) {
ErrorTableEntry *err = err_union_val->data.x_err_union.err;
assert(err);
@ -19406,7 +19533,9 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
if (!ptr_val)
return ira->codegen->builtin_types.entry_invalid;
ConstExprValue *err_union_val = const_ptr_pointee(ira->codegen, ptr_val);
ConstExprValue *err_union_val = ir_const_ptr_pointee(ira, ptr_val, instruction->base.source_node);
if (err_union_val == nullptr)
return ira->codegen->builtin_types.entry_invalid;
if (err_union_val->special != ConstValSpecialRuntime) {
ErrorTableEntry *err = err_union_val->data.x_err_union.err;
if (err != nullptr) {

View File

@ -1,6 +1,18 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"load too many bytes from comptime reinterpreted pointer",
\\export fn entry() void {
\\ const float: f32 = 5.99999999999994648725e-01;
\\ const float_ptr = &float;
\\ const int_ptr = @ptrCast(*const i64, float_ptr);
\\ const int_val = int_ptr.*;
\\}
,
".tmp_source.zig:5:28: error: attempt to read 8 bytes from pointer to f32 which is 4 bytes",
);
cases.add(
"invalid type used in array type",
\\const Item = struct {