stage1: validate pointer attributes when coercing anon literals

This commit is contained in:
Vexu 2020-11-23 03:02:37 +02:00 committed by Veikka Tuominen
parent 990eccf282
commit 0bc82a9070
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 40 additions and 15 deletions

View File

@ -15955,38 +15955,46 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
anon_type->data.structure.special == StructSpecialInferredTuple;
const uint32_t field_count = anon_type->data.structure.src_field_count;
if (wanted_type->id == ZigTypeIdPointer) {
if (wanted_type->id == ZigTypeIdPointer &&
(!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
{
ZigType *wanted_child = wanted_type->data.pointer.child_type;
bool const_ok = (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const);
if (wanted_child->id == ZigTypeIdArray && (is_array_init || field_count == 0) &&
wanted_child->data.array.len == field_count)
wanted_child->data.array.len == field_count && (const_ok || field_count == 0))
{
IrInstGen *res = ir_analyze_struct_literal_to_array(ira, source_instr, value, anon_type, wanted_child);
if (res->value->type->id == ZigTypeIdPointer)
return res;
return ir_get_ref(ira, source_instr, res, wanted_type->data.pointer.is_const, wanted_type->data.pointer.is_volatile);
return ir_get_ref(ira, source_instr, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
} else if (wanted_child->id == ZigTypeIdStruct && !is_slice(wanted_type) &&
(!is_array_init || field_count == 0))
(!is_array_init || field_count == 0) && const_ok)
{
IrInstGen *res = ir_analyze_struct_literal_to_struct(ira, source_instr, value, anon_type, wanted_child);
if (res->value->type->id == ZigTypeIdPointer)
return res;
return ir_get_ref(ira, source_instr, res, wanted_type->data.pointer.is_const, wanted_type->data.pointer.is_volatile);
} else if (wanted_child->id == ZigTypeIdUnion && !is_array_init && field_count == 1) {
return ir_get_ref(ira, source_instr, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
} else if (wanted_child->id == ZigTypeIdUnion && !is_array_init && field_count == 1 && const_ok) {
IrInstGen *res = ir_analyze_struct_literal_to_union(ira, source_instr, value, anon_type, wanted_child);
if (res->value->type->id == ZigTypeIdPointer)
return res;
return ir_get_ref(ira, source_instr, res, wanted_type->data.pointer.is_const, wanted_type->data.pointer.is_volatile);
return ir_get_ref(ira, source_instr, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
}
} else if (is_slice(wanted_type) && (is_array_init || field_count == 0)) {
ZigType *slice_child_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.child_type;
ZigType *slice_array_type = get_array_type(ira->codegen, slice_child_type, field_count, nullptr);
IrInstGen *res = ir_analyze_struct_literal_to_array(ira, source_instr, value, anon_type, slice_array_type);
if (type_is_invalid(res->value->type))
return ira->codegen->invalid_inst_gen;
if (res->value->type->id != ZigTypeIdPointer)
res = ir_get_ref(ira, source_instr, res, wanted_type->data.pointer.is_const, wanted_type->data.pointer.is_volatile);
ZigType *slice_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry;
if ((!actual_type->data.pointer.is_const || slice_type->data.pointer.is_const || field_count == 0) &&
(!actual_type->data.pointer.is_volatile || slice_type->data.pointer.is_volatile))
{
ZigType *slice_child_type = slice_type->data.pointer.child_type;
ZigType *slice_array_type = get_array_type(ira->codegen, slice_child_type, field_count, nullptr);
IrInstGen *res = ir_analyze_struct_literal_to_array(ira, source_instr, value, anon_type, slice_array_type);
if (type_is_invalid(res->value->type))
return ira->codegen->invalid_inst_gen;
if (res->value->type->id != ZigTypeIdPointer)
res = ir_get_ref(ira, source_instr, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
return ir_resolve_ptr_of_array_to_slice(ira, source_instr, res, wanted_type, nullptr);
return ir_resolve_ptr_of_array_to_slice(ira, source_instr, res, wanted_type, nullptr);
}
}
}

View File

@ -12,6 +12,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:4:17: error: integer value 1 cannot be coerced to type '*[10]u8'",
});
cases.add("pointer attributes checked when coercing pointer to anon literal",
\\comptime {
\\ const c: [][]const u8 = &.{"hello", "world" };
\\}
\\comptime {
\\ const c: *[2][]const u8 = &.{"hello", "world" };
\\}
\\const S = struct {a: u8 = 1, b: u32 = 2};
\\comptime {
\\ const c: *S = &.{};
\\}
, &[_][]const u8{
"mp.zig:2:31: error: expected type '[][]const u8', found '*const struct:2:31'",
"mp.zig:5:33: error: expected type '*[2][]const u8', found '*const struct:5:33'",
"mp.zig:9:21: error: expected type '*S', found '*const struct:9:21'",
});
cases.add("@Type() union payload is undefined",
\\const Foo = @Type(@import("std").builtin.TypeInfo{
\\ .Struct = undefined,