From c0c9d11d8c509fdd1e60492abb1215d9860c3d39 Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Fri, 5 Jun 2020 00:48:36 -0400 Subject: [PATCH] stage1: fix constness in some corner cases - for one-possible-value types, ir_analyze_struct_field_ptr() no longer hardcodes const/volatile - when slicing arrays, ir_analyze_instruction_slice() no longer consults ConstValSpecialStatic closes #5474 --- src/ir.cpp | 8 ++--- test/stage1/behavior.zig | 1 + test/stage1/behavior/bugs/5474.zig | 57 ++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 test/stage1/behavior/bugs/5474.zig diff --git a/src/ir.cpp b/src/ir.cpp index 54442861ca..e1ca01e67e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -21924,7 +21924,9 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins case OnePossibleValueYes: { IrInstGen *elem = ir_const_move(ira, source_instr, get_the_one_possible_value(ira->codegen, field_type)); - return ir_get_ref(ira, source_instr, elem, false, false); + return ir_get_ref(ira, source_instr, elem, + struct_ptr->value->type->data.pointer.is_const, + struct_ptr->value->type->data.pointer.is_volatile); } case OnePossibleValueNo: break; @@ -27097,10 +27099,8 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i if (array_type->id == ZigTypeIdArray) { elem_type = array_type->data.array.child_type; - bool is_comptime_const = ptr_ptr->value->special == ConstValSpecialStatic && - ptr_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst; non_sentinel_slice_ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type, - ptr_ptr_type->data.pointer.is_const || is_comptime_const, + ptr_ptr_type->data.pointer.is_const, ptr_ptr_type->data.pointer.is_volatile, PtrLenUnknown, ptr_ptr_type->data.pointer.explicit_alignment, 0, 0, false); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 2961ffee47..83bd2ddce8 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -50,6 +50,7 @@ comptime { _ = @import("behavior/bugs/4769_b.zig"); _ = @import("behavior/bugs/4769_c.zig"); _ = @import("behavior/bugs/4954.zig"); + _ = @import("behavior/bugs/5474.zig"); _ = @import("behavior/bugs/5487.zig"); _ = @import("behavior/bugs/394.zig"); _ = @import("behavior/bugs/421.zig"); diff --git a/test/stage1/behavior/bugs/5474.zig b/test/stage1/behavior/bugs/5474.zig new file mode 100644 index 0000000000..88ce96095e --- /dev/null +++ b/test/stage1/behavior/bugs/5474.zig @@ -0,0 +1,57 @@ +const std = @import("std"); + +// baseline (control) struct with array of scalar +const Box0 = struct { + items: [4]Item, + + const Item = struct { + num: u32, + }; +}; + +// struct with array of empty struct +const Box1 = struct { + items: [4]Item, + + const Item = struct {}; +}; + +// struct with array of zero-size struct +const Box2 = struct { + items: [4]Item, + + const Item = struct { + nothing: void, + }; +}; + +fn doTest() void { + // var + { + var box0: Box0 = .{ .items = undefined }; + std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == false); + + var box1: Box1 = .{ .items = undefined }; + std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == false); + + var box2: Box2 = .{ .items = undefined }; + std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == false); + } + + // const + { + const box0: Box0 = .{ .items = undefined }; + std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).Pointer.is_const == true); + + const box1: Box1 = .{ .items = undefined }; + std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).Pointer.is_const == true); + + const box2: Box2 = .{ .items = undefined }; + std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).Pointer.is_const == true); + } +} + +test "pointer-to-array constness for zero-size elements" { + doTest(); + comptime doTest(); +}