| author | |
| committer | |
| log | cf059ee08716300e924bced08ebdd5bd8f97d789 |
| tree | 7d948ad7249e7c8ca4a4ae87e319ec219d5e8fc8 |
| parent | d72f3d353f771daced78af70c049e3c5075b3529 |
| signature |
8 files changed, 93 insertions(+), 4 deletions(-)
lib/std/zig/Ast.zig+17| ... | ... | @@ -458,6 +458,19 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void { |
| 458 | 458 | return stream.writeAll("for input is not captured"); |
| 459 | 459 | }, |
| 460 | 460 | |
| 461 | .invalid_byte => { | |
| 462 | const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..]; | |
| 463 | return stream.print("{s} contains invalid byte: '{'}'", .{ | |
| 464 | switch (tok_slice[0]) { | |
| 465 | '\'' => "character literal", | |
| 466 | '"', '\\' => "string literal", | |
| 467 | '/' => "comment", | |
| 468 | else => unreachable, | |
| 469 | }, | |
| 470 | std.zig.fmtEscapes(tok_slice[parse_error.extra.offset..][0..1]), | |
| 471 | }); | |
| 472 | }, | |
| 473 | ||
| 461 | 474 | .expected_token => { |
| 462 | 475 | const found_tag = token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)]; |
| 463 | 476 | const expected_symbol = parse_error.extra.expected_tag.symbol(); |
| ... | ... | @@ -2926,6 +2939,7 @@ pub const Error = struct { |
| 2926 | 2939 | extra: union { |
| 2927 | 2940 | none: void, |
| 2928 | 2941 | expected_tag: Token.Tag, |
| 2942 | offset: usize, | |
| 2929 | 2943 | } = .{ .none = {} }, |
| 2930 | 2944 | |
| 2931 | 2945 | pub const Tag = enum { |
| ... | ... | @@ -2996,6 +3010,9 @@ pub const Error = struct { |
| 2996 | 3010 | |
| 2997 | 3011 | /// `expected_tag` is populated. |
| 2998 | 3012 | expected_token, |
| 3013 | ||
| 3014 | /// `offset` is populated | |
| 3015 | invalid_byte, | |
| 2999 | 3016 | }; |
| 3000 | 3017 | }; |
| 3001 | 3018 |
lib/std/zig/AstGen.zig+33| ... | ... | @@ -14017,6 +14017,39 @@ fn lowerAstErrors(astgen: *AstGen) !void { |
| 14017 | 14017 | var notes: std.ArrayListUnmanaged(u32) = .empty; |
| 14018 | 14018 | defer notes.deinit(gpa); |
| 14019 | 14019 | |
| 14020 | const token_starts = tree.tokens.items(.start); | |
| 14021 | const token_tags = tree.tokens.items(.tag); | |
| 14022 | const parse_err = tree.errors[0]; | |
| 14023 | const tok = parse_err.token + @intFromBool(parse_err.token_is_prev); | |
| 14024 | const tok_start = token_starts[tok]; | |
| 14025 | const start_char = tree.source[tok_start]; | |
| 14026 | ||
| 14027 | if (token_tags[tok] == .invalid and | |
| 14028 | (start_char == '\"' or start_char == '\'' or start_char == '/' or mem.startsWith(u8, tree.source[tok_start..], "\\\\"))) | |
| 14029 | { | |
| 14030 | const tok_len: u32 = @intCast(tree.tokenSlice(tok).len); | |
| 14031 | const tok_end = tok_start + tok_len; | |
| 14032 | const bad_off = blk: { | |
| 14033 | var idx = tok_start; | |
| 14034 | while (idx < tok_end) : (idx += 1) { | |
| 14035 | switch (tree.source[idx]) { | |
| 14036 | 0x00...0x09, 0x0b...0x1f, 0x7f => break, | |
| 14037 | else => {}, | |
| 14038 | } | |
| 14039 | } | |
| 14040 | break :blk idx - tok_start; | |
| 14041 | }; | |
| 14042 | ||
| 14043 | const err: Ast.Error = .{ | |
| 14044 | .tag = Ast.Error.Tag.invalid_byte, | |
| 14045 | .token = tok, | |
| 14046 | .extra = .{ .offset = bad_off }, | |
| 14047 | }; | |
| 14048 | msg.clearRetainingCapacity(); | |
| 14049 | try tree.renderError(err, msg.writer(gpa)); | |
| 14050 | return try astgen.appendErrorTokNotesOff(tok, bad_off, "{s}", .{msg.items}, notes.items); | |
| 14051 | } | |
| 14052 | ||
| 14020 | 14053 | var cur_err = tree.errors[0]; |
| 14021 | 14054 | for (tree.errors[1..]) |err| { |
| 14022 | 14055 | if (err.is_note) { |
test/cases/compile_errors/normal_string_with_newline.zig+1-1| ... | ... | @@ -5,4 +5,4 @@ b"; |
| 5 | 5 | // backend=stage2 |
| 6 | 6 | // target=native |
| 7 | 7 | // |
| 8 | // :1:13: error: expected expression, found 'invalid token' | |
| 8 | // :1:15: error: string literal contains invalid byte: '\n' |
test/cases/compile_errors/tab_inside_comment.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | // Some		comment | |
| 2 | export fn entry() void {} | |
| 3 | ||
| 4 | // error | |
| 5 | // backend=stage2 | |
| 6 | // target=native | |
| 7 | // | |
| 8 | // :1:8: error: comment contains invalid byte: '\t' |
test/cases/compile_errors/tab_inside_doc_comment.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | /// Some doc		comment | |
| 2 | export fn entry() void {} | |
| 3 | ||
| 4 | // error | |
| 5 | // backend=stage2 | |
| 6 | // target=native | |
| 7 | // | |
| 8 | // :1:13: error: comment contains invalid byte: '\t' |
test/cases/compile_errors/tab_inside_multiline_string.zig created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | export fn entry() void { | |
| 2 | const foo = | |
| 3 | \\const S = struct { | |
| 4 | \\	// hello | |
| 5 | \\} | |
| 6 | ; | |
| 7 | _ = foo; | |
| 8 | } | |
| 9 | // error | |
| 10 | // backend=stage2 | |
| 11 | // target=native | |
| 12 | // | |
| 13 | // :4:11: error: string literal contains invalid byte: '\t' |
test/cases/compile_errors/tab_inside_string.zig created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | export fn entry() void { | |
| 2 | const foo = "	hello"; | |
| 3 | _ = foo; | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // backend=stage2 | |
| 8 | // target=native | |
| 9 | // | |
| 10 | // :2:18: error: string literal contains invalid byte: '\t' |
test/compile_errors.zig+3-3| ... | ... | @@ -217,7 +217,7 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void { |
| 217 | 217 | const case = ctx.obj("invalid byte in string", b.graph.host); |
| 218 | 218 | |
| 219 | 219 | case.addError("_ = \"\x01Q\";", &[_][]const u8{ |
| 220 | ":1:5: error: expected expression, found 'invalid token'", | |
| 220 | ":1:6: error: string literal contains invalid byte: '\\x01'", | |
| 221 | 221 | }); |
| 222 | 222 | } |
| 223 | 223 | |
| ... | ... | @@ -225,7 +225,7 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void { |
| 225 | 225 | const case = ctx.obj("invalid byte in comment", b.graph.host); |
| 226 | 226 | |
| 227 | 227 | case.addError("//\x01Q", &[_][]const u8{ |
| 228 | ":1:1: error: expected type expression, found 'invalid token'", | |
| 228 | ":1:3: error: comment contains invalid byte: '\\x01'", | |
| 229 | 229 | }); |
| 230 | 230 | } |
| 231 | 231 | |
| ... | ... | @@ -233,7 +233,7 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void { |
| 233 | 233 | const case = ctx.obj("control character in character literal", b.graph.host); |
| 234 | 234 | |
| 235 | 235 | case.addError("const c = '\x01';", &[_][]const u8{ |
| 236 | ":1:11: error: expected expression, found 'invalid token'", | |
| 236 | ":1:12: error: character literal contains invalid byte: '\\x01'", | |
| 237 | 237 | }); |
| 238 | 238 | } |
| 239 | 239 |