authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-24 02:14:21-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-24 02:14:21-05:00
log4c7b52503b064b8be2f2afd4152311aff1941d92
tree3f8ea590d0dc73dbfd94b0863aa1bb8c32e4d0b9
parent2dd20aa04a35f46a189d0aaa5d2d628e46a77999
signaturelock-open Commit is signed but in an unrecognized format.

all tests passing


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
954954 .AngleBracketAngleBracketRight,
955955 .AngleBracketAngleBracketRightEqual,
956956 .Tilde,
957 .BracketStarBracket,
958 .BracketStarCBracket,
959957 => try writeEscaped(out, src[token.start..token.end]),
960958
961959 .Invalid, .Invalid_ampersands => return parseError(
doc/langref.html.in+12-28
......@@ -563,7 +563,7 @@ const mem = @import("std").mem;
563563
564564test "string literals" {
565565 const bytes = "hello";
566 assert(@typeOf(bytes) == *const [5]null u8);
566 assert(@typeOf(bytes) == *const [5:0]u8);
567567 assert(bytes.len == 5);
568568 assert(bytes[1] == 'e');
569569 assert(bytes[5] == 0);
......@@ -1795,7 +1795,7 @@ test "null terminated array" {
17951795
17961796 assert(@typeOf(array) == [4:0]u8);
17971797 assert(array.len == 4);
1798 assert(slice[4] == 0);
1798 assert(array[4] == 0);
17991799}
18001800 {#code_end#}
18011801 {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Slices#}
......@@ -4863,7 +4863,7 @@ const assert = std.debug.assert;
48634863const mem = std.mem;
48644864
48654865test "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"};
48674867 const x: [*]const ?[*]const u8 = &window_name;
48684868 assert(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));
48694869}
......@@ -4905,7 +4905,7 @@ test "float widening" {
49054905 {#code_end#}
49064906 {#header_close#}
49074907 {#header_open|Type Coercion: Arrays and Pointers#}
4908 {#code_begin|test#}
4908 {#code_begin|test|coerce_arrays_and_ptrs#}
49094909const std = @import("std");
49104910const assert = std.debug.assert;
49114911
......@@ -4944,7 +4944,7 @@ test "[N]T to ?[]const T" {
49444944
49454945// In this cast, the array length becomes the slice length.
49464946test "*[N]T to []T" {
4947 var buf: [5]u8 = "hello";
4947 var buf: [5]u8 = "hello".*;
49484948 const x: []u8 = &buf;
49494949 assert(std.mem.eql(u8, x, "hello"));
49504950
......@@ -4956,7 +4956,7 @@ test "*[N]T to []T" {
49564956// Single-item pointers to arrays can be coerced to
49574957// unknown length pointers.
49584958test "*[N]T to [*]T" {
4959 var buf: [5]u8 = "hello";
4959 var buf: [5]u8 = "hello".*;
49604960 const x: [*]u8 = &buf;
49614961 assert(x[4] == 'o');
49624962 // x[5] would be an uncaught out of bounds pointer dereference!
......@@ -4964,7 +4964,7 @@ test "*[N]T to [*]T" {
49644964
49654965// Likewise, it works when the destination type is an optional.
49664966test "*[N]T to ?[*]T" {
4967 var buf: [5]u8 = "hello";
4967 var buf: [5]u8 = "hello".*;
49684968 const x: ?[*]u8 = &buf;
49694969 assert(x.?[4] == 'o');
49704970}
......@@ -5135,7 +5135,7 @@ test "coercion of zero bit types" {
51355135 This kind of type resolution chooses a type that all peer types can coerce into. Here are
51365136 some examples:
51375137 </p>
5138 {#code_begin|test#}
5138 {#code_begin|test|peer_type_resolution#}
51395139const std = @import("std");
51405140const assert = std.debug.assert;
51415141const mem = std.mem;
......@@ -5202,13 +5202,13 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
52025202}
52035203test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
52045204 {
5205 var data = "hi";
5205 var data = "hi".*;
52065206 const slice = data[0..];
52075207 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
52085208 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
52095209 }
52105210 comptime {
5211 var data = "hi";
5211 var data = "hi".*;
52125212 const slice = data[0..];
52135213 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
52145214 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
......@@ -8673,7 +8673,7 @@ pub fn main() void {
86738673 <p>At compile-time:</p>
86748674 {#code_begin|test_err|index 5 outside array of size 5#}
86758675comptime {
8676 const array = "hello";
8676 const array: [5]u8 = "hello".*;
86778677 const garbage = array[5];
86788678}
86798679 {#code_end#}
......@@ -9649,22 +9649,6 @@ test "assert in release fast mode" {
96499649 </ul>
96509650 {#see_also|Primitive Types#}
96519651 {#header_close#}
9652 {#header_open|C String Literals#}
9653 {#code_begin|exe#}
9654 {#link_libc#}
9655extern fn puts([*]const u8) void;
9656
9657pub 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#}
96689652
96699653 {#header_open|Import from C Header File#}
96709654 <p>
......@@ -9679,7 +9663,7 @@ const c = @cImport({
96799663 @cInclude("stdio.h");
96809664});
96819665pub fn main() void {
9682 _ = c.printf(c"hello\n");
9666 _ = c.printf("hello\n");
96839667}
96849668 {#code_end#}
96859669 <p>
src/analyze.cpp+1-17
......@@ -496,7 +496,7 @@ static void append_ptr_type_attrs(Buf *type_name, ZigType *ptr_type) {
496496 } else if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
497497 buf_appendf(type_name, ":%" PRIu32, ptr_type->data.pointer.vector_index);
498498 }
499 buf_appendf(type_name, ")");
499 buf_appendf(type_name, ") ");
500500 }
501501 buf_appendf(type_name, "%s%s%s", const_str, volatile_str, allow_zero_str);
502502 if (ptr_type->data.pointer.inferred_struct_field != nullptr) {
......@@ -861,22 +861,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
861861 entry->data.structure.fields[slice_len_index]->gen_index = 0;
862862 }
863863
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
880864 if (type_has_bits(ptr_type)) {
881865 entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits;
882866 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
37523752 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
37533753 assert(array_type->data.structure.is_slice);
37543754
3755 ZigType *ptr_type = instruction->base.value.type;
3755 ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
37563756 if (!type_has_bits(ptr_type)) {
37573757 if (safety_check_on) {
37583758 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind);
......@@ -3769,7 +3769,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
37693769 assert(len_index != SIZE_MAX);
37703770 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, "");
37713771 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);
37733774 }
37743775
37753776 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
1824418244
1824518245static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) {
1824618246 assert(ptr_type->id == ZigTypeIdPointer);
18247 return get_pointer_to_type_extra(g,
18247 return get_pointer_to_type_extra2(g,
1824818248 ptr_type->data.pointer.child_type,
1824918249 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
1825018250 ptr_type->data.pointer.ptr_len,
1825118251 new_align,
1825218252 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);
1825418257}
1825518258
1825618259static 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
1859518598 ConstExprValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index];
1859618599 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
1859718600 ConstExprValue *out_val = &result->value;
18601 ZigType *slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
1859818602 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) {
1860018606 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
1860118607 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,
1860218608 index, slice_len));
......@@ -18615,8 +18621,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1861518621 {
1861618622 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
1861718623 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,
1861918629 &elem_ptr_instruction->base);
18630 }
1862018631 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
1862118632 out_val->data.x_ptr.data.base_array.array_val =
1862218633 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 {
7070
7171 cases.add(
7272 "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;
7474 \\pub fn main() void {
7575 \\ const no_zero_array = [_]u8{'h', 'e', 'l', 'l', 'o'};
7676 \\ const no_zero_ptr: [*]const u8 = &no_zero_array;
7777 \\ _ = puts(no_zero_ptr);
7878 \\}
7979 ,
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'",
8181 );
8282
8383 cases.add(
......@@ -784,7 +784,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
784784 \\ strValue = strValue orelse "";
785785 \\}
786786 ,
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'",
788788 "tmp.zig:3:32: note: cast discards const qualifier",
789789 );
790790
......@@ -2442,12 +2442,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
24422442 );
24432443
24442444 cases.add(
2445 "var not allowed in structs",
2445 "var makes structs required to be comptime known",
24462446 \\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)};
24482449 \\}
24492450 ,
2450 "tmp.zig:2:23: error: invalid token: 'var'",
2451 "tmp.zig:3:4: error: variable of type 'S' must be const or comptime",
24512452 );
24522453
24532454 cases.add(
......@@ -3357,7 +3358,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
33573358 \\ return a;
33583359 \\}
33593360 ,
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'",
33613362 );
33623363
33633364 cases.add(
......@@ -6212,7 +6213,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
62126213 \\}
62136214 \\pub extern fn foo(format: *const u8, ...) void;
62146215 ,
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'",
62166217 );
62176218
62186219 cases.add(
test/stage1/behavior/slice.zig+13
......@@ -65,3 +65,16 @@ test "slice type with custom alignment" {
6565 slice[1].anything = 42;
6666 expect(array[1].anything == 42);
6767}
68
69test "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}