From 0bc82a9070b514bf61fb245f906bf03f8e51ce35 Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 23 Nov 2020 03:02:37 +0200 Subject: [PATCH] stage1: validate pointer attributes when coercing anon literals --- src/stage1/ir.cpp | 38 +++++++++++++++++++++++--------------- test/compile_errors.zig | 17 +++++++++++++++++ 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 369886a6b6..7a7e4765ac 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -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); + } } } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 14462b2382..a4297cb854 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -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,