| author | |
| committer | |
| log | 4c7b52503b064b8be2f2afd4152311aff1941d92 |
| tree | 3f8ea590d0dc73dbfd94b0863aa1bb8c32e4d0b9 |
| parent | 2dd20aa04a35f46a189d0aaa5d2d628e46a77999 |
| signature |
7 files changed, 53 insertions(+), 61 deletions(-)
doc/docgen.zig-2| ... | @@ -954,8 +954,6 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok | ... | @@ -954,8 +954,6 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok |
| 954 | .AngleBracketAngleBracketRight, | 954 | .AngleBracketAngleBracketRight, |
| 955 | .AngleBracketAngleBracketRightEqual, | 955 | .AngleBracketAngleBracketRightEqual, |
| 956 | .Tilde, | 956 | .Tilde, |
| 957 | .BracketStarBracket, | ||
| 958 | .BracketStarCBracket, | ||
| 959 | => try writeEscaped(out, src[token.start..token.end]), | 957 | => try writeEscaped(out, src[token.start..token.end]), |
| 960 | 958 | ||
| 961 | .Invalid, .Invalid_ampersands => return parseError( | 959 | .Invalid, .Invalid_ampersands => return parseError( |
doc/langref.html.in+12-28| ... | @@ -563,7 +563,7 @@ const mem = @import("std").mem; | ... | @@ -563,7 +563,7 @@ const mem = @import("std").mem; |
| 563 | 563 | ||
| 564 | test "string literals" { | 564 | test "string literals" { |
| 565 | const bytes = "hello"; | 565 | const bytes = "hello"; |
| 566 | assert(@typeOf(bytes) == *const [5]null u8); | 566 | assert(@typeOf(bytes) == *const [5:0]u8); |
| 567 | assert(bytes.len == 5); | 567 | assert(bytes.len == 5); |
| 568 | assert(bytes[1] == 'e'); | 568 | assert(bytes[1] == 'e'); |
| 569 | assert(bytes[5] == 0); | 569 | assert(bytes[5] == 0); |
| ... | @@ -1795,7 +1795,7 @@ test "null terminated array" { | ... | @@ -1795,7 +1795,7 @@ test "null terminated array" { |
| 1795 | 1795 | ||
| 1796 | assert(@typeOf(array) == [4:0]u8); | 1796 | assert(@typeOf(array) == [4:0]u8); |
| 1797 | assert(array.len == 4); | 1797 | assert(array.len == 4); |
| 1798 | assert(slice[4] == 0); | 1798 | assert(array[4] == 0); |
| 1799 | } | 1799 | } |
| 1800 | {#code_end#} | 1800 | {#code_end#} |
| 1801 | {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Slices#} | 1801 | {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Slices#} |
| ... | @@ -4863,7 +4863,7 @@ const assert = std.debug.assert; | ... | @@ -4863,7 +4863,7 @@ const assert = std.debug.assert; |
| 4863 | const mem = std.mem; | 4863 | const mem = std.mem; |
| 4864 | 4864 | ||
| 4865 | test "cast *[1][*]const u8 to [*]const ?[*]const u8" { | 4865 | test "cast *[1][*]const u8 to [*]const ?[*]const u8" { |
| 4866 | const window_name = [1][*]const u8{c"window name"}; | 4866 | const window_name = [1][*]const u8{"window name"}; |
| 4867 | const x: [*]const ?[*]const u8 = &window_name; | 4867 | const x: [*]const ?[*]const u8 = &window_name; |
| 4868 | assert(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name")); | 4868 | assert(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name")); |
| 4869 | } | 4869 | } |
| ... | @@ -4905,7 +4905,7 @@ test "float widening" { | ... | @@ -4905,7 +4905,7 @@ test "float widening" { |
| 4905 | {#code_end#} | 4905 | {#code_end#} |
| 4906 | {#header_close#} | 4906 | {#header_close#} |
| 4907 | {#header_open|Type Coercion: Arrays and Pointers#} | 4907 | {#header_open|Type Coercion: Arrays and Pointers#} |
| 4908 | {#code_begin|test#} | 4908 | {#code_begin|test|coerce_arrays_and_ptrs#} |
| 4909 | const std = @import("std"); | 4909 | const std = @import("std"); |
| 4910 | const assert = std.debug.assert; | 4910 | const assert = std.debug.assert; |
| 4911 | 4911 | ||
| ... | @@ -4944,7 +4944,7 @@ test "[N]T to ?[]const T" { | ... | @@ -4944,7 +4944,7 @@ test "[N]T to ?[]const T" { |
| 4944 | 4944 | ||
| 4945 | // In this cast, the array length becomes the slice length. | 4945 | // In this cast, the array length becomes the slice length. |
| 4946 | test "*[N]T to []T" { | 4946 | test "*[N]T to []T" { |
| 4947 | var buf: [5]u8 = "hello"; | 4947 | var buf: [5]u8 = "hello".*; |
| 4948 | const x: []u8 = &buf; | 4948 | const x: []u8 = &buf; |
| 4949 | assert(std.mem.eql(u8, x, "hello")); | 4949 | assert(std.mem.eql(u8, x, "hello")); |
| 4950 | 4950 | ||
| ... | @@ -4956,7 +4956,7 @@ test "*[N]T to []T" { | ... | @@ -4956,7 +4956,7 @@ test "*[N]T to []T" { |
| 4956 | // Single-item pointers to arrays can be coerced to | 4956 | // Single-item pointers to arrays can be coerced to |
| 4957 | // unknown length pointers. | 4957 | // unknown length pointers. |
| 4958 | test "*[N]T to [*]T" { | 4958 | test "*[N]T to [*]T" { |
| 4959 | var buf: [5]u8 = "hello"; | 4959 | var buf: [5]u8 = "hello".*; |
| 4960 | const x: [*]u8 = &buf; | 4960 | const x: [*]u8 = &buf; |
| 4961 | assert(x[4] == 'o'); | 4961 | assert(x[4] == 'o'); |
| 4962 | // x[5] would be an uncaught out of bounds pointer dereference! | 4962 | // x[5] would be an uncaught out of bounds pointer dereference! |
| ... | @@ -4964,7 +4964,7 @@ test "*[N]T to [*]T" { | ... | @@ -4964,7 +4964,7 @@ test "*[N]T to [*]T" { |
| 4964 | 4964 | ||
| 4965 | // Likewise, it works when the destination type is an optional. | 4965 | // Likewise, it works when the destination type is an optional. |
| 4966 | test "*[N]T to ?[*]T" { | 4966 | test "*[N]T to ?[*]T" { |
| 4967 | var buf: [5]u8 = "hello"; | 4967 | var buf: [5]u8 = "hello".*; |
| 4968 | const x: ?[*]u8 = &buf; | 4968 | const x: ?[*]u8 = &buf; |
| 4969 | assert(x.?[4] == 'o'); | 4969 | assert(x.?[4] == 'o'); |
| 4970 | } | 4970 | } |
| ... | @@ -5135,7 +5135,7 @@ test "coercion of zero bit types" { | ... | @@ -5135,7 +5135,7 @@ test "coercion of zero bit types" { |
| 5135 | This kind of type resolution chooses a type that all peer types can coerce into. Here are | 5135 | This kind of type resolution chooses a type that all peer types can coerce into. Here are |
| 5136 | some examples: | 5136 | some examples: |
| 5137 | </p> | 5137 | </p> |
| 5138 | {#code_begin|test#} | 5138 | {#code_begin|test|peer_type_resolution#} |
| 5139 | const std = @import("std"); | 5139 | const std = @import("std"); |
| 5140 | const assert = std.debug.assert; | 5140 | const assert = std.debug.assert; |
| 5141 | const mem = std.mem; | 5141 | const mem = std.mem; |
| ... | @@ -5202,13 +5202,13 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { | ... | @@ -5202,13 +5202,13 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { |
| 5202 | } | 5202 | } |
| 5203 | test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" { | 5203 | test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" { |
| 5204 | { | 5204 | { |
| 5205 | var data = "hi"; | 5205 | var data = "hi".*; |
| 5206 | const slice = data[0..]; | 5206 | const slice = data[0..]; |
| 5207 | assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); | 5207 | assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); |
| 5208 | assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); | 5208 | assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); |
| 5209 | } | 5209 | } |
| 5210 | comptime { | 5210 | comptime { |
| 5211 | var data = "hi"; | 5211 | var data = "hi".*; |
| 5212 | const slice = data[0..]; | 5212 | const slice = data[0..]; |
| 5213 | assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); | 5213 | assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); |
| 5214 | assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); | 5214 | assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); |
| ... | @@ -8673,7 +8673,7 @@ pub fn main() void { | ... | @@ -8673,7 +8673,7 @@ pub fn main() void { |
| 8673 | <p>At compile-time:</p> | 8673 | <p>At compile-time:</p> |
| 8674 | {#code_begin|test_err|index 5 outside array of size 5#} | 8674 | {#code_begin|test_err|index 5 outside array of size 5#} |
| 8675 | comptime { | 8675 | comptime { |
| 8676 | const array = "hello"; | 8676 | const array: [5]u8 = "hello".*; |
| 8677 | const garbage = array[5]; | 8677 | const garbage = array[5]; |
| 8678 | } | 8678 | } |
| 8679 | {#code_end#} | 8679 | {#code_end#} |
| ... | @@ -9649,22 +9649,6 @@ test "assert in release fast mode" { | ... | @@ -9649,22 +9649,6 @@ test "assert in release fast mode" { |
| 9649 | </ul> | 9649 | </ul> |
| 9650 | {#see_also|Primitive Types#} | 9650 | {#see_also|Primitive Types#} |
| 9651 | {#header_close#} | 9651 | {#header_close#} |
| 9652 | {#header_open|C String Literals#} | ||
| 9653 | {#code_begin|exe#} | ||
| 9654 | {#link_libc#} | ||
| 9655 | extern fn puts([*]const u8) void; | ||
| 9656 | |||
| 9657 | pub fn main() void { | ||
| 9658 | puts(c"this has a null terminator"); | ||
| 9659 | puts( | ||
| 9660 | c\\and so | ||
| 9661 | c\\does this | ||
| 9662 | c\\multiline C string literal | ||
| 9663 | ); | ||
| 9664 | } | ||
| 9665 | {#code_end#} | ||
| 9666 | {#see_also|String Literals and Character Literals#} | ||
| 9667 | {#header_close#} | ||
| 9668 | 9652 | ||
| 9669 | {#header_open|Import from C Header File#} | 9653 | {#header_open|Import from C Header File#} |
| 9670 | <p> | 9654 | <p> |
| ... | @@ -9679,7 +9663,7 @@ const c = @cImport({ | ... | @@ -9679,7 +9663,7 @@ const c = @cImport({ |
| 9679 | @cInclude("stdio.h"); | 9663 | @cInclude("stdio.h"); |
| 9680 | }); | 9664 | }); |
| 9681 | pub fn main() void { | 9665 | pub fn main() void { |
| 9682 | _ = c.printf(c"hello\n"); | 9666 | _ = c.printf("hello\n"); |
| 9683 | } | 9667 | } |
| 9684 | {#code_end#} | 9668 | {#code_end#} |
| 9685 | <p> | 9669 | <p> |
src/analyze.cpp+1-17| ... | @@ -496,7 +496,7 @@ static void append_ptr_type_attrs(Buf *type_name, ZigType *ptr_type) { | ... | @@ -496,7 +496,7 @@ static void append_ptr_type_attrs(Buf *type_name, ZigType *ptr_type) { |
| 496 | } else if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) { | 496 | } else if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) { |
| 497 | buf_appendf(type_name, ":%" PRIu32, ptr_type->data.pointer.vector_index); | 497 | buf_appendf(type_name, ":%" PRIu32, ptr_type->data.pointer.vector_index); |
| 498 | } | 498 | } |
| 499 | buf_appendf(type_name, ")"); | 499 | buf_appendf(type_name, ") "); |
| 500 | } | 500 | } |
| 501 | buf_appendf(type_name, "%s%s%s", const_str, volatile_str, allow_zero_str); | 501 | buf_appendf(type_name, "%s%s%s", const_str, volatile_str, allow_zero_str); |
| 502 | if (ptr_type->data.pointer.inferred_struct_field != nullptr) { | 502 | if (ptr_type->data.pointer.inferred_struct_field != nullptr) { |
| ... | @@ -861,22 +861,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { | ... | @@ -861,22 +861,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { |
| 861 | entry->data.structure.fields[slice_len_index]->gen_index = 0; | 861 | entry->data.structure.fields[slice_len_index]->gen_index = 0; |
| 862 | } | 862 | } |
| 863 | 863 | ||
| 864 | ZigType *child_type = ptr_type->data.pointer.child_type; | ||
| 865 | if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile || | ||
| 866 | ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero) | ||
| 867 | { | ||
| 868 | ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false, | ||
| 869 | PtrLenUnknown, 0, 0, 0, false); | ||
| 870 | ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type); | ||
| 871 | |||
| 872 | entry->size_in_bits = peer_slice_type->size_in_bits; | ||
| 873 | entry->abi_size = peer_slice_type->abi_size; | ||
| 874 | entry->abi_align = peer_slice_type->abi_align; | ||
| 875 | |||
| 876 | *parent_pointer = entry; | ||
| 877 | return entry; | ||
| 878 | } | ||
| 879 | |||
| 880 | if (type_has_bits(ptr_type)) { | 864 | if (type_has_bits(ptr_type)) { |
| 881 | entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits; | 865 | entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits; |
| 882 | entry->abi_size = ptr_type->abi_size + g->builtin_types.entry_usize->abi_size; | 866 | entry->abi_size = ptr_type->abi_size + g->builtin_types.entry_usize->abi_size; |
src/codegen.cpp+3-2| ... | @@ -3752,7 +3752,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3752,7 +3752,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3752 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); | 3752 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); |
| 3753 | assert(array_type->data.structure.is_slice); | 3753 | assert(array_type->data.structure.is_slice); |
| 3754 | 3754 | ||
| 3755 | ZigType *ptr_type = instruction->base.value.type; | 3755 | ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry; |
| 3756 | if (!type_has_bits(ptr_type)) { | 3756 | if (!type_has_bits(ptr_type)) { |
| 3757 | if (safety_check_on) { | 3757 | if (safety_check_on) { |
| 3758 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind); | 3758 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind); |
| ... | @@ -3769,7 +3769,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3769,7 +3769,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3769 | assert(len_index != SIZE_MAX); | 3769 | assert(len_index != SIZE_MAX); |
| 3770 | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, ""); | 3770 | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, ""); |
| 3771 | LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, ""); | 3771 | LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, ""); |
| 3772 | add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len); | 3772 | LLVMIntPredicate upper_op = (ptr_type->data.pointer.sentinel != nullptr) ? LLVMIntULE : LLVMIntULT; |
| 3773 | add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, upper_op, len); | ||
| 3773 | } | 3774 | } |
| 3774 | 3775 | ||
| 3775 | size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; | 3776 | size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; |
src/ir.cpp+15-4| ... | @@ -18244,13 +18244,16 @@ static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructi | ... | @@ -18244,13 +18244,16 @@ static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructi |
| 18244 | 18244 | ||
| 18245 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) { | 18245 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) { |
| 18246 | assert(ptr_type->id == ZigTypeIdPointer); | 18246 | assert(ptr_type->id == ZigTypeIdPointer); |
| 18247 | return get_pointer_to_type_extra(g, | 18247 | return get_pointer_to_type_extra2(g, |
| 18248 | ptr_type->data.pointer.child_type, | 18248 | ptr_type->data.pointer.child_type, |
| 18249 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | 18249 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 18250 | ptr_type->data.pointer.ptr_len, | 18250 | ptr_type->data.pointer.ptr_len, |
| 18251 | new_align, | 18251 | new_align, |
| 18252 | ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes, | 18252 | ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes, |
| 18253 | ptr_type->data.pointer.allow_zero); | 18253 | ptr_type->data.pointer.allow_zero, |
| 18254 | ptr_type->data.pointer.vector_index, | ||
| 18255 | ptr_type->data.pointer.inferred_struct_field, | ||
| 18256 | ptr_type->data.pointer.sentinel); | ||
| 18254 | } | 18257 | } |
| 18255 | 18258 | ||
| 18256 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) { | 18259 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) { |
| ... | @@ -18595,8 +18598,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -18595,8 +18598,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 18595 | ConstExprValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index]; | 18598 | ConstExprValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index]; |
| 18596 | IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type); | 18599 | IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type); |
| 18597 | ConstExprValue *out_val = &result->value; | 18600 | ConstExprValue *out_val = &result->value; |
| 18601 | ZigType *slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry; | ||
| 18598 | uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint); | 18602 | uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint); |
| 18599 | if (index >= slice_len) { | 18603 | uint64_t full_slice_len = slice_len + |
| 18604 | ((slice_ptr_type->data.pointer.sentinel != nullptr) ? 1 : 0); | ||
| 18605 | if (index >= full_slice_len) { | ||
| 18600 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, | 18606 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| 18601 | buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64, | 18607 | buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64, |
| 18602 | index, slice_len)); | 18608 | index, slice_len)); |
| ... | @@ -18615,8 +18621,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -18615,8 +18621,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 18615 | { | 18621 | { |
| 18616 | size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index; | 18622 | size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index; |
| 18617 | uint64_t new_index = offset + index; | 18623 | uint64_t new_index = offset + index; |
| 18618 | ir_assert(new_index < ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len, | 18624 | if (ptr_field->data.x_ptr.data.base_array.array_val->data.x_array.special != |
| 18625 | ConstArraySpecialBuf) | ||
| 18626 | { | ||
| 18627 | ir_assert(new_index < | ||
| 18628 | ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len, | ||
| 18619 | &elem_ptr_instruction->base); | 18629 | &elem_ptr_instruction->base); |
| 18630 | } | ||
| 18620 | out_val->data.x_ptr.special = ConstPtrSpecialBaseArray; | 18631 | out_val->data.x_ptr.special = ConstPtrSpecialBaseArray; |
| 18621 | out_val->data.x_ptr.data.base_array.array_val = | 18632 | out_val->data.x_ptr.data.base_array.array_val = |
| 18622 | ptr_field->data.x_ptr.data.base_array.array_val; | 18633 | ptr_field->data.x_ptr.data.base_array.array_val; |
test/compile_errors.zig+9-8| ... | @@ -70,14 +70,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -70,14 +70,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 70 | 70 | ||
| 71 | cases.add( | 71 | cases.add( |
| 72 | "disallow coercion from non-null-terminated pointer to null-terminated pointer", | 72 | "disallow coercion from non-null-terminated pointer to null-terminated pointer", |
| 73 | \\extern fn puts(s: [*]null const u8) c_int; | 73 | \\extern fn puts(s: [*:0]const u8) c_int; |
| 74 | \\pub fn main() void { | 74 | \\pub fn main() void { |
| 75 | \\ const no_zero_array = [_]u8{'h', 'e', 'l', 'l', 'o'}; | 75 | \\ const no_zero_array = [_]u8{'h', 'e', 'l', 'l', 'o'}; |
| 76 | \\ const no_zero_ptr: [*]const u8 = &no_zero_array; | 76 | \\ const no_zero_ptr: [*]const u8 = &no_zero_array; |
| 77 | \\ _ = puts(no_zero_ptr); | 77 | \\ _ = puts(no_zero_ptr); |
| 78 | \\} | 78 | \\} |
| 79 | , | 79 | , |
| 80 | "tmp.zig:5:14: error: expected type '[*]null const u8', found '[*]const u8'", | 80 | "tmp.zig:5:14: error: expected type '[*:0]const u8', found '[*]const u8'", |
| 81 | ); | 81 | ); |
| 82 | 82 | ||
| 83 | cases.add( | 83 | cases.add( |
| ... | @@ -784,7 +784,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -784,7 +784,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 784 | \\ strValue = strValue orelse ""; | 784 | \\ strValue = strValue orelse ""; |
| 785 | \\} | 785 | \\} |
| 786 | , | 786 | , |
| 787 | "tmp.zig:3:32: error: expected type '[*c]u8', found '*const [0]null u8'", | 787 | "tmp.zig:3:32: error: expected type '[*c]u8', found '*const [0:0]u8'", |
| 788 | "tmp.zig:3:32: note: cast discards const qualifier", | 788 | "tmp.zig:3:32: note: cast discards const qualifier", |
| 789 | ); | 789 | ); |
| 790 | 790 | ||
| ... | @@ -2442,12 +2442,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2442,12 +2442,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2442 | ); | 2442 | ); |
| 2443 | 2443 | ||
| 2444 | cases.add( | 2444 | cases.add( |
| 2445 | "var not allowed in structs", | 2445 | "var makes structs required to be comptime known", |
| 2446 | \\export fn entry() void { | 2446 | \\export fn entry() void { |
| 2447 | \\ var s = (struct{v: var}){.v=@as(i32, 10)}; | 2447 | \\ const S = struct{v: var}; |
| 2448 | \\ var s = S{.v=@as(i32, 10)}; | ||
| 2448 | \\} | 2449 | \\} |
| 2449 | , | 2450 | , |
| 2450 | "tmp.zig:2:23: error: invalid token: 'var'", | 2451 | "tmp.zig:3:4: error: variable of type 'S' must be const or comptime", |
| 2451 | ); | 2452 | ); |
| 2452 | 2453 | ||
| 2453 | cases.add( | 2454 | cases.add( |
| ... | @@ -3357,7 +3358,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3357,7 +3358,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3357 | \\ return a; | 3358 | \\ return a; |
| 3358 | \\} | 3359 | \\} |
| 3359 | , | 3360 | , |
| 3360 | "tmp.zig:3:12: error: expected type 'i32', found '*const [1]null u8'", | 3361 | "tmp.zig:3:12: error: expected type 'i32', found '*const [1:0]u8'", |
| 3361 | ); | 3362 | ); |
| 3362 | 3363 | ||
| 3363 | cases.add( | 3364 | cases.add( |
| ... | @@ -6212,7 +6213,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -6212,7 +6213,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 6212 | \\} | 6213 | \\} |
| 6213 | \\pub extern fn foo(format: *const u8, ...) void; | 6214 | \\pub extern fn foo(format: *const u8, ...) void; |
| 6214 | , | 6215 | , |
| 6215 | "tmp.zig:2:16: error: expected type '*const u8', found '[5]null u8'", | 6216 | "tmp.zig:2:16: error: expected type '*const u8', found '[5:0]u8'", |
| 6216 | ); | 6217 | ); |
| 6217 | 6218 | ||
| 6218 | cases.add( | 6219 | cases.add( |
test/stage1/behavior/slice.zig+13| ... | @@ -65,3 +65,16 @@ test "slice type with custom alignment" { | ... | @@ -65,3 +65,16 @@ test "slice type with custom alignment" { |
| 65 | slice[1].anything = 42; | 65 | slice[1].anything = 42; |
| 66 | expect(array[1].anything == 42); | 66 | expect(array[1].anything == 42); |
| 67 | } | 67 | } |
| 68 | |||
| 69 | test "access len index of sentinel-terminated slice" { | ||
| 70 | const S = struct { | ||
| 71 | fn doTheTest() void { | ||
| 72 | var slice: [:0]const u8 = "hello"; | ||
| 73 | |||
| 74 | expect(slice.len == 5); | ||
| 75 | expect(slice[5] == 0); | ||
| 76 | } | ||
| 77 | }; | ||
| 78 | S.doTheTest(); | ||
| 79 | comptime S.doTheTest(); | ||
| 80 | } |