| author | |
| committer | |
| log | 21f344b3b903b41fd4793faa82a4ac26ad2544aa |
| tree | 713437712564e80b512629fa657da5f7cb56730b |
| parent | 1aa978f32e88b4c83fde95f62938c97c7c22164c |
| signature |
as well as `@typeInfo` and `@Type`14 files changed, 240 insertions(+), 123 deletions(-)
lib/std/builtin.zig+1| ... | ... | @@ -161,6 +161,7 @@ pub const TypeInfo = union(enum) { |
| 161 | 161 | pub const Array = struct { |
| 162 | 162 | len: comptime_int, |
| 163 | 163 | child: type, |
| 164 | is_null_terminated: bool, | |
| 164 | 165 | }; |
| 165 | 166 | |
| 166 | 167 | /// This data structure is used by the Zig language code generation and |
lib/std/zig/ast.zig+13-3| ... | ... | @@ -137,6 +137,7 @@ pub const Error = union(enum) { |
| 137 | 137 | ExpectedCallOrFnProto: ExpectedCallOrFnProto, |
| 138 | 138 | ExpectedSliceOrRBracket: ExpectedSliceOrRBracket, |
| 139 | 139 | ExtraAlignQualifier: ExtraAlignQualifier, |
| 140 | ExtraNullQualifier: ExtraNullQualifier, | |
| 140 | 141 | ExtraConstQualifier: ExtraConstQualifier, |
| 141 | 142 | ExtraVolatileQualifier: ExtraVolatileQualifier, |
| 142 | 143 | ExtraAllowZeroQualifier: ExtraAllowZeroQualifier, |
| ... | ... | @@ -184,6 +185,7 @@ pub const Error = union(enum) { |
| 184 | 185 | .ExpectedCallOrFnProto => |*x| return x.render(tokens, stream), |
| 185 | 186 | .ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream), |
| 186 | 187 | .ExtraAlignQualifier => |*x| return x.render(tokens, stream), |
| 188 | .ExtraNullQualifier => |*x| return x.render(tokens, stream), | |
| 187 | 189 | .ExtraConstQualifier => |*x| return x.render(tokens, stream), |
| 188 | 190 | .ExtraVolatileQualifier => |*x| return x.render(tokens, stream), |
| 189 | 191 | .ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream), |
| ... | ... | @@ -233,6 +235,7 @@ pub const Error = union(enum) { |
| 233 | 235 | .ExpectedCallOrFnProto => |x| return x.node.firstToken(), |
| 234 | 236 | .ExpectedSliceOrRBracket => |x| return x.token, |
| 235 | 237 | .ExtraAlignQualifier => |x| return x.token, |
| 238 | .ExtraNullQualifier => |x| return x.token, | |
| 236 | 239 | .ExtraConstQualifier => |x| return x.token, |
| 237 | 240 | .ExtraVolatileQualifier => |x| return x.token, |
| 238 | 241 | .ExtraAllowZeroQualifier => |x| return x.token, |
| ... | ... | @@ -293,6 +296,7 @@ pub const Error = union(enum) { |
| 293 | 296 | pub const ExpectedPubItem = SimpleError("Expected function or variable declaration after pub"); |
| 294 | 297 | pub const UnattachedDocComment = SimpleError("Unattached documentation comment"); |
| 295 | 298 | pub const ExtraAlignQualifier = SimpleError("Extra align qualifier"); |
| 299 | pub const ExtraNullQualifier = SimpleError("Extra null qualifier"); | |
| 296 | 300 | pub const ExtraConstQualifier = SimpleError("Extra const qualifier"); |
| 297 | 301 | pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier"); |
| 298 | 302 | pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier"); |
| ... | ... | @@ -1538,7 +1542,7 @@ pub const Node = struct { |
| 1538 | 1542 | |
| 1539 | 1543 | pub const Op = union(enum) { |
| 1540 | 1544 | AddressOf, |
| 1541 | ArrayType: *Node, | |
| 1545 | ArrayType: ArrayInfo, | |
| 1542 | 1546 | Await, |
| 1543 | 1547 | BitNot, |
| 1544 | 1548 | BoolNot, |
| ... | ... | @@ -1552,11 +1556,17 @@ pub const Node = struct { |
| 1552 | 1556 | Try, |
| 1553 | 1557 | }; |
| 1554 | 1558 | |
| 1559 | pub const ArrayInfo = struct { | |
| 1560 | len_expr: *Node, | |
| 1561 | null_token: ?TokenIndex, | |
| 1562 | }; | |
| 1563 | ||
| 1555 | 1564 | pub const PtrInfo = struct { |
| 1556 | 1565 | allowzero_token: ?TokenIndex, |
| 1557 | 1566 | align_info: ?Align, |
| 1558 | 1567 | const_token: ?TokenIndex, |
| 1559 | 1568 | volatile_token: ?TokenIndex, |
| 1569 | null_token: ?TokenIndex, | |
| 1560 | 1570 | |
| 1561 | 1571 | pub const Align = struct { |
| 1562 | 1572 | node: *Node, |
| ... | ... | @@ -1588,8 +1598,8 @@ pub const Node = struct { |
| 1588 | 1598 | } |
| 1589 | 1599 | }, |
| 1590 | 1600 | |
| 1591 | Op.ArrayType => |size_expr| { | |
| 1592 | if (i < 1) return size_expr; | |
| 1601 | Op.ArrayType => |array_info| { | |
| 1602 | if (i < 1) return array_info.len_expr; | |
| 1593 | 1603 | i -= 1; |
| 1594 | 1604 | }, |
| 1595 | 1605 |
lib/std/zig/parse.zig+31-8| ... | ... | @@ -1085,7 +1085,7 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf |
| 1085 | 1085 | const node = try arena.create(Node.SuffixOp); |
| 1086 | 1086 | node.* = Node.SuffixOp{ |
| 1087 | 1087 | .base = Node{ .id = .SuffixOp }, |
| 1088 | .lhs = .{.node = undefined}, // set by caller | |
| 1088 | .lhs = .{ .node = undefined }, // set by caller | |
| 1089 | 1089 | .op = op, |
| 1090 | 1090 | .rtoken = try expectToken(it, tree, .RBrace), |
| 1091 | 1091 | }; |
| ... | ... | @@ -1138,7 +1138,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1138 | 1138 | |
| 1139 | 1139 | while (try parseSuffixOp(arena, it, tree)) |node| { |
| 1140 | 1140 | switch (node.id) { |
| 1141 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res}, | |
| 1141 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{ .node = res }, | |
| 1142 | 1142 | .InfixOp => node.cast(Node.InfixOp).?.lhs = res, |
| 1143 | 1143 | else => unreachable, |
| 1144 | 1144 | } |
| ... | ... | @@ -1154,7 +1154,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1154 | 1154 | const node = try arena.create(Node.SuffixOp); |
| 1155 | 1155 | node.* = Node.SuffixOp{ |
| 1156 | 1156 | .base = Node{ .id = .SuffixOp }, |
| 1157 | .lhs = .{.node = res}, | |
| 1157 | .lhs = .{ .node = res }, | |
| 1158 | 1158 | .op = Node.SuffixOp.Op{ |
| 1159 | 1159 | .Call = Node.SuffixOp.Op.Call{ |
| 1160 | 1160 | .params = params.list, |
| ... | ... | @@ -1171,7 +1171,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1171 | 1171 | while (true) { |
| 1172 | 1172 | if (try parseSuffixOp(arena, it, tree)) |node| { |
| 1173 | 1173 | switch (node.id) { |
| 1174 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res}, | |
| 1174 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{ .node = res }, | |
| 1175 | 1175 | .InfixOp => node.cast(Node.InfixOp).?.lhs = res, |
| 1176 | 1176 | else => unreachable, |
| 1177 | 1177 | } |
| ... | ... | @@ -1182,7 +1182,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1182 | 1182 | const call = try arena.create(Node.SuffixOp); |
| 1183 | 1183 | call.* = Node.SuffixOp{ |
| 1184 | 1184 | .base = Node{ .id = .SuffixOp }, |
| 1185 | .lhs = .{.node = res}, | |
| 1185 | .lhs = .{ .node = res }, | |
| 1186 | 1186 | .op = Node.SuffixOp.Op{ |
| 1187 | 1187 | .Call = Node.SuffixOp.Op.Call{ |
| 1188 | 1188 | .params = params.list, |
| ... | ... | @@ -1531,7 +1531,7 @@ fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 1531 | 1531 | |
| 1532 | 1532 | // anon container literal |
| 1533 | 1533 | if (try parseInitList(arena, it, tree)) |node| { |
| 1534 | node.lhs = .{.dot = dot}; | |
| 1534 | node.lhs = .{ .dot = dot }; | |
| 1535 | 1535 | return &node.base; |
| 1536 | 1536 | } |
| 1537 | 1537 | |
| ... | ... | @@ -2252,6 +2252,16 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 2252 | 2252 | .SliceType => |*slice_type| { |
| 2253 | 2253 | // Collect pointer qualifiers in any order, but disallow duplicates |
| 2254 | 2254 | while (true) { |
| 2255 | if (eatToken(it, .Keyword_null)) |null_token| { | |
| 2256 | if (slice_type.null_token != null) { | |
| 2257 | try tree.errors.push(AstError{ | |
| 2258 | .ExtraNullQualifier = AstError.ExtraNullQualifier{ .token = it.index }, | |
| 2259 | }); | |
| 2260 | return error.ParseError; | |
| 2261 | } | |
| 2262 | slice_type.null_token = null_token; | |
| 2263 | continue; | |
| 2264 | } | |
| 2255 | 2265 | if (try parseByteAlign(arena, it, tree)) |align_expr| { |
| 2256 | 2266 | if (slice_type.align_info != null) { |
| 2257 | 2267 | try tree.errors.push(AstError{ |
| ... | ... | @@ -2313,6 +2323,10 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 2313 | 2323 | &prefix_op.op.PtrType; |
| 2314 | 2324 | |
| 2315 | 2325 | while (true) { |
| 2326 | if (eatToken(it, .Keyword_null)) |null_token| { | |
| 2327 | ptr_info.null_token = null_token; | |
| 2328 | continue; | |
| 2329 | } | |
| 2316 | 2330 | if (eatToken(it, .Keyword_align)) |align_token| { |
| 2317 | 2331 | const lparen = try expectToken(it, tree, .LParen); |
| 2318 | 2332 | const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{ |
| ... | ... | @@ -2460,9 +2474,15 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No |
| 2460 | 2474 | const lbracket = eatToken(it, .LBracket) orelse return null; |
| 2461 | 2475 | const expr = try parseExpr(arena, it, tree); |
| 2462 | 2476 | const rbracket = try expectToken(it, tree, .RBracket); |
| 2477 | const null_token = eatToken(it, .Keyword_null); | |
| 2463 | 2478 | |
| 2464 | const op = if (expr) |element_type| | |
| 2465 | Node.PrefixOp.Op{ .ArrayType = element_type } | |
| 2479 | const op = if (expr) |len_expr| | |
| 2480 | Node.PrefixOp.Op{ | |
| 2481 | .ArrayType = .{ | |
| 2482 | .len_expr = len_expr, | |
| 2483 | .null_token = null_token, | |
| 2484 | }, | |
| 2485 | } | |
| 2466 | 2486 | else |
| 2467 | 2487 | Node.PrefixOp.Op{ |
| 2468 | 2488 | .SliceType = Node.PrefixOp.PtrInfo{ |
| ... | ... | @@ -2470,6 +2490,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No |
| 2470 | 2490 | .align_info = null, |
| 2471 | 2491 | .const_token = null, |
| 2472 | 2492 | .volatile_token = null, |
| 2493 | .null_token = null, | |
| 2473 | 2494 | }, |
| 2474 | 2495 | }; |
| 2475 | 2496 | |
| ... | ... | @@ -2505,6 +2526,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 2505 | 2526 | .align_info = null, |
| 2506 | 2527 | .const_token = null, |
| 2507 | 2528 | .volatile_token = null, |
| 2529 | .null_token = null, | |
| 2508 | 2530 | }, |
| 2509 | 2531 | }, |
| 2510 | 2532 | .rhs = undefined, // set by caller |
| ... | ... | @@ -2522,6 +2544,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 2522 | 2544 | .align_info = null, |
| 2523 | 2545 | .const_token = null, |
| 2524 | 2546 | .volatile_token = null, |
| 2547 | .null_token = null, | |
| 2525 | 2548 | }, |
| 2526 | 2549 | }, |
| 2527 | 2550 | .rhs = undefined, // set by caller |
lib/std/zig/parser_test.zig+3| ... | ... | @@ -1552,6 +1552,7 @@ test "zig fmt: pointer attributes" { |
| 1552 | 1552 | \\extern fn f2(s: **align(1) *const *volatile u8) c_int; |
| 1553 | 1553 | \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int; |
| 1554 | 1554 | \\extern fn f4(s: *align(1) const volatile u8) c_int; |
| 1555 | \\extern fn f5(s: [*]null align(1) const volatile u8) c_int; | |
| 1555 | 1556 | \\ |
| 1556 | 1557 | ); |
| 1557 | 1558 | } |
| ... | ... | @@ -1562,6 +1563,7 @@ test "zig fmt: slice attributes" { |
| 1562 | 1563 | \\extern fn f2(s: **align(1) *const *volatile u8) c_int; |
| 1563 | 1564 | \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int; |
| 1564 | 1565 | \\extern fn f4(s: *align(1) const volatile u8) c_int; |
| 1566 | \\extern fn f5(s: [*]null align(1) const volatile u8) c_int; | |
| 1565 | 1567 | \\ |
| 1566 | 1568 | ); |
| 1567 | 1569 | } |
| ... | ... | @@ -1889,6 +1891,7 @@ test "zig fmt: arrays" { |
| 1889 | 1891 | \\ 2, |
| 1890 | 1892 | \\ }; |
| 1891 | 1893 | \\ const a: [0]u8 = []u8{}; |
| 1894 | \\ const x: [4]null u8 = undefined; | |
| 1892 | 1895 | \\} |
| 1893 | 1896 | \\ |
| 1894 | 1897 | ); |
lib/std/zig/render.zig+9-3| ... | ... | @@ -423,6 +423,9 @@ fn renderExpression( |
| 423 | 423 | else => @as(usize, 0), |
| 424 | 424 | }; |
| 425 | 425 | try renderTokenOffset(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None, star_offset); // * |
| 426 | if (ptr_info.null_token) |null_token| { | |
| 427 | try renderToken(tree, stream, null_token, indent, start_col, Space.Space); // null | |
| 428 | } | |
| 426 | 429 | if (ptr_info.allowzero_token) |allowzero_token| { |
| 427 | 430 | try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero |
| 428 | 431 | } |
| ... | ... | @@ -499,9 +502,9 @@ fn renderExpression( |
| 499 | 502 | } |
| 500 | 503 | }, |
| 501 | 504 | |
| 502 | ast.Node.PrefixOp.Op.ArrayType => |array_index| { | |
| 505 | ast.Node.PrefixOp.Op.ArrayType => |array_info| { | |
| 503 | 506 | const lbracket = prefix_op_node.op_token; |
| 504 | const rbracket = tree.nextToken(array_index.lastToken()); | |
| 507 | const rbracket = tree.nextToken(array_info.len_expr.lastToken()); | |
| 505 | 508 | |
| 506 | 509 | try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ |
| 507 | 510 | |
| ... | ... | @@ -509,7 +512,7 @@ fn renderExpression( |
| 509 | 512 | const ends_with_comment = tree.tokens.at(rbracket - 1).id == .LineComment; |
| 510 | 513 | const new_indent = if (ends_with_comment) indent + indent_delta else indent; |
| 511 | 514 | const new_space = if (ends_with_comment) Space.Newline else Space.None; |
| 512 | try renderExpression(allocator, stream, tree, new_indent, start_col, array_index, new_space); | |
| 515 | try renderExpression(allocator, stream, tree, new_indent, start_col, array_info.len_expr, new_space); | |
| 513 | 516 | if (starts_with_comment) { |
| 514 | 517 | try stream.writeByte('\n'); |
| 515 | 518 | } |
| ... | ... | @@ -517,6 +520,9 @@ fn renderExpression( |
| 517 | 520 | try stream.writeByteNTimes(' ', indent); |
| 518 | 521 | } |
| 519 | 522 | try renderToken(tree, stream, rbracket, indent, start_col, Space.None); // ] |
| 523 | if (array_info.null_token) |null_token| { | |
| 524 | try renderToken(tree, stream, null_token, indent, start_col, Space.Space); // null | |
| 525 | } | |
| 520 | 526 | }, |
| 521 | 527 | ast.Node.PrefixOp.Op.BitNot, |
| 522 | 528 | ast.Node.PrefixOp.Op.BoolNot, |
src-self-hosted/translate_c.zig+1| ... | ... | @@ -1118,6 +1118,7 @@ fn transCreateNodePtrType( |
| 1118 | 1118 | .align_info = null, |
| 1119 | 1119 | .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null, |
| 1120 | 1120 | .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null, |
| 1121 | .null_token = null, | |
| 1121 | 1122 | }, |
| 1122 | 1123 | }, |
| 1123 | 1124 | .rhs = undefined, // translate and set afterward |
src/all_types.hpp+5| ... | ... | @@ -358,6 +358,7 @@ struct LazyValueSliceType { |
| 358 | 358 | bool is_const; |
| 359 | 359 | bool is_volatile; |
| 360 | 360 | bool is_allowzero; |
| 361 | bool is_null_terminated; | |
| 361 | 362 | }; |
| 362 | 363 | |
| 363 | 364 | struct LazyValuePtrType { |
| ... | ... | @@ -1234,6 +1235,7 @@ struct ZigTypeFloat { |
| 1234 | 1235 | struct ZigTypeArray { |
| 1235 | 1236 | ZigType *child_type; |
| 1236 | 1237 | uint64_t len; |
| 1238 | bool is_null_terminated; | |
| 1237 | 1239 | }; |
| 1238 | 1240 | |
| 1239 | 1241 | struct TypeStructField { |
| ... | ... | @@ -1775,6 +1777,7 @@ struct TypeId { |
| 1775 | 1777 | struct { |
| 1776 | 1778 | ZigType *child_type; |
| 1777 | 1779 | uint64_t size; |
| 1780 | bool is_null_terminated; | |
| 1778 | 1781 | } array; |
| 1779 | 1782 | struct { |
| 1780 | 1783 | bool is_signed; |
| ... | ... | @@ -2986,6 +2989,7 @@ struct IrInstructionArrayType { |
| 2986 | 2989 | |
| 2987 | 2990 | IrInstruction *size; |
| 2988 | 2991 | IrInstruction *child_type; |
| 2992 | bool is_null_terminated; | |
| 2989 | 2993 | }; |
| 2990 | 2994 | |
| 2991 | 2995 | struct IrInstructionPtrType { |
| ... | ... | @@ -3015,6 +3019,7 @@ struct IrInstructionSliceType { |
| 3015 | 3019 | bool is_const; |
| 3016 | 3020 | bool is_volatile; |
| 3017 | 3021 | bool is_allow_zero; |
| 3022 | bool is_null_terminated; | |
| 3018 | 3023 | }; |
| 3019 | 3024 | |
| 3020 | 3025 | struct IrInstructionGlobalAsm { |
src/analyze.cpp+18-13| ... | ... | @@ -752,11 +752,12 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa |
| 752 | 752 | return entry; |
| 753 | 753 | } |
| 754 | 754 | |
| 755 | ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) { | |
| 755 | ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bool is_null_terminated) { | |
| 756 | 756 | TypeId type_id = {}; |
| 757 | 757 | type_id.id = ZigTypeIdArray; |
| 758 | 758 | type_id.data.array.child_type = child_type; |
| 759 | 759 | type_id.data.array.size = array_size; |
| 760 | type_id.data.array.is_null_terminated = is_null_terminated; | |
| 760 | 761 | auto existing_entry = g->type_table.maybe_get(type_id); |
| 761 | 762 | if (existing_entry) { |
| 762 | 763 | return existing_entry->value; |
| ... | ... | @@ -769,12 +770,14 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) { |
| 769 | 770 | buf_resize(&entry->name, 0); |
| 770 | 771 | buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name)); |
| 771 | 772 | |
| 772 | entry->size_in_bits = child_type->size_in_bits * array_size; | |
| 773 | size_t full_array_size = array_size + (is_null_terminated ? 1 : 0); | |
| 774 | entry->size_in_bits = child_type->size_in_bits * full_array_size; | |
| 773 | 775 | entry->abi_align = child_type->abi_align; |
| 774 | entry->abi_size = child_type->abi_size * array_size; | |
| 776 | entry->abi_size = child_type->abi_size * full_array_size; | |
| 775 | 777 | |
| 776 | 778 | entry->data.array.child_type = child_type; |
| 777 | 779 | entry->data.array.len = array_size; |
| 780 | entry->data.array.is_null_terminated = is_null_terminated; | |
| 778 | 781 | |
| 779 | 782 | g->type_table.put(type_id, entry); |
| 780 | 783 | return entry; |
| ... | ... | @@ -782,7 +785,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) { |
| 782 | 785 | |
| 783 | 786 | ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { |
| 784 | 787 | assert(ptr_type->id == ZigTypeIdPointer); |
| 785 | assert(ptr_type->data.pointer.ptr_len == PtrLenUnknown); | |
| 788 | assert(ptr_type->data.pointer.ptr_len == PtrLenUnknown || ptr_type->data.pointer.ptr_len == PtrLenNull); | |
| 786 | 789 | |
| 787 | 790 | ZigType **parent_pointer = &ptr_type->data.pointer.slice_parent; |
| 788 | 791 | if (*parent_pointer) { |
| ... | ... | @@ -5615,7 +5618,7 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) { |
| 5615 | 5618 | } |
| 5616 | 5619 | |
| 5617 | 5620 | const_val->special = ConstValSpecialStatic; |
| 5618 | const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str)); | |
| 5621 | const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), false); | |
| 5619 | 5622 | const_val->data.x_array.special = ConstArraySpecialBuf; |
| 5620 | 5623 | const_val->data.x_array.data.s_buf = str; |
| 5621 | 5624 | |
| ... | ... | @@ -5633,7 +5636,7 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) { |
| 5633 | 5636 | size_t len_with_null = buf_len(str) + 1; |
| 5634 | 5637 | ConstExprValue *array_val = create_const_vals(1); |
| 5635 | 5638 | array_val->special = ConstValSpecialStatic; |
| 5636 | array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null); | |
| 5639 | array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null, false); | |
| 5637 | 5640 | // TODO buf optimization |
| 5638 | 5641 | array_val->data.x_array.data.s_none.elements = create_const_vals(len_with_null); |
| 5639 | 5642 | for (size_t i = 0; i < buf_len(str); i += 1) { |
| ... | ... | @@ -6071,7 +6074,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { |
| 6071 | 6074 | |
| 6072 | 6075 | fields.append({"@stack_trace", get_stack_trace_type(g), 0}); |
| 6073 | 6076 | fields.append({"@instruction_addresses", |
| 6074 | get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0}); | |
| 6077 | get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, false), 0}); | |
| 6075 | 6078 | } |
| 6076 | 6079 | |
| 6077 | 6080 | frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name), |
| ... | ... | @@ -6279,7 +6282,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { |
| 6279 | 6282 | if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) { |
| 6280 | 6283 | fields.append({"@stack_trace", get_stack_trace_type(g), 0}); |
| 6281 | 6284 | fields.append({"@instruction_addresses", |
| 6282 | get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0}); | |
| 6285 | get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, false), 0}); | |
| 6283 | 6286 | } |
| 6284 | 6287 | |
| 6285 | 6288 | for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) { |
| ... | ... | @@ -7043,8 +7046,9 @@ uint32_t type_id_hash(TypeId x) { |
| 7043 | 7046 | (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) + |
| 7044 | 7047 | (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881); |
| 7045 | 7048 | case ZigTypeIdArray: |
| 7046 | return hash_ptr(x.data.array.child_type) + | |
| 7047 | ((uint32_t)x.data.array.size ^ (uint32_t)2122979968); | |
| 7049 | return hash_ptr(x.data.array.child_type) * | |
| 7050 | ((uint32_t)x.data.array.size ^ (uint32_t)2122979968) * | |
| 7051 | ((uint32_t)x.data.array.is_null_terminated ^ (uint32_t)2048352596); | |
| 7048 | 7052 | case ZigTypeIdInt: |
| 7049 | 7053 | return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) + |
| 7050 | 7054 | (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557); |
| ... | ... | @@ -7106,7 +7110,8 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 7106 | 7110 | ); |
| 7107 | 7111 | case ZigTypeIdArray: |
| 7108 | 7112 | return a.data.array.child_type == b.data.array.child_type && |
| 7109 | a.data.array.size == b.data.array.size; | |
| 7113 | a.data.array.size == b.data.array.size && | |
| 7114 | a.data.array.is_null_terminated == b.data.array.is_null_terminated; | |
| 7110 | 7115 | case ZigTypeIdInt: |
| 7111 | 7116 | return a.data.integer.is_signed == b.data.integer.is_signed && |
| 7112 | 7117 | a.data.integer.bit_count == b.data.integer.bit_count; |
| ... | ... | @@ -8292,7 +8297,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta |
| 8292 | 8297 | size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size; |
| 8293 | 8298 | if (padding_bytes > 0) { |
| 8294 | 8299 | ZigType *u8_type = get_int_type(g, false, 8); |
| 8295 | ZigType *padding_array = get_array_type(g, u8_type, padding_bytes); | |
| 8300 | ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, false); | |
| 8296 | 8301 | LLVMTypeRef union_element_types[] = { |
| 8297 | 8302 | most_aligned_union_member->type_entry->llvm_type, |
| 8298 | 8303 | get_llvm_type(g, padding_array), |
| ... | ... | @@ -8326,7 +8331,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta |
| 8326 | 8331 | union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry); |
| 8327 | 8332 | } else { |
| 8328 | 8333 | ZigType *u8_type = get_int_type(g, false, 8); |
| 8329 | ZigType *padding_array = get_array_type(g, u8_type, padding_bytes); | |
| 8334 | ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, false); | |
| 8330 | 8335 | LLVMTypeRef union_element_types[] = { |
| 8331 | 8336 | get_llvm_type(g, most_aligned_union_member->type_entry), |
| 8332 | 8337 | get_llvm_type(g, padding_array), |
src/analyze.hpp+1-1| ... | ... | @@ -33,7 +33,7 @@ ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type); |
| 33 | 33 | ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type); |
| 34 | 34 | ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id); |
| 35 | 35 | ZigType *get_optional_type(CodeGen *g, ZigType *child_type); |
| 36 | ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size); | |
| 36 | ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bool is_null_terminated); | |
| 37 | 37 | ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type); |
| 38 | 38 | ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, |
| 39 | 39 | AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout); |
src/codegen.cpp+2-2| ... | ... | @@ -7465,7 +7465,7 @@ static void do_code_gen(CodeGen *g) { |
| 7465 | 7465 | !is_async && !have_err_ret_trace_arg; |
| 7466 | 7466 | LLVMValueRef err_ret_array_val = nullptr; |
| 7467 | 7467 | if (have_err_ret_trace_stack) { |
| 7468 | ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count); | |
| 7468 | ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, false); | |
| 7469 | 7469 | err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type)); |
| 7470 | 7470 | |
| 7471 | 7471 | (void)get_llvm_type(g, get_stack_trace_type(g)); |
| ... | ... | @@ -9067,7 +9067,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { |
| 9067 | 9067 | zig_unreachable(); |
| 9068 | 9068 | |
| 9069 | 9069 | ConstExprValue *test_fn_array = create_const_vals(1); |
| 9070 | test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length); | |
| 9070 | test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length, false); | |
| 9071 | 9071 | test_fn_array->special = ConstValSpecialStatic; |
| 9072 | 9072 | test_fn_array->data.x_array.data.s_none.elements = create_const_vals(g->test_fns.length); |
| 9073 | 9073 |
src/ir.cpp+43-24| ... | ... | @@ -1772,11 +1772,12 @@ static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstN |
| 1772 | 1772 | } |
| 1773 | 1773 | |
| 1774 | 1774 | static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size, |
| 1775 | IrInstruction *child_type) | |
| 1775 | IrInstruction *child_type, bool is_null_terminated) | |
| 1776 | 1776 | { |
| 1777 | 1777 | IrInstructionArrayType *instruction = ir_build_instruction<IrInstructionArrayType>(irb, scope, source_node); |
| 1778 | 1778 | instruction->size = size; |
| 1779 | 1779 | instruction->child_type = child_type; |
| 1780 | instruction->is_null_terminated = is_null_terminated; | |
| 1780 | 1781 | |
| 1781 | 1782 | ir_ref_instruction(size, irb->current_basic_block); |
| 1782 | 1783 | ir_ref_instruction(child_type, irb->current_basic_block); |
| ... | ... | @@ -1795,7 +1796,8 @@ static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNo |
| 1795 | 1796 | return &instruction->base; |
| 1796 | 1797 | } |
| 1797 | 1798 | static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1798 | IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value, bool is_allow_zero) | |
| 1799 | IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value, bool is_allow_zero, | |
| 1800 | bool is_null_terminated) | |
| 1799 | 1801 | { |
| 1800 | 1802 | IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node); |
| 1801 | 1803 | instruction->is_const = is_const; |
| ... | ... | @@ -1803,6 +1805,7 @@ static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode |
| 1803 | 1805 | instruction->child_type = child_type; |
| 1804 | 1806 | instruction->align_value = align_value; |
| 1805 | 1807 | instruction->is_allow_zero = is_allow_zero; |
| 1808 | instruction->is_null_terminated = is_null_terminated; | |
| 1806 | 1809 | |
| 1807 | 1810 | ir_ref_instruction(child_type, irb->current_basic_block); |
| 1808 | 1811 | if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); |
| ... | ... | @@ -6216,7 +6219,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A |
| 6216 | 6219 | return elem_type; |
| 6217 | 6220 | size_t item_count = container_init_expr->entries.length; |
| 6218 | 6221 | IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); |
| 6219 | container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type); | |
| 6222 | container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type, false); | |
| 6220 | 6223 | } else { |
| 6221 | 6224 | container_type = ir_gen_node(irb, container_init_expr->type, scope); |
| 6222 | 6225 | if (container_type == irb->codegen->invalid_instruction) |
| ... | ... | @@ -6944,6 +6947,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n |
| 6944 | 6947 | bool is_const = node->data.array_type.is_const; |
| 6945 | 6948 | bool is_volatile = node->data.array_type.is_volatile; |
| 6946 | 6949 | bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr; |
| 6950 | bool is_null_terminated = node->data.array_type.is_null_terminated; | |
| 6947 | 6951 | AstNode *align_expr = node->data.array_type.align_expr; |
| 6948 | 6952 | |
| 6949 | 6953 | Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); |
| ... | ... | @@ -6973,7 +6977,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n |
| 6973 | 6977 | if (child_type == irb->codegen->invalid_instruction) |
| 6974 | 6978 | return child_type; |
| 6975 | 6979 | |
| 6976 | return ir_build_array_type(irb, scope, node, size_value, child_type); | |
| 6980 | return ir_build_array_type(irb, scope, node, size_value, child_type, is_null_terminated); | |
| 6977 | 6981 | } else { |
| 6978 | 6982 | IrInstruction *align_value; |
| 6979 | 6983 | if (align_expr != nullptr) { |
| ... | ... | @@ -6988,7 +6992,8 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n |
| 6988 | 6992 | if (child_type == irb->codegen->invalid_instruction) |
| 6989 | 6993 | return child_type; |
| 6990 | 6994 | |
| 6991 | return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, align_value, is_allow_zero); | |
| 6995 | return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, align_value, is_allow_zero, | |
| 6996 | is_null_terminated); | |
| 6992 | 6997 | } |
| 6993 | 6998 | } |
| 6994 | 6999 | |
| ... | ... | @@ -10631,6 +10636,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 10631 | 10636 | // *[N]T to []T |
| 10632 | 10637 | // *[N]T to E![]T |
| 10633 | 10638 | if (cur_type->id == ZigTypeIdPointer && |
| 10639 | cur_type->data.pointer.ptr_len == PtrLenSingle && | |
| 10634 | 10640 | cur_type->data.pointer.child_type->id == ZigTypeIdArray && |
| 10635 | 10641 | ((prev_type->id == ZigTypeIdErrorUnion && is_slice(prev_type->data.error_union.payload_type)) || |
| 10636 | 10642 | is_slice(prev_type))) |
| ... | ... | @@ -10639,7 +10645,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 10639 | 10645 | ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ? |
| 10640 | 10646 | prev_type->data.error_union.payload_type : prev_type; |
| 10641 | 10647 | ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; |
| 10642 | if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && | |
| 10648 | if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 || | |
| 10649 | !cur_type->data.pointer.is_const) && | |
| 10643 | 10650 | types_match_const_cast_only(ira, |
| 10644 | 10651 | slice_ptr_type->data.pointer.child_type, |
| 10645 | 10652 | array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) |
| ... | ... | @@ -10653,6 +10660,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 10653 | 10660 | // *[N]T to E![]T |
| 10654 | 10661 | if (prev_type->id == ZigTypeIdPointer && |
| 10655 | 10662 | prev_type->data.pointer.child_type->id == ZigTypeIdArray && |
| 10663 | prev_type->data.pointer.ptr_len == PtrLenSingle && | |
| 10656 | 10664 | ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) || |
| 10657 | 10665 | is_slice(cur_type))) |
| 10658 | 10666 | { |
| ... | ... | @@ -10660,7 +10668,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 10660 | 10668 | ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ? |
| 10661 | 10669 | cur_type->data.error_union.payload_type : cur_type; |
| 10662 | 10670 | ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; |
| 10663 | if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && | |
| 10671 | if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 || | |
| 10672 | !prev_type->data.pointer.is_const) && | |
| 10664 | 10673 | types_match_const_cast_only(ira, |
| 10665 | 10674 | slice_ptr_type->data.pointer.child_type, |
| 10666 | 10675 | array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) |
| ... | ... | @@ -14893,7 +14902,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 14893 | 14902 | ConstExprValue *out_array_val; |
| 14894 | 14903 | size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index); |
| 14895 | 14904 | if (op1_type->id == ZigTypeIdArray || op2_type->id == ZigTypeIdArray) { |
| 14896 | result->value.type = get_array_type(ira->codegen, child_type, new_len); | |
| 14905 | result->value.type = get_array_type(ira->codegen, child_type, new_len, false); | |
| 14897 | 14906 | |
| 14898 | 14907 | out_array_val = out_val; |
| 14899 | 14908 | } else if (is_slice(op1_type) || is_slice(op2_type)) { |
| ... | ... | @@ -14902,7 +14911,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 14902 | 14911 | result->value.type = get_slice_type(ira->codegen, ptr_type); |
| 14903 | 14912 | out_array_val = create_const_vals(1); |
| 14904 | 14913 | out_array_val->special = ConstValSpecialStatic; |
| 14905 | out_array_val->type = get_array_type(ira->codegen, child_type, new_len); | |
| 14914 | out_array_val->type = get_array_type(ira->codegen, child_type, new_len, false); | |
| 14906 | 14915 | |
| 14907 | 14916 | out_val->data.x_struct.fields = alloc_const_vals_ptrs(2); |
| 14908 | 14917 | |
| ... | ... | @@ -14923,7 +14932,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 14923 | 14932 | |
| 14924 | 14933 | out_array_val = create_const_vals(1); |
| 14925 | 14934 | out_array_val->special = ConstValSpecialStatic; |
| 14926 | out_array_val->type = get_array_type(ira->codegen, child_type, new_len); | |
| 14935 | out_array_val->type = get_array_type(ira->codegen, child_type, new_len, false); | |
| 14927 | 14936 | out_val->data.x_ptr.special = ConstPtrSpecialBaseArray; |
| 14928 | 14937 | out_val->data.x_ptr.data.base_array.is_cstr = true; |
| 14929 | 14938 | out_val->data.x_ptr.data.base_array.array_val = out_array_val; |
| ... | ... | @@ -14994,7 +15003,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp * |
| 14994 | 15003 | ZigType *child_type = array_type->data.array.child_type; |
| 14995 | 15004 | |
| 14996 | 15005 | IrInstruction *result = ir_const(ira, &instruction->base, |
| 14997 | get_array_type(ira->codegen, child_type, new_array_len)); | |
| 15006 | get_array_type(ira->codegen, child_type, new_array_len, false)); | |
| 14998 | 15007 | ConstExprValue *out_val = &result->value; |
| 14999 | 15008 | if (array_val->data.x_array.special == ConstArraySpecialUndef) { |
| 15000 | 15009 | out_val->data.x_array.special = ConstArraySpecialUndef; |
| ... | ... | @@ -19311,6 +19320,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 19311 | 19320 | lazy_slice_type->is_const = slice_type_instruction->is_const; |
| 19312 | 19321 | lazy_slice_type->is_volatile = slice_type_instruction->is_volatile; |
| 19313 | 19322 | lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero; |
| 19323 | lazy_slice_type->is_null_terminated = slice_type_instruction->is_null_terminated; | |
| 19314 | 19324 | |
| 19315 | 19325 | return result; |
| 19316 | 19326 | } |
| ... | ... | @@ -19420,7 +19430,8 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 19420 | 19430 | { |
| 19421 | 19431 | if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) |
| 19422 | 19432 | return ira->codegen->invalid_instruction; |
| 19423 | ZigType *result_type = get_array_type(ira->codegen, child_type, size); | |
| 19433 | ZigType *result_type = get_array_type(ira->codegen, child_type, size, | |
| 19434 | array_type_instruction->is_null_terminated); | |
| 19424 | 19435 | return ir_const_type(ira, &array_type_instruction->base, result_type); |
| 19425 | 19436 | } |
| 19426 | 19437 | } |
| ... | ... | @@ -20496,7 +20507,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, |
| 20496 | 20507 | if (container_type->id == ZigTypeIdArray) { |
| 20497 | 20508 | ZigType *child_type = container_type->data.array.child_type; |
| 20498 | 20509 | if (container_type->data.array.len != elem_count) { |
| 20499 | ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); | |
| 20510 | ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count, false); | |
| 20500 | 20511 | |
| 20501 | 20512 | ir_add_error(ira, &instruction->base, |
| 20502 | 20513 | buf_sprintf("expected %s literal, found %s literal", |
| ... | ... | @@ -20983,7 +20994,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr |
| 20983 | 20994 | |
| 20984 | 20995 | ConstExprValue *declaration_array = create_const_vals(1); |
| 20985 | 20996 | declaration_array->special = ConstValSpecialStatic; |
| 20986 | declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count); | |
| 20997 | declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count, false); | |
| 20987 | 20998 | declaration_array->data.x_array.special = ConstArraySpecialNone; |
| 20988 | 20999 | declaration_array->data.x_array.data.s_none.elements = create_const_vals(declaration_count); |
| 20989 | 21000 | init_const_slice(ira->codegen, out_val, declaration_array, 0, declaration_count, false); |
| ... | ... | @@ -21128,7 +21139,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr |
| 21128 | 21139 | ConstExprValue *fn_arg_name_array = create_const_vals(1); |
| 21129 | 21140 | fn_arg_name_array->special = ConstValSpecialStatic; |
| 21130 | 21141 | fn_arg_name_array->type = get_array_type(ira->codegen, |
| 21131 | get_slice_type(ira->codegen, u8_ptr), fn_arg_count); | |
| 21142 | get_slice_type(ira->codegen, u8_ptr), fn_arg_count, false); | |
| 21132 | 21143 | fn_arg_name_array->data.x_array.special = ConstArraySpecialNone; |
| 21133 | 21144 | fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); |
| 21134 | 21145 | |
| ... | ... | @@ -21376,7 +21387,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 21376 | 21387 | result->special = ConstValSpecialStatic; |
| 21377 | 21388 | result->type = ir_type_info_get_type(ira, "Array", nullptr); |
| 21378 | 21389 | |
| 21379 | ConstExprValue **fields = alloc_const_vals_ptrs(2); | |
| 21390 | ConstExprValue **fields = alloc_const_vals_ptrs(3); | |
| 21380 | 21391 | result->data.x_struct.fields = fields; |
| 21381 | 21392 | |
| 21382 | 21393 | // len: usize |
| ... | ... | @@ -21389,6 +21400,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 21389 | 21400 | fields[1]->special = ConstValSpecialStatic; |
| 21390 | 21401 | fields[1]->type = ira->codegen->builtin_types.entry_type; |
| 21391 | 21402 | fields[1]->data.x_type = type_entry->data.array.child_type; |
| 21403 | // is_null_terminated: bool | |
| 21404 | ensure_field_index(result->type, "is_null_terminated", 2); | |
| 21405 | fields[2]->special = ConstValSpecialStatic; | |
| 21406 | fields[2]->type = ira->codegen->builtin_types.entry_bool; | |
| 21407 | fields[2]->data.x_bool = type_entry->data.array.is_null_terminated; | |
| 21392 | 21408 | |
| 21393 | 21409 | break; |
| 21394 | 21410 | } |
| ... | ... | @@ -21476,7 +21492,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 21476 | 21492 | |
| 21477 | 21493 | ConstExprValue *enum_field_array = create_const_vals(1); |
| 21478 | 21494 | enum_field_array->special = ConstValSpecialStatic; |
| 21479 | enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count); | |
| 21495 | enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count, false); | |
| 21480 | 21496 | enum_field_array->data.x_array.special = ConstArraySpecialNone; |
| 21481 | 21497 | enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count); |
| 21482 | 21498 | |
| ... | ... | @@ -21524,7 +21540,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 21524 | 21540 | uint32_t error_count = type_entry->data.error_set.err_count; |
| 21525 | 21541 | ConstExprValue *error_array = create_const_vals(1); |
| 21526 | 21542 | error_array->special = ConstValSpecialStatic; |
| 21527 | error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count); | |
| 21543 | error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count, false); | |
| 21528 | 21544 | error_array->data.x_array.special = ConstArraySpecialNone; |
| 21529 | 21545 | error_array->data.x_array.data.s_none.elements = create_const_vals(error_count); |
| 21530 | 21546 | |
| ... | ... | @@ -21620,7 +21636,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 21620 | 21636 | |
| 21621 | 21637 | ConstExprValue *union_field_array = create_const_vals(1); |
| 21622 | 21638 | union_field_array->special = ConstValSpecialStatic; |
| 21623 | union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count); | |
| 21639 | union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count, false); | |
| 21624 | 21640 | union_field_array->data.x_array.special = ConstArraySpecialNone; |
| 21625 | 21641 | union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count); |
| 21626 | 21642 | |
| ... | ... | @@ -21700,7 +21716,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 21700 | 21716 | |
| 21701 | 21717 | ConstExprValue *struct_field_array = create_const_vals(1); |
| 21702 | 21718 | struct_field_array->special = ConstValSpecialStatic; |
| 21703 | struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count); | |
| 21719 | struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count, false); | |
| 21704 | 21720 | struct_field_array->data.x_array.special = ConstArraySpecialNone; |
| 21705 | 21721 | struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count); |
| 21706 | 21722 | |
| ... | ... | @@ -21803,7 +21819,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 21803 | 21819 | |
| 21804 | 21820 | ConstExprValue *fn_arg_array = create_const_vals(1); |
| 21805 | 21821 | fn_arg_array->special = ConstValSpecialStatic; |
| 21806 | fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count); | |
| 21822 | fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count, false); | |
| 21807 | 21823 | fn_arg_array->data.x_array.special = ConstArraySpecialNone; |
| 21808 | 21824 | fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); |
| 21809 | 21825 | |
| ... | ... | @@ -21983,7 +21999,8 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi |
| 21983 | 21999 | assert(payload->type == ir_type_info_get_type(ira, "Array", nullptr)); |
| 21984 | 22000 | return get_array_type(ira->codegen, |
| 21985 | 22001 | get_const_field_meta_type(ira, payload, "child", 1), |
| 21986 | bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0)) | |
| 22002 | bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0)), | |
| 22003 | get_const_field_bool(ira, payload, "is_null_terminated", 2) | |
| 21987 | 22004 | ); |
| 21988 | 22005 | case ZigTypeIdComptimeFloat: |
| 21989 | 22006 | return ira->codegen->builtin_types.entry_num_lit_float; |
| ... | ... | @@ -22366,7 +22383,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru |
| 22366 | 22383 | } |
| 22367 | 22384 | |
| 22368 | 22385 | ZigType *result_type = get_array_type(ira->codegen, |
| 22369 | ira->codegen->builtin_types.entry_u8, buf_len(file_contents)); | |
| 22386 | ira->codegen->builtin_types.entry_u8, buf_len(file_contents), false); | |
| 22370 | 22387 | IrInstruction *result = ir_const(ira, &instruction->base, result_type); |
| 22371 | 22388 | init_const_str_lit(ira->codegen, &result->value, file_contents); |
| 22372 | 22389 | return result; |
| ... | ... | @@ -27581,7 +27598,9 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) { |
| 27581 | 27598 | if ((err = type_resolve(ira->codegen, elem_type, needed_status))) |
| 27582 | 27599 | return err; |
| 27583 | 27600 | ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type, |
| 27584 | lazy_slice_type->is_const, lazy_slice_type->is_volatile, PtrLenUnknown, align_bytes, | |
| 27601 | lazy_slice_type->is_const, lazy_slice_type->is_volatile, | |
| 27602 | lazy_slice_type->is_null_terminated ? PtrLenNull : PtrLenUnknown, | |
| 27603 | align_bytes, | |
| 27585 | 27604 | 0, 0, lazy_slice_type->is_allowzero); |
| 27586 | 27605 | val->special = ConstValSpecialStatic; |
| 27587 | 27606 | assert(val->type->id == ZigTypeIdMetaType); |
test/stage1/behavior/if.zig+4| ... | ... | @@ -81,6 +81,10 @@ test "if prongs cast to expected type instead of peer type resolution" { |
| 81 | 81 | var x: i32 = 0; |
| 82 | 82 | x = if (f) 1 else 2; |
| 83 | 83 | expect(x == 2); |
| 84 | ||
| 85 | var b = true; | |
| 86 | const y: i32 = if (b) 1 else 2; | |
| 87 | expect(y == 1); | |
| 84 | 88 | } |
| 85 | 89 | }; |
| 86 | 90 | S.doTheTest(false); |
test/stage1/behavior/type.zig+83-64| ... | ... | @@ -11,103 +11,122 @@ fn testTypes(comptime types: []const type) void { |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | 13 | test "Type.MetaType" { |
| 14 | testing.expect(type == @Type(TypeInfo { .Type = undefined })); | |
| 15 | testTypes([_]type {type}); | |
| 14 | testing.expect(type == @Type(TypeInfo{ .Type = undefined })); | |
| 15 | testTypes([_]type{type}); | |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | test "Type.Void" { |
| 19 | testing.expect(void == @Type(TypeInfo { .Void = undefined })); | |
| 20 | testTypes([_]type {void}); | |
| 19 | testing.expect(void == @Type(TypeInfo{ .Void = undefined })); | |
| 20 | testTypes([_]type{void}); | |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | 23 | test "Type.Bool" { |
| 24 | testing.expect(bool == @Type(TypeInfo { .Bool = undefined })); | |
| 25 | testTypes([_]type {bool}); | |
| 24 | testing.expect(bool == @Type(TypeInfo{ .Bool = undefined })); | |
| 25 | testTypes([_]type{bool}); | |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | test "Type.NoReturn" { |
| 29 | testing.expect(noreturn == @Type(TypeInfo { .NoReturn = undefined })); | |
| 30 | testTypes([_]type {noreturn}); | |
| 29 | testing.expect(noreturn == @Type(TypeInfo{ .NoReturn = undefined })); | |
| 30 | testTypes([_]type{noreturn}); | |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | 33 | test "Type.Int" { |
| 34 | testing.expect(u1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 1 } })); | |
| 35 | testing.expect(i1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 1 } })); | |
| 36 | testing.expect(u8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 8 } })); | |
| 37 | testing.expect(i8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 8 } })); | |
| 38 | testing.expect(u64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 64 } })); | |
| 39 | testing.expect(i64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 64 } })); | |
| 40 | testTypes([_]type {u8,u32,i64}); | |
| 34 | testing.expect(u1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 1 } })); | |
| 35 | testing.expect(i1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 1 } })); | |
| 36 | testing.expect(u8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 8 } })); | |
| 37 | testing.expect(i8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 8 } })); | |
| 38 | testing.expect(u64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 64 } })); | |
| 39 | testing.expect(i64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 64 } })); | |
| 40 | testTypes([_]type{ u8, u32, i64 }); | |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | 43 | test "Type.Float" { |
| 44 | testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 16 } })); | |
| 45 | testing.expect(f32 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 32 } })); | |
| 46 | testing.expect(f64 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 64 } })); | |
| 47 | testing.expect(f128 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 128 } })); | |
| 48 | testTypes([_]type {f16, f32, f64, f128}); | |
| 44 | testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } })); | |
| 45 | testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } })); | |
| 46 | testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } })); | |
| 47 | testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } })); | |
| 48 | testTypes([_]type{ f16, f32, f64, f128 }); | |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | test "Type.Pointer" { |
| 52 | testTypes([_]type { | |
| 52 | testTypes([_]type{ | |
| 53 | 53 | // One Value Pointer Types |
| 54 | *u8, *const u8, | |
| 55 | *volatile u8, *const volatile u8, | |
| 56 | *align(4) u8, *const align(4) u8, | |
| 57 | *volatile align(4) u8, *const volatile align(4) u8, | |
| 58 | *align(8) u8, *const align(8) u8, | |
| 59 | *volatile align(8) u8, *const volatile align(8) u8, | |
| 60 | *allowzero u8, *const allowzero u8, | |
| 61 | *volatile allowzero u8, *const volatile allowzero u8, | |
| 62 | *align(4) allowzero u8, *const align(4) allowzero u8, | |
| 63 | *volatile align(4) allowzero u8, *const volatile align(4) allowzero u8, | |
| 54 | *u8, *const u8, | |
| 55 | *volatile u8, *const volatile u8, | |
| 56 | *align(4) u8, *align(4) const u8, | |
| 57 | *align(4) volatile u8, *align(4) const volatile u8, | |
| 58 | *align(8) u8, *align(8) const u8, | |
| 59 | *align(8) volatile u8, *align(8) const volatile u8, | |
| 60 | *allowzero u8, *allowzero const u8, | |
| 61 | *allowzero volatile u8, *allowzero const volatile u8, | |
| 62 | *allowzero align(4) u8, *allowzero align(4) const u8, | |
| 63 | *allowzero align(4) volatile u8, *allowzero align(4) const volatile u8, | |
| 64 | 64 | // Many Values Pointer Types |
| 65 | [*]u8, [*]const u8, | |
| 66 | [*]volatile u8, [*]const volatile u8, | |
| 67 | [*]align(4) u8, [*]const align(4) u8, | |
| 68 | [*]volatile align(4) u8, [*]const volatile align(4) u8, | |
| 69 | [*]align(8) u8, [*]const align(8) u8, | |
| 70 | [*]volatile align(8) u8, [*]const volatile align(8) u8, | |
| 71 | [*]allowzero u8, [*]const allowzero u8, | |
| 72 | [*]volatile allowzero u8, [*]const volatile allowzero u8, | |
| 73 | [*]align(4) allowzero u8, [*]const align(4) allowzero u8, | |
| 74 | [*]volatile align(4) allowzero u8, [*]const volatile align(4) allowzero u8, | |
| 65 | [*]u8, [*]const u8, | |
| 66 | [*]volatile u8, [*]const volatile u8, | |
| 67 | [*]align(4) u8, [*]align(4) const u8, | |
| 68 | [*]align(4) volatile u8, [*]align(4) const volatile u8, | |
| 69 | [*]align(8) u8, [*]align(8) const u8, | |
| 70 | [*]align(8) volatile u8, [*]align(8) const volatile u8, | |
| 71 | [*]allowzero u8, [*]allowzero const u8, | |
| 72 | [*]allowzero volatile u8, [*]allowzero const volatile u8, | |
| 73 | [*]allowzero align(4) u8, [*]allowzero align(4) const u8, | |
| 74 | [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8, | |
| 75 | 75 | // Slice Types |
| 76 | []u8, []const u8, | |
| 77 | []volatile u8, []const volatile u8, | |
| 78 | []align(4) u8, []const align(4) u8, | |
| 79 | []volatile align(4) u8, []const volatile align(4) u8, | |
| 80 | []align(8) u8, []const align(8) u8, | |
| 81 | []volatile align(8) u8, []const volatile align(8) u8, | |
| 82 | []allowzero u8, []const allowzero u8, | |
| 83 | []volatile allowzero u8, []const volatile allowzero u8, | |
| 84 | []align(4) allowzero u8, []const align(4) allowzero u8, | |
| 85 | []volatile align(4) allowzero u8, []const volatile align(4) allowzero u8, | |
| 76 | []u8, []const u8, | |
| 77 | []volatile u8, []const volatile u8, | |
| 78 | []align(4) u8, []align(4) const u8, | |
| 79 | []align(4) volatile u8, []align(4) const volatile u8, | |
| 80 | []align(8) u8, []align(8) const u8, | |
| 81 | []align(8) volatile u8, []align(8) const volatile u8, | |
| 82 | []allowzero u8, []allowzero const u8, | |
| 83 | []allowzero volatile u8, []allowzero const volatile u8, | |
| 84 | []allowzero align(4) u8, []allowzero align(4) const u8, | |
| 85 | []allowzero align(4) volatile u8, []allowzero align(4) const volatile u8, | |
| 86 | 86 | // C Pointer Types |
| 87 | [*c]u8, [*c]const u8, | |
| 88 | [*c]volatile u8, [*c]const volatile u8, | |
| 89 | [*c]align(4) u8, [*c]const align(4) u8, | |
| 90 | [*c]volatile align(4) u8, [*c]const volatile align(4) u8, | |
| 91 | [*c]align(8) u8, [*c]const align(8) u8, | |
| 92 | [*c]volatile align(8) u8, [*c]const volatile align(8) u8, | |
| 87 | [*c]u8, [*c]const u8, | |
| 88 | [*c]volatile u8, [*c]const volatile u8, | |
| 89 | [*c]align(4) u8, [*c]align(4) const u8, | |
| 90 | [*c]align(4) volatile u8, [*c]align(4) const volatile u8, | |
| 91 | [*c]align(8) u8, [*c]align(8) const u8, | |
| 92 | [*c]align(8) volatile u8, [*c]align(8) const volatile u8, | |
| 93 | 93 | }); |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | 96 | test "Type.Array" { |
| 97 | testing.expect([123]u8 == @Type(TypeInfo { .Array = TypeInfo.Array { .len = 123, .child = u8 } })); | |
| 98 | testing.expect([2]u32 == @Type(TypeInfo { .Array = TypeInfo.Array { .len = 2, .child = u32 } })); | |
| 99 | testTypes([_]type {[1]u8, [30]usize, [7]bool}); | |
| 97 | testing.expect([123]u8 == @Type(TypeInfo{ | |
| 98 | .Array = TypeInfo.Array{ | |
| 99 | .len = 123, | |
| 100 | .child = u8, | |
| 101 | .is_null_terminated = false, | |
| 102 | }, | |
| 103 | })); | |
| 104 | testing.expect([2]u32 == @Type(TypeInfo{ | |
| 105 | .Array = TypeInfo.Array{ | |
| 106 | .len = 2, | |
| 107 | .child = u32, | |
| 108 | .is_null_terminated = false, | |
| 109 | }, | |
| 110 | })); | |
| 111 | testing.expect([2]null u32 == @Type(TypeInfo{ | |
| 112 | .Array = TypeInfo.Array{ | |
| 113 | .len = 2, | |
| 114 | .child = u32, | |
| 115 | .is_null_terminated = true, | |
| 116 | }, | |
| 117 | })); | |
| 118 | testTypes([_]type{ [1]u8, [30]usize, [7]bool }); | |
| 100 | 119 | } |
| 101 | 120 | |
| 102 | 121 | test "Type.ComptimeFloat" { |
| 103 | testTypes([_]type {comptime_float}); | |
| 122 | testTypes([_]type{comptime_float}); | |
| 104 | 123 | } |
| 105 | 124 | test "Type.ComptimeInt" { |
| 106 | testTypes([_]type {comptime_int}); | |
| 125 | testTypes([_]type{comptime_int}); | |
| 107 | 126 | } |
| 108 | 127 | test "Type.Undefined" { |
| 109 | testTypes([_]type {@typeOf(undefined)}); | |
| 128 | testTypes([_]type{@typeOf(undefined)}); | |
| 110 | 129 | } |
| 111 | 130 | test "Type.Null" { |
| 112 | testTypes([_]type {@typeOf(null)}); | |
| 131 | testTypes([_]type{@typeOf(null)}); | |
| 113 | 132 | } |
test/stage1/behavior/type_info.zig+26-5| ... | ... | @@ -46,6 +46,7 @@ fn testPointer() void { |
| 46 | 46 | expect(u32_ptr_info.Pointer.is_volatile == false); |
| 47 | 47 | expect(u32_ptr_info.Pointer.alignment == @alignOf(u32)); |
| 48 | 48 | expect(u32_ptr_info.Pointer.child == u32); |
| 49 | expect(u32_ptr_info.Pointer.is_null_terminated == false); | |
| 49 | 50 | } |
| 50 | 51 | |
| 51 | 52 | test "type info: unknown length pointer type info" { |
| ... | ... | @@ -55,14 +56,34 @@ test "type info: unknown length pointer type info" { |
| 55 | 56 | |
| 56 | 57 | fn testUnknownLenPtr() void { |
| 57 | 58 | const u32_ptr_info = @typeInfo([*]const volatile f64); |
| 58 | expect(@as(TypeId,u32_ptr_info) == TypeId.Pointer); | |
| 59 | expect(@as(TypeId, u32_ptr_info) == TypeId.Pointer); | |
| 59 | 60 | expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); |
| 60 | 61 | expect(u32_ptr_info.Pointer.is_const == true); |
| 61 | 62 | expect(u32_ptr_info.Pointer.is_volatile == true); |
| 63 | expect(u32_ptr_info.Pointer.is_null_terminated == false); | |
| 62 | 64 | expect(u32_ptr_info.Pointer.alignment == @alignOf(f64)); |
| 63 | 65 | expect(u32_ptr_info.Pointer.child == f64); |
| 64 | 66 | } |
| 65 | 67 | |
| 68 | test "type info: null terminated pointer type info" { | |
| 69 | testNullTerminatedPtr(); | |
| 70 | comptime testNullTerminatedPtr(); | |
| 71 | } | |
| 72 | ||
| 73 | fn testNullTerminatedPtr() void { | |
| 74 | const ptr_info = @typeInfo([*]null u8); | |
| 75 | expect(@as(TypeId, ptr_info) == TypeId.Pointer); | |
| 76 | expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); | |
| 77 | expect(ptr_info.Pointer.is_const == false); | |
| 78 | expect(ptr_info.Pointer.is_volatile == false); | |
| 79 | expect(ptr_info.Pointer.is_null_terminated == true); | |
| 80 | ||
| 81 | expect(@typeInfo([]null u8).Pointer.is_null_terminated == true); | |
| 82 | expect(@typeInfo([10]null u8).Array.is_null_terminated == true); | |
| 83 | expect(@typeInfo([10]null u8).Array.len == 10); | |
| 84 | expect(@sizeOf([10]null u8) == 11); | |
| 85 | } | |
| 86 | ||
| 66 | 87 | test "type info: C pointer type info" { |
| 67 | 88 | testCPtr(); |
| 68 | 89 | comptime testCPtr(); |
| ... | ... | @@ -70,7 +91,7 @@ test "type info: C pointer type info" { |
| 70 | 91 | |
| 71 | 92 | fn testCPtr() void { |
| 72 | 93 | const ptr_info = @typeInfo([*c]align(4) const i8); |
| 73 | expect(@as(TypeId,ptr_info) == TypeId.Pointer); | |
| 94 | expect(@as(TypeId, ptr_info) == TypeId.Pointer); | |
| 74 | 95 | expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C); |
| 75 | 96 | expect(ptr_info.Pointer.is_const); |
| 76 | 97 | expect(!ptr_info.Pointer.is_volatile); |
| ... | ... | @@ -288,13 +309,13 @@ test "type info: anyframe and anyframe->T" { |
| 288 | 309 | fn testAnyFrame() void { |
| 289 | 310 | { |
| 290 | 311 | const anyframe_info = @typeInfo(anyframe->i32); |
| 291 | expect(@as(TypeId,anyframe_info) == .AnyFrame); | |
| 312 | expect(@as(TypeId, anyframe_info) == .AnyFrame); | |
| 292 | 313 | expect(anyframe_info.AnyFrame.child.? == i32); |
| 293 | 314 | } |
| 294 | 315 | |
| 295 | 316 | { |
| 296 | 317 | const anyframe_info = @typeInfo(anyframe); |
| 297 | expect(@as(TypeId,anyframe_info) == .AnyFrame); | |
| 318 | expect(@as(TypeId, anyframe_info) == .AnyFrame); | |
| 298 | 319 | expect(anyframe_info.AnyFrame.child == null); |
| 299 | 320 | } |
| 300 | 321 | } |
| ... | ... | @@ -334,7 +355,7 @@ test "type info: extern fns with and without lib names" { |
| 334 | 355 | if (std.mem.eql(u8, decl.name, "bar1")) { |
| 335 | 356 | expect(decl.data.Fn.lib_name == null); |
| 336 | 357 | } else { |
| 337 | std.testing.expectEqual(@as([]const u8,"cool"), decl.data.Fn.lib_name.?); | |
| 358 | std.testing.expectEqual(@as([]const u8, "cool"), decl.data.Fn.lib_name.?); | |
| 338 | 359 | } |
| 339 | 360 | } |
| 340 | 361 | } |