| author | |
| committer | |
| log | e53b683bd3958a7b1c517e2391edce42b9d4e48b |
| tree | c9b8aacf92b2140c1cc076e2de280e10657d0a98 |
| parent | 32e0dfd4f0dab351a024e7680280343db5d7c43e |
| signature |
* enable slicing for single-item ptr to arrays
* disable slicing for other single-item pointers
* enable indexing for single-item ptr to arrays
* disable indexing for other single-item pointers
see #770
closes #38621 files changed, 268 insertions(+), 79 deletions(-)
doc/langref.html.in+8-5| ... | @@ -1565,7 +1565,7 @@ var foo: u8 align(4) = 100; | ... | @@ -1565,7 +1565,7 @@ var foo: u8 align(4) = 100; |
| 1565 | test "global variable alignment" { | 1565 | test "global variable alignment" { |
| 1566 | assert(@typeOf(&foo).alignment == 4); | 1566 | assert(@typeOf(&foo).alignment == 4); |
| 1567 | assert(@typeOf(&foo) == *align(4) u8); | 1567 | assert(@typeOf(&foo) == *align(4) u8); |
| 1568 | const slice = (&foo)[0..1]; | 1568 | const slice = (*[1]u8)(&foo)[0..]; |
| 1569 | assert(@typeOf(slice) == []align(4) u8); | 1569 | assert(@typeOf(slice) == []align(4) u8); |
| 1570 | } | 1570 | } |
| 1571 | 1571 | ||
| ... | @@ -1671,7 +1671,7 @@ test "using slices for strings" { | ... | @@ -1671,7 +1671,7 @@ test "using slices for strings" { |
| 1671 | 1671 | ||
| 1672 | test "slice pointer" { | 1672 | test "slice pointer" { |
| 1673 | var array: [10]u8 = undefined; | 1673 | var array: [10]u8 = undefined; |
| 1674 | const ptr = &array[0]; | 1674 | const ptr = &array; |
| 1675 | 1675 | ||
| 1676 | // You can use slicing syntax to convert a pointer into a slice: | 1676 | // You can use slicing syntax to convert a pointer into a slice: |
| 1677 | const slice = ptr[0..5]; | 1677 | const slice = ptr[0..5]; |
| ... | @@ -6004,9 +6004,12 @@ const c = @cImport({ | ... | @@ -6004,9 +6004,12 @@ const c = @cImport({ |
| 6004 | {#code_begin|syntax#} | 6004 | {#code_begin|syntax#} |
| 6005 | const base64 = @import("std").base64; | 6005 | const base64 = @import("std").base64; |
| 6006 | 6006 | ||
| 6007 | export fn decode_base_64(dest_ptr: *u8, dest_len: usize, | 6007 | export fn decode_base_64( |
| 6008 | source_ptr: *const u8, source_len: usize) usize | 6008 | dest_ptr: [*]u8, |
| 6009 | { | 6009 | dest_len: usize, |
| 6010 | source_ptr: [*]const u8, | ||
| 6011 | source_len: usize, | ||
| 6012 | ) usize { | ||
| 6010 | const src = source_ptr[0..source_len]; | 6013 | const src = source_ptr[0..source_len]; |
| 6011 | const dest = dest_ptr[0..dest_len]; | 6014 | const dest = dest_ptr[0..dest_len]; |
| 6012 | const base64_decoder = base64.standard_decoder_unsafe; | 6015 | const base64_decoder = base64.standard_decoder_unsafe; |
example/mix_o_files/base64.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const base64 = @import("std").base64; | 1 | const base64 = @import("std").base64; |
| 2 | 2 | ||
| 3 | export fn decode_base_64(dest_ptr: *u8, dest_len: usize, source_ptr: *const u8, source_len: usize) usize { | 3 | export fn decode_base_64(dest_ptr: [*]u8, dest_len: usize, source_ptr: [*]const u8, source_len: usize) usize { |
| 4 | const src = source_ptr[0..source_len]; | 4 | const src = source_ptr[0..source_len]; |
| 5 | const dest = dest_ptr[0..dest_len]; | 5 | const dest = dest_ptr[0..dest_len]; |
| 6 | const base64_decoder = base64.standard_decoder_unsafe; | 6 | const base64_decoder = base64.standard_decoder_unsafe; |
src/all_types.hpp+5| ... | @@ -83,6 +83,7 @@ enum ConstParentId { | ... | @@ -83,6 +83,7 @@ enum ConstParentId { |
| 83 | ConstParentIdStruct, | 83 | ConstParentIdStruct, |
| 84 | ConstParentIdArray, | 84 | ConstParentIdArray, |
| 85 | ConstParentIdUnion, | 85 | ConstParentIdUnion, |
| 86 | ConstParentIdScalar, | ||
| 86 | }; | 87 | }; |
| 87 | 88 | ||
| 88 | struct ConstParent { | 89 | struct ConstParent { |
| ... | @@ -100,6 +101,9 @@ struct ConstParent { | ... | @@ -100,6 +101,9 @@ struct ConstParent { |
| 100 | struct { | 101 | struct { |
| 101 | ConstExprValue *union_val; | 102 | ConstExprValue *union_val; |
| 102 | } p_union; | 103 | } p_union; |
| 104 | struct { | ||
| 105 | ConstExprValue *scalar_val; | ||
| 106 | } p_scalar; | ||
| 103 | } data; | 107 | } data; |
| 104 | }; | 108 | }; |
| 105 | 109 | ||
| ... | @@ -578,6 +582,7 @@ enum CastOp { | ... | @@ -578,6 +582,7 @@ enum CastOp { |
| 578 | CastOpBytesToSlice, | 582 | CastOpBytesToSlice, |
| 579 | CastOpNumLitToConcrete, | 583 | CastOpNumLitToConcrete, |
| 580 | CastOpErrSet, | 584 | CastOpErrSet, |
| 585 | CastOpBitCast, | ||
| 581 | }; | 586 | }; |
| 582 | 587 | ||
| 583 | struct AstNodeFnCallExpr { | 588 | struct AstNodeFnCallExpr { |
src/analyze.cpp+9-5| ... | @@ -5158,7 +5158,8 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr | ... | @@ -5158,7 +5158,8 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr |
| 5158 | const_val->type = get_slice_type(g, ptr_type); | 5158 | const_val->type = get_slice_type(g, ptr_type); |
| 5159 | const_val->data.x_struct.fields = create_const_vals(2); | 5159 | const_val->data.x_struct.fields = create_const_vals(2); |
| 5160 | 5160 | ||
| 5161 | init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const); | 5161 | init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const, |
| 5162 | PtrLenUnknown); | ||
| 5162 | init_const_usize(g, &const_val->data.x_struct.fields[slice_len_index], len); | 5163 | init_const_usize(g, &const_val->data.x_struct.fields[slice_len_index], len); |
| 5163 | } | 5164 | } |
| 5164 | 5165 | ||
| ... | @@ -5169,21 +5170,24 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t | ... | @@ -5169,21 +5170,24 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t |
| 5169 | } | 5170 | } |
| 5170 | 5171 | ||
| 5171 | void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val, | 5172 | void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val, |
| 5172 | size_t elem_index, bool is_const) | 5173 | size_t elem_index, bool is_const, PtrLen ptr_len) |
| 5173 | { | 5174 | { |
| 5174 | assert(array_val->type->id == TypeTableEntryIdArray); | 5175 | assert(array_val->type->id == TypeTableEntryIdArray); |
| 5175 | TypeTableEntry *child_type = array_val->type->data.array.child_type; | 5176 | TypeTableEntry *child_type = array_val->type->data.array.child_type; |
| 5176 | 5177 | ||
| 5177 | const_val->special = ConstValSpecialStatic; | 5178 | const_val->special = ConstValSpecialStatic; |
| 5178 | const_val->type = get_pointer_to_type(g, child_type, is_const); | 5179 | const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false, |
| 5180 | ptr_len, get_abi_alignment(g, child_type), 0, 0); | ||
| 5179 | const_val->data.x_ptr.special = ConstPtrSpecialBaseArray; | 5181 | const_val->data.x_ptr.special = ConstPtrSpecialBaseArray; |
| 5180 | const_val->data.x_ptr.data.base_array.array_val = array_val; | 5182 | const_val->data.x_ptr.data.base_array.array_val = array_val; |
| 5181 | const_val->data.x_ptr.data.base_array.elem_index = elem_index; | 5183 | const_val->data.x_ptr.data.base_array.elem_index = elem_index; |
| 5182 | } | 5184 | } |
| 5183 | 5185 | ||
| 5184 | ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const) { | 5186 | ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const, |
| 5187 | PtrLen ptr_len) | ||
| 5188 | { | ||
| 5185 | ConstExprValue *const_val = create_const_vals(1); | 5189 | ConstExprValue *const_val = create_const_vals(1); |
| 5186 | init_const_ptr_array(g, const_val, array_val, elem_index, is_const); | 5190 | init_const_ptr_array(g, const_val, array_val, elem_index, is_const, ptr_len); |
| 5187 | return const_val; | 5191 | return const_val; |
| 5188 | } | 5192 | } |
| 5189 | 5193 |
src/analyze.hpp+3-2| ... | @@ -152,8 +152,9 @@ ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *poi | ... | @@ -152,8 +152,9 @@ ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *poi |
| 152 | size_t addr, bool is_const); | 152 | size_t addr, bool is_const); |
| 153 | 153 | ||
| 154 | void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val, | 154 | void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val, |
| 155 | size_t elem_index, bool is_const); | 155 | size_t elem_index, bool is_const, PtrLen ptr_len); |
| 156 | ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const); | 156 | ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, |
| 157 | bool is_const, PtrLen ptr_len); | ||
| 157 | 158 | ||
| 158 | void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val, | 159 | void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val, |
| 159 | size_t start, size_t len, bool is_const); | 160 | size_t start, size_t len, bool is_const); |
src/codegen.cpp+23-4| ... | @@ -2574,6 +2574,8 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, | ... | @@ -2574,6 +2574,8 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2574 | add_error_range_check(g, wanted_type, g->err_tag_type, expr_val); | 2574 | add_error_range_check(g, wanted_type, g->err_tag_type, expr_val); |
| 2575 | } | 2575 | } |
| 2576 | return expr_val; | 2576 | return expr_val; |
| 2577 | case CastOpBitCast: | ||
| 2578 | return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, ""); | ||
| 2577 | } | 2579 | } |
| 2578 | zig_unreachable(); | 2580 | zig_unreachable(); |
| 2579 | } | 2581 | } |
| ... | @@ -2884,7 +2886,13 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -2884,7 +2886,13 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 2884 | 2886 | ||
| 2885 | bool safety_check_on = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on; | 2887 | bool safety_check_on = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on; |
| 2886 | 2888 | ||
| 2887 | if (array_type->id == TypeTableEntryIdArray) { | 2889 | if (array_type->id == TypeTableEntryIdArray || |
| 2890 | (array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle)) | ||
| 2891 | { | ||
| 2892 | if (array_type->id == TypeTableEntryIdPointer) { | ||
| 2893 | assert(array_type->data.pointer.child_type->id == TypeTableEntryIdArray); | ||
| 2894 | array_type = array_type->data.pointer.child_type; | ||
| 2895 | } | ||
| 2888 | if (safety_check_on) { | 2896 | if (safety_check_on) { |
| 2889 | LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref, | 2897 | LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 2890 | array_type->data.array.len, false); | 2898 | array_type->data.array.len, false); |
| ... | @@ -3794,7 +3802,12 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst | ... | @@ -3794,7 +3802,12 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 3794 | 3802 | ||
| 3795 | bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base); | 3803 | bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base); |
| 3796 | 3804 | ||
| 3797 | if (array_type->id == TypeTableEntryIdArray) { | 3805 | if (array_type->id == TypeTableEntryIdArray || |
| 3806 | (array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle)) | ||
| 3807 | { | ||
| 3808 | if (array_type->id == TypeTableEntryIdPointer) { | ||
| 3809 | array_type = array_type->data.pointer.child_type; | ||
| 3810 | } | ||
| 3798 | LLVMValueRef start_val = ir_llvm_value(g, instruction->start); | 3811 | LLVMValueRef start_val = ir_llvm_value(g, instruction->start); |
| 3799 | LLVMValueRef end_val; | 3812 | LLVMValueRef end_val; |
| 3800 | if (instruction->end) { | 3813 | if (instruction->end) { |
| ... | @@ -3835,6 +3848,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst | ... | @@ -3835,6 +3848,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 3835 | 3848 | ||
| 3836 | return tmp_struct_ptr; | 3849 | return tmp_struct_ptr; |
| 3837 | } else if (array_type->id == TypeTableEntryIdPointer) { | 3850 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 3851 | assert(array_type->data.pointer.ptr_len == PtrLenUnknown); | ||
| 3838 | LLVMValueRef start_val = ir_llvm_value(g, instruction->start); | 3852 | LLVMValueRef start_val = ir_llvm_value(g, instruction->start); |
| 3839 | LLVMValueRef end_val = ir_llvm_value(g, instruction->end); | 3853 | LLVMValueRef end_val = ir_llvm_value(g, instruction->end); |
| 3840 | 3854 | ||
| ... | @@ -4812,7 +4826,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) { | ... | @@ -4812,7 +4826,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) { |
| 4812 | 4826 | ||
| 4813 | static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index); | 4827 | static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index); |
| 4814 | static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index); | 4828 | static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index); |
| 4815 | static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *array_const_val); | 4829 | static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val); |
| 4816 | 4830 | ||
| 4817 | static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) { | 4831 | static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) { |
| 4818 | switch (parent->id) { | 4832 | switch (parent->id) { |
| ... | @@ -4828,6 +4842,10 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent | ... | @@ -4828,6 +4842,10 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent |
| 4828 | parent->data.p_array.elem_index); | 4842 | parent->data.p_array.elem_index); |
| 4829 | case ConstParentIdUnion: | 4843 | case ConstParentIdUnion: |
| 4830 | return gen_const_ptr_union_recursive(g, parent->data.p_union.union_val); | 4844 | return gen_const_ptr_union_recursive(g, parent->data.p_union.union_val); |
| 4845 | case ConstParentIdScalar: | ||
| 4846 | render_const_val(g, parent->data.p_scalar.scalar_val, ""); | ||
| 4847 | render_const_val_global(g, parent->data.p_scalar.scalar_val, ""); | ||
| 4848 | return parent->data.p_scalar.scalar_val->global_refs->llvm_global; | ||
| 4831 | } | 4849 | } |
| 4832 | zig_unreachable(); | 4850 | zig_unreachable(); |
| 4833 | } | 4851 | } |
| ... | @@ -4853,7 +4871,8 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar | ... | @@ -4853,7 +4871,8 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar |
| 4853 | }; | 4871 | }; |
| 4854 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | 4872 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); |
| 4855 | } else { | 4873 | } else { |
| 4856 | zig_unreachable(); | 4874 | assert(parent->id == ConstParentIdScalar); |
| 4875 | return base_ptr; | ||
| 4857 | } | 4876 | } |
| 4858 | } | 4877 | } |
| 4859 | 4878 |
src/ir.cpp+135-22| ... | @@ -107,6 +107,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ | ... | @@ -107,6 +107,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 107 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, VariableTableEntry *var); | 107 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, VariableTableEntry *var); |
| 108 | static TypeTableEntry *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op); | 108 | static TypeTableEntry *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op); |
| 109 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval); | 109 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval); |
| 110 | static TypeTableEntry *adjust_ptr_align(CodeGen *g, TypeTableEntry *ptr_type, uint32_t new_align); | ||
| 110 | 111 | ||
| 111 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { | 112 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { |
| 112 | assert(const_val->type->id == TypeTableEntryIdPointer); | 113 | assert(const_val->type->id == TypeTableEntryIdPointer); |
| ... | @@ -6849,7 +6850,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -6849,7 +6850,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6849 | IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr); | 6850 | IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr); |
| 6850 | IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0); | 6851 | IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0); |
| 6851 | IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle); | 6852 | IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle); |
| 6852 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_mem_ptr_maybe); | 6853 | IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node, |
| 6854 | get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, | ||
| 6855 | false, false, PtrLenUnknown, get_abi_alignment(irb->codegen, irb->codegen->builtin_types.entry_u8), | ||
| 6856 | 0, 0)); | ||
| 6857 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe); | ||
| 6853 | IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false); | 6858 | IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false); |
| 6854 | IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var); | 6859 | IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var); |
| 6855 | IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr); | 6860 | IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr); |
| ... | @@ -8729,6 +8734,7 @@ static void eval_const_expr_implicit_cast(CastOp cast_op, | ... | @@ -8729,6 +8734,7 @@ static void eval_const_expr_implicit_cast(CastOp cast_op, |
| 8729 | case CastOpNoCast: | 8734 | case CastOpNoCast: |
| 8730 | zig_unreachable(); | 8735 | zig_unreachable(); |
| 8731 | case CastOpErrSet: | 8736 | case CastOpErrSet: |
| 8737 | case CastOpBitCast: | ||
| 8732 | zig_panic("TODO"); | 8738 | zig_panic("TODO"); |
| 8733 | case CastOpNoop: | 8739 | case CastOpNoop: |
| 8734 | { | 8740 | { |
| ... | @@ -9750,6 +9756,49 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -9750,6 +9756,49 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc |
| 9750 | return result; | 9756 | return result; |
| 9751 | } | 9757 | } |
| 9752 | 9758 | ||
| 9759 | static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, | ||
| 9760 | TypeTableEntry *wanted_type) | ||
| 9761 | { | ||
| 9762 | assert(wanted_type->id == TypeTableEntryIdPointer); | ||
| 9763 | wanted_type = adjust_ptr_align(ira->codegen, wanted_type, target->value.type->data.pointer.alignment); | ||
| 9764 | TypeTableEntry *array_type = wanted_type->data.pointer.child_type; | ||
| 9765 | assert(array_type->id == TypeTableEntryIdArray); | ||
| 9766 | assert(array_type->data.array.len == 1); | ||
| 9767 | |||
| 9768 | if (instr_is_comptime(target)) { | ||
| 9769 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | ||
| 9770 | if (!val) | ||
| 9771 | return ira->codegen->invalid_instruction; | ||
| 9772 | |||
| 9773 | assert(val->type->id == TypeTableEntryIdPointer); | ||
| 9774 | ConstExprValue *pointee = const_ptr_pointee(ira->codegen, val); | ||
| 9775 | if (pointee->special != ConstValSpecialRuntime) { | ||
| 9776 | ConstExprValue *array_val = create_const_vals(1); | ||
| 9777 | array_val->special = ConstValSpecialStatic; | ||
| 9778 | array_val->type = array_type; | ||
| 9779 | array_val->data.x_array.special = ConstArraySpecialNone; | ||
| 9780 | array_val->data.x_array.s_none.elements = pointee; | ||
| 9781 | array_val->data.x_array.s_none.parent.id = ConstParentIdScalar; | ||
| 9782 | array_val->data.x_array.s_none.parent.data.p_scalar.scalar_val = pointee; | ||
| 9783 | |||
| 9784 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | ||
| 9785 | source_instr->scope, source_instr->source_node); | ||
| 9786 | const_instruction->base.value.type = wanted_type; | ||
| 9787 | const_instruction->base.value.special = ConstValSpecialStatic; | ||
| 9788 | const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialRef; | ||
| 9789 | const_instruction->base.value.data.x_ptr.data.ref.pointee = array_val; | ||
| 9790 | const_instruction->base.value.data.x_ptr.mut = val->data.x_ptr.mut; | ||
| 9791 | return &const_instruction->base; | ||
| 9792 | } | ||
| 9793 | } | ||
| 9794 | |||
| 9795 | // pointer to array and pointer to single item are represented the same way at runtime | ||
| 9796 | IrInstruction *result = ir_build_cast(&ira->new_irb, target->scope, target->source_node, | ||
| 9797 | wanted_type, target, CastOpBitCast); | ||
| 9798 | result->value.type = wanted_type; | ||
| 9799 | return result; | ||
| 9800 | } | ||
| 9801 | |||
| 9753 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, | 9802 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 9754 | TypeTableEntry *wanted_type, IrInstruction *value) | 9803 | TypeTableEntry *wanted_type, IrInstruction *value) |
| 9755 | { | 9804 | { |
| ... | @@ -10156,6 +10205,30 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10156,6 +10205,30 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10156 | } | 10205 | } |
| 10157 | } | 10206 | } |
| 10158 | 10207 | ||
| 10208 | // explicit cast from *T to *[1]T | ||
| 10209 | if (wanted_type->id == TypeTableEntryIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle && | ||
| 10210 | actual_type->id == TypeTableEntryIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle) | ||
| 10211 | { | ||
| 10212 | TypeTableEntry *array_type = wanted_type->data.pointer.child_type; | ||
| 10213 | if (array_type->id == TypeTableEntryIdArray && array_type->data.array.len == 1 && | ||
| 10214 | types_match_const_cast_only(ira, array_type->data.array.child_type, | ||
| 10215 | actual_type->data.pointer.child_type, source_node).id == ConstCastResultIdOk) | ||
| 10216 | { | ||
| 10217 | if (wanted_type->data.pointer.alignment > actual_type->data.pointer.alignment) { | ||
| 10218 | ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment")); | ||
| 10219 | add_error_note(ira->codegen, msg, value->source_node, | ||
| 10220 | buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name), | ||
| 10221 | actual_type->data.pointer.alignment)); | ||
| 10222 | add_error_note(ira->codegen, msg, source_instr->source_node, | ||
| 10223 | buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name), | ||
| 10224 | wanted_type->data.pointer.alignment)); | ||
| 10225 | return ira->codegen->invalid_instruction; | ||
| 10226 | } | ||
| 10227 | return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type); | ||
| 10228 | } | ||
| 10229 | } | ||
| 10230 | |||
| 10231 | |||
| 10159 | // explicit cast from undefined to anything | 10232 | // explicit cast from undefined to anything |
| 10160 | if (actual_type->id == TypeTableEntryIdUndefLit) { | 10233 | if (actual_type->id == TypeTableEntryIdUndefLit) { |
| 10161 | return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type); | 10234 | return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type); |
| ... | @@ -13162,11 +13235,13 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -13162,11 +13235,13 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 13162 | if (type_is_invalid(array_ptr->value.type)) | 13235 | if (type_is_invalid(array_ptr->value.type)) |
| 13163 | return ira->codegen->builtin_types.entry_invalid; | 13236 | return ira->codegen->builtin_types.entry_invalid; |
| 13164 | 13237 | ||
| 13238 | ConstExprValue *orig_array_ptr_val = &array_ptr->value; | ||
| 13239 | |||
| 13165 | IrInstruction *elem_index = elem_ptr_instruction->elem_index->other; | 13240 | IrInstruction *elem_index = elem_ptr_instruction->elem_index->other; |
| 13166 | if (type_is_invalid(elem_index->value.type)) | 13241 | if (type_is_invalid(elem_index->value.type)) |
| 13167 | return ira->codegen->builtin_types.entry_invalid; | 13242 | return ira->codegen->builtin_types.entry_invalid; |
| 13168 | 13243 | ||
| 13169 | TypeTableEntry *ptr_type = array_ptr->value.type; | 13244 | TypeTableEntry *ptr_type = orig_array_ptr_val->type; |
| 13170 | assert(ptr_type->id == TypeTableEntryIdPointer); | 13245 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 13171 | 13246 | ||
| 13172 | TypeTableEntry *array_type = ptr_type->data.pointer.child_type; | 13247 | TypeTableEntry *array_type = ptr_type->data.pointer.child_type; |
| ... | @@ -13177,7 +13252,18 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -13177,7 +13252,18 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 13177 | 13252 | ||
| 13178 | if (type_is_invalid(array_type)) { | 13253 | if (type_is_invalid(array_type)) { |
| 13179 | return array_type; | 13254 | return array_type; |
| 13180 | } else if (array_type->id == TypeTableEntryIdArray) { | 13255 | } else if (array_type->id == TypeTableEntryIdArray || |
| 13256 | (array_type->id == TypeTableEntryIdPointer && | ||
| 13257 | array_type->data.pointer.ptr_len == PtrLenSingle && | ||
| 13258 | array_type->data.pointer.child_type->id == TypeTableEntryIdArray)) | ||
| 13259 | { | ||
| 13260 | if (array_type->id == TypeTableEntryIdPointer) { | ||
| 13261 | array_type = array_type->data.pointer.child_type; | ||
| 13262 | ptr_type = ptr_type->data.pointer.child_type; | ||
| 13263 | if (orig_array_ptr_val->special != ConstValSpecialRuntime) { | ||
| 13264 | orig_array_ptr_val = const_ptr_pointee(ira->codegen, orig_array_ptr_val); | ||
| 13265 | } | ||
| 13266 | } | ||
| 13181 | if (array_type->data.array.len == 0) { | 13267 | if (array_type->data.array.len == 0) { |
| 13182 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, | 13268 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| 13183 | buf_sprintf("index 0 outside array of size 0")); | 13269 | buf_sprintf("index 0 outside array of size 0")); |
| ... | @@ -13205,7 +13291,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -13205,7 +13291,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 13205 | } else if (array_type->id == TypeTableEntryIdPointer) { | 13291 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 13206 | if (array_type->data.pointer.ptr_len == PtrLenSingle) { | 13292 | if (array_type->data.pointer.ptr_len == PtrLenSingle) { |
| 13207 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, | 13293 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| 13208 | buf_sprintf("indexing not allowed on pointer to single item")); | 13294 | buf_sprintf("index of single-item pointer")); |
| 13209 | return ira->codegen->builtin_types.entry_invalid; | 13295 | return ira->codegen->builtin_types.entry_invalid; |
| 13210 | } | 13296 | } |
| 13211 | return_type = adjust_ptr_len(ira->codegen, array_type, elem_ptr_instruction->ptr_len); | 13297 | return_type = adjust_ptr_len(ira->codegen, array_type, elem_ptr_instruction->ptr_len); |
| ... | @@ -13294,9 +13380,9 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -13294,9 +13380,9 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 13294 | } | 13380 | } |
| 13295 | 13381 | ||
| 13296 | ConstExprValue *array_ptr_val; | 13382 | ConstExprValue *array_ptr_val; |
| 13297 | if (array_ptr->value.special != ConstValSpecialRuntime && | 13383 | if (orig_array_ptr_val->special != ConstValSpecialRuntime && |
| 13298 | (array_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == TypeTableEntryIdArray) && | 13384 | (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == TypeTableEntryIdArray) && |
| 13299 | (array_ptr_val = const_ptr_pointee(ira->codegen, &array_ptr->value)) && | 13385 | (array_ptr_val = const_ptr_pointee(ira->codegen, orig_array_ptr_val)) && |
| 13300 | array_ptr_val->special != ConstValSpecialRuntime && | 13386 | array_ptr_val->special != ConstValSpecialRuntime && |
| 13301 | (array_type->id != TypeTableEntryIdPointer || | 13387 | (array_type->id != TypeTableEntryIdPointer || |
| 13302 | array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)) | 13388 | array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)) |
| ... | @@ -13401,7 +13487,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -13401,7 +13487,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 13401 | } else if (array_type->id == TypeTableEntryIdArray) { | 13487 | } else if (array_type->id == TypeTableEntryIdArray) { |
| 13402 | ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base); | 13488 | ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base); |
| 13403 | out_val->data.x_ptr.special = ConstPtrSpecialBaseArray; | 13489 | out_val->data.x_ptr.special = ConstPtrSpecialBaseArray; |
| 13404 | out_val->data.x_ptr.mut = array_ptr->value.data.x_ptr.mut; | 13490 | out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut; |
| 13405 | out_val->data.x_ptr.data.base_array.array_val = array_ptr_val; | 13491 | out_val->data.x_ptr.data.base_array.array_val = array_ptr_val; |
| 13406 | out_val->data.x_ptr.data.base_array.elem_index = index; | 13492 | out_val->data.x_ptr.data.base_array.elem_index = index; |
| 13407 | return return_type; | 13493 | return return_type; |
| ... | @@ -17406,14 +17492,29 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -17406,14 +17492,29 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 17406 | byte_alignment, 0, 0); | 17492 | byte_alignment, 0, 0); |
| 17407 | return_type = get_slice_type(ira->codegen, slice_ptr_type); | 17493 | return_type = get_slice_type(ira->codegen, slice_ptr_type); |
| 17408 | } else if (array_type->id == TypeTableEntryIdPointer) { | 17494 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 17409 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type, | 17495 | if (array_type->data.pointer.ptr_len == PtrLenSingle) { |
| 17410 | array_type->data.pointer.is_const, array_type->data.pointer.is_volatile, | 17496 | TypeTableEntry *main_type = array_type->data.pointer.child_type; |
| 17411 | PtrLenUnknown, | 17497 | if (main_type->id == TypeTableEntryIdArray) { |
| 17412 | array_type->data.pointer.alignment, 0, 0); | 17498 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, |
| 17413 | return_type = get_slice_type(ira->codegen, slice_ptr_type); | 17499 | main_type->data.pointer.child_type, |
| 17414 | if (!end) { | 17500 | array_type->data.pointer.is_const, array_type->data.pointer.is_volatile, |
| 17415 | ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value")); | 17501 | PtrLenUnknown, |
| 17416 | return ira->codegen->builtin_types.entry_invalid; | 17502 | array_type->data.pointer.alignment, 0, 0); |
| 17503 | return_type = get_slice_type(ira->codegen, slice_ptr_type); | ||
| 17504 | } else { | ||
| 17505 | ir_add_error(ira, &instruction->base, buf_sprintf("slice of single-item pointer")); | ||
| 17506 | return ira->codegen->builtin_types.entry_invalid; | ||
| 17507 | } | ||
| 17508 | } else { | ||
| 17509 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type, | ||
| 17510 | array_type->data.pointer.is_const, array_type->data.pointer.is_volatile, | ||
| 17511 | PtrLenUnknown, | ||
| 17512 | array_type->data.pointer.alignment, 0, 0); | ||
| 17513 | return_type = get_slice_type(ira->codegen, slice_ptr_type); | ||
| 17514 | if (!end) { | ||
| 17515 | ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value")); | ||
| 17516 | return ira->codegen->builtin_types.entry_invalid; | ||
| 17517 | } | ||
| 17417 | } | 17518 | } |
| 17418 | } else if (is_slice(array_type)) { | 17519 | } else if (is_slice(array_type)) { |
| 17419 | TypeTableEntry *ptr_type = array_type->data.structure.fields[slice_ptr_index].type_entry; | 17520 | TypeTableEntry *ptr_type = array_type->data.structure.fields[slice_ptr_index].type_entry; |
| ... | @@ -17433,12 +17534,24 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -17433,12 +17534,24 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 17433 | size_t abs_offset; | 17534 | size_t abs_offset; |
| 17434 | size_t rel_end; | 17535 | size_t rel_end; |
| 17435 | bool ptr_is_undef = false; | 17536 | bool ptr_is_undef = false; |
| 17436 | if (array_type->id == TypeTableEntryIdArray) { | 17537 | if (array_type->id == TypeTableEntryIdArray || |
| 17437 | array_val = const_ptr_pointee(ira->codegen, &ptr_ptr->value); | 17538 | (array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle)) |
| 17438 | abs_offset = 0; | 17539 | { |
| 17439 | rel_end = array_type->data.array.len; | 17540 | if (array_type->id == TypeTableEntryIdPointer) { |
| 17440 | parent_ptr = nullptr; | 17541 | TypeTableEntry *child_array_type = array_type->data.pointer.child_type; |
| 17542 | assert(child_array_type->id == TypeTableEntryIdArray); | ||
| 17543 | parent_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value); | ||
| 17544 | array_val = const_ptr_pointee(ira->codegen, parent_ptr); | ||
| 17545 | rel_end = child_array_type->data.array.len; | ||
| 17546 | abs_offset = 0; | ||
| 17547 | } else { | ||
| 17548 | array_val = const_ptr_pointee(ira->codegen, &ptr_ptr->value); | ||
| 17549 | rel_end = array_type->data.array.len; | ||
| 17550 | parent_ptr = nullptr; | ||
| 17551 | abs_offset = 0; | ||
| 17552 | } | ||
| 17441 | } else if (array_type->id == TypeTableEntryIdPointer) { | 17553 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 17554 | assert(array_type->data.pointer.ptr_len == PtrLenUnknown); | ||
| 17442 | parent_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value); | 17555 | parent_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value); |
| 17443 | if (parent_ptr->special == ConstValSpecialUndef) { | 17556 | if (parent_ptr->special == ConstValSpecialUndef) { |
| 17444 | array_val = nullptr; | 17557 | array_val = nullptr; |
| ... | @@ -17537,7 +17650,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -17537,7 +17650,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 17537 | if (array_val) { | 17650 | if (array_val) { |
| 17538 | size_t index = abs_offset + start_scalar; | 17651 | size_t index = abs_offset + start_scalar; |
| 17539 | bool is_const = slice_is_const(return_type); | 17652 | bool is_const = slice_is_const(return_type); |
| 17540 | init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const); | 17653 | init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const, PtrLenUnknown); |
| 17541 | if (array_type->id == TypeTableEntryIdArray) { | 17654 | if (array_type->id == TypeTableEntryIdArray) { |
| 17542 | ptr_val->data.x_ptr.mut = ptr_ptr->value.data.x_ptr.mut; | 17655 | ptr_val->data.x_ptr.mut = ptr_ptr->value.data.x_ptr.mut; |
| 17543 | } else if (is_slice(array_type)) { | 17656 | } else if (is_slice(array_type)) { |
std/fmt/errol/index.zig+1-1| ... | @@ -59,7 +59,7 @@ pub fn roundToPrecision(float_decimal: *FloatDecimal, precision: usize, mode: Ro | ... | @@ -59,7 +59,7 @@ pub fn roundToPrecision(float_decimal: *FloatDecimal, precision: usize, mode: Ro |
| 59 | float_decimal.exp += 1; | 59 | float_decimal.exp += 1; |
| 60 | 60 | ||
| 61 | // Re-size the buffer to use the reserved leading byte. | 61 | // Re-size the buffer to use the reserved leading byte. |
| 62 | const one_before = @intToPtr(*u8, @ptrToInt(&float_decimal.digits[0]) - 1); | 62 | const one_before = @intToPtr([*]u8, @ptrToInt(&float_decimal.digits[0]) - 1); |
| 63 | float_decimal.digits = one_before[0 .. float_decimal.digits.len + 1]; | 63 | float_decimal.digits = one_before[0 .. float_decimal.digits.len + 1]; |
| 64 | float_decimal.digits[0] = '1'; | 64 | float_decimal.digits[0] = '1'; |
| 65 | return; | 65 | return; |
std/fmt/index.zig+4-4| ... | @@ -278,7 +278,7 @@ pub fn formatAsciiChar( | ... | @@ -278,7 +278,7 @@ pub fn formatAsciiChar( |
| 278 | comptime Errors: type, | 278 | comptime Errors: type, |
| 279 | output: fn (@typeOf(context), []const u8) Errors!void, | 279 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 280 | ) Errors!void { | 280 | ) Errors!void { |
| 281 | return output(context, (&c)[0..1]); | 281 | return output(context, (*[1]u8)(&c)[0..]); |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | pub fn formatBuf( | 284 | pub fn formatBuf( |
| ... | @@ -603,7 +603,7 @@ fn formatIntSigned( | ... | @@ -603,7 +603,7 @@ fn formatIntSigned( |
| 603 | const uint = @IntType(false, @typeOf(value).bit_count); | 603 | const uint = @IntType(false, @typeOf(value).bit_count); |
| 604 | if (value < 0) { | 604 | if (value < 0) { |
| 605 | const minus_sign: u8 = '-'; | 605 | const minus_sign: u8 = '-'; |
| 606 | try output(context, (&minus_sign)[0..1]); | 606 | try output(context, (*[1]u8)(&minus_sign)[0..]); |
| 607 | const new_value = uint(-(value + 1)) + 1; | 607 | const new_value = uint(-(value + 1)) + 1; |
| 608 | const new_width = if (width == 0) 0 else (width - 1); | 608 | const new_width = if (width == 0) 0 else (width - 1); |
| 609 | return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output); | 609 | return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output); |
| ... | @@ -611,7 +611,7 @@ fn formatIntSigned( | ... | @@ -611,7 +611,7 @@ fn formatIntSigned( |
| 611 | return formatIntUnsigned(uint(value), base, uppercase, width, context, Errors, output); | 611 | return formatIntUnsigned(uint(value), base, uppercase, width, context, Errors, output); |
| 612 | } else { | 612 | } else { |
| 613 | const plus_sign: u8 = '+'; | 613 | const plus_sign: u8 = '+'; |
| 614 | try output(context, (&plus_sign)[0..1]); | 614 | try output(context, (*[1]u8)(&plus_sign)[0..]); |
| 615 | const new_value = uint(value); | 615 | const new_value = uint(value); |
| 616 | const new_width = if (width == 0) 0 else (width - 1); | 616 | const new_width = if (width == 0) 0 else (width - 1); |
| 617 | return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output); | 617 | return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output); |
| ... | @@ -648,7 +648,7 @@ fn formatIntUnsigned( | ... | @@ -648,7 +648,7 @@ fn formatIntUnsigned( |
| 648 | const zero_byte: u8 = '0'; | 648 | const zero_byte: u8 = '0'; |
| 649 | var leftover_padding = padding - index; | 649 | var leftover_padding = padding - index; |
| 650 | while (true) { | 650 | while (true) { |
| 651 | try output(context, (&zero_byte)[0..1]); | 651 | try output(context, (*[1]u8)(&zero_byte)[0..]); |
| 652 | leftover_padding -= 1; | 652 | leftover_padding -= 1; |
| 653 | if (leftover_padding == 0) break; | 653 | if (leftover_padding == 0) break; |
| 654 | } | 654 | } |
std/heap.zig+1-1| ... | @@ -24,7 +24,7 @@ fn cAlloc(self: *Allocator, n: usize, alignment: u29) ![]u8 { | ... | @@ -24,7 +24,7 @@ fn cAlloc(self: *Allocator, n: usize, alignment: u29) ![]u8 { |
| 24 | fn cRealloc(self: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 { | 24 | fn cRealloc(self: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 { |
| 25 | const old_ptr = @ptrCast([*]c_void, old_mem.ptr); | 25 | const old_ptr = @ptrCast([*]c_void, old_mem.ptr); |
| 26 | if (c.realloc(old_ptr, new_size)) |buf| { | 26 | if (c.realloc(old_ptr, new_size)) |buf| { |
| 27 | return @ptrCast(*u8, buf)[0..new_size]; | 27 | return @ptrCast([*]u8, buf)[0..new_size]; |
| 28 | } else if (new_size <= old_mem.len) { | 28 | } else if (new_size <= old_mem.len) { |
| 29 | return old_mem[0..new_size]; | 29 | return old_mem[0..new_size]; |
| 30 | } else { | 30 | } else { |
std/io.zig+2-2| ... | @@ -219,12 +219,12 @@ pub fn OutStream(comptime WriteError: type) type { | ... | @@ -219,12 +219,12 @@ pub fn OutStream(comptime WriteError: type) type { |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | pub fn writeByte(self: *Self, byte: u8) !void { | 221 | pub fn writeByte(self: *Self, byte: u8) !void { |
| 222 | const slice = (&byte)[0..1]; | 222 | const slice = (*[1]u8)(&byte)[0..]; |
| 223 | return self.writeFn(self, slice); | 223 | return self.writeFn(self, slice); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) !void { | 226 | pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) !void { |
| 227 | const slice = (&byte)[0..1]; | 227 | const slice = (*[1]u8)(&byte)[0..]; |
| 228 | var i: usize = 0; | 228 | var i: usize = 0; |
| 229 | while (i < n) : (i += 1) { | 229 | while (i < n) : (i += 1) { |
| 230 | try self.writeFn(self, slice); | 230 | try self.writeFn(self, slice); |
std/macho.zig+1-1| ... | @@ -164,7 +164,7 @@ fn readNoEof(in: *io.FileInStream, comptime T: type, result: []T) !void { | ... | @@ -164,7 +164,7 @@ fn readNoEof(in: *io.FileInStream, comptime T: type, result: []T) !void { |
| 164 | return in.stream.readNoEof(([]u8)(result)); | 164 | return in.stream.readNoEof(([]u8)(result)); |
| 165 | } | 165 | } |
| 166 | fn readOneNoEof(in: *io.FileInStream, comptime T: type, result: *T) !void { | 166 | fn readOneNoEof(in: *io.FileInStream, comptime T: type, result: *T) !void { |
| 167 | return readNoEof(in, T, result[0..1]); | 167 | return readNoEof(in, T, (*[1]T)(result)[0..]); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | fn isSymbol(sym: *const Nlist64) bool { | 170 | fn isSymbol(sym: *const Nlist64) bool { |
std/mem.zig+19-15| ... | @@ -31,14 +31,16 @@ pub const Allocator = struct { | ... | @@ -31,14 +31,16 @@ pub const Allocator = struct { |
| 31 | /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn` | 31 | /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn` |
| 32 | freeFn: fn (self: *Allocator, old_mem: []u8) void, | 32 | freeFn: fn (self: *Allocator, old_mem: []u8) void, |
| 33 | 33 | ||
| 34 | fn create(self: *Allocator, comptime T: type) !*T { | 34 | /// Call destroy with the result |
| 35 | pub fn create(self: *Allocator, comptime T: type) !*T { | ||
| 35 | if (@sizeOf(T) == 0) return *{}; | 36 | if (@sizeOf(T) == 0) return *{}; |
| 36 | const slice = try self.alloc(T, 1); | 37 | const slice = try self.alloc(T, 1); |
| 37 | return &slice[0]; | 38 | return &slice[0]; |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | // TODO once #733 is solved, this will replace create | 41 | /// Call destroy with the result |
| 41 | fn construct(self: *Allocator, init: var) t: { | 42 | /// TODO once #733 is solved, this will replace create |
| 43 | pub fn construct(self: *Allocator, init: var) t: { | ||
| 42 | // TODO this is a workaround for type getting parsed as Error!&const T | 44 | // TODO this is a workaround for type getting parsed as Error!&const T |
| 43 | const T = @typeOf(init).Child; | 45 | const T = @typeOf(init).Child; |
| 44 | break :t Error!*T; | 46 | break :t Error!*T; |
| ... | @@ -51,17 +53,19 @@ pub const Allocator = struct { | ... | @@ -51,17 +53,19 @@ pub const Allocator = struct { |
| 51 | return ptr; | 53 | return ptr; |
| 52 | } | 54 | } |
| 53 | 55 | ||
| 54 | fn destroy(self: *Allocator, ptr: var) void { | 56 | /// `ptr` should be the return value of `construct` or `create` |
| 55 | self.free(ptr[0..1]); | 57 | pub fn destroy(self: *Allocator, ptr: var) void { |
| 58 | const non_const_ptr = @intToPtr([*]u8, @ptrToInt(ptr)); | ||
| 59 | self.freeFn(self, non_const_ptr[0..@sizeOf(@typeOf(ptr).Child)]); | ||
| 56 | } | 60 | } |
| 57 | 61 | ||
| 58 | fn alloc(self: *Allocator, comptime T: type, n: usize) ![]T { | 62 | pub fn alloc(self: *Allocator, comptime T: type, n: usize) ![]T { |
| 59 | return self.alignedAlloc(T, @alignOf(T), n); | 63 | return self.alignedAlloc(T, @alignOf(T), n); |
| 60 | } | 64 | } |
| 61 | 65 | ||
| 62 | fn alignedAlloc(self: *Allocator, comptime T: type, comptime alignment: u29, n: usize) ![]align(alignment) T { | 66 | pub fn alignedAlloc(self: *Allocator, comptime T: type, comptime alignment: u29, n: usize) ![]align(alignment) T { |
| 63 | if (n == 0) { | 67 | if (n == 0) { |
| 64 | return (*align(alignment) T)(undefined)[0..0]; | 68 | return ([*]align(alignment) T)(undefined)[0..0]; |
| 65 | } | 69 | } |
| 66 | const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory; | 70 | const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory; |
| 67 | const byte_slice = try self.allocFn(self, byte_count, alignment); | 71 | const byte_slice = try self.allocFn(self, byte_count, alignment); |
| ... | @@ -73,17 +77,17 @@ pub const Allocator = struct { | ... | @@ -73,17 +77,17 @@ pub const Allocator = struct { |
| 73 | return ([]align(alignment) T)(@alignCast(alignment, byte_slice)); | 77 | return ([]align(alignment) T)(@alignCast(alignment, byte_slice)); |
| 74 | } | 78 | } |
| 75 | 79 | ||
| 76 | fn realloc(self: *Allocator, comptime T: type, old_mem: []T, n: usize) ![]T { | 80 | pub fn realloc(self: *Allocator, comptime T: type, old_mem: []T, n: usize) ![]T { |
| 77 | return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n); | 81 | return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n); |
| 78 | } | 82 | } |
| 79 | 83 | ||
| 80 | fn alignedRealloc(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) ![]align(alignment) T { | 84 | pub fn alignedRealloc(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) ![]align(alignment) T { |
| 81 | if (old_mem.len == 0) { | 85 | if (old_mem.len == 0) { |
| 82 | return self.alloc(T, n); | 86 | return self.alloc(T, n); |
| 83 | } | 87 | } |
| 84 | if (n == 0) { | 88 | if (n == 0) { |
| 85 | self.free(old_mem); | 89 | self.free(old_mem); |
| 86 | return (*align(alignment) T)(undefined)[0..0]; | 90 | return ([*]align(alignment) T)(undefined)[0..0]; |
| 87 | } | 91 | } |
| 88 | 92 | ||
| 89 | const old_byte_slice = ([]u8)(old_mem); | 93 | const old_byte_slice = ([]u8)(old_mem); |
| ... | @@ -102,11 +106,11 @@ pub const Allocator = struct { | ... | @@ -102,11 +106,11 @@ pub const Allocator = struct { |
| 102 | /// Reallocate, but `n` must be less than or equal to `old_mem.len`. | 106 | /// Reallocate, but `n` must be less than or equal to `old_mem.len`. |
| 103 | /// Unlike `realloc`, this function cannot fail. | 107 | /// Unlike `realloc`, this function cannot fail. |
| 104 | /// Shrinking to 0 is the same as calling `free`. | 108 | /// Shrinking to 0 is the same as calling `free`. |
| 105 | fn shrink(self: *Allocator, comptime T: type, old_mem: []T, n: usize) []T { | 109 | pub fn shrink(self: *Allocator, comptime T: type, old_mem: []T, n: usize) []T { |
| 106 | return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n); | 110 | return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n); |
| 107 | } | 111 | } |
| 108 | 112 | ||
| 109 | fn alignedShrink(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) []align(alignment) T { | 113 | pub fn alignedShrink(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) []align(alignment) T { |
| 110 | if (n == 0) { | 114 | if (n == 0) { |
| 111 | self.free(old_mem); | 115 | self.free(old_mem); |
| 112 | return old_mem[0..0]; | 116 | return old_mem[0..0]; |
| ... | @@ -123,10 +127,10 @@ pub const Allocator = struct { | ... | @@ -123,10 +127,10 @@ pub const Allocator = struct { |
| 123 | return ([]align(alignment) T)(@alignCast(alignment, byte_slice)); | 127 | return ([]align(alignment) T)(@alignCast(alignment, byte_slice)); |
| 124 | } | 128 | } |
| 125 | 129 | ||
| 126 | fn free(self: *Allocator, memory: var) void { | 130 | pub fn free(self: *Allocator, memory: var) void { |
| 127 | const bytes = ([]const u8)(memory); | 131 | const bytes = ([]const u8)(memory); |
| 128 | if (bytes.len == 0) return; | 132 | if (bytes.len == 0) return; |
| 129 | const non_const_ptr = @intToPtr(*u8, @ptrToInt(bytes.ptr)); | 133 | const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr)); |
| 130 | self.freeFn(self, non_const_ptr[0..bytes.len]); | 134 | self.freeFn(self, non_const_ptr[0..bytes.len]); |
| 131 | } | 135 | } |
| 132 | }; | 136 | }; |
std/net.zig+1-1| ... | @@ -68,7 +68,7 @@ pub const Address = struct { | ... | @@ -68,7 +68,7 @@ pub const Address = struct { |
| 68 | 68 | ||
| 69 | pub fn parseIp4(buf: []const u8) !u32 { | 69 | pub fn parseIp4(buf: []const u8) !u32 { |
| 70 | var result: u32 = undefined; | 70 | var result: u32 = undefined; |
| 71 | const out_ptr = ([]u8)((&result)[0..1]); | 71 | const out_ptr = ([]u8)((*[1]u32)(&result)[0..]); |
| 72 | 72 | ||
| 73 | var x: u8 = 0; | 73 | var x: u8 = 0; |
| 74 | var index: u8 = 0; | 74 | var index: u8 = 0; |
std/os/index.zig+2-2| ... | @@ -1240,7 +1240,7 @@ pub const Dir = struct { | ... | @@ -1240,7 +1240,7 @@ pub const Dir = struct { |
| 1240 | const next_index = self.index + darwin_entry.d_reclen; | 1240 | const next_index = self.index + darwin_entry.d_reclen; |
| 1241 | self.index = next_index; | 1241 | self.index = next_index; |
| 1242 | 1242 | ||
| 1243 | const name = (&darwin_entry.d_name)[0..darwin_entry.d_namlen]; | 1243 | const name = @ptrCast([*]u8, &darwin_entry.d_name)[0..darwin_entry.d_namlen]; |
| 1244 | 1244 | ||
| 1245 | // skip . and .. entries | 1245 | // skip . and .. entries |
| 1246 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) { | 1246 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) { |
| ... | @@ -1704,7 +1704,7 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void { | ... | @@ -1704,7 +1704,7 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void { |
| 1704 | for (args_alloc) |arg| { | 1704 | for (args_alloc) |arg| { |
| 1705 | total_bytes += @sizeOf([]u8) + arg.len; | 1705 | total_bytes += @sizeOf([]u8) + arg.len; |
| 1706 | } | 1706 | } |
| 1707 | const unaligned_allocated_buf = @ptrCast(*const u8, args_alloc.ptr)[0..total_bytes]; | 1707 | const unaligned_allocated_buf = @ptrCast([*]const u8, args_alloc.ptr)[0..total_bytes]; |
| 1708 | const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf); | 1708 | const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf); |
| 1709 | return allocator.free(aligned_allocated_buf); | 1709 | return allocator.free(aligned_allocated_buf); |
| 1710 | } | 1710 | } |
test/cases/align.zig+2-2| ... | @@ -6,7 +6,7 @@ var foo: u8 align(4) = 100; | ... | @@ -6,7 +6,7 @@ var foo: u8 align(4) = 100; |
| 6 | test "global variable alignment" { | 6 | test "global variable alignment" { |
| 7 | assert(@typeOf(&foo).alignment == 4); | 7 | assert(@typeOf(&foo).alignment == 4); |
| 8 | assert(@typeOf(&foo) == *align(4) u8); | 8 | assert(@typeOf(&foo) == *align(4) u8); |
| 9 | const slice = (&foo)[0..1]; | 9 | const slice = (*[1]u8)(&foo)[0..]; |
| 10 | assert(@typeOf(slice) == []align(4) u8); | 10 | assert(@typeOf(slice) == []align(4) u8); |
| 11 | } | 11 | } |
| 12 | 12 | ||
| ... | @@ -60,7 +60,7 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { | ... | @@ -60,7 +60,7 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { |
| 60 | test "implicitly decreasing slice alignment" { | 60 | test "implicitly decreasing slice alignment" { |
| 61 | const a: u32 align(4) = 3; | 61 | const a: u32 align(4) = 3; |
| 62 | const b: u32 align(8) = 4; | 62 | const b: u32 align(8) = 4; |
| 63 | assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7); | 63 | assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7); |
| 64 | } | 64 | } |
| 65 | fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { | 65 | fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { |
| 66 | return a[0] + b[0]; | 66 | return a[0] + b[0]; |
test/cases/array.zig+29| ... | @@ -115,3 +115,32 @@ test "array len property" { | ... | @@ -115,3 +115,32 @@ test "array len property" { |
| 115 | var x: [5]i32 = undefined; | 115 | var x: [5]i32 = undefined; |
| 116 | assert(@typeOf(x).len == 5); | 116 | assert(@typeOf(x).len == 5); |
| 117 | } | 117 | } |
| 118 | |||
| 119 | test "single-item pointer to array indexing and slicing" { | ||
| 120 | testSingleItemPtrArrayIndexSlice(); | ||
| 121 | comptime testSingleItemPtrArrayIndexSlice(); | ||
| 122 | } | ||
| 123 | |||
| 124 | fn testSingleItemPtrArrayIndexSlice() void { | ||
| 125 | var array = "aaaa"; | ||
| 126 | doSomeMangling(&array); | ||
| 127 | assert(mem.eql(u8, "azya", array)); | ||
| 128 | } | ||
| 129 | |||
| 130 | fn doSomeMangling(array: *[4]u8) void { | ||
| 131 | array[1] = 'z'; | ||
| 132 | array[2..3][0] = 'y'; | ||
| 133 | } | ||
| 134 | |||
| 135 | test "implicit cast single-item pointer" { | ||
| 136 | testImplicitCastSingleItemPtr(); | ||
| 137 | comptime testImplicitCastSingleItemPtr(); | ||
| 138 | } | ||
| 139 | |||
| 140 | fn testImplicitCastSingleItemPtr() void { | ||
| 141 | var byte: u8 = 100; | ||
| 142 | const slice = (*[1]u8)(&byte)[0..]; | ||
| 143 | slice[0] += 1; | ||
| 144 | assert(byte == 101); | ||
| 145 | } | ||
| 146 |
test/cases/eval.zig+3-3| ... | @@ -418,9 +418,9 @@ test "string literal used as comptime slice is memoized" { | ... | @@ -418,9 +418,9 @@ test "string literal used as comptime slice is memoized" { |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | test "comptime slice of undefined pointer of length 0" { | 420 | test "comptime slice of undefined pointer of length 0" { |
| 421 | const slice1 = (*i32)(undefined)[0..0]; | 421 | const slice1 = ([*]i32)(undefined)[0..0]; |
| 422 | assert(slice1.len == 0); | 422 | assert(slice1.len == 0); |
| 423 | const slice2 = (*i32)(undefined)[100..100]; | 423 | const slice2 = ([*]i32)(undefined)[100..100]; |
| 424 | assert(slice2.len == 0); | 424 | assert(slice2.len == 0); |
| 425 | } | 425 | } |
| 426 | 426 | ||
| ... | @@ -508,7 +508,7 @@ test "comptime slice of slice preserves comptime var" { | ... | @@ -508,7 +508,7 @@ test "comptime slice of slice preserves comptime var" { |
| 508 | test "comptime slice of pointer preserves comptime var" { | 508 | test "comptime slice of pointer preserves comptime var" { |
| 509 | comptime { | 509 | comptime { |
| 510 | var buff: [10]u8 = undefined; | 510 | var buff: [10]u8 = undefined; |
| 511 | var a = &buff[0]; | 511 | var a = buff[0..].ptr; |
| 512 | a[0..1][0] = 1; | 512 | a[0..1][0] = 1; |
| 513 | assert(buff[0..][0..][0] == 1); | 513 | assert(buff[0..][0..][0] == 1); |
| 514 | } | 514 | } |
test/cases/misc.zig+2-2| ... | @@ -274,7 +274,7 @@ test "generic malloc free" { | ... | @@ -274,7 +274,7 @@ test "generic malloc free" { |
| 274 | } | 274 | } |
| 275 | var some_mem: [100]u8 = undefined; | 275 | var some_mem: [100]u8 = undefined; |
| 276 | fn memAlloc(comptime T: type, n: usize) error![]T { | 276 | fn memAlloc(comptime T: type, n: usize) error![]T { |
| 277 | return @ptrCast(*T, &some_mem[0])[0..n]; | 277 | return @ptrCast([*]T, &some_mem[0])[0..n]; |
| 278 | } | 278 | } |
| 279 | fn memFree(comptime T: type, memory: []T) void {} | 279 | fn memFree(comptime T: type, memory: []T) void {} |
| 280 | 280 | ||
| ... | @@ -588,7 +588,7 @@ var global_ptr = &gdt[0]; | ... | @@ -588,7 +588,7 @@ var global_ptr = &gdt[0]; |
| 588 | 588 | ||
| 589 | // can't really run this test but we can make sure it has no compile error | 589 | // can't really run this test but we can make sure it has no compile error |
| 590 | // and generates code | 590 | // and generates code |
| 591 | const vram = @intToPtr(*volatile u8, 0x20000000)[0..0x8000]; | 591 | const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000]; |
| 592 | export fn writeToVRam() void { | 592 | export fn writeToVRam() void { |
| 593 | vram[0] = 'X'; | 593 | vram[0] = 'X'; |
| 594 | } | 594 | } |
test/cases/slice.zig+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | const mem = @import("std").mem; | 2 | const mem = @import("std").mem; |
| 3 | 3 | ||
| 4 | const x = @intToPtr(*i32, 0x1000)[0..0x500]; | 4 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; |
| 5 | const y = x[0x100..]; | 5 | const y = x[0x100..]; |
| 6 | test "compile time slice of pointer to hard coded address" { | 6 | test "compile time slice of pointer to hard coded address" { |
| 7 | assert(@ptrToInt(x.ptr) == 0x1000); | 7 | assert(@ptrToInt(x.ptr) == 0x1000); |
test/compile_errors.zig+16-5| ... | @@ -1,13 +1,22 @@ | ... | @@ -1,13 +1,22 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4 | cases.add( | ||
| 5 | "slicing single-item pointer", | ||
| 6 | \\export fn entry(ptr: *i32) void { | ||
| 7 | \\ const slice = ptr[0..2]; | ||
| 8 | \\} | ||
| 9 | , | ||
| 10 | ".tmp_source.zig:2:22: error: slice of single-item pointer", | ||
| 11 | ); | ||
| 12 | |||
| 4 | cases.add( | 13 | cases.add( |
| 5 | "indexing single-item pointer", | 14 | "indexing single-item pointer", |
| 6 | \\export fn entry(ptr: *i32) i32 { | 15 | \\export fn entry(ptr: *i32) i32 { |
| 7 | \\ return ptr[1]; | 16 | \\ return ptr[1]; |
| 8 | \\} | 17 | \\} |
| 9 | , | 18 | , |
| 10 | ".tmp_source.zig:2:15: error: indexing not allowed on pointer to single item", | 19 | ".tmp_source.zig:2:15: error: index of single-item pointer", |
| 11 | ); | 20 | ); |
| 12 | 21 | ||
| 13 | cases.add( | 22 | cases.add( |
| ... | @@ -144,10 +153,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -144,10 +153,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 144 | cases.add( | 153 | cases.add( |
| 145 | "comptime slice of undefined pointer non-zero len", | 154 | "comptime slice of undefined pointer non-zero len", |
| 146 | \\export fn entry() void { | 155 | \\export fn entry() void { |
| 147 | \\ const slice = (*i32)(undefined)[0..1]; | 156 | \\ const slice = ([*]i32)(undefined)[0..1]; |
| 148 | \\} | 157 | \\} |
| 149 | , | 158 | , |
| 150 | ".tmp_source.zig:2:36: error: non-zero length slice of undefined pointer", | 159 | ".tmp_source.zig:2:38: error: non-zero length slice of undefined pointer", |
| 151 | ); | 160 | ); |
| 152 | 161 | ||
| 153 | cases.add( | 162 | cases.add( |
| ... | @@ -3129,14 +3138,16 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3129,14 +3138,16 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3129 | \\export fn entry() void { | 3138 | \\export fn entry() void { |
| 3130 | \\ var foo = Foo { .a = 1, .b = 10 }; | 3139 | \\ var foo = Foo { .a = 1, .b = 10 }; |
| 3131 | \\ foo.b += 1; | 3140 | \\ foo.b += 1; |
| 3132 | \\ bar((&foo.b)[0..1]); | 3141 | \\ bar((*[1]u32)(&foo.b)[0..]); |
| 3133 | \\} | 3142 | \\} |
| 3134 | \\ | 3143 | \\ |
| 3135 | \\fn bar(x: []u32) void { | 3144 | \\fn bar(x: []u32) void { |
| 3136 | \\ x[0] += 1; | 3145 | \\ x[0] += 1; |
| 3137 | \\} | 3146 | \\} |
| 3138 | , | 3147 | , |
| 3139 | ".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align(1) u32'", | 3148 | ".tmp_source.zig:9:18: error: cast increases pointer alignment", |
| 3149 | ".tmp_source.zig:9:23: note: '*align(1) u32' has alignment 1", | ||
| 3150 | ".tmp_source.zig:9:18: note: '*[1]u32' has alignment 4", | ||
| 3140 | ); | 3151 | ); |
| 3141 | 3152 | ||
| 3142 | cases.add( | 3153 | cases.add( |