| author | |
| committer | |
| log | 7103088e4a51d4362e6665d5949a9677e18fb74a |
| tree | 858c52055896b6d6085b3810b6263eed3bafae0a |
| parent | 2ff707be789046a733d0d23c6fe42dd2b7210396 |
| parent | 74010fecc7bbeaf9de77c28dda5906c3c1f4a6df |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
Use Aro's tokenizer in `translate-c`26 files changed, 1299 insertions(+), 2543 deletions(-)
CMakeLists.txt-1| ... | @@ -218,7 +218,6 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -218,7 +218,6 @@ set(ZIG_STAGE2_SOURCES |
| 218 | "${CMAKE_SOURCE_DIR}/lib/std/builtin.zig" | 218 | "${CMAKE_SOURCE_DIR}/lib/std/builtin.zig" |
| 219 | "${CMAKE_SOURCE_DIR}/lib/std/c.zig" | 219 | "${CMAKE_SOURCE_DIR}/lib/std/c.zig" |
| 220 | "${CMAKE_SOURCE_DIR}/lib/std/c/linux.zig" | 220 | "${CMAKE_SOURCE_DIR}/lib/std/c/linux.zig" |
| 221 | "${CMAKE_SOURCE_DIR}/lib/std/c/tokenizer.zig" | ||
| 222 | "${CMAKE_SOURCE_DIR}/lib/std/child_process.zig" | 221 | "${CMAKE_SOURCE_DIR}/lib/std/child_process.zig" |
| 223 | "${CMAKE_SOURCE_DIR}/lib/std/coff.zig" | 222 | "${CMAKE_SOURCE_DIR}/lib/std/coff.zig" |
| 224 | "${CMAKE_SOURCE_DIR}/lib/std/comptime_string_map.zig" | 223 | "${CMAKE_SOURCE_DIR}/lib/std/comptime_string_map.zig" |
deps/aro/aro/Builtins/Builtin.def+152| ... | @@ -17008,3 +17008,155 @@ wmemmove | ... | @@ -17008,3 +17008,155 @@ wmemmove |
| 17008 | .param_str = "w*w*wC*z" | 17008 | .param_str = "w*w*wC*z" |
| 17009 | .header = .wchar | 17009 | .header = .wchar |
| 17010 | .attributes = .{ .lib_function_without_prefix = true, .const_evaluable = true } | 17010 | .attributes = .{ .lib_function_without_prefix = true, .const_evaluable = true } |
| 17011 | |||
| 17012 | __c11_atomic_init | ||
| 17013 | .param_str = "v." | ||
| 17014 | .attributes = .{ .custom_typecheck = true } | ||
| 17015 | |||
| 17016 | __c11_atomic_load | ||
| 17017 | .param_str = "v." | ||
| 17018 | .attributes = .{ .custom_typecheck = true } | ||
| 17019 | |||
| 17020 | __c11_atomic_store | ||
| 17021 | .param_str = "v." | ||
| 17022 | .attributes = .{ .custom_typecheck = true } | ||
| 17023 | |||
| 17024 | __c11_atomic_exchange | ||
| 17025 | .param_str = "v." | ||
| 17026 | .attributes = .{ .custom_typecheck = true } | ||
| 17027 | |||
| 17028 | __c11_atomic_compare_exchange_strong | ||
| 17029 | .param_str = "v." | ||
| 17030 | .attributes = .{ .custom_typecheck = true } | ||
| 17031 | |||
| 17032 | __c11_atomic_compare_exchange_weak | ||
| 17033 | .param_str = "v." | ||
| 17034 | .attributes = .{ .custom_typecheck = true } | ||
| 17035 | |||
| 17036 | __c11_atomic_fetch_add | ||
| 17037 | .param_str = "v." | ||
| 17038 | .attributes = .{ .custom_typecheck = true } | ||
| 17039 | |||
| 17040 | __c11_atomic_fetch_sub | ||
| 17041 | .param_str = "v." | ||
| 17042 | .attributes = .{ .custom_typecheck = true } | ||
| 17043 | |||
| 17044 | __c11_atomic_fetch_and | ||
| 17045 | .param_str = "v." | ||
| 17046 | .attributes = .{ .custom_typecheck = true } | ||
| 17047 | |||
| 17048 | __c11_atomic_fetch_or | ||
| 17049 | .param_str = "v." | ||
| 17050 | .attributes = .{ .custom_typecheck = true } | ||
| 17051 | |||
| 17052 | __c11_atomic_fetch_xor | ||
| 17053 | .param_str = "v." | ||
| 17054 | .attributes = .{ .custom_typecheck = true } | ||
| 17055 | |||
| 17056 | __c11_atomic_fetch_nand | ||
| 17057 | .param_str = "v." | ||
| 17058 | .attributes = .{ .custom_typecheck = true } | ||
| 17059 | |||
| 17060 | __c11_atomic_fetch_max | ||
| 17061 | .param_str = "v." | ||
| 17062 | .attributes = .{ .custom_typecheck = true } | ||
| 17063 | |||
| 17064 | __c11_atomic_fetch_min | ||
| 17065 | .param_str = "v." | ||
| 17066 | .attributes = .{ .custom_typecheck = true } | ||
| 17067 | |||
| 17068 | __atomic_load | ||
| 17069 | .param_str = "v." | ||
| 17070 | .attributes = .{ .custom_typecheck = true } | ||
| 17071 | |||
| 17072 | __atomic_load_n | ||
| 17073 | .param_str = "v." | ||
| 17074 | .attributes = .{ .custom_typecheck = true } | ||
| 17075 | |||
| 17076 | __atomic_store | ||
| 17077 | .param_str = "v." | ||
| 17078 | .attributes = .{ .custom_typecheck = true } | ||
| 17079 | |||
| 17080 | __atomic_store_n | ||
| 17081 | .param_str = "v." | ||
| 17082 | .attributes = .{ .custom_typecheck = true } | ||
| 17083 | |||
| 17084 | __atomic_exchange | ||
| 17085 | .param_str = "v." | ||
| 17086 | .attributes = .{ .custom_typecheck = true } | ||
| 17087 | |||
| 17088 | __atomic_exchange_n | ||
| 17089 | .param_str = "v." | ||
| 17090 | .attributes = .{ .custom_typecheck = true } | ||
| 17091 | |||
| 17092 | __atomic_compare_exchange | ||
| 17093 | .param_str = "v." | ||
| 17094 | .attributes = .{ .custom_typecheck = true } | ||
| 17095 | |||
| 17096 | __atomic_compare_exchange_n | ||
| 17097 | .param_str = "v." | ||
| 17098 | .attributes = .{ .custom_typecheck = true } | ||
| 17099 | |||
| 17100 | __atomic_fetch_add | ||
| 17101 | .param_str = "v." | ||
| 17102 | .attributes = .{ .custom_typecheck = true } | ||
| 17103 | |||
| 17104 | __atomic_fetch_sub | ||
| 17105 | .param_str = "v." | ||
| 17106 | .attributes = .{ .custom_typecheck = true } | ||
| 17107 | |||
| 17108 | __atomic_fetch_and | ||
| 17109 | .param_str = "v." | ||
| 17110 | .attributes = .{ .custom_typecheck = true } | ||
| 17111 | |||
| 17112 | __atomic_fetch_or | ||
| 17113 | .param_str = "v." | ||
| 17114 | .attributes = .{ .custom_typecheck = true } | ||
| 17115 | |||
| 17116 | __atomic_fetch_xor | ||
| 17117 | .param_str = "v." | ||
| 17118 | .attributes = .{ .custom_typecheck = true } | ||
| 17119 | |||
| 17120 | __atomic_fetch_nand | ||
| 17121 | .param_str = "v." | ||
| 17122 | .attributes = .{ .custom_typecheck = true } | ||
| 17123 | |||
| 17124 | __atomic_add_fetch | ||
| 17125 | .param_str = "v." | ||
| 17126 | .attributes = .{ .custom_typecheck = true } | ||
| 17127 | |||
| 17128 | __atomic_sub_fetch | ||
| 17129 | .param_str = "v." | ||
| 17130 | .attributes = .{ .custom_typecheck = true } | ||
| 17131 | |||
| 17132 | __atomic_and_fetch | ||
| 17133 | .param_str = "v." | ||
| 17134 | .attributes = .{ .custom_typecheck = true } | ||
| 17135 | |||
| 17136 | __atomic_or_fetch | ||
| 17137 | .param_str = "v." | ||
| 17138 | .attributes = .{ .custom_typecheck = true } | ||
| 17139 | |||
| 17140 | __atomic_xor_fetch | ||
| 17141 | .param_str = "v." | ||
| 17142 | .attributes = .{ .custom_typecheck = true } | ||
| 17143 | |||
| 17144 | __atomic_max_fetch | ||
| 17145 | .param_str = "v." | ||
| 17146 | .attributes = .{ .custom_typecheck = true } | ||
| 17147 | |||
| 17148 | __atomic_min_fetch | ||
| 17149 | .param_str = "v." | ||
| 17150 | .attributes = .{ .custom_typecheck = true } | ||
| 17151 | |||
| 17152 | __atomic_nand_fetch | ||
| 17153 | .param_str = "v." | ||
| 17154 | .attributes = .{ .custom_typecheck = true } | ||
| 17155 | |||
| 17156 | __atomic_fetch_min | ||
| 17157 | .param_str = "v." | ||
| 17158 | .attributes = .{ .custom_typecheck = true } | ||
| 17159 | |||
| 17160 | __atomic_fetch_max | ||
| 17161 | .param_str = "v." | ||
| 17162 | .attributes = .{ .custom_typecheck = true } |
deps/aro/aro/Compilation.zig+73-2| ... | @@ -408,6 +408,17 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { | ... | @@ -408,6 +408,17 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { |
| 408 | \\ | 408 | \\ |
| 409 | ); | 409 | ); |
| 410 | 410 | ||
| 411 | // atomics | ||
| 412 | try w.writeAll( | ||
| 413 | \\#define __ATOMIC_RELAXED 0 | ||
| 414 | \\#define __ATOMIC_CONSUME 1 | ||
| 415 | \\#define __ATOMIC_ACQUIRE 2 | ||
| 416 | \\#define __ATOMIC_RELEASE 3 | ||
| 417 | \\#define __ATOMIC_ACQ_REL 4 | ||
| 418 | \\#define __ATOMIC_SEQ_CST 5 | ||
| 419 | \\ | ||
| 420 | ); | ||
| 421 | |||
| 411 | // types | 422 | // types |
| 412 | if (comp.getCharSignedness() == .unsigned) try w.writeAll("#define __CHAR_UNSIGNED__ 1\n"); | 423 | if (comp.getCharSignedness() == .unsigned) try w.writeAll("#define __CHAR_UNSIGNED__ 1\n"); |
| 413 | try w.writeAll("#define __CHAR_BIT__ 8\n"); | 424 | try w.writeAll("#define __CHAR_BIT__ 8\n"); |
| ... | @@ -445,6 +456,10 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { | ... | @@ -445,6 +456,10 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { |
| 445 | try comp.generateSizeofType(w, "__SIZEOF_WCHAR_T__", comp.types.wchar); | 456 | try comp.generateSizeofType(w, "__SIZEOF_WCHAR_T__", comp.types.wchar); |
| 446 | // try comp.generateSizeofType(w, "__SIZEOF_WINT_T__", .{ .specifier = .pointer }); | 457 | // try comp.generateSizeofType(w, "__SIZEOF_WINT_T__", .{ .specifier = .pointer }); |
| 447 | 458 | ||
| 459 | if (target_util.hasInt128(comp.target)) { | ||
| 460 | try comp.generateSizeofType(w, "__SIZEOF_INT128__", .{ .specifier = .int128 }); | ||
| 461 | } | ||
| 462 | |||
| 448 | // various int types | 463 | // various int types |
| 449 | const mapper = comp.string_interner.getSlowTypeMapper(); | 464 | const mapper = comp.string_interner.getSlowTypeMapper(); |
| 450 | try generateTypeMacro(w, mapper, "__INTPTR_TYPE__", comp.types.intptr, comp.langopts); | 465 | try generateTypeMacro(w, mapper, "__INTPTR_TYPE__", comp.types.intptr, comp.langopts); |
| ... | @@ -461,6 +476,7 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { | ... | @@ -461,6 +476,7 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { |
| 461 | try generateTypeMacro(w, mapper, "__WCHAR_TYPE__", comp.types.wchar, comp.langopts); | 476 | try generateTypeMacro(w, mapper, "__WCHAR_TYPE__", comp.types.wchar, comp.langopts); |
| 462 | 477 | ||
| 463 | try comp.generateExactWidthTypes(w, mapper); | 478 | try comp.generateExactWidthTypes(w, mapper); |
| 479 | try comp.generateFastAndLeastWidthTypes(w, mapper); | ||
| 464 | 480 | ||
| 465 | if (target_util.FPSemantics.halfPrecisionType(comp.target)) |half| { | 481 | if (target_util.FPSemantics.halfPrecisionType(comp.target)) |half| { |
| 466 | try generateFloatMacros(w, "FLT16", half, "F16"); | 482 | try generateFloatMacros(w, "FLT16", half, "F16"); |
| ... | @@ -497,10 +513,11 @@ pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefi | ... | @@ -497,10 +513,11 @@ pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefi |
| 497 | ); | 513 | ); |
| 498 | } | 514 | } |
| 499 | 515 | ||
| 516 | try buf.appendSlice("#define __STDC__ 1\n"); | ||
| 517 | try buf.writer().print("#define __STDC_HOSTED__ {d}\n", .{@intFromBool(comp.target.os.tag != .freestanding)}); | ||
| 518 | |||
| 500 | // standard macros | 519 | // standard macros |
| 501 | try buf.appendSlice( | 520 | try buf.appendSlice( |
| 502 | \\#define __STDC__ 1 | ||
| 503 | \\#define __STDC_HOSTED__ 1 | ||
| 504 | \\#define __STDC_NO_ATOMICS__ 1 | 521 | \\#define __STDC_NO_ATOMICS__ 1 |
| 505 | \\#define __STDC_NO_COMPLEX__ 1 | 522 | \\#define __STDC_NO_COMPLEX__ 1 |
| 506 | \\#define __STDC_NO_THREADS__ 1 | 523 | \\#define __STDC_NO_THREADS__ 1 |
| ... | @@ -678,6 +695,14 @@ fn generateBuiltinTypes(comp: *Compilation) !void { | ... | @@ -678,6 +695,14 @@ fn generateBuiltinTypes(comp: *Compilation) !void { |
| 678 | 695 | ||
| 679 | /// Smallest integer type with at least N bits | 696 | /// Smallest integer type with at least N bits |
| 680 | fn intLeastN(comp: *const Compilation, bits: usize, signedness: std.builtin.Signedness) Type { | 697 | fn intLeastN(comp: *const Compilation, bits: usize, signedness: std.builtin.Signedness) Type { |
| 698 | if (bits == 64 and (comp.target.isDarwin() or comp.target.isWasm())) { | ||
| 699 | // WebAssembly and Darwin use `long long` for `int_least64_t` and `int_fast64_t`. | ||
| 700 | return .{ .specifier = if (signedness == .signed) .long_long else .ulong_long }; | ||
| 701 | } | ||
| 702 | if (bits == 16 and comp.target.cpu.arch == .avr) { | ||
| 703 | // AVR uses int for int_least16_t and int_fast16_t. | ||
| 704 | return .{ .specifier = if (signedness == .signed) .int else .uint }; | ||
| 705 | } | ||
| 681 | const candidates = switch (signedness) { | 706 | const candidates = switch (signedness) { |
| 682 | .signed => &[_]Type.Specifier{ .schar, .short, .int, .long, .long_long }, | 707 | .signed => &[_]Type.Specifier{ .schar, .short, .int, .long, .long_long }, |
| 683 | .unsigned => &[_]Type.Specifier{ .uchar, .ushort, .uint, .ulong, .ulong_long }, | 708 | .unsigned => &[_]Type.Specifier{ .uchar, .ushort, .uint, .ulong, .ulong_long }, |
| ... | @@ -693,6 +718,52 @@ fn intSize(comp: *const Compilation, specifier: Type.Specifier) u64 { | ... | @@ -693,6 +718,52 @@ fn intSize(comp: *const Compilation, specifier: Type.Specifier) u64 { |
| 693 | return ty.sizeof(comp).?; | 718 | return ty.sizeof(comp).?; |
| 694 | } | 719 | } |
| 695 | 720 | ||
| 721 | fn generateFastOrLeastType( | ||
| 722 | comp: *Compilation, | ||
| 723 | bits: usize, | ||
| 724 | kind: enum { least, fast }, | ||
| 725 | signedness: std.builtin.Signedness, | ||
| 726 | w: anytype, | ||
| 727 | mapper: StrInt.TypeMapper, | ||
| 728 | ) !void { | ||
| 729 | const ty = comp.intLeastN(bits, signedness); // defining the fast types as the least types is permitted | ||
| 730 | |||
| 731 | var buf: [32]u8 = undefined; | ||
| 732 | const suffix = "_TYPE__"; | ||
| 733 | const base_name = switch (signedness) { | ||
| 734 | .signed => "__INT_", | ||
| 735 | .unsigned => "__UINT_", | ||
| 736 | }; | ||
| 737 | const kind_str = switch (kind) { | ||
| 738 | .fast => "FAST", | ||
| 739 | .least => "LEAST", | ||
| 740 | }; | ||
| 741 | |||
| 742 | const full = std.fmt.bufPrint(&buf, "{s}{s}{d}{s}", .{ | ||
| 743 | base_name, kind_str, bits, suffix, | ||
| 744 | }) catch return error.OutOfMemory; | ||
| 745 | |||
| 746 | try generateTypeMacro(w, mapper, full, ty, comp.langopts); | ||
| 747 | |||
| 748 | const prefix = full[2 .. full.len - suffix.len]; // remove "__" and "_TYPE__" | ||
| 749 | |||
| 750 | switch (signedness) { | ||
| 751 | .signed => try comp.generateIntMaxAndWidth(w, prefix, ty), | ||
| 752 | .unsigned => try comp.generateIntMax(w, prefix, ty), | ||
| 753 | } | ||
| 754 | try comp.generateFmt(prefix, w, ty); | ||
| 755 | } | ||
| 756 | |||
| 757 | fn generateFastAndLeastWidthTypes(comp: *Compilation, w: anytype, mapper: StrInt.TypeMapper) !void { | ||
| 758 | const sizes = [_]usize{ 8, 16, 32, 64 }; | ||
| 759 | for (sizes) |size| { | ||
| 760 | try comp.generateFastOrLeastType(size, .least, .signed, w, mapper); | ||
| 761 | try comp.generateFastOrLeastType(size, .least, .unsigned, w, mapper); | ||
| 762 | try comp.generateFastOrLeastType(size, .fast, .signed, w, mapper); | ||
| 763 | try comp.generateFastOrLeastType(size, .fast, .unsigned, w, mapper); | ||
| 764 | } | ||
| 765 | } | ||
| 766 | |||
| 696 | fn generateExactWidthTypes(comp: *const Compilation, w: anytype, mapper: StrInt.TypeMapper) !void { | 767 | fn generateExactWidthTypes(comp: *const Compilation, w: anytype, mapper: StrInt.TypeMapper) !void { |
| 697 | try comp.generateExactWidthType(w, mapper, .schar); | 768 | try comp.generateExactWidthType(w, mapper, .schar); |
| 698 | 769 |
deps/aro/aro/Diagnostics.zig+4-3| ... | @@ -236,7 +236,7 @@ pub fn set(d: *Diagnostics, name: []const u8, to: Kind) !void { | ... | @@ -236,7 +236,7 @@ pub fn set(d: *Diagnostics, name: []const u8, to: Kind) !void { |
| 236 | try d.addExtra(.{}, .{ | 236 | try d.addExtra(.{}, .{ |
| 237 | .tag = .unknown_warning, | 237 | .tag = .unknown_warning, |
| 238 | .extra = .{ .str = name }, | 238 | .extra = .{ .str = name }, |
| 239 | }, &.{}); | 239 | }, &.{}, true); |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | pub fn init(gpa: Allocator) Diagnostics { | 242 | pub fn init(gpa: Allocator) Diagnostics { |
| ... | @@ -251,7 +251,7 @@ pub fn deinit(d: *Diagnostics) void { | ... | @@ -251,7 +251,7 @@ pub fn deinit(d: *Diagnostics) void { |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | pub fn add(comp: *Compilation, msg: Message, expansion_locs: []const Source.Location) Compilation.Error!void { | 253 | pub fn add(comp: *Compilation, msg: Message, expansion_locs: []const Source.Location) Compilation.Error!void { |
| 254 | return comp.diagnostics.addExtra(comp.langopts, msg, expansion_locs); | 254 | return comp.diagnostics.addExtra(comp.langopts, msg, expansion_locs, true); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | pub fn addExtra( | 257 | pub fn addExtra( |
| ... | @@ -259,6 +259,7 @@ pub fn addExtra( | ... | @@ -259,6 +259,7 @@ pub fn addExtra( |
| 259 | langopts: LangOpts, | 259 | langopts: LangOpts, |
| 260 | msg: Message, | 260 | msg: Message, |
| 261 | expansion_locs: []const Source.Location, | 261 | expansion_locs: []const Source.Location, |
| 262 | note_msg_loc: bool, | ||
| 262 | ) Compilation.Error!void { | 263 | ) Compilation.Error!void { |
| 263 | const kind = d.tagKind(msg.tag, langopts); | 264 | const kind = d.tagKind(msg.tag, langopts); |
| 264 | if (kind == .off) return; | 265 | if (kind == .off) return; |
| ... | @@ -301,7 +302,7 @@ pub fn addExtra( | ... | @@ -301,7 +302,7 @@ pub fn addExtra( |
| 301 | } | 302 | } |
| 302 | } | 303 | } |
| 303 | 304 | ||
| 304 | d.list.appendAssumeCapacity(.{ | 305 | if (note_msg_loc) d.list.appendAssumeCapacity(.{ |
| 305 | .tag = .expanded_from_here, | 306 | .tag = .expanded_from_here, |
| 306 | .kind = .note, | 307 | .kind = .note, |
| 307 | .loc = msg.loc, | 308 | .loc = msg.loc, |
deps/aro/aro/Driver.zig+16| ... | @@ -98,8 +98,10 @@ pub const usage = | ... | @@ -98,8 +98,10 @@ pub const usage = |
| 98 | \\ -fno-declspec Disable support for __declspec attributes | 98 | \\ -fno-declspec Disable support for __declspec attributes |
| 99 | \\ -ffp-eval-method=[source|double|extended] | 99 | \\ -ffp-eval-method=[source|double|extended] |
| 100 | \\ Evaluation method to use for floating-point arithmetic | 100 | \\ Evaluation method to use for floating-point arithmetic |
| 101 | \\ -ffreestanding Compilation in a freestanding environment | ||
| 101 | \\ -fgnu-inline-asm Enable GNU style inline asm (default: enabled) | 102 | \\ -fgnu-inline-asm Enable GNU style inline asm (default: enabled) |
| 102 | \\ -fno-gnu-inline-asm Disable GNU style inline asm | 103 | \\ -fno-gnu-inline-asm Disable GNU style inline asm |
| 104 | \\ -fhosted Compilation in a hosted environment | ||
| 103 | \\ -fms-extensions Enable support for Microsoft extensions | 105 | \\ -fms-extensions Enable support for Microsoft extensions |
| 104 | \\ -fno-ms-extensions Disable support for Microsoft extensions | 106 | \\ -fno-ms-extensions Disable support for Microsoft extensions |
| 105 | \\ -fdollars-in-identifiers | 107 | \\ -fdollars-in-identifiers |
| ... | @@ -177,6 +179,7 @@ pub fn parseArgs( | ... | @@ -177,6 +179,7 @@ pub fn parseArgs( |
| 177 | ) !bool { | 179 | ) !bool { |
| 178 | var i: usize = 1; | 180 | var i: usize = 1; |
| 179 | var comment_arg: []const u8 = ""; | 181 | var comment_arg: []const u8 = ""; |
| 182 | var hosted: ?bool = null; | ||
| 180 | while (i < args.len) : (i += 1) { | 183 | while (i < args.len) : (i += 1) { |
| 181 | const arg = args[i]; | 184 | const arg = args[i]; |
| 182 | if (mem.startsWith(u8, arg, "-") and arg.len > 1) { | 185 | if (mem.startsWith(u8, arg, "-") and arg.len > 1) { |
| ... | @@ -277,6 +280,10 @@ pub fn parseArgs( | ... | @@ -277,6 +280,10 @@ pub fn parseArgs( |
| 277 | d.comp.langopts.declspec_attrs = true; | 280 | d.comp.langopts.declspec_attrs = true; |
| 278 | } else if (mem.eql(u8, arg, "-fno-declspec")) { | 281 | } else if (mem.eql(u8, arg, "-fno-declspec")) { |
| 279 | d.comp.langopts.declspec_attrs = false; | 282 | d.comp.langopts.declspec_attrs = false; |
| 283 | } else if (mem.eql(u8, arg, "-ffreestanding")) { | ||
| 284 | hosted = false; | ||
| 285 | } else if (mem.eql(u8, arg, "-fhosted")) { | ||
| 286 | hosted = true; | ||
| 280 | } else if (mem.eql(u8, arg, "-fms-extensions")) { | 287 | } else if (mem.eql(u8, arg, "-fms-extensions")) { |
| 281 | d.comp.langopts.enableMSExtensions(); | 288 | d.comp.langopts.enableMSExtensions(); |
| 282 | } else if (mem.eql(u8, arg, "-fno-ms-extensions")) { | 289 | } else if (mem.eql(u8, arg, "-fno-ms-extensions")) { |
| ... | @@ -440,6 +447,15 @@ pub fn parseArgs( | ... | @@ -440,6 +447,15 @@ pub fn parseArgs( |
| 440 | if (d.comp.langopts.preserve_comments and !d.only_preprocess) { | 447 | if (d.comp.langopts.preserve_comments and !d.only_preprocess) { |
| 441 | return d.fatal("invalid argument '{s}' only allowed with '-E'", .{comment_arg}); | 448 | return d.fatal("invalid argument '{s}' only allowed with '-E'", .{comment_arg}); |
| 442 | } | 449 | } |
| 450 | if (hosted) |is_hosted| { | ||
| 451 | if (is_hosted) { | ||
| 452 | if (d.comp.target.os.tag == .freestanding) { | ||
| 453 | return d.fatal("Cannot use freestanding target with `-fhosted`", .{}); | ||
| 454 | } | ||
| 455 | } else { | ||
| 456 | d.comp.target.os.tag = .freestanding; | ||
| 457 | } | ||
| 458 | } | ||
| 443 | return false; | 459 | return false; |
| 444 | } | 460 | } |
| 445 | 461 |
deps/aro/aro/Driver/Filesystem.zig+10-10| ... | @@ -121,7 +121,7 @@ pub const Filesystem = union(enum) { | ... | @@ -121,7 +121,7 @@ pub const Filesystem = union(enum) { |
| 121 | base: []const u8, | 121 | base: []const u8, |
| 122 | i: usize = 0, | 122 | i: usize = 0, |
| 123 | 123 | ||
| 124 | fn next(self: *@This()) !?std.fs.IterableDir.Entry { | 124 | fn next(self: *@This()) !?std.fs.Dir.Entry { |
| 125 | while (self.i < self.entries.len) { | 125 | while (self.i < self.entries.len) { |
| 126 | const entry = self.entries[self.i]; | 126 | const entry = self.entries[self.i]; |
| 127 | self.i += 1; | 127 | self.i += 1; |
| ... | @@ -130,7 +130,7 @@ pub const Filesystem = union(enum) { | ... | @@ -130,7 +130,7 @@ pub const Filesystem = union(enum) { |
| 130 | const remaining = entry.path[self.base.len + 1 ..]; | 130 | const remaining = entry.path[self.base.len + 1 ..]; |
| 131 | if (std.mem.indexOfScalar(u8, remaining, std.fs.path.sep) != null) continue; | 131 | if (std.mem.indexOfScalar(u8, remaining, std.fs.path.sep) != null) continue; |
| 132 | const extension = std.fs.path.extension(remaining); | 132 | const extension = std.fs.path.extension(remaining); |
| 133 | const kind: std.fs.IterableDir.Entry.Kind = if (extension.len == 0) .directory else .file; | 133 | const kind: std.fs.Dir.Entry.Kind = if (extension.len == 0) .directory else .file; |
| 134 | return .{ .name = remaining, .kind = kind }; | 134 | return .{ .name = remaining, .kind = kind }; |
| 135 | } | 135 | } |
| 136 | } | 136 | } |
| ... | @@ -139,18 +139,18 @@ pub const Filesystem = union(enum) { | ... | @@ -139,18 +139,18 @@ pub const Filesystem = union(enum) { |
| 139 | }; | 139 | }; |
| 140 | }; | 140 | }; |
| 141 | 141 | ||
| 142 | const IterableDir = union(enum) { | 142 | const Dir = union(enum) { |
| 143 | dir: std.fs.IterableDir, | 143 | dir: std.fs.Dir, |
| 144 | fake: FakeDir, | 144 | fake: FakeDir, |
| 145 | 145 | ||
| 146 | pub fn iterate(self: IterableDir) Iterator { | 146 | pub fn iterate(self: Dir) Iterator { |
| 147 | return switch (self) { | 147 | return switch (self) { |
| 148 | .dir => |dir| .{ .iterator = dir.iterate() }, | 148 | .dir => |dir| .{ .iterator = dir.iterate() }, |
| 149 | .fake => |fake| .{ .fake = fake.iterate() }, | 149 | .fake => |fake| .{ .fake = fake.iterate() }, |
| 150 | }; | 150 | }; |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | pub fn close(self: *IterableDir) void { | 153 | pub fn close(self: *Dir) void { |
| 154 | switch (self.*) { | 154 | switch (self.*) { |
| 155 | .dir => |*d| d.close(), | 155 | .dir => |*d| d.close(), |
| 156 | .fake => {}, | 156 | .fake => {}, |
| ... | @@ -159,10 +159,10 @@ pub const Filesystem = union(enum) { | ... | @@ -159,10 +159,10 @@ pub const Filesystem = union(enum) { |
| 159 | }; | 159 | }; |
| 160 | 160 | ||
| 161 | const Iterator = union(enum) { | 161 | const Iterator = union(enum) { |
| 162 | iterator: std.fs.IterableDir.Iterator, | 162 | iterator: std.fs.Dir.Iterator, |
| 163 | fake: FakeDir.Iterator, | 163 | fake: FakeDir.Iterator, |
| 164 | 164 | ||
| 165 | pub fn next(self: *Iterator) std.fs.IterableDir.Iterator.Error!?std.fs.IterableDir.Entry { | 165 | pub fn next(self: *Iterator) std.fs.Dir.Iterator.Error!?std.fs.Dir.Entry { |
| 166 | return switch (self.*) { | 166 | return switch (self.*) { |
| 167 | .iterator => |*it| it.next(), | 167 | .iterator => |*it| it.next(), |
| 168 | .fake => |*it| it.next(), | 168 | .fake => |*it| it.next(), |
| ... | @@ -221,9 +221,9 @@ pub const Filesystem = union(enum) { | ... | @@ -221,9 +221,9 @@ pub const Filesystem = union(enum) { |
| 221 | }; | 221 | }; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | pub fn openIterableDir(fs: Filesystem, dir_name: []const u8) std.fs.Dir.OpenError!IterableDir { | 224 | pub fn openDir(fs: Filesystem, dir_name: []const u8) std.fs.Dir.OpenError!Dir { |
| 225 | return switch (fs) { | 225 | return switch (fs) { |
| 226 | .real => .{ .dir = try std.fs.cwd().openIterableDir(dir_name, .{ .access_sub_paths = false }) }, | 226 | .real => .{ .dir = try std.fs.cwd().openDir(dir_name, .{ .access_sub_paths = false, .iterate = true }) }, |
| 227 | .fake => |entries| .{ .fake = .{ .entries = entries, .path = dir_name } }, | 227 | .fake => |entries| .{ .fake = .{ .entries = entries, .path = dir_name } }, |
| 228 | }; | 228 | }; |
| 229 | } | 229 | } |
deps/aro/aro/Driver/GCCDetector.zig+1-1| ... | @@ -602,7 +602,7 @@ fn scanLibDirForGCCTriple( | ... | @@ -602,7 +602,7 @@ fn scanLibDirForGCCTriple( |
| 602 | const lib_suffix = std.fs.path.join(suffix_buf_fib.allocator(), &.{ base, candidate_triple }) catch continue; | 602 | const lib_suffix = std.fs.path.join(suffix_buf_fib.allocator(), &.{ base, candidate_triple }) catch continue; |
| 603 | 603 | ||
| 604 | const dir_name = std.fs.path.join(fib.allocator(), &.{ lib_dir, lib_suffix }) catch continue; | 604 | const dir_name = std.fs.path.join(fib.allocator(), &.{ lib_dir, lib_suffix }) catch continue; |
| 605 | var parent_dir = tc.filesystem.openIterableDir(dir_name) catch continue; | 605 | var parent_dir = tc.filesystem.openDir(dir_name) catch continue; |
| 606 | defer parent_dir.close(); | 606 | defer parent_dir.close(); |
| 607 | 607 | ||
| 608 | var it = parent_dir.iterate(); | 608 | var it = parent_dir.iterate(); |
deps/aro/aro/Parser.zig+79-32| ... | @@ -9,6 +9,8 @@ const Tokenizer = @import("Tokenizer.zig"); | ... | @@ -9,6 +9,8 @@ const Tokenizer = @import("Tokenizer.zig"); |
| 9 | const Preprocessor = @import("Preprocessor.zig"); | 9 | const Preprocessor = @import("Preprocessor.zig"); |
| 10 | const Tree = @import("Tree.zig"); | 10 | const Tree = @import("Tree.zig"); |
| 11 | const Token = Tree.Token; | 11 | const Token = Tree.Token; |
| 12 | const NumberPrefix = Token.NumberPrefix; | ||
| 13 | const NumberSuffix = Token.NumberSuffix; | ||
| 12 | const TokenIndex = Tree.TokenIndex; | 14 | const TokenIndex = Tree.TokenIndex; |
| 13 | const NodeIndex = Tree.NodeIndex; | 15 | const NodeIndex = Tree.NodeIndex; |
| 14 | const Type = @import("Type.zig"); | 16 | const Type = @import("Type.zig"); |
| ... | @@ -24,9 +26,6 @@ const Symbol = SymbolStack.Symbol; | ... | @@ -24,9 +26,6 @@ const Symbol = SymbolStack.Symbol; |
| 24 | const record_layout = @import("record_layout.zig"); | 26 | const record_layout = @import("record_layout.zig"); |
| 25 | const StrInt = @import("StringInterner.zig"); | 27 | const StrInt = @import("StringInterner.zig"); |
| 26 | const StringId = StrInt.StringId; | 28 | const StringId = StrInt.StringId; |
| 27 | const number_affixes = @import("number_affixes.zig"); | ||
| 28 | const NumberPrefix = number_affixes.Prefix; | ||
| 29 | const NumberSuffix = number_affixes.Suffix; | ||
| 30 | const Builtins = @import("Builtins.zig"); | 29 | const Builtins = @import("Builtins.zig"); |
| 31 | const Builtin = Builtins.Builtin; | 30 | const Builtin = Builtins.Builtin; |
| 32 | const target_util = @import("target.zig"); | 31 | const target_util = @import("target.zig"); |
| ... | @@ -323,7 +322,7 @@ fn expectIdentifier(p: *Parser) Error!TokenIndex { | ... | @@ -323,7 +322,7 @@ fn expectIdentifier(p: *Parser) Error!TokenIndex { |
| 323 | return p.errExpectedToken(.identifier, actual); | 322 | return p.errExpectedToken(.identifier, actual); |
| 324 | } | 323 | } |
| 325 | 324 | ||
| 326 | return (try p.eatIdentifier()) orelse unreachable; | 325 | return (try p.eatIdentifier()) orelse error.ParsingFailed; |
| 327 | } | 326 | } |
| 328 | 327 | ||
| 329 | fn eatToken(p: *Parser, id: Token.Id) ?TokenIndex { | 328 | fn eatToken(p: *Parser, id: Token.Id) ?TokenIndex { |
| ... | @@ -347,7 +346,7 @@ pub fn tokSlice(p: *Parser, tok: TokenIndex) []const u8 { | ... | @@ -347,7 +346,7 @@ pub fn tokSlice(p: *Parser, tok: TokenIndex) []const u8 { |
| 347 | const loc = p.pp.tokens.items(.loc)[tok]; | 346 | const loc = p.pp.tokens.items(.loc)[tok]; |
| 348 | var tmp_tokenizer = Tokenizer{ | 347 | var tmp_tokenizer = Tokenizer{ |
| 349 | .buf = p.comp.getSource(loc.id).buf, | 348 | .buf = p.comp.getSource(loc.id).buf, |
| 350 | .comp = p.comp, | 349 | .langopts = p.comp.langopts, |
| 351 | .index = loc.byte_offset, | 350 | .index = loc.byte_offset, |
| 352 | .source = .generated, | 351 | .source = .generated, |
| 353 | }; | 352 | }; |
| ... | @@ -715,6 +714,9 @@ pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { | ... | @@ -715,6 +714,9 @@ pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { |
| 715 | p.field_attr_buf.deinit(); | 714 | p.field_attr_buf.deinit(); |
| 716 | } | 715 | } |
| 717 | 716 | ||
| 717 | try p.syms.pushScope(&p); | ||
| 718 | defer p.syms.popScope(); | ||
| 719 | |||
| 718 | // NodeIndex 0 must be invalid | 720 | // NodeIndex 0 must be invalid |
| 719 | _ = try p.addNode(.{ .tag = .invalid, .ty = undefined, .data = undefined }); | 721 | _ = try p.addNode(.{ .tag = .invalid, .ty = undefined, .data = undefined }); |
| 720 | 722 | ||
| ... | @@ -1010,7 +1012,7 @@ fn decl(p: *Parser) Error!bool { | ... | @@ -1010,7 +1012,7 @@ fn decl(p: *Parser) Error!bool { |
| 1010 | // Collect old style parameter declarations. | 1012 | // Collect old style parameter declarations. |
| 1011 | if (init_d.d.old_style_func != null) { | 1013 | if (init_d.d.old_style_func != null) { |
| 1012 | const attrs = init_d.d.ty.getAttributes(); | 1014 | const attrs = init_d.d.ty.getAttributes(); |
| 1013 | var base_ty = if (init_d.d.ty.specifier == .attributed) init_d.d.ty.elemType() else init_d.d.ty; | 1015 | var base_ty = if (init_d.d.ty.specifier == .attributed) init_d.d.ty.data.attributed.base else init_d.d.ty; |
| 1014 | base_ty.specifier = .func; | 1016 | base_ty.specifier = .func; |
| 1015 | init_d.d.ty = try base_ty.withAttributes(p.arena, attrs); | 1017 | init_d.d.ty = try base_ty.withAttributes(p.arena, attrs); |
| 1016 | 1018 | ||
| ... | @@ -1066,7 +1068,7 @@ fn decl(p: *Parser) Error!bool { | ... | @@ -1066,7 +1068,7 @@ fn decl(p: *Parser) Error!bool { |
| 1066 | d.ty = try Attribute.applyParameterAttributes(p, d.ty, attr_buf_top_declarator, .alignas_on_param); | 1068 | d.ty = try Attribute.applyParameterAttributes(p, d.ty, attr_buf_top_declarator, .alignas_on_param); |
| 1067 | 1069 | ||
| 1068 | // bypass redefinition check to avoid duplicate errors | 1070 | // bypass redefinition check to avoid duplicate errors |
| 1069 | try p.syms.syms.append(p.gpa, .{ | 1071 | try p.syms.define(p.gpa, .{ |
| 1070 | .kind = .def, | 1072 | .kind = .def, |
| 1071 | .name = interned_name, | 1073 | .name = interned_name, |
| 1072 | .tok = d.name, | 1074 | .tok = d.name, |
| ... | @@ -1088,7 +1090,7 @@ fn decl(p: *Parser) Error!bool { | ... | @@ -1088,7 +1090,7 @@ fn decl(p: *Parser) Error!bool { |
| 1088 | } | 1090 | } |
| 1089 | 1091 | ||
| 1090 | // bypass redefinition check to avoid duplicate errors | 1092 | // bypass redefinition check to avoid duplicate errors |
| 1091 | try p.syms.syms.append(p.gpa, .{ | 1093 | try p.syms.define(p.gpa, .{ |
| 1092 | .kind = .def, | 1094 | .kind = .def, |
| 1093 | .name = param.name, | 1095 | .name = param.name, |
| 1094 | .tok = param.name_tok, | 1096 | .tok = param.name_tok, |
| ... | @@ -1428,12 +1430,14 @@ fn typeof(p: *Parser) Error!?Type { | ... | @@ -1428,12 +1430,14 @@ fn typeof(p: *Parser) Error!?Type { |
| 1428 | .data = typeof_expr.ty.data, | 1430 | .data = typeof_expr.ty.data, |
| 1429 | .qual = if (unqual) .{} else typeof_expr.ty.qual.inheritFromTypeof(), | 1431 | .qual = if (unqual) .{} else typeof_expr.ty.qual.inheritFromTypeof(), |
| 1430 | .specifier = typeof_expr.ty.specifier, | 1432 | .specifier = typeof_expr.ty.specifier, |
| 1433 | .decayed = typeof_expr.ty.decayed, | ||
| 1431 | }, | 1434 | }, |
| 1432 | }; | 1435 | }; |
| 1433 | 1436 | ||
| 1434 | return Type{ | 1437 | return Type{ |
| 1435 | .data = .{ .expr = inner }, | 1438 | .data = .{ .expr = inner }, |
| 1436 | .specifier = .typeof_expr, | 1439 | .specifier = .typeof_expr, |
| 1440 | .decayed = typeof_expr.ty.decayed, | ||
| 1437 | }; | 1441 | }; |
| 1438 | } | 1442 | } |
| 1439 | 1443 | ||
| ... | @@ -1814,6 +1818,7 @@ fn initDeclarator(p: *Parser, decl_spec: *DeclSpec, attr_buf_top: usize) Error!? | ... | @@ -1814,6 +1818,7 @@ fn initDeclarator(p: *Parser, decl_spec: *DeclSpec, attr_buf_top: usize) Error!? |
| 1814 | } else { | 1818 | } else { |
| 1815 | init_d.d.ty.specifier = init_d.initializer.ty.specifier; | 1819 | init_d.d.ty.specifier = init_d.initializer.ty.specifier; |
| 1816 | init_d.d.ty.data = init_d.initializer.ty.data; | 1820 | init_d.d.ty.data = init_d.initializer.ty.data; |
| 1821 | init_d.d.ty.decayed = init_d.initializer.ty.decayed; | ||
| 1817 | } | 1822 | } |
| 1818 | } | 1823 | } |
| 1819 | if (apply_var_attributes) { | 1824 | if (apply_var_attributes) { |
| ... | @@ -2105,7 +2110,7 @@ fn recordSpec(p: *Parser) Error!Type { | ... | @@ -2105,7 +2110,7 @@ fn recordSpec(p: *Parser) Error!Type { |
| 2105 | .specifier = if (is_struct) .@"struct" else .@"union", | 2110 | .specifier = if (is_struct) .@"struct" else .@"union", |
| 2106 | .data = .{ .record = record_ty }, | 2111 | .data = .{ .record = record_ty }, |
| 2107 | }, attr_buf_top, null); | 2112 | }, attr_buf_top, null); |
| 2108 | try p.syms.syms.append(p.gpa, .{ | 2113 | try p.syms.define(p.gpa, .{ |
| 2109 | .kind = if (is_struct) .@"struct" else .@"union", | 2114 | .kind = if (is_struct) .@"struct" else .@"union", |
| 2110 | .name = interned_name, | 2115 | .name = interned_name, |
| 2111 | .tok = ident, | 2116 | .tok = ident, |
| ... | @@ -2151,10 +2156,8 @@ fn recordSpec(p: *Parser) Error!Type { | ... | @@ -2151,10 +2156,8 @@ fn recordSpec(p: *Parser) Error!Type { |
| 2151 | 2156 | ||
| 2152 | // declare a symbol for the type | 2157 | // declare a symbol for the type |
| 2153 | // We need to replace the symbol's type if it has attributes | 2158 | // We need to replace the symbol's type if it has attributes |
| 2154 | var symbol_index: ?usize = null; | ||
| 2155 | if (maybe_ident != null and !defined) { | 2159 | if (maybe_ident != null and !defined) { |
| 2156 | symbol_index = p.syms.syms.len; | 2160 | try p.syms.define(p.gpa, .{ |
| 2157 | try p.syms.syms.append(p.gpa, .{ | ||
| 2158 | .kind = if (is_struct) .@"struct" else .@"union", | 2161 | .kind = if (is_struct) .@"struct" else .@"union", |
| 2159 | .name = record_ty.name, | 2162 | .name = record_ty.name, |
| 2160 | .tok = maybe_ident.?, | 2163 | .tok = maybe_ident.?, |
| ... | @@ -2216,8 +2219,11 @@ fn recordSpec(p: *Parser) Error!Type { | ... | @@ -2216,8 +2219,11 @@ fn recordSpec(p: *Parser) Error!Type { |
| 2216 | .specifier = if (is_struct) .@"struct" else .@"union", | 2219 | .specifier = if (is_struct) .@"struct" else .@"union", |
| 2217 | .data = .{ .record = record_ty }, | 2220 | .data = .{ .record = record_ty }, |
| 2218 | }, attr_buf_top, null); | 2221 | }, attr_buf_top, null); |
| 2219 | if (ty.specifier == .attributed and symbol_index != null) { | 2222 | if (ty.specifier == .attributed and maybe_ident != null) { |
| 2220 | p.syms.syms.items(.ty)[symbol_index.?] = ty; | 2223 | const ident_str = p.tokSlice(maybe_ident.?); |
| 2224 | const interned_name = try StrInt.intern(p.comp, ident_str); | ||
| 2225 | const ptr = p.syms.getPtr(interned_name, .tags); | ||
| 2226 | ptr.ty = ty; | ||
| 2221 | } | 2227 | } |
| 2222 | 2228 | ||
| 2223 | if (!ty.hasIncompleteSize()) { | 2229 | if (!ty.hasIncompleteSize()) { |
| ... | @@ -2474,7 +2480,7 @@ fn enumSpec(p: *Parser) Error!Type { | ... | @@ -2474,7 +2480,7 @@ fn enumSpec(p: *Parser) Error!Type { |
| 2474 | .specifier = .@"enum", | 2480 | .specifier = .@"enum", |
| 2475 | .data = .{ .@"enum" = enum_ty }, | 2481 | .data = .{ .@"enum" = enum_ty }, |
| 2476 | }, attr_buf_top, null); | 2482 | }, attr_buf_top, null); |
| 2477 | try p.syms.syms.append(p.gpa, .{ | 2483 | try p.syms.define(p.gpa, .{ |
| 2478 | .kind = .@"enum", | 2484 | .kind = .@"enum", |
| 2479 | .name = interned_name, | 2485 | .name = interned_name, |
| 2480 | .tok = ident, | 2486 | .tok = ident, |
| ... | @@ -2525,7 +2531,6 @@ fn enumSpec(p: *Parser) Error!Type { | ... | @@ -2525,7 +2531,6 @@ fn enumSpec(p: *Parser) Error!Type { |
| 2525 | p.enum_buf.items.len = enum_buf_top; | 2531 | p.enum_buf.items.len = enum_buf_top; |
| 2526 | } | 2532 | } |
| 2527 | 2533 | ||
| 2528 | const sym_stack_top = p.syms.syms.len; | ||
| 2529 | var e = Enumerator.init(fixed_ty); | 2534 | var e = Enumerator.init(fixed_ty); |
| 2530 | while (try p.enumerator(&e)) |field_and_node| { | 2535 | while (try p.enumerator(&e)) |field_and_node| { |
| 2531 | try p.enum_buf.append(field_and_node.field); | 2536 | try p.enum_buf.append(field_and_node.field); |
| ... | @@ -2551,13 +2556,12 @@ fn enumSpec(p: *Parser) Error!Type { | ... | @@ -2551,13 +2556,12 @@ fn enumSpec(p: *Parser) Error!Type { |
| 2551 | const field_nodes = p.list_buf.items[list_buf_top..]; | 2556 | const field_nodes = p.list_buf.items[list_buf_top..]; |
| 2552 | 2557 | ||
| 2553 | if (fixed_ty == null) { | 2558 | if (fixed_ty == null) { |
| 2554 | const vals = p.syms.syms.items(.val)[sym_stack_top..]; | ||
| 2555 | const types = p.syms.syms.items(.ty)[sym_stack_top..]; | ||
| 2556 | |||
| 2557 | for (enum_fields, 0..) |*field, i| { | 2559 | for (enum_fields, 0..) |*field, i| { |
| 2558 | if (field.ty.eql(Type.int, p.comp, false)) continue; | 2560 | if (field.ty.eql(Type.int, p.comp, false)) continue; |
| 2559 | 2561 | ||
| 2560 | var res = Result{ .node = field.node, .ty = field.ty, .val = vals[i] }; | 2562 | const sym = p.syms.get(field.name, .vars) orelse continue; |
| 2563 | |||
| 2564 | var res = Result{ .node = field.node, .ty = field.ty, .val = sym.val }; | ||
| 2561 | const dest_ty = if (p.comp.fixedEnumTagSpecifier()) |some| | 2565 | const dest_ty = if (p.comp.fixedEnumTagSpecifier()) |some| |
| 2562 | Type{ .specifier = some } | 2566 | Type{ .specifier = some } |
| 2563 | else if (try res.intFitsInType(p, Type.int)) | 2567 | else if (try res.intFitsInType(p, Type.int)) |
| ... | @@ -2567,8 +2571,9 @@ fn enumSpec(p: *Parser) Error!Type { | ... | @@ -2567,8 +2571,9 @@ fn enumSpec(p: *Parser) Error!Type { |
| 2567 | else | 2571 | else |
| 2568 | continue; | 2572 | continue; |
| 2569 | 2573 | ||
| 2570 | try vals[i].intCast(dest_ty, p.comp); | 2574 | const symbol = p.syms.getPtr(field.name, .vars); |
| 2571 | types[i] = dest_ty; | 2575 | try symbol.val.intCast(dest_ty, p.comp); |
| 2576 | symbol.ty = dest_ty; | ||
| 2572 | p.nodes.items(.ty)[@intFromEnum(field_nodes[i])] = dest_ty; | 2577 | p.nodes.items(.ty)[@intFromEnum(field_nodes[i])] = dest_ty; |
| 2573 | field.ty = dest_ty; | 2578 | field.ty = dest_ty; |
| 2574 | res.ty = dest_ty; | 2579 | res.ty = dest_ty; |
| ... | @@ -2585,7 +2590,7 @@ fn enumSpec(p: *Parser) Error!Type { | ... | @@ -2585,7 +2590,7 @@ fn enumSpec(p: *Parser) Error!Type { |
| 2585 | 2590 | ||
| 2586 | // declare a symbol for the type | 2591 | // declare a symbol for the type |
| 2587 | if (maybe_ident != null and !defined) { | 2592 | if (maybe_ident != null and !defined) { |
| 2588 | try p.syms.syms.append(p.gpa, .{ | 2593 | try p.syms.define(p.gpa, .{ |
| 2589 | .kind = .@"enum", | 2594 | .kind = .@"enum", |
| 2590 | .name = enum_ty.name, | 2595 | .name = enum_ty.name, |
| 2591 | .ty = ty, | 2596 | .ty = ty, |
| ... | @@ -2885,7 +2890,7 @@ fn declarator( | ... | @@ -2885,7 +2890,7 @@ fn declarator( |
| 2885 | try res.ty.combine(outer); | 2890 | try res.ty.combine(outer); |
| 2886 | try res.ty.validateCombinedType(p, suffix_start); | 2891 | try res.ty.validateCombinedType(p, suffix_start); |
| 2887 | res.old_style_func = d.old_style_func; | 2892 | res.old_style_func = d.old_style_func; |
| 2888 | res.func_declarator = d.func_declarator; | 2893 | if (d.func_declarator) |some| res.func_declarator = some; |
| 2889 | return res; | 2894 | return res; |
| 2890 | } | 2895 | } |
| 2891 | 2896 | ||
| ... | @@ -4376,7 +4381,7 @@ fn stmt(p: *Parser) Error!NodeIndex { | ... | @@ -4376,7 +4381,7 @@ fn stmt(p: *Parser) Error!NodeIndex { |
| 4376 | /// | keyword_default ':' stmt | 4381 | /// | keyword_default ':' stmt |
| 4377 | fn labeledStmt(p: *Parser) Error!?NodeIndex { | 4382 | fn labeledStmt(p: *Parser) Error!?NodeIndex { |
| 4378 | if ((p.tok_ids[p.tok_i] == .identifier or p.tok_ids[p.tok_i] == .extended_identifier) and p.tok_ids[p.tok_i + 1] == .colon) { | 4383 | if ((p.tok_ids[p.tok_i] == .identifier or p.tok_ids[p.tok_i] == .extended_identifier) and p.tok_ids[p.tok_i + 1] == .colon) { |
| 4379 | const name_tok = p.expectIdentifier() catch unreachable; | 4384 | const name_tok = try p.expectIdentifier(); |
| 4380 | const str = p.tokSlice(name_tok); | 4385 | const str = p.tokSlice(name_tok); |
| 4381 | if (p.findLabel(str)) |some| { | 4386 | if (p.findLabel(str)) |some| { |
| 4382 | try p.errStr(.duplicate_label, name_tok, str); | 4387 | try p.errStr(.duplicate_label, name_tok, str); |
| ... | @@ -4814,10 +4819,23 @@ const CallExpr = union(enum) { | ... | @@ -4814,10 +4819,23 @@ const CallExpr = union(enum) { |
| 4814 | /// of arguments, `paramCountOverride` is used to tell us how many arguments we should actually expect to see for | 4819 | /// of arguments, `paramCountOverride` is used to tell us how many arguments we should actually expect to see for |
| 4815 | /// these custom-typechecked functions. | 4820 | /// these custom-typechecked functions. |
| 4816 | fn paramCountOverride(self: CallExpr) ?u32 { | 4821 | fn paramCountOverride(self: CallExpr) ?u32 { |
| 4822 | @setEvalBranchQuota(10_000); | ||
| 4817 | return switch (self) { | 4823 | return switch (self) { |
| 4818 | .standard => null, | 4824 | .standard => null, |
| 4819 | .builtin => |builtin| switch (builtin.tag) { | 4825 | .builtin => |builtin| switch (builtin.tag) { |
| 4820 | Builtin.tagFromName("__builtin_complex").? => 2, | 4826 | Builtin.tagFromName("__builtin_complex").? => 2, |
| 4827 | |||
| 4828 | Builtin.tagFromName("__atomic_fetch_add").?, | ||
| 4829 | Builtin.tagFromName("__atomic_fetch_sub").?, | ||
| 4830 | Builtin.tagFromName("__atomic_fetch_and").?, | ||
| 4831 | Builtin.tagFromName("__atomic_fetch_xor").?, | ||
| 4832 | Builtin.tagFromName("__atomic_fetch_or").?, | ||
| 4833 | Builtin.tagFromName("__atomic_fetch_nand").?, | ||
| 4834 | => 3, | ||
| 4835 | |||
| 4836 | Builtin.tagFromName("__atomic_compare_exchange").?, | ||
| 4837 | Builtin.tagFromName("__atomic_compare_exchange_n").?, | ||
| 4838 | => 6, | ||
| 4821 | else => null, | 4839 | else => null, |
| 4822 | }, | 4840 | }, |
| 4823 | }; | 4841 | }; |
| ... | @@ -4827,10 +4845,25 @@ const CallExpr = union(enum) { | ... | @@ -4827,10 +4845,25 @@ const CallExpr = union(enum) { |
| 4827 | return switch (self) { | 4845 | return switch (self) { |
| 4828 | .standard => callable_ty.returnType(), | 4846 | .standard => callable_ty.returnType(), |
| 4829 | .builtin => |builtin| switch (builtin.tag) { | 4847 | .builtin => |builtin| switch (builtin.tag) { |
| 4848 | Builtin.tagFromName("__atomic_fetch_add").?, | ||
| 4849 | Builtin.tagFromName("__atomic_fetch_sub").?, | ||
| 4850 | Builtin.tagFromName("__atomic_fetch_and").?, | ||
| 4851 | Builtin.tagFromName("__atomic_fetch_xor").?, | ||
| 4852 | Builtin.tagFromName("__atomic_fetch_or").?, | ||
| 4853 | Builtin.tagFromName("__atomic_fetch_nand").?, | ||
| 4854 | => { | ||
| 4855 | if (p.list_buf.items.len < 2) return Type.invalid; // not enough arguments; already an error | ||
| 4856 | const second_param = p.list_buf.items[p.list_buf.items.len - 2]; | ||
| 4857 | return p.nodes.items(.ty)[@intFromEnum(second_param)]; | ||
| 4858 | }, | ||
| 4830 | Builtin.tagFromName("__builtin_complex").? => { | 4859 | Builtin.tagFromName("__builtin_complex").? => { |
| 4860 | if (p.list_buf.items.len < 1) return Type.invalid; // not enough arguments; already an error | ||
| 4831 | const last_param = p.list_buf.items[p.list_buf.items.len - 1]; | 4861 | const last_param = p.list_buf.items[p.list_buf.items.len - 1]; |
| 4832 | return p.nodes.items(.ty)[@intFromEnum(last_param)].makeComplex(); | 4862 | return p.nodes.items(.ty)[@intFromEnum(last_param)].makeComplex(); |
| 4833 | }, | 4863 | }, |
| 4864 | Builtin.tagFromName("__atomic_compare_exchange").?, | ||
| 4865 | Builtin.tagFromName("__atomic_compare_exchange_n").?, | ||
| 4866 | => .{ .specifier = .bool }, | ||
| 4834 | else => callable_ty.returnType(), | 4867 | else => callable_ty.returnType(), |
| 4835 | }, | 4868 | }, |
| 4836 | }; | 4869 | }; |
| ... | @@ -7458,7 +7491,7 @@ fn primaryExpr(p: *Parser) Error!Result { | ... | @@ -7458,7 +7491,7 @@ fn primaryExpr(p: *Parser) Error!Result { |
| 7458 | } | 7491 | } |
| 7459 | switch (p.tok_ids[p.tok_i]) { | 7492 | switch (p.tok_ids[p.tok_i]) { |
| 7460 | .identifier, .extended_identifier => { | 7493 | .identifier, .extended_identifier => { |
| 7461 | const name_tok = p.expectIdentifier() catch unreachable; | 7494 | const name_tok = try p.expectIdentifier(); |
| 7462 | const name = p.tokSlice(name_tok); | 7495 | const name = p.tokSlice(name_tok); |
| 7463 | const interned_name = try StrInt.intern(p.comp, name); | 7496 | const interned_name = try StrInt.intern(p.comp, name); |
| 7464 | if (p.syms.findSymbol(interned_name)) |sym| { | 7497 | if (p.syms.findSymbol(interned_name)) |sym| { |
| ... | @@ -7938,6 +7971,8 @@ fn parseFloat(p: *Parser, buf: []const u8, suffix: NumberSuffix) !Result { | ... | @@ -7938,6 +7971,8 @@ fn parseFloat(p: *Parser, buf: []const u8, suffix: NumberSuffix) !Result { |
| 7938 | .F, .IF => .float, | 7971 | .F, .IF => .float, |
| 7939 | .F16 => .float16, | 7972 | .F16 => .float16, |
| 7940 | .L, .IL => .long_double, | 7973 | .L, .IL => .long_double, |
| 7974 | .W, .IW => .float80, | ||
| 7975 | .Q, .IQ, .F128, .IF128 => .float128, | ||
| 7941 | else => unreachable, | 7976 | else => unreachable, |
| 7942 | } }; | 7977 | } }; |
| 7943 | const val = try Value.intern(p.comp, key: { | 7978 | const val = try Value.intern(p.comp, key: { |
| ... | @@ -7946,7 +7981,7 @@ fn parseFloat(p: *Parser, buf: []const u8, suffix: NumberSuffix) !Result { | ... | @@ -7946,7 +7981,7 @@ fn parseFloat(p: *Parser, buf: []const u8, suffix: NumberSuffix) !Result { |
| 7946 | const strings_top = p.strings.items.len; | 7981 | const strings_top = p.strings.items.len; |
| 7947 | defer p.strings.items.len = strings_top; | 7982 | defer p.strings.items.len = strings_top; |
| 7948 | for (buf) |c| { | 7983 | for (buf) |c| { |
| 7949 | if (c != '_') p.strings.appendAssumeCapacity(c); | 7984 | if (c != '\'') p.strings.appendAssumeCapacity(c); |
| 7950 | } | 7985 | } |
| 7951 | 7986 | ||
| 7952 | const float = std.fmt.parseFloat(f128, p.strings.items[strings_top..]) catch unreachable; | 7987 | const float = std.fmt.parseFloat(f128, p.strings.items[strings_top..]) catch unreachable; |
| ... | @@ -7971,6 +8006,8 @@ fn parseFloat(p: *Parser, buf: []const u8, suffix: NumberSuffix) !Result { | ... | @@ -7971,6 +8006,8 @@ fn parseFloat(p: *Parser, buf: []const u8, suffix: NumberSuffix) !Result { |
| 7971 | .I => .complex_double, | 8006 | .I => .complex_double, |
| 7972 | .IF => .complex_float, | 8007 | .IF => .complex_float, |
| 7973 | .IL => .complex_long_double, | 8008 | .IL => .complex_long_double, |
| 8009 | .IW => .complex_float80, | ||
| 8010 | .IQ, .IF128 => .complex_float128, | ||
| 7974 | else => unreachable, | 8011 | else => unreachable, |
| 7975 | } }; | 8012 | } }; |
| 7976 | res.val = .{}; // TODO add complex values | 8013 | res.val = .{}; // TODO add complex values |
| ... | @@ -8123,11 +8160,21 @@ fn bitInt(p: *Parser, base: u8, buf: []const u8, suffix: NumberSuffix, tok_i: To | ... | @@ -8123,11 +8160,21 @@ fn bitInt(p: *Parser, base: u8, buf: []const u8, suffix: NumberSuffix, tok_i: To |
| 8123 | var managed = try big.int.Managed.init(p.gpa); | 8160 | var managed = try big.int.Managed.init(p.gpa); |
| 8124 | defer managed.deinit(); | 8161 | defer managed.deinit(); |
| 8125 | 8162 | ||
| 8126 | managed.setString(base, buf) catch |e| switch (e) { | 8163 | { |
| 8127 | error.InvalidBase => unreachable, // `base` is one of 2, 8, 10, 16 | 8164 | try p.strings.ensureUnusedCapacity(buf.len); |
| 8128 | error.InvalidCharacter => unreachable, // digits validated by Tokenizer | 8165 | |
| 8129 | else => |er| return er, | 8166 | const strings_top = p.strings.items.len; |
| 8130 | }; | 8167 | defer p.strings.items.len = strings_top; |
| 8168 | for (buf) |c| { | ||
| 8169 | if (c != '\'') p.strings.appendAssumeCapacity(c); | ||
| 8170 | } | ||
| 8171 | |||
| 8172 | managed.setString(base, p.strings.items[strings_top..]) catch |e| switch (e) { | ||
| 8173 | error.InvalidBase => unreachable, // `base` is one of 2, 8, 10, 16 | ||
| 8174 | error.InvalidCharacter => unreachable, // digits validated by Tokenizer | ||
| 8175 | else => |er| return er, | ||
| 8176 | }; | ||
| 8177 | } | ||
| 8131 | const c = managed.toConst(); | 8178 | const c = managed.toConst(); |
| 8132 | const bits_needed: std.math.IntFittingRange(0, Compilation.bit_int_max_bits) = blk: { | 8179 | const bits_needed: std.math.IntFittingRange(0, Compilation.bit_int_max_bits) = blk: { |
| 8133 | // Literal `0` requires at least 1 bit | 8180 | // Literal `0` requires at least 1 bit |
deps/aro/aro/Preprocessor.zig+60-25| ... | @@ -315,7 +315,7 @@ fn invalidTokenDiagnostic(tok_id: Token.Id) Diagnostics.Tag { | ... | @@ -315,7 +315,7 @@ fn invalidTokenDiagnostic(tok_id: Token.Id) Diagnostics.Tag { |
| 315 | fn findIncludeGuard(pp: *Preprocessor, source: Source) ?[]const u8 { | 315 | fn findIncludeGuard(pp: *Preprocessor, source: Source) ?[]const u8 { |
| 316 | var tokenizer = Tokenizer{ | 316 | var tokenizer = Tokenizer{ |
| 317 | .buf = source.buf, | 317 | .buf = source.buf, |
| 318 | .comp = pp.comp, | 318 | .langopts = pp.comp.langopts, |
| 319 | .source = source.id, | 319 | .source = source.id, |
| 320 | }; | 320 | }; |
| 321 | var hash = tokenizer.nextNoWS(); | 321 | var hash = tokenizer.nextNoWS(); |
| ... | @@ -334,7 +334,7 @@ fn preprocessExtra(pp: *Preprocessor, source: Source) MacroError!Token { | ... | @@ -334,7 +334,7 @@ fn preprocessExtra(pp: *Preprocessor, source: Source) MacroError!Token { |
| 334 | pp.preprocess_count += 1; | 334 | pp.preprocess_count += 1; |
| 335 | var tokenizer = Tokenizer{ | 335 | var tokenizer = Tokenizer{ |
| 336 | .buf = source.buf, | 336 | .buf = source.buf, |
| 337 | .comp = pp.comp, | 337 | .langopts = pp.comp.langopts, |
| 338 | .source = source.id, | 338 | .source = source.id, |
| 339 | }; | 339 | }; |
| 340 | 340 | ||
| ... | @@ -747,6 +747,17 @@ fn fatal(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args: anyty | ... | @@ -747,6 +747,17 @@ fn fatal(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args: anyty |
| 747 | return error.FatalError; | 747 | return error.FatalError; |
| 748 | } | 748 | } |
| 749 | 749 | ||
| 750 | fn fatalNotFound(pp: *Preprocessor, tok: Token, filename: []const u8) Compilation.Error { | ||
| 751 | const old = pp.comp.diagnostics.fatal_errors; | ||
| 752 | pp.comp.diagnostics.fatal_errors = true; | ||
| 753 | defer pp.comp.diagnostics.fatal_errors = old; | ||
| 754 | |||
| 755 | try pp.comp.diagnostics.addExtra(pp.comp.langopts, .{ .tag = .cli_error, .loc = tok.loc, .extra = .{ | ||
| 756 | .str = try std.fmt.allocPrint(pp.comp.diagnostics.arena.allocator(), "'{s}' not found", .{filename}), | ||
| 757 | } }, tok.expansionSlice(), false); | ||
| 758 | unreachable; // addExtra should've returned FatalError | ||
| 759 | } | ||
| 760 | |||
| 750 | fn verboseLog(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args: anytype) void { | 761 | fn verboseLog(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args: anytype) void { |
| 751 | const source = pp.comp.getSource(raw.source); | 762 | const source = pp.comp.getSource(raw.source); |
| 752 | const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start }); | 763 | const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start }); |
| ... | @@ -1185,7 +1196,7 @@ fn pragmaOperator(pp: *Preprocessor, arg_tok: Token, operator_loc: Source.Locati | ... | @@ -1185,7 +1196,7 @@ fn pragmaOperator(pp: *Preprocessor, arg_tok: Token, operator_loc: Source.Locati |
| 1185 | try pp.comp.generated_buf.appendSlice(pp.gpa, pp.char_buf.items); | 1196 | try pp.comp.generated_buf.appendSlice(pp.gpa, pp.char_buf.items); |
| 1186 | var tmp_tokenizer = Tokenizer{ | 1197 | var tmp_tokenizer = Tokenizer{ |
| 1187 | .buf = pp.comp.generated_buf.items, | 1198 | .buf = pp.comp.generated_buf.items, |
| 1188 | .comp = pp.comp, | 1199 | .langopts = pp.comp.langopts, |
| 1189 | .index = @intCast(start), | 1200 | .index = @intCast(start), |
| 1190 | .source = .generated, | 1201 | .source = .generated, |
| 1191 | .line = pp.generated_line, | 1202 | .line = pp.generated_line, |
| ... | @@ -1864,7 +1875,7 @@ fn expandVaOpt( | ... | @@ -1864,7 +1875,7 @@ fn expandVaOpt( |
| 1864 | .buf = source.buf, | 1875 | .buf = source.buf, |
| 1865 | .index = raw.start, | 1876 | .index = raw.start, |
| 1866 | .source = raw.source, | 1877 | .source = raw.source, |
| 1867 | .comp = pp.comp, | 1878 | .langopts = pp.comp.langopts, |
| 1868 | .line = raw.line, | 1879 | .line = raw.line, |
| 1869 | }; | 1880 | }; |
| 1870 | while (tokenizer.index < raw.end) { | 1881 | while (tokenizer.index < raw.end) { |
| ... | @@ -2282,11 +2293,11 @@ fn expandMacro(pp: *Preprocessor, tokenizer: *Tokenizer, raw: RawToken) MacroErr | ... | @@ -2282,11 +2293,11 @@ fn expandMacro(pp: *Preprocessor, tokenizer: *Tokenizer, raw: RawToken) MacroErr |
| 2282 | 2293 | ||
| 2283 | fn expandedSliceExtra(pp: *const Preprocessor, tok: Token, macro_ws_handling: enum { single_macro_ws, preserve_macro_ws }) []const u8 { | 2294 | fn expandedSliceExtra(pp: *const Preprocessor, tok: Token, macro_ws_handling: enum { single_macro_ws, preserve_macro_ws }) []const u8 { |
| 2284 | if (tok.id.lexeme()) |some| { | 2295 | if (tok.id.lexeme()) |some| { |
| 2285 | if (!tok.id.allowsDigraphs(pp.comp) and !(tok.id == .macro_ws and macro_ws_handling == .preserve_macro_ws)) return some; | 2296 | if (!tok.id.allowsDigraphs(pp.comp.langopts) and !(tok.id == .macro_ws and macro_ws_handling == .preserve_macro_ws)) return some; |
| 2286 | } | 2297 | } |
| 2287 | var tmp_tokenizer = Tokenizer{ | 2298 | var tmp_tokenizer = Tokenizer{ |
| 2288 | .buf = pp.comp.getSource(tok.loc.id).buf, | 2299 | .buf = pp.comp.getSource(tok.loc.id).buf, |
| 2289 | .comp = pp.comp, | 2300 | .langopts = pp.comp.langopts, |
| 2290 | .index = tok.loc.byte_offset, | 2301 | .index = tok.loc.byte_offset, |
| 2291 | .source = .generated, | 2302 | .source = .generated, |
| 2292 | }; | 2303 | }; |
| ... | @@ -2340,7 +2351,7 @@ fn pasteTokens(pp: *Preprocessor, lhs_toks: *ExpandBuf, rhs_toks: []const Token) | ... | @@ -2340,7 +2351,7 @@ fn pasteTokens(pp: *Preprocessor, lhs_toks: *ExpandBuf, rhs_toks: []const Token) |
| 2340 | // Try to tokenize the result. | 2351 | // Try to tokenize the result. |
| 2341 | var tmp_tokenizer = Tokenizer{ | 2352 | var tmp_tokenizer = Tokenizer{ |
| 2342 | .buf = pp.comp.generated_buf.items, | 2353 | .buf = pp.comp.generated_buf.items, |
| 2343 | .comp = pp.comp, | 2354 | .langopts = pp.comp.langopts, |
| 2344 | .index = @intCast(start), | 2355 | .index = @intCast(start), |
| 2345 | .source = .generated, | 2356 | .source = .generated, |
| 2346 | }; | 2357 | }; |
| ... | @@ -2703,6 +2714,7 @@ fn embed(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!void { | ... | @@ -2703,6 +2714,7 @@ fn embed(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!void { |
| 2703 | error.InvalidInclude => return, | 2714 | error.InvalidInclude => return, |
| 2704 | else => |e| return e, | 2715 | else => |e| return e, |
| 2705 | }; | 2716 | }; |
| 2717 | defer Token.free(filename_tok.expansion_locs, pp.gpa); | ||
| 2706 | 2718 | ||
| 2707 | // Check for empty filename. | 2719 | // Check for empty filename. |
| 2708 | const tok_slice = pp.expandedSliceExtra(filename_tok, .single_macro_ws); | 2720 | const tok_slice = pp.expandedSliceExtra(filename_tok, .single_macro_ws); |
| ... | @@ -2836,7 +2848,7 @@ fn embed(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!void { | ... | @@ -2836,7 +2848,7 @@ fn embed(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!void { |
| 2836 | } | 2848 | } |
| 2837 | 2849 | ||
| 2838 | const embed_bytes = (try pp.comp.findEmbed(filename, first.source, include_type, limit)) orelse | 2850 | const embed_bytes = (try pp.comp.findEmbed(filename, first.source, include_type, limit)) orelse |
| 2839 | return pp.fatal(first, "'{s}' not found", .{filename}); | 2851 | return pp.fatalNotFound(filename_tok, filename); |
| 2840 | defer pp.comp.gpa.free(embed_bytes); | 2852 | defer pp.comp.gpa.free(embed_bytes); |
| 2841 | 2853 | ||
| 2842 | try Range.expand(prefix, pp, tokenizer); | 2854 | try Range.expand(prefix, pp, tokenizer); |
| ... | @@ -2984,8 +2996,6 @@ fn findIncludeFilenameToken( | ... | @@ -2984,8 +2996,6 @@ fn findIncludeFilenameToken( |
| 2984 | tokenizer: *Tokenizer, | 2996 | tokenizer: *Tokenizer, |
| 2985 | trailing_token_behavior: enum { ignore_trailing_tokens, expect_nl_eof }, | 2997 | trailing_token_behavior: enum { ignore_trailing_tokens, expect_nl_eof }, |
| 2986 | ) !Token { | 2998 | ) !Token { |
| 2987 | const start = pp.tokens.len; | ||
| 2988 | defer pp.tokens.len = start; | ||
| 2989 | var first = first_token; | 2999 | var first = first_token; |
| 2990 | 3000 | ||
| 2991 | if (first.id == .angle_bracket_left) to_end: { | 3001 | if (first.id == .angle_bracket_left) to_end: { |
| ... | @@ -3008,35 +3018,60 @@ fn findIncludeFilenameToken( | ... | @@ -3008,35 +3018,60 @@ fn findIncludeFilenameToken( |
| 3008 | }, &.{}); | 3018 | }, &.{}); |
| 3009 | try pp.err(first, .header_str_match); | 3019 | try pp.err(first, .header_str_match); |
| 3010 | } | 3020 | } |
| 3011 | // Try to expand if the argument is a macro. | ||
| 3012 | try pp.expandMacro(tokenizer, first); | ||
| 3013 | 3021 | ||
| 3014 | // Check that we actually got a string. | 3022 | const source_tok = tokFromRaw(first); |
| 3015 | const filename_tok = pp.tokens.get(start); | 3023 | const filename_tok, const expanded_trailing = switch (source_tok.id) { |
| 3016 | switch (filename_tok.id) { | 3024 | .string_literal, .macro_string => .{ source_tok, false }, |
| 3017 | .string_literal, .macro_string => {}, | 3025 | else => expanded: { |
| 3018 | else => { | 3026 | // Try to expand if the argument is a macro. |
| 3019 | try pp.err(first, .expected_filename); | 3027 | pp.top_expansion_buf.items.len = 0; |
| 3020 | try pp.expectNl(tokenizer); | 3028 | defer for (pp.top_expansion_buf.items) |tok| Token.free(tok.expansion_locs, pp.gpa); |
| 3021 | return error.InvalidInclude; | 3029 | try pp.top_expansion_buf.append(source_tok); |
| 3030 | pp.expansion_source_loc = source_tok.loc; | ||
| 3031 | |||
| 3032 | try pp.expandMacroExhaustive(tokenizer, &pp.top_expansion_buf, 0, 1, true, .non_expr); | ||
| 3033 | var trailing_toks: []const Token = &.{}; | ||
| 3034 | const include_str = (try pp.reconstructIncludeString(pp.top_expansion_buf.items, &trailing_toks)) orelse { | ||
| 3035 | try pp.err(first, .expected_filename); | ||
| 3036 | try pp.expectNl(tokenizer); | ||
| 3037 | return error.InvalidInclude; | ||
| 3038 | }; | ||
| 3039 | const start = pp.comp.generated_buf.items.len; | ||
| 3040 | try pp.comp.generated_buf.appendSlice(pp.gpa, include_str); | ||
| 3041 | |||
| 3042 | break :expanded .{ try pp.makeGeneratedToken(start, switch (include_str[0]) { | ||
| 3043 | '"' => .string_literal, | ||
| 3044 | '<' => .macro_string, | ||
| 3045 | else => unreachable, | ||
| 3046 | }, pp.top_expansion_buf.items[0]), trailing_toks.len != 0 }; | ||
| 3022 | }, | 3047 | }, |
| 3023 | } | 3048 | }; |
| 3049 | |||
| 3024 | switch (trailing_token_behavior) { | 3050 | switch (trailing_token_behavior) { |
| 3025 | .expect_nl_eof => { | 3051 | .expect_nl_eof => { |
| 3026 | // Error on extra tokens. | 3052 | // Error on extra tokens. |
| 3027 | const nl = tokenizer.nextNoWS(); | 3053 | const nl = tokenizer.nextNoWS(); |
| 3028 | if ((nl.id != .nl and nl.id != .eof) or pp.tokens.len > start + 1) { | 3054 | if ((nl.id != .nl and nl.id != .eof) or expanded_trailing) { |
| 3029 | skipToNl(tokenizer); | 3055 | skipToNl(tokenizer); |
| 3030 | try pp.err(first, .extra_tokens_directive_end); | 3056 | try pp.comp.diagnostics.addExtra(pp.comp.langopts, .{ |
| 3057 | .tag = .extra_tokens_directive_end, | ||
| 3058 | .loc = filename_tok.loc, | ||
| 3059 | }, filename_tok.expansionSlice(), false); | ||
| 3031 | } | 3060 | } |
| 3032 | }, | 3061 | }, |
| 3033 | .ignore_trailing_tokens => {}, | 3062 | .ignore_trailing_tokens => if (expanded_trailing) { |
| 3063 | try pp.comp.diagnostics.addExtra(pp.comp.langopts, .{ | ||
| 3064 | .tag = .extra_tokens_directive_end, | ||
| 3065 | .loc = filename_tok.loc, | ||
| 3066 | }, filename_tok.expansionSlice(), false); | ||
| 3067 | }, | ||
| 3034 | } | 3068 | } |
| 3035 | return filename_tok; | 3069 | return filename_tok; |
| 3036 | } | 3070 | } |
| 3037 | 3071 | ||
| 3038 | fn findIncludeSource(pp: *Preprocessor, tokenizer: *Tokenizer, first: RawToken, which: Compilation.WhichInclude) !Source { | 3072 | fn findIncludeSource(pp: *Preprocessor, tokenizer: *Tokenizer, first: RawToken, which: Compilation.WhichInclude) !Source { |
| 3039 | const filename_tok = try pp.findIncludeFilenameToken(first, tokenizer, .expect_nl_eof); | 3073 | const filename_tok = try pp.findIncludeFilenameToken(first, tokenizer, .expect_nl_eof); |
| 3074 | defer Token.free(filename_tok.expansion_locs, pp.gpa); | ||
| 3040 | 3075 | ||
| 3041 | // Check for empty filename. | 3076 | // Check for empty filename. |
| 3042 | const tok_slice = pp.expandedSliceExtra(filename_tok, .single_macro_ws); | 3077 | const tok_slice = pp.expandedSliceExtra(filename_tok, .single_macro_ws); |
| ... | @@ -3054,7 +3089,7 @@ fn findIncludeSource(pp: *Preprocessor, tokenizer: *Tokenizer, first: RawToken, | ... | @@ -3054,7 +3089,7 @@ fn findIncludeSource(pp: *Preprocessor, tokenizer: *Tokenizer, first: RawToken, |
| 3054 | }; | 3089 | }; |
| 3055 | 3090 | ||
| 3056 | return (try pp.comp.findInclude(filename, first, include_type, which)) orelse | 3091 | return (try pp.comp.findInclude(filename, first, include_type, which)) orelse |
| 3057 | pp.fatal(first, "'{s}' not found", .{filename}); | 3092 | return pp.fatalNotFound(filename_tok, filename); |
| 3058 | } | 3093 | } |
| 3059 | 3094 | ||
| 3060 | fn printLinemarker( | 3095 | fn printLinemarker( |
deps/aro/aro/SymbolStack.zig+201-184| ... | @@ -11,6 +11,8 @@ const Parser = @import("Parser.zig"); | ... | @@ -11,6 +11,8 @@ const Parser = @import("Parser.zig"); |
| 11 | const Value = @import("Value.zig"); | 11 | const Value = @import("Value.zig"); |
| 12 | const StringId = @import("StringInterner.zig").StringId; | 12 | const StringId = @import("StringInterner.zig").StringId; |
| 13 | 13 | ||
| 14 | const SymbolStack = @This(); | ||
| 15 | |||
| 14 | pub const Symbol = struct { | 16 | pub const Symbol = struct { |
| 15 | name: StringId, | 17 | name: StringId, |
| 16 | ty: Type, | 18 | ty: Type, |
| ... | @@ -31,72 +33,74 @@ pub const Kind = enum { | ... | @@ -31,72 +33,74 @@ pub const Kind = enum { |
| 31 | constexpr, | 33 | constexpr, |
| 32 | }; | 34 | }; |
| 33 | 35 | ||
| 34 | const SymbolStack = @This(); | 36 | scopes: std.ArrayListUnmanaged(Scope) = .{}, |
| 37 | /// allocations from nested scopes are retained after popping; `active_len` is the number | ||
| 38 | /// of currently-active items in `scopes`. | ||
| 39 | active_len: usize = 0, | ||
| 35 | 40 | ||
| 36 | syms: std.MultiArrayList(Symbol) = .{}, | 41 | const Scope = struct { |
| 37 | scopes: std.ArrayListUnmanaged(u32) = .{}, | 42 | vars: std.AutoHashMapUnmanaged(StringId, Symbol) = .{}, |
| 43 | tags: std.AutoHashMapUnmanaged(StringId, Symbol) = .{}, | ||
| 44 | |||
| 45 | fn deinit(self: *Scope, allocator: Allocator) void { | ||
| 46 | self.vars.deinit(allocator); | ||
| 47 | self.tags.deinit(allocator); | ||
| 48 | } | ||
| 49 | |||
| 50 | fn clearRetainingCapacity(self: *Scope) void { | ||
| 51 | self.vars.clearRetainingCapacity(); | ||
| 52 | self.tags.clearRetainingCapacity(); | ||
| 53 | } | ||
| 54 | }; | ||
| 38 | 55 | ||
| 39 | pub fn deinit(s: *SymbolStack, gpa: Allocator) void { | 56 | pub fn deinit(s: *SymbolStack, gpa: Allocator) void { |
| 40 | s.syms.deinit(gpa); | 57 | std.debug.assert(s.active_len == 0); // all scopes should have been popped |
| 58 | for (s.scopes.items) |*scope| { | ||
| 59 | scope.deinit(gpa); | ||
| 60 | } | ||
| 41 | s.scopes.deinit(gpa); | 61 | s.scopes.deinit(gpa); |
| 42 | s.* = undefined; | 62 | s.* = undefined; |
| 43 | } | 63 | } |
| 44 | 64 | ||
| 45 | pub fn scopeEnd(s: SymbolStack) u32 { | ||
| 46 | if (s.scopes.items.len == 0) return 0; | ||
| 47 | return s.scopes.items[s.scopes.items.len - 1]; | ||
| 48 | } | ||
| 49 | |||
| 50 | pub fn pushScope(s: *SymbolStack, p: *Parser) !void { | 65 | pub fn pushScope(s: *SymbolStack, p: *Parser) !void { |
| 51 | try s.scopes.append(p.gpa, @intCast(s.syms.len)); | 66 | if (s.active_len + 1 > s.scopes.items.len) { |
| 67 | try s.scopes.append(p.gpa, .{}); | ||
| 68 | s.active_len = s.scopes.items.len; | ||
| 69 | } else { | ||
| 70 | s.scopes.items[s.active_len].clearRetainingCapacity(); | ||
| 71 | s.active_len += 1; | ||
| 72 | } | ||
| 52 | } | 73 | } |
| 53 | 74 | ||
| 54 | pub fn popScope(s: *SymbolStack) void { | 75 | pub fn popScope(s: *SymbolStack) void { |
| 55 | s.syms.len = s.scopes.pop(); | 76 | s.active_len -= 1; |
| 56 | } | 77 | } |
| 57 | 78 | ||
| 58 | pub fn findTypedef(s: *SymbolStack, p: *Parser, name: StringId, name_tok: TokenIndex, no_type_yet: bool) !?Symbol { | 79 | pub fn findTypedef(s: *SymbolStack, p: *Parser, name: StringId, name_tok: TokenIndex, no_type_yet: bool) !?Symbol { |
| 59 | const kinds = s.syms.items(.kind); | 80 | const prev = s.lookup(name, .vars) orelse s.lookup(name, .tags) orelse return null; |
| 60 | const names = s.syms.items(.name); | 81 | switch (prev.kind) { |
| 61 | var i = s.syms.len; | 82 | .typedef => return prev, |
| 62 | while (i > 0) { | 83 | .@"struct" => { |
| 63 | i -= 1; | 84 | if (no_type_yet) return null; |
| 64 | switch (kinds[i]) { | 85 | try p.errStr(.must_use_struct, name_tok, p.tokSlice(name_tok)); |
| 65 | .typedef => if (names[i] == name) return s.syms.get(i), | 86 | return prev; |
| 66 | .@"struct" => if (names[i] == name) { | 87 | }, |
| 67 | if (no_type_yet) return null; | 88 | .@"union" => { |
| 68 | try p.errStr(.must_use_struct, name_tok, p.tokSlice(name_tok)); | 89 | if (no_type_yet) return null; |
| 69 | return s.syms.get(i); | 90 | try p.errStr(.must_use_union, name_tok, p.tokSlice(name_tok)); |
| 70 | }, | 91 | return prev; |
| 71 | .@"union" => if (names[i] == name) { | 92 | }, |
| 72 | if (no_type_yet) return null; | 93 | .@"enum" => { |
| 73 | try p.errStr(.must_use_union, name_tok, p.tokSlice(name_tok)); | 94 | if (no_type_yet) return null; |
| 74 | return s.syms.get(i); | 95 | try p.errStr(.must_use_enum, name_tok, p.tokSlice(name_tok)); |
| 75 | }, | 96 | return prev; |
| 76 | .@"enum" => if (names[i] == name) { | 97 | }, |
| 77 | if (no_type_yet) return null; | 98 | else => return null, |
| 78 | try p.errStr(.must_use_enum, name_tok, p.tokSlice(name_tok)); | ||
| 79 | return s.syms.get(i); | ||
| 80 | }, | ||
| 81 | .def, .decl, .constexpr => if (names[i] == name) return null, | ||
| 82 | else => {}, | ||
| 83 | } | ||
| 84 | } | 99 | } |
| 85 | return null; | ||
| 86 | } | 100 | } |
| 87 | 101 | ||
| 88 | pub fn findSymbol(s: *SymbolStack, name: StringId) ?Symbol { | 102 | pub fn findSymbol(s: *SymbolStack, name: StringId) ?Symbol { |
| 89 | const kinds = s.syms.items(.kind); | 103 | return s.lookup(name, .vars); |
| 90 | const names = s.syms.items(.name); | ||
| 91 | var i = s.syms.len; | ||
| 92 | while (i > 0) { | ||
| 93 | i -= 1; | ||
| 94 | switch (kinds[i]) { | ||
| 95 | .def, .decl, .enumeration, .constexpr => if (names[i] == name) return s.syms.get(i), | ||
| 96 | else => {}, | ||
| 97 | } | ||
| 98 | } | ||
| 99 | return null; | ||
| 100 | } | 104 | } |
| 101 | 105 | ||
| 102 | pub fn findTag( | 106 | pub fn findTag( |
| ... | @@ -107,36 +111,62 @@ pub fn findTag( | ... | @@ -107,36 +111,62 @@ pub fn findTag( |
| 107 | name_tok: TokenIndex, | 111 | name_tok: TokenIndex, |
| 108 | next_tok_id: Token.Id, | 112 | next_tok_id: Token.Id, |
| 109 | ) !?Symbol { | 113 | ) !?Symbol { |
| 110 | const kinds = s.syms.items(.kind); | ||
| 111 | const names = s.syms.items(.name); | ||
| 112 | // `tag Name;` should always result in a new type if in a new scope. | 114 | // `tag Name;` should always result in a new type if in a new scope. |
| 113 | const end = if (next_tok_id == .semicolon) s.scopeEnd() else 0; | 115 | const prev = (if (next_tok_id == .semicolon) s.get(name, .tags) else s.lookup(name, .tags)) orelse return null; |
| 114 | var i = s.syms.len; | 116 | switch (prev.kind) { |
| 115 | while (i > end) { | 117 | .@"enum" => if (kind == .keyword_enum) return prev, |
| 118 | .@"struct" => if (kind == .keyword_struct) return prev, | ||
| 119 | .@"union" => if (kind == .keyword_union) return prev, | ||
| 120 | else => unreachable, | ||
| 121 | } | ||
| 122 | if (s.get(name, .tags) == null) return null; | ||
| 123 | try p.errStr(.wrong_tag, name_tok, p.tokSlice(name_tok)); | ||
| 124 | try p.errTok(.previous_definition, prev.tok); | ||
| 125 | return null; | ||
| 126 | } | ||
| 127 | |||
| 128 | const ScopeKind = enum { | ||
| 129 | /// structs, enums, unions | ||
| 130 | tags, | ||
| 131 | /// everything else | ||
| 132 | vars, | ||
| 133 | }; | ||
| 134 | |||
| 135 | /// Return the Symbol for `name` (or null if not found) in the innermost scope | ||
| 136 | pub fn get(s: *SymbolStack, name: StringId, kind: ScopeKind) ?Symbol { | ||
| 137 | return switch (kind) { | ||
| 138 | .vars => s.scopes.items[s.active_len - 1].vars.get(name), | ||
| 139 | .tags => s.scopes.items[s.active_len - 1].tags.get(name), | ||
| 140 | }; | ||
| 141 | } | ||
| 142 | |||
| 143 | /// Return the Symbol for `name` (or null if not found) in the nearest active scope, | ||
| 144 | /// starting at the innermost. | ||
| 145 | fn lookup(s: *SymbolStack, name: StringId, kind: ScopeKind) ?Symbol { | ||
| 146 | var i = s.active_len; | ||
| 147 | while (i > 0) { | ||
| 116 | i -= 1; | 148 | i -= 1; |
| 117 | switch (kinds[i]) { | 149 | switch (kind) { |
| 118 | .@"enum" => if (names[i] == name) { | 150 | .vars => if (s.scopes.items[i].vars.get(name)) |sym| return sym, |
| 119 | if (kind == .keyword_enum) return s.syms.get(i); | 151 | .tags => if (s.scopes.items[i].tags.get(name)) |sym| return sym, |
| 120 | break; | ||
| 121 | }, | ||
| 122 | .@"struct" => if (names[i] == name) { | ||
| 123 | if (kind == .keyword_struct) return s.syms.get(i); | ||
| 124 | break; | ||
| 125 | }, | ||
| 126 | .@"union" => if (names[i] == name) { | ||
| 127 | if (kind == .keyword_union) return s.syms.get(i); | ||
| 128 | break; | ||
| 129 | }, | ||
| 130 | else => {}, | ||
| 131 | } | 152 | } |
| 132 | } else return null; | 153 | } |
| 133 | |||
| 134 | if (i < s.scopeEnd()) return null; | ||
| 135 | try p.errStr(.wrong_tag, name_tok, p.tokSlice(name_tok)); | ||
| 136 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | ||
| 137 | return null; | 154 | return null; |
| 138 | } | 155 | } |
| 139 | 156 | ||
| 157 | /// Define a symbol in the innermost scope. Does not issue diagnostics or check correctness | ||
| 158 | /// with regard to the C standard. | ||
| 159 | pub fn define(s: *SymbolStack, allocator: Allocator, symbol: Symbol) !void { | ||
| 160 | switch (symbol.kind) { | ||
| 161 | .constexpr, .def, .decl, .enumeration, .typedef => { | ||
| 162 | try s.scopes.items[s.active_len - 1].vars.put(allocator, symbol.name, symbol); | ||
| 163 | }, | ||
| 164 | .@"struct", .@"union", .@"enum" => { | ||
| 165 | try s.scopes.items[s.active_len - 1].tags.put(allocator, symbol.name, symbol); | ||
| 166 | }, | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 140 | pub fn defineTypedef( | 170 | pub fn defineTypedef( |
| 141 | s: *SymbolStack, | 171 | s: *SymbolStack, |
| 142 | p: *Parser, | 172 | p: *Parser, |
| ... | @@ -145,25 +175,22 @@ pub fn defineTypedef( | ... | @@ -145,25 +175,22 @@ pub fn defineTypedef( |
| 145 | tok: TokenIndex, | 175 | tok: TokenIndex, |
| 146 | node: NodeIndex, | 176 | node: NodeIndex, |
| 147 | ) !void { | 177 | ) !void { |
| 148 | const kinds = s.syms.items(.kind); | 178 | if (s.get(name, .vars)) |prev| { |
| 149 | const names = s.syms.items(.name); | 179 | switch (prev.kind) { |
| 150 | const end = s.scopeEnd(); | 180 | .typedef => { |
| 151 | var i = s.syms.len; | 181 | if (!ty.eql(prev.ty, p.comp, true)) { |
| 152 | while (i > end) { | 182 | try p.errStr(.redefinition_of_typedef, tok, try p.typePairStrExtra(ty, " vs ", prev.ty)); |
| 153 | i -= 1; | 183 | if (prev.tok != 0) try p.errTok(.previous_definition, prev.tok); |
| 154 | switch (kinds[i]) { | 184 | } |
| 155 | .typedef => if (names[i] == name) { | 185 | }, |
| 156 | const prev_ty = s.syms.items(.ty)[i]; | 186 | .enumeration, .decl, .def, .constexpr => { |
| 157 | if (ty.eql(prev_ty, p.comp, true)) break; | 187 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); |
| 158 | try p.errStr(.redefinition_of_typedef, tok, try p.typePairStrExtra(ty, " vs ", prev_ty)); | 188 | try p.errTok(.previous_definition, prev.tok); |
| 159 | const previous_tok = s.syms.items(.tok)[i]; | ||
| 160 | if (previous_tok != 0) try p.errTok(.previous_definition, previous_tok); | ||
| 161 | break; | ||
| 162 | }, | 189 | }, |
| 163 | else => {}, | 190 | else => unreachable, |
| 164 | } | 191 | } |
| 165 | } | 192 | } |
| 166 | try s.syms.append(p.gpa, .{ | 193 | try s.define(p.gpa, .{ |
| 167 | .kind = .typedef, | 194 | .kind = .typedef, |
| 168 | .name = name, | 195 | .name = name, |
| 169 | .tok = tok, | 196 | .tok = tok, |
| ... | @@ -183,35 +210,31 @@ pub fn defineSymbol( | ... | @@ -183,35 +210,31 @@ pub fn defineSymbol( |
| 183 | val: Value, | 210 | val: Value, |
| 184 | constexpr: bool, | 211 | constexpr: bool, |
| 185 | ) !void { | 212 | ) !void { |
| 186 | const kinds = s.syms.items(.kind); | 213 | if (s.get(name, .vars)) |prev| { |
| 187 | const names = s.syms.items(.name); | 214 | switch (prev.kind) { |
| 188 | const end = s.scopeEnd(); | 215 | .enumeration => { |
| 189 | var i = s.syms.len; | ||
| 190 | while (i > end) { | ||
| 191 | i -= 1; | ||
| 192 | switch (kinds[i]) { | ||
| 193 | .enumeration => if (names[i] == name) { | ||
| 194 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); | 216 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); |
| 195 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 217 | try p.errTok(.previous_definition, prev.tok); |
| 196 | break; | ||
| 197 | }, | 218 | }, |
| 198 | .decl => if (names[i] == name) { | 219 | .decl => { |
| 199 | const prev_ty = s.syms.items(.ty)[i]; | 220 | if (!ty.eql(prev.ty, p.comp, true)) { |
| 200 | if (!ty.eql(prev_ty, p.comp, true)) { | ||
| 201 | try p.errStr(.redefinition_incompatible, tok, p.tokSlice(tok)); | 221 | try p.errStr(.redefinition_incompatible, tok, p.tokSlice(tok)); |
| 202 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 222 | try p.errTok(.previous_definition, prev.tok); |
| 203 | } | 223 | } |
| 204 | break; | ||
| 205 | }, | 224 | }, |
| 206 | .def, .constexpr => if (names[i] == name) { | 225 | .def, .constexpr => { |
| 207 | try p.errStr(.redefinition, tok, p.tokSlice(tok)); | 226 | try p.errStr(.redefinition, tok, p.tokSlice(tok)); |
| 208 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 227 | try p.errTok(.previous_definition, prev.tok); |
| 209 | break; | ||
| 210 | }, | 228 | }, |
| 211 | else => {}, | 229 | .typedef => { |
| 230 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); | ||
| 231 | try p.errTok(.previous_definition, prev.tok); | ||
| 232 | }, | ||
| 233 | else => unreachable, | ||
| 212 | } | 234 | } |
| 213 | } | 235 | } |
| 214 | try s.syms.append(p.gpa, .{ | 236 | |
| 237 | try s.define(p.gpa, .{ | ||
| 215 | .kind = if (constexpr) .constexpr else .def, | 238 | .kind = if (constexpr) .constexpr else .def, |
| 216 | .name = name, | 239 | .name = name, |
| 217 | .tok = tok, | 240 | .tok = tok, |
| ... | @@ -221,6 +244,15 @@ pub fn defineSymbol( | ... | @@ -221,6 +244,15 @@ pub fn defineSymbol( |
| 221 | }); | 244 | }); |
| 222 | } | 245 | } |
| 223 | 246 | ||
| 247 | /// Get a pointer to the named symbol in the innermost scope. | ||
| 248 | /// Asserts that a symbol with the name exists. | ||
| 249 | pub fn getPtr(s: *SymbolStack, name: StringId, kind: ScopeKind) *Symbol { | ||
| 250 | return switch (kind) { | ||
| 251 | .tags => s.scopes.items[s.active_len - 1].tags.getPtr(name).?, | ||
| 252 | .vars => s.scopes.items[s.active_len - 1].vars.getPtr(name).?, | ||
| 253 | }; | ||
| 254 | } | ||
| 255 | |||
| 224 | pub fn declareSymbol( | 256 | pub fn declareSymbol( |
| 225 | s: *SymbolStack, | 257 | s: *SymbolStack, |
| 226 | p: *Parser, | 258 | p: *Parser, |
| ... | @@ -229,39 +261,34 @@ pub fn declareSymbol( | ... | @@ -229,39 +261,34 @@ pub fn declareSymbol( |
| 229 | tok: TokenIndex, | 261 | tok: TokenIndex, |
| 230 | node: NodeIndex, | 262 | node: NodeIndex, |
| 231 | ) !void { | 263 | ) !void { |
| 232 | const kinds = s.syms.items(.kind); | 264 | if (s.get(name, .vars)) |prev| { |
| 233 | const names = s.syms.items(.name); | 265 | switch (prev.kind) { |
| 234 | const end = s.scopeEnd(); | 266 | .enumeration => { |
| 235 | var i = s.syms.len; | ||
| 236 | while (i > end) { | ||
| 237 | i -= 1; | ||
| 238 | switch (kinds[i]) { | ||
| 239 | .enumeration => if (names[i] == name) { | ||
| 240 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); | 267 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); |
| 241 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 268 | try p.errTok(.previous_definition, prev.tok); |
| 242 | break; | ||
| 243 | }, | 269 | }, |
| 244 | .decl => if (names[i] == name) { | 270 | .decl => { |
| 245 | const prev_ty = s.syms.items(.ty)[i]; | 271 | if (!ty.eql(prev.ty, p.comp, true)) { |
| 246 | if (!ty.eql(prev_ty, p.comp, true)) { | ||
| 247 | try p.errStr(.redefinition_incompatible, tok, p.tokSlice(tok)); | 272 | try p.errStr(.redefinition_incompatible, tok, p.tokSlice(tok)); |
| 248 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 273 | try p.errTok(.previous_definition, prev.tok); |
| 249 | } | 274 | } |
| 250 | break; | ||
| 251 | }, | 275 | }, |
| 252 | .def, .constexpr => if (names[i] == name) { | 276 | .def, .constexpr => { |
| 253 | const prev_ty = s.syms.items(.ty)[i]; | 277 | if (!ty.eql(prev.ty, p.comp, true)) { |
| 254 | if (!ty.eql(prev_ty, p.comp, true)) { | ||
| 255 | try p.errStr(.redefinition_incompatible, tok, p.tokSlice(tok)); | 278 | try p.errStr(.redefinition_incompatible, tok, p.tokSlice(tok)); |
| 256 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 279 | try p.errTok(.previous_definition, prev.tok); |
| 257 | break; | 280 | } else { |
| 281 | return; | ||
| 258 | } | 282 | } |
| 259 | return; | ||
| 260 | }, | 283 | }, |
| 261 | else => {}, | 284 | .typedef => { |
| 285 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); | ||
| 286 | try p.errTok(.previous_definition, prev.tok); | ||
| 287 | }, | ||
| 288 | else => unreachable, | ||
| 262 | } | 289 | } |
| 263 | } | 290 | } |
| 264 | try s.syms.append(p.gpa, .{ | 291 | try s.define(p.gpa, .{ |
| 265 | .kind = .decl, | 292 | .kind = .decl, |
| 266 | .name = name, | 293 | .name = name, |
| 267 | .tok = tok, | 294 | .tok = tok, |
| ... | @@ -272,25 +299,23 @@ pub fn declareSymbol( | ... | @@ -272,25 +299,23 @@ pub fn declareSymbol( |
| 272 | } | 299 | } |
| 273 | 300 | ||
| 274 | pub fn defineParam(s: *SymbolStack, p: *Parser, name: StringId, ty: Type, tok: TokenIndex) !void { | 301 | pub fn defineParam(s: *SymbolStack, p: *Parser, name: StringId, ty: Type, tok: TokenIndex) !void { |
| 275 | const kinds = s.syms.items(.kind); | 302 | if (s.get(name, .vars)) |prev| { |
| 276 | const names = s.syms.items(.name); | 303 | switch (prev.kind) { |
| 277 | const end = s.scopeEnd(); | 304 | .enumeration, .decl, .def, .constexpr => { |
| 278 | var i = s.syms.len; | ||
| 279 | while (i > end) { | ||
| 280 | i -= 1; | ||
| 281 | switch (kinds[i]) { | ||
| 282 | .enumeration, .decl, .def, .constexpr => if (names[i] == name) { | ||
| 283 | try p.errStr(.redefinition_of_parameter, tok, p.tokSlice(tok)); | 305 | try p.errStr(.redefinition_of_parameter, tok, p.tokSlice(tok)); |
| 284 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 306 | try p.errTok(.previous_definition, prev.tok); |
| 285 | break; | 307 | }, |
| 308 | .typedef => { | ||
| 309 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); | ||
| 310 | try p.errTok(.previous_definition, prev.tok); | ||
| 286 | }, | 311 | }, |
| 287 | else => {}, | 312 | else => unreachable, |
| 288 | } | 313 | } |
| 289 | } | 314 | } |
| 290 | if (ty.is(.fp16) and !p.comp.hasHalfPrecisionFloatABI()) { | 315 | if (ty.is(.fp16) and !p.comp.hasHalfPrecisionFloatABI()) { |
| 291 | try p.errStr(.suggest_pointer_for_invalid_fp16, tok, "parameters"); | 316 | try p.errStr(.suggest_pointer_for_invalid_fp16, tok, "parameters"); |
| 292 | } | 317 | } |
| 293 | try s.syms.append(p.gpa, .{ | 318 | try s.define(p.gpa, .{ |
| 294 | .kind = .def, | 319 | .kind = .def, |
| 295 | .name = name, | 320 | .name = name, |
| 296 | .tok = tok, | 321 | .tok = tok, |
| ... | @@ -306,35 +331,28 @@ pub fn defineTag( | ... | @@ -306,35 +331,28 @@ pub fn defineTag( |
| 306 | kind: Token.Id, | 331 | kind: Token.Id, |
| 307 | tok: TokenIndex, | 332 | tok: TokenIndex, |
| 308 | ) !?Symbol { | 333 | ) !?Symbol { |
| 309 | const kinds = s.syms.items(.kind); | 334 | const prev = s.get(name, .tags) orelse return null; |
| 310 | const names = s.syms.items(.name); | 335 | switch (prev.kind) { |
| 311 | const end = s.scopeEnd(); | 336 | .@"enum" => { |
| 312 | var i = s.syms.len; | 337 | if (kind == .keyword_enum) return prev; |
| 313 | while (i > end) { | 338 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); |
| 314 | i -= 1; | 339 | try p.errTok(.previous_definition, prev.tok); |
| 315 | switch (kinds[i]) { | 340 | return null; |
| 316 | .@"enum" => if (names[i] == name) { | 341 | }, |
| 317 | if (kind == .keyword_enum) return s.syms.get(i); | 342 | .@"struct" => { |
| 318 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); | 343 | if (kind == .keyword_struct) return prev; |
| 319 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 344 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); |
| 320 | return null; | 345 | try p.errTok(.previous_definition, prev.tok); |
| 321 | }, | 346 | return null; |
| 322 | .@"struct" => if (names[i] == name) { | 347 | }, |
| 323 | if (kind == .keyword_struct) return s.syms.get(i); | 348 | .@"union" => { |
| 324 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); | 349 | if (kind == .keyword_union) return prev; |
| 325 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 350 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); |
| 326 | return null; | 351 | try p.errTok(.previous_definition, prev.tok); |
| 327 | }, | 352 | return null; |
| 328 | .@"union" => if (names[i] == name) { | 353 | }, |
| 329 | if (kind == .keyword_union) return s.syms.get(i); | 354 | else => unreachable, |
| 330 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); | ||
| 331 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | ||
| 332 | return null; | ||
| 333 | }, | ||
| 334 | else => {}, | ||
| 335 | } | ||
| 336 | } | 355 | } |
| 337 | return null; | ||
| 338 | } | 356 | } |
| 339 | 357 | ||
| 340 | pub fn defineEnumeration( | 358 | pub fn defineEnumeration( |
| ... | @@ -345,27 +363,26 @@ pub fn defineEnumeration( | ... | @@ -345,27 +363,26 @@ pub fn defineEnumeration( |
| 345 | tok: TokenIndex, | 363 | tok: TokenIndex, |
| 346 | val: Value, | 364 | val: Value, |
| 347 | ) !void { | 365 | ) !void { |
| 348 | const kinds = s.syms.items(.kind); | 366 | if (s.get(name, .vars)) |prev| { |
| 349 | const names = s.syms.items(.name); | 367 | switch (prev.kind) { |
| 350 | const end = s.scopeEnd(); | 368 | .enumeration => { |
| 351 | var i = s.syms.len; | ||
| 352 | while (i > end) { | ||
| 353 | i -= 1; | ||
| 354 | switch (kinds[i]) { | ||
| 355 | .enumeration => if (names[i] == name) { | ||
| 356 | try p.errStr(.redefinition, tok, p.tokSlice(tok)); | 369 | try p.errStr(.redefinition, tok, p.tokSlice(tok)); |
| 357 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 370 | try p.errTok(.previous_definition, prev.tok); |
| 358 | return; | 371 | return; |
| 359 | }, | 372 | }, |
| 360 | .decl, .def, .constexpr => if (names[i] == name) { | 373 | .decl, .def, .constexpr => { |
| 361 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); | 374 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); |
| 362 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | 375 | try p.errTok(.previous_definition, prev.tok); |
| 363 | return; | 376 | return; |
| 364 | }, | 377 | }, |
| 365 | else => {}, | 378 | .typedef => { |
| 379 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); | ||
| 380 | try p.errTok(.previous_definition, prev.tok); | ||
| 381 | }, | ||
| 382 | else => unreachable, | ||
| 366 | } | 383 | } |
| 367 | } | 384 | } |
| 368 | try s.syms.append(p.gpa, .{ | 385 | try s.define(p.gpa, .{ |
| 369 | .kind = .enumeration, | 386 | .kind = .enumeration, |
| 370 | .name = name, | 387 | .name = name, |
| 371 | .tok = tok, | 388 | .tok = tok, |
deps/aro/aro/Tokenizer.zig+26-23| ... | @@ -749,12 +749,15 @@ pub const Token = struct { | ... | @@ -749,12 +749,15 @@ pub const Token = struct { |
| 749 | .string_literal_utf_8, | 749 | .string_literal_utf_8, |
| 750 | .string_literal_utf_32, | 750 | .string_literal_utf_32, |
| 751 | .string_literal_wide, | 751 | .string_literal_wide, |
| 752 | .unterminated_string_literal, | ||
| 752 | => "a string literal", | 753 | => "a string literal", |
| 753 | .char_literal, | 754 | .char_literal, |
| 754 | .char_literal_utf_8, | 755 | .char_literal_utf_8, |
| 755 | .char_literal_utf_16, | 756 | .char_literal_utf_16, |
| 756 | .char_literal_utf_32, | 757 | .char_literal_utf_32, |
| 757 | .char_literal_wide, | 758 | .char_literal_wide, |
| 759 | .unterminated_char_literal, | ||
| 760 | .empty_char_literal, | ||
| 758 | => "a character literal", | 761 | => "a character literal", |
| 759 | .pp_num, .embed_byte => "A number", | 762 | .pp_num, .embed_byte => "A number", |
| 760 | else => id.lexeme().?, | 763 | else => id.lexeme().?, |
| ... | @@ -798,7 +801,7 @@ pub const Token = struct { | ... | @@ -798,7 +801,7 @@ pub const Token = struct { |
| 798 | }; | 801 | }; |
| 799 | } | 802 | } |
| 800 | 803 | ||
| 801 | pub fn allowsDigraphs(id: Id, comp: *const Compilation) bool { | 804 | pub fn allowsDigraphs(id: Id, langopts: LangOpts) bool { |
| 802 | return switch (id) { | 805 | return switch (id) { |
| 803 | .l_bracket, | 806 | .l_bracket, |
| 804 | .r_bracket, | 807 | .r_bracket, |
| ... | @@ -806,7 +809,7 @@ pub const Token = struct { | ... | @@ -806,7 +809,7 @@ pub const Token = struct { |
| 806 | .r_brace, | 809 | .r_brace, |
| 807 | .hash, | 810 | .hash, |
| 808 | .hash_hash, | 811 | .hash_hash, |
| 809 | => comp.langopts.hasDigraphs(), | 812 | => langopts.hasDigraphs(), |
| 810 | else => false, | 813 | else => false, |
| 811 | }; | 814 | }; |
| 812 | } | 815 | } |
| ... | @@ -829,15 +832,15 @@ pub const Token = struct { | ... | @@ -829,15 +832,15 @@ pub const Token = struct { |
| 829 | /// double underscore and underscore + capital letter identifiers | 832 | /// double underscore and underscore + capital letter identifiers |
| 830 | /// belong to the implementation namespace, so we always convert them | 833 | /// belong to the implementation namespace, so we always convert them |
| 831 | /// to keywords. | 834 | /// to keywords. |
| 832 | pub fn getTokenId(comp: *const Compilation, str: []const u8) Token.Id { | 835 | pub fn getTokenId(langopts: LangOpts, str: []const u8) Token.Id { |
| 833 | const kw = all_kws.get(str) orelse return .identifier; | 836 | const kw = all_kws.get(str) orelse return .identifier; |
| 834 | const standard = comp.langopts.standard; | 837 | const standard = langopts.standard; |
| 835 | return switch (kw) { | 838 | return switch (kw) { |
| 836 | .keyword_inline => if (standard.isGNU() or standard.atLeast(.c99)) kw else .identifier, | 839 | .keyword_inline => if (standard.isGNU() or standard.atLeast(.c99)) kw else .identifier, |
| 837 | .keyword_restrict => if (standard.atLeast(.c99)) kw else .identifier, | 840 | .keyword_restrict => if (standard.atLeast(.c99)) kw else .identifier, |
| 838 | .keyword_typeof => if (standard.isGNU() or standard.atLeast(.c23)) kw else .identifier, | 841 | .keyword_typeof => if (standard.isGNU() or standard.atLeast(.c23)) kw else .identifier, |
| 839 | .keyword_asm => if (standard.isGNU()) kw else .identifier, | 842 | .keyword_asm => if (standard.isGNU()) kw else .identifier, |
| 840 | .keyword_declspec => if (comp.langopts.declspec_attrs) kw else .identifier, | 843 | .keyword_declspec => if (langopts.declspec_attrs) kw else .identifier, |
| 841 | 844 | ||
| 842 | .keyword_c23_alignas, | 845 | .keyword_c23_alignas, |
| 843 | .keyword_c23_alignof, | 846 | .keyword_c23_alignof, |
| ... | @@ -864,7 +867,7 @@ pub const Token = struct { | ... | @@ -864,7 +867,7 @@ pub const Token = struct { |
| 864 | .keyword_stdcall2, | 867 | .keyword_stdcall2, |
| 865 | .keyword_thiscall2, | 868 | .keyword_thiscall2, |
| 866 | .keyword_vectorcall2, | 869 | .keyword_vectorcall2, |
| 867 | => if (comp.langopts.ms_extensions) kw else .identifier, | 870 | => if (langopts.ms_extensions) kw else .identifier, |
| 868 | else => kw, | 871 | else => kw, |
| 869 | }; | 872 | }; |
| 870 | } | 873 | } |
| ... | @@ -1023,7 +1026,7 @@ const Tokenizer = @This(); | ... | @@ -1023,7 +1026,7 @@ const Tokenizer = @This(); |
| 1023 | buf: []const u8, | 1026 | buf: []const u8, |
| 1024 | index: u32 = 0, | 1027 | index: u32 = 0, |
| 1025 | source: Source.Id, | 1028 | source: Source.Id, |
| 1026 | comp: *const Compilation, | 1029 | langopts: LangOpts, |
| 1027 | line: u32 = 1, | 1030 | line: u32 = 1, |
| 1028 | 1031 | ||
| 1029 | pub fn next(self: *Tokenizer) Token { | 1032 | pub fn next(self: *Tokenizer) Token { |
| ... | @@ -1162,14 +1165,14 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1162,14 +1165,14 @@ pub fn next(self: *Tokenizer) Token { |
| 1162 | '#' => state = .hash, | 1165 | '#' => state = .hash, |
| 1163 | '0'...'9' => state = .pp_num, | 1166 | '0'...'9' => state = .pp_num, |
| 1164 | '\t', '\x0B', '\x0C', ' ' => state = .whitespace, | 1167 | '\t', '\x0B', '\x0C', ' ' => state = .whitespace, |
| 1165 | '$' => if (self.comp.langopts.dollars_in_identifiers) { | 1168 | '$' => if (self.langopts.dollars_in_identifiers) { |
| 1166 | state = .extended_identifier; | 1169 | state = .extended_identifier; |
| 1167 | } else { | 1170 | } else { |
| 1168 | id = .invalid; | 1171 | id = .invalid; |
| 1169 | self.index += 1; | 1172 | self.index += 1; |
| 1170 | break; | 1173 | break; |
| 1171 | }, | 1174 | }, |
| 1172 | 0x1A => if (self.comp.langopts.ms_extensions) { | 1175 | 0x1A => if (self.langopts.ms_extensions) { |
| 1173 | id = .eof; | 1176 | id = .eof; |
| 1174 | break; | 1177 | break; |
| 1175 | } else { | 1178 | } else { |
| ... | @@ -1306,15 +1309,15 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1306,15 +1309,15 @@ pub fn next(self: *Tokenizer) Token { |
| 1306 | }, | 1309 | }, |
| 1307 | .identifier, .extended_identifier => switch (c) { | 1310 | .identifier, .extended_identifier => switch (c) { |
| 1308 | 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, | 1311 | 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, |
| 1309 | '$' => if (self.comp.langopts.dollars_in_identifiers) { | 1312 | '$' => if (self.langopts.dollars_in_identifiers) { |
| 1310 | state = .extended_identifier; | 1313 | state = .extended_identifier; |
| 1311 | } else { | 1314 | } else { |
| 1312 | id = if (state == .identifier) Token.getTokenId(self.comp, self.buf[start..self.index]) else .extended_identifier; | 1315 | id = if (state == .identifier) Token.getTokenId(self.langopts, self.buf[start..self.index]) else .extended_identifier; |
| 1313 | break; | 1316 | break; |
| 1314 | }, | 1317 | }, |
| 1315 | 0x80...0xFF => state = .extended_identifier, | 1318 | 0x80...0xFF => state = .extended_identifier, |
| 1316 | else => { | 1319 | else => { |
| 1317 | id = if (state == .identifier) Token.getTokenId(self.comp, self.buf[start..self.index]) else .extended_identifier; | 1320 | id = if (state == .identifier) Token.getTokenId(self.langopts, self.buf[start..self.index]) else .extended_identifier; |
| 1318 | break; | 1321 | break; |
| 1319 | }, | 1322 | }, |
| 1320 | }, | 1323 | }, |
| ... | @@ -1358,7 +1361,7 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1358,7 +1361,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1358 | }, | 1361 | }, |
| 1359 | .colon => switch (c) { | 1362 | .colon => switch (c) { |
| 1360 | '>' => { | 1363 | '>' => { |
| 1361 | if (self.comp.langopts.hasDigraphs()) { | 1364 | if (self.langopts.hasDigraphs()) { |
| 1362 | id = .r_bracket; | 1365 | id = .r_bracket; |
| 1363 | self.index += 1; | 1366 | self.index += 1; |
| 1364 | } else { | 1367 | } else { |
| ... | @@ -1367,7 +1370,7 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1367,7 +1370,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1367 | break; | 1370 | break; |
| 1368 | }, | 1371 | }, |
| 1369 | ':' => { | 1372 | ':' => { |
| 1370 | if (self.comp.langopts.standard.atLeast(.c23)) { | 1373 | if (self.langopts.standard.atLeast(.c23)) { |
| 1371 | id = .colon_colon; | 1374 | id = .colon_colon; |
| 1372 | self.index += 1; | 1375 | self.index += 1; |
| 1373 | break; | 1376 | break; |
| ... | @@ -1388,7 +1391,7 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1388,7 +1391,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1388 | break; | 1391 | break; |
| 1389 | }, | 1392 | }, |
| 1390 | '>' => { | 1393 | '>' => { |
| 1391 | if (self.comp.langopts.hasDigraphs()) { | 1394 | if (self.langopts.hasDigraphs()) { |
| 1392 | id = .r_brace; | 1395 | id = .r_brace; |
| 1393 | self.index += 1; | 1396 | self.index += 1; |
| 1394 | } else { | 1397 | } else { |
| ... | @@ -1397,7 +1400,7 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1397,7 +1400,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1397 | break; | 1400 | break; |
| 1398 | }, | 1401 | }, |
| 1399 | ':' => { | 1402 | ':' => { |
| 1400 | if (self.comp.langopts.hasDigraphs()) { | 1403 | if (self.langopts.hasDigraphs()) { |
| 1401 | state = .hash_digraph; | 1404 | state = .hash_digraph; |
| 1402 | } else { | 1405 | } else { |
| 1403 | id = .percent; | 1406 | id = .percent; |
| ... | @@ -1444,7 +1447,7 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1444,7 +1447,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1444 | break; | 1447 | break; |
| 1445 | }, | 1448 | }, |
| 1446 | ':' => { | 1449 | ':' => { |
| 1447 | if (self.comp.langopts.hasDigraphs()) { | 1450 | if (self.langopts.hasDigraphs()) { |
| 1448 | id = .l_bracket; | 1451 | id = .l_bracket; |
| 1449 | self.index += 1; | 1452 | self.index += 1; |
| 1450 | } else { | 1453 | } else { |
| ... | @@ -1453,7 +1456,7 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1453,7 +1456,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1453 | break; | 1456 | break; |
| 1454 | }, | 1457 | }, |
| 1455 | '%' => { | 1458 | '%' => { |
| 1456 | if (self.comp.langopts.hasDigraphs()) { | 1459 | if (self.langopts.hasDigraphs()) { |
| 1457 | id = .l_brace; | 1460 | id = .l_brace; |
| 1458 | self.index += 1; | 1461 | self.index += 1; |
| 1459 | } else { | 1462 | } else { |
| ... | @@ -1613,7 +1616,7 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1613,7 +1616,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1613 | }, | 1616 | }, |
| 1614 | .line_comment => switch (c) { | 1617 | .line_comment => switch (c) { |
| 1615 | '\n' => { | 1618 | '\n' => { |
| 1616 | if (self.comp.langopts.preserve_comments) { | 1619 | if (self.langopts.preserve_comments) { |
| 1617 | id = .comment; | 1620 | id = .comment; |
| 1618 | break; | 1621 | break; |
| 1619 | } | 1622 | } |
| ... | @@ -1629,7 +1632,7 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1629,7 +1632,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1629 | }, | 1632 | }, |
| 1630 | .multi_line_comment_asterisk => switch (c) { | 1633 | .multi_line_comment_asterisk => switch (c) { |
| 1631 | '/' => { | 1634 | '/' => { |
| 1632 | if (self.comp.langopts.preserve_comments) { | 1635 | if (self.langopts.preserve_comments) { |
| 1633 | self.index += 1; | 1636 | self.index += 1; |
| 1634 | id = .comment; | 1637 | id = .comment; |
| 1635 | break; | 1638 | break; |
| ... | @@ -1673,7 +1676,7 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1673,7 +1676,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1673 | '.', | 1676 | '.', |
| 1674 | => {}, | 1677 | => {}, |
| 1675 | 'e', 'E', 'p', 'P' => state = .pp_num_exponent, | 1678 | 'e', 'E', 'p', 'P' => state = .pp_num_exponent, |
| 1676 | '\'' => if (self.comp.langopts.standard.atLeast(.c23)) { | 1679 | '\'' => if (self.langopts.standard.atLeast(.c23)) { |
| 1677 | state = .pp_num_digit_separator; | 1680 | state = .pp_num_digit_separator; |
| 1678 | } else { | 1681 | } else { |
| 1679 | id = .pp_num; | 1682 | id = .pp_num; |
| ... | @@ -1721,7 +1724,7 @@ pub fn next(self: *Tokenizer) Token { | ... | @@ -1721,7 +1724,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1721 | } else if (self.index == self.buf.len) { | 1724 | } else if (self.index == self.buf.len) { |
| 1722 | switch (state) { | 1725 | switch (state) { |
| 1723 | .start, .line_comment => {}, | 1726 | .start, .line_comment => {}, |
| 1724 | .u, .u8, .U, .L, .identifier => id = Token.getTokenId(self.comp, self.buf[start..self.index]), | 1727 | .u, .u8, .U, .L, .identifier => id = Token.getTokenId(self.langopts, self.buf[start..self.index]), |
| 1725 | .extended_identifier => id = .extended_identifier, | 1728 | .extended_identifier => id = .extended_identifier, |
| 1726 | 1729 | ||
| 1727 | .period2 => { | 1730 | .period2 => { |
| ... | @@ -2149,7 +2152,7 @@ fn expectTokensExtra(contents: []const u8, expected_tokens: []const Token.Id, st | ... | @@ -2149,7 +2152,7 @@ fn expectTokensExtra(contents: []const u8, expected_tokens: []const Token.Id, st |
| 2149 | var tokenizer = Tokenizer{ | 2152 | var tokenizer = Tokenizer{ |
| 2150 | .buf = source.buf, | 2153 | .buf = source.buf, |
| 2151 | .source = source.id, | 2154 | .source = source.id, |
| 2152 | .comp = &comp, | 2155 | .langopts = comp.langopts, |
| 2153 | }; | 2156 | }; |
| 2154 | var i: usize = 0; | 2157 | var i: usize = 0; |
| 2155 | while (i < expected_tokens.len) { | 2158 | while (i < expected_tokens.len) { |
deps/aro/aro/Toolchain.zig+5-8| ... | @@ -183,18 +183,15 @@ pub fn getLinkerPath(tc: *const Toolchain, buf: []u8) ![]const u8 { | ... | @@ -183,18 +183,15 @@ pub fn getLinkerPath(tc: *const Toolchain, buf: []u8) ![]const u8 { |
| 183 | return tc.getProgramPath(default_linker, buf); | 183 | return tc.getProgramPath(default_linker, buf); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | const TargetSpecificToolName = std.BoundedArray(u8, 64); | ||
| 187 | |||
| 188 | /// If an explicit target is provided, also check the prefixed tool-specific name | 186 | /// If an explicit target is provided, also check the prefixed tool-specific name |
| 189 | /// TODO: this isn't exactly right since our target names don't necessarily match up | 187 | /// TODO: this isn't exactly right since our target names don't necessarily match up |
| 190 | /// with GCC's. | 188 | /// with GCC's. |
| 191 | /// For example the Zig target `arm-freestanding-eabi` would need the `arm-none-eabi` tools | 189 | /// For example the Zig target `arm-freestanding-eabi` would need the `arm-none-eabi` tools |
| 192 | fn possibleProgramNames(raw_triple: ?[]const u8, name: []const u8, target_specific: *TargetSpecificToolName) std.BoundedArray([]const u8, 2) { | 190 | fn possibleProgramNames(raw_triple: ?[]const u8, name: []const u8, buf: *[64]u8) std.BoundedArray([]const u8, 2) { |
| 193 | var possible_names: std.BoundedArray([]const u8, 2) = .{}; | 191 | var possible_names: std.BoundedArray([]const u8, 2) = .{}; |
| 194 | if (raw_triple) |triple| { | 192 | if (raw_triple) |triple| { |
| 195 | const w = target_specific.writer(); | 193 | if (std.fmt.bufPrint(buf, "{s}-{s}", .{ triple, name })) |res| { |
| 196 | if (w.print("{s}-{s}", .{ triple, name })) { | 194 | possible_names.appendAssumeCapacity(res); |
| 197 | possible_names.appendAssumeCapacity(target_specific.constSlice()); | ||
| 198 | } else |_| {} | 195 | } else |_| {} |
| 199 | } | 196 | } |
| 200 | possible_names.appendAssumeCapacity(name); | 197 | possible_names.appendAssumeCapacity(name); |
| ... | @@ -227,8 +224,8 @@ fn getProgramPath(tc: *const Toolchain, name: []const u8, buf: []u8) []const u8 | ... | @@ -227,8 +224,8 @@ fn getProgramPath(tc: *const Toolchain, name: []const u8, buf: []u8) []const u8 |
| 227 | var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; | 224 | var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; |
| 228 | var fib = std.heap.FixedBufferAllocator.init(&path_buf); | 225 | var fib = std.heap.FixedBufferAllocator.init(&path_buf); |
| 229 | 226 | ||
| 230 | var tool_specific_name: TargetSpecificToolName = .{}; | 227 | var tool_specific_buf: [64]u8 = undefined; |
| 231 | const possible_names = possibleProgramNames(tc.driver.raw_target_triple, name, &tool_specific_name); | 228 | const possible_names = possibleProgramNames(tc.driver.raw_target_triple, name, &tool_specific_buf); |
| 232 | 229 | ||
| 233 | for (possible_names.constSlice()) |tool_name| { | 230 | for (possible_names.constSlice()) |tool_name| { |
| 234 | for (tc.program_paths.items) |program_path| { | 231 | for (tc.program_paths.items) |program_path| { |
deps/aro/aro/Tree.zig+7-4| ... | @@ -1,11 +1,12 @@ | ... | @@ -1,11 +1,12 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const Interner = @import("backend").Interner; | 2 | const Interner = @import("backend").Interner; |
| 3 | const Type = @import("Type.zig"); | 3 | const Attribute = @import("Attribute.zig"); |
| 4 | const Tokenizer = @import("Tokenizer.zig"); | ||
| 5 | const CodeGen = @import("CodeGen.zig"); | 4 | const CodeGen = @import("CodeGen.zig"); |
| 6 | const Compilation = @import("Compilation.zig"); | 5 | const Compilation = @import("Compilation.zig"); |
| 6 | const number_affixes = @import("Tree/number_affixes.zig"); | ||
| 7 | const Source = @import("Source.zig"); | 7 | const Source = @import("Source.zig"); |
| 8 | const Attribute = @import("Attribute.zig"); | 8 | const Tokenizer = @import("Tokenizer.zig"); |
| 9 | const Type = @import("Type.zig"); | ||
| 9 | const Value = @import("Value.zig"); | 10 | const Value = @import("Value.zig"); |
| 10 | const StringInterner = @import("StringInterner.zig"); | 11 | const StringInterner = @import("StringInterner.zig"); |
| 11 | 12 | ||
| ... | @@ -92,6 +93,8 @@ pub const Token = struct { | ... | @@ -92,6 +93,8 @@ pub const Token = struct { |
| 92 | 93 | ||
| 93 | pub const List = std.MultiArrayList(Token); | 94 | pub const List = std.MultiArrayList(Token); |
| 94 | pub const Id = Tokenizer.Token.Id; | 95 | pub const Id = Tokenizer.Token.Id; |
| 96 | pub const NumberPrefix = number_affixes.Prefix; | ||
| 97 | pub const NumberSuffix = number_affixes.Suffix; | ||
| 95 | }; | 98 | }; |
| 96 | 99 | ||
| 97 | pub const TokenIndex = u32; | 100 | pub const TokenIndex = u32; |
| ... | @@ -669,7 +672,7 @@ pub fn tokSlice(tree: *const Tree, tok_i: TokenIndex) []const u8 { | ... | @@ -669,7 +672,7 @@ pub fn tokSlice(tree: *const Tree, tok_i: TokenIndex) []const u8 { |
| 669 | const loc = tree.tokens.items(.loc)[tok_i]; | 672 | const loc = tree.tokens.items(.loc)[tok_i]; |
| 670 | var tmp_tokenizer = Tokenizer{ | 673 | var tmp_tokenizer = Tokenizer{ |
| 671 | .buf = tree.comp.getSource(loc.id).buf, | 674 | .buf = tree.comp.getSource(loc.id).buf, |
| 672 | .comp = tree.comp, | 675 | .langopts = tree.comp.langopts, |
| 673 | .index = loc.byte_offset, | 676 | .index = loc.byte_offset, |
| 674 | .source = .generated, | 677 | .source = .generated, |
| 675 | }; | 678 | }; |
deps/aro/aro/Tree/number_affixes.zig created+187| ... | @@ -0,0 +1,187 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const mem = std.mem; | ||
| 3 | |||
| 4 | pub const Prefix = enum(u8) { | ||
| 5 | binary = 2, | ||
| 6 | octal = 8, | ||
| 7 | decimal = 10, | ||
| 8 | hex = 16, | ||
| 9 | |||
| 10 | pub fn digitAllowed(prefix: Prefix, c: u8) bool { | ||
| 11 | return switch (c) { | ||
| 12 | '0', '1' => true, | ||
| 13 | '2'...'7' => prefix != .binary, | ||
| 14 | '8'...'9' => prefix == .decimal or prefix == .hex, | ||
| 15 | 'a'...'f', 'A'...'F' => prefix == .hex, | ||
| 16 | else => false, | ||
| 17 | }; | ||
| 18 | } | ||
| 19 | |||
| 20 | pub fn fromString(buf: []const u8) Prefix { | ||
| 21 | if (buf.len == 1) return .decimal; | ||
| 22 | // tokenizer enforces that first byte is a decimal digit or period | ||
| 23 | switch (buf[0]) { | ||
| 24 | '.', '1'...'9' => return .decimal, | ||
| 25 | '0' => {}, | ||
| 26 | else => unreachable, | ||
| 27 | } | ||
| 28 | switch (buf[1]) { | ||
| 29 | 'x', 'X' => return if (buf.len == 2) .decimal else .hex, | ||
| 30 | 'b', 'B' => return if (buf.len == 2) .decimal else .binary, | ||
| 31 | else => { | ||
| 32 | if (mem.indexOfAny(u8, buf, "eE.")) |_| { | ||
| 33 | // This is a decimal floating point number that happens to start with zero | ||
| 34 | return .decimal; | ||
| 35 | } else if (Suffix.fromString(buf[1..], .int)) |_| { | ||
| 36 | // This is `0` with a valid suffix | ||
| 37 | return .decimal; | ||
| 38 | } else { | ||
| 39 | return .octal; | ||
| 40 | } | ||
| 41 | }, | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | /// Length of this prefix as a string | ||
| 46 | pub fn stringLen(prefix: Prefix) usize { | ||
| 47 | return switch (prefix) { | ||
| 48 | .binary => 2, | ||
| 49 | .octal => 1, | ||
| 50 | .decimal => 0, | ||
| 51 | .hex => 2, | ||
| 52 | }; | ||
| 53 | } | ||
| 54 | }; | ||
| 55 | |||
| 56 | pub const Suffix = enum { | ||
| 57 | // zig fmt: off | ||
| 58 | |||
| 59 | // int and imaginary int | ||
| 60 | None, I, | ||
| 61 | |||
| 62 | // unsigned real integers | ||
| 63 | U, UL, ULL, | ||
| 64 | |||
| 65 | // unsigned imaginary integers | ||
| 66 | IU, IUL, IULL, | ||
| 67 | |||
| 68 | // long or long double, real and imaginary | ||
| 69 | L, IL, | ||
| 70 | |||
| 71 | // long long and imaginary long long | ||
| 72 | LL, ILL, | ||
| 73 | |||
| 74 | // float and imaginary float | ||
| 75 | F, IF, | ||
| 76 | |||
| 77 | // _Float16 | ||
| 78 | F16, | ||
| 79 | |||
| 80 | // __float80 | ||
| 81 | W, | ||
| 82 | |||
| 83 | // Imaginary __float80 | ||
| 84 | IW, | ||
| 85 | |||
| 86 | // _Float128 | ||
| 87 | Q, F128, | ||
| 88 | |||
| 89 | // Imaginary _Float128 | ||
| 90 | IQ, IF128, | ||
| 91 | |||
| 92 | // Imaginary _Bitint | ||
| 93 | IWB, IUWB, | ||
| 94 | |||
| 95 | // _Bitint | ||
| 96 | WB, UWB, | ||
| 97 | |||
| 98 | // zig fmt: on | ||
| 99 | |||
| 100 | const Tuple = struct { Suffix, []const []const u8 }; | ||
| 101 | |||
| 102 | const IntSuffixes = &[_]Tuple{ | ||
| 103 | .{ .U, &.{"U"} }, | ||
| 104 | .{ .L, &.{"L"} }, | ||
| 105 | .{ .WB, &.{"WB"} }, | ||
| 106 | .{ .UL, &.{ "U", "L" } }, | ||
| 107 | .{ .UWB, &.{ "U", "WB" } }, | ||
| 108 | .{ .LL, &.{"LL"} }, | ||
| 109 | .{ .ULL, &.{ "U", "LL" } }, | ||
| 110 | |||
| 111 | .{ .I, &.{"I"} }, | ||
| 112 | |||
| 113 | .{ .IWB, &.{ "I", "WB" } }, | ||
| 114 | .{ .IU, &.{ "I", "U" } }, | ||
| 115 | .{ .IL, &.{ "I", "L" } }, | ||
| 116 | .{ .IUL, &.{ "I", "U", "L" } }, | ||
| 117 | .{ .IUWB, &.{ "I", "U", "WB" } }, | ||
| 118 | .{ .ILL, &.{ "I", "LL" } }, | ||
| 119 | .{ .IULL, &.{ "I", "U", "LL" } }, | ||
| 120 | }; | ||
| 121 | |||
| 122 | const FloatSuffixes = &[_]Tuple{ | ||
| 123 | .{ .F16, &.{"F16"} }, | ||
| 124 | .{ .F, &.{"F"} }, | ||
| 125 | .{ .L, &.{"L"} }, | ||
| 126 | .{ .W, &.{"W"} }, | ||
| 127 | .{ .F128, &.{"F128"} }, | ||
| 128 | .{ .Q, &.{"Q"} }, | ||
| 129 | |||
| 130 | .{ .I, &.{"I"} }, | ||
| 131 | .{ .IL, &.{ "I", "L" } }, | ||
| 132 | .{ .IF, &.{ "I", "F" } }, | ||
| 133 | .{ .IW, &.{ "I", "W" } }, | ||
| 134 | .{ .IF128, &.{ "I", "F128" } }, | ||
| 135 | .{ .IQ, &.{ "I", "Q" } }, | ||
| 136 | }; | ||
| 137 | |||
| 138 | pub fn fromString(buf: []const u8, suffix_kind: enum { int, float }) ?Suffix { | ||
| 139 | if (buf.len == 0) return .None; | ||
| 140 | |||
| 141 | const suffixes = switch (suffix_kind) { | ||
| 142 | .float => FloatSuffixes, | ||
| 143 | .int => IntSuffixes, | ||
| 144 | }; | ||
| 145 | var scratch: [4]u8 = undefined; | ||
| 146 | top: for (suffixes) |candidate| { | ||
| 147 | const tag = candidate[0]; | ||
| 148 | const parts = candidate[1]; | ||
| 149 | var len: usize = 0; | ||
| 150 | for (parts) |part| len += part.len; | ||
| 151 | if (len != buf.len) continue; | ||
| 152 | |||
| 153 | for (parts) |part| { | ||
| 154 | const lower = std.ascii.lowerString(&scratch, part); | ||
| 155 | if (mem.indexOf(u8, buf, part) == null and mem.indexOf(u8, buf, lower) == null) continue :top; | ||
| 156 | } | ||
| 157 | return tag; | ||
| 158 | } | ||
| 159 | return null; | ||
| 160 | } | ||
| 161 | |||
| 162 | pub fn isImaginary(suffix: Suffix) bool { | ||
| 163 | return switch (suffix) { | ||
| 164 | .I, .IL, .IF, .IU, .IUL, .ILL, .IULL, .IWB, .IUWB, .IF128, .IQ, .IW => true, | ||
| 165 | .None, .L, .F16, .F, .U, .UL, .LL, .ULL, .WB, .UWB, .F128, .Q, .W => false, | ||
| 166 | }; | ||
| 167 | } | ||
| 168 | |||
| 169 | pub fn isSignedInteger(suffix: Suffix) bool { | ||
| 170 | return switch (suffix) { | ||
| 171 | .None, .L, .LL, .I, .IL, .ILL, .WB, .IWB => true, | ||
| 172 | .U, .UL, .ULL, .IU, .IUL, .IULL, .UWB, .IUWB => false, | ||
| 173 | .F, .IF, .F16, .F128, .IF128, .Q, .IQ, .W, .IW => unreachable, | ||
| 174 | }; | ||
| 175 | } | ||
| 176 | |||
| 177 | pub fn signedness(suffix: Suffix) std.builtin.Signedness { | ||
| 178 | return if (suffix.isSignedInteger()) .signed else .unsigned; | ||
| 179 | } | ||
| 180 | |||
| 181 | pub fn isBitInt(suffix: Suffix) bool { | ||
| 182 | return switch (suffix) { | ||
| 183 | .WB, .UWB, .IWB, .IUWB => true, | ||
| 184 | else => false, | ||
| 185 | }; | ||
| 186 | } | ||
| 187 | }; | ||
deps/aro/aro/Type.zig+157-212| ... | @@ -363,7 +363,6 @@ pub const Specifier = enum { | ... | @@ -363,7 +363,6 @@ pub const Specifier = enum { |
| 363 | // data.sub_type | 363 | // data.sub_type |
| 364 | pointer, | 364 | pointer, |
| 365 | unspecified_variable_len_array, | 365 | unspecified_variable_len_array, |
| 366 | decayed_unspecified_variable_len_array, | ||
| 367 | // data.func | 366 | // data.func |
| 368 | /// int foo(int bar, char baz) and int (void) | 367 | /// int foo(int bar, char baz) and int (void) |
| 369 | func, | 368 | func, |
| ... | @@ -375,15 +374,11 @@ pub const Specifier = enum { | ... | @@ -375,15 +374,11 @@ pub const Specifier = enum { |
| 375 | 374 | ||
| 376 | // data.array | 375 | // data.array |
| 377 | array, | 376 | array, |
| 378 | decayed_array, | ||
| 379 | static_array, | 377 | static_array, |
| 380 | decayed_static_array, | ||
| 381 | incomplete_array, | 378 | incomplete_array, |
| 382 | decayed_incomplete_array, | ||
| 383 | vector, | 379 | vector, |
| 384 | // data.expr | 380 | // data.expr |
| 385 | variable_len_array, | 381 | variable_len_array, |
| 386 | decayed_variable_len_array, | ||
| 387 | 382 | ||
| 388 | // data.record | 383 | // data.record |
| 389 | @"struct", | 384 | @"struct", |
| ... | @@ -394,13 +389,9 @@ pub const Specifier = enum { | ... | @@ -394,13 +389,9 @@ pub const Specifier = enum { |
| 394 | 389 | ||
| 395 | /// typeof(type-name) | 390 | /// typeof(type-name) |
| 396 | typeof_type, | 391 | typeof_type, |
| 397 | /// decayed array created with typeof(type-name) | ||
| 398 | decayed_typeof_type, | ||
| 399 | 392 | ||
| 400 | /// typeof(expression) | 393 | /// typeof(expression) |
| 401 | typeof_expr, | 394 | typeof_expr, |
| 402 | /// decayed array created with typeof(expression) | ||
| 403 | decayed_typeof_expr, | ||
| 404 | 395 | ||
| 405 | /// data.attributed | 396 | /// data.attributed |
| 406 | attributed, | 397 | attributed, |
| ... | @@ -428,6 +419,7 @@ data: union { | ... | @@ -428,6 +419,7 @@ data: union { |
| 428 | } = .{ .none = {} }, | 419 | } = .{ .none = {} }, |
| 429 | specifier: Specifier, | 420 | specifier: Specifier, |
| 430 | qual: Qualifiers = .{}, | 421 | qual: Qualifiers = .{}, |
| 422 | decayed: bool = false, | ||
| 431 | 423 | ||
| 432 | pub const int = Type{ .specifier = .int }; | 424 | pub const int = Type{ .specifier = .int }; |
| 433 | pub const invalid = Type{ .specifier = .invalid }; | 425 | pub const invalid = Type{ .specifier = .invalid }; |
| ... | @@ -442,7 +434,7 @@ pub fn is(ty: Type, specifier: Specifier) bool { | ... | @@ -442,7 +434,7 @@ pub fn is(ty: Type, specifier: Specifier) bool { |
| 442 | pub fn withAttributes(self: Type, allocator: std.mem.Allocator, attributes: []const Attribute) !Type { | 434 | pub fn withAttributes(self: Type, allocator: std.mem.Allocator, attributes: []const Attribute) !Type { |
| 443 | if (attributes.len == 0) return self; | 435 | if (attributes.len == 0) return self; |
| 444 | const attributed_type = try Type.Attributed.create(allocator, self, self.getAttributes(), attributes); | 436 | const attributed_type = try Type.Attributed.create(allocator, self, self.getAttributes(), attributes); |
| 445 | return Type{ .specifier = .attributed, .data = .{ .attributed = attributed_type } }; | 437 | return Type{ .specifier = .attributed, .data = .{ .attributed = attributed_type }, .decayed = self.decayed }; |
| 446 | } | 438 | } |
| 447 | 439 | ||
| 448 | pub fn isCallable(ty: Type) ?Type { | 440 | pub fn isCallable(ty: Type) ?Type { |
| ... | @@ -468,10 +460,10 @@ pub fn isFunc(ty: Type) bool { | ... | @@ -468,10 +460,10 @@ pub fn isFunc(ty: Type) bool { |
| 468 | 460 | ||
| 469 | pub fn isArray(ty: Type) bool { | 461 | pub fn isArray(ty: Type) bool { |
| 470 | return switch (ty.specifier) { | 462 | return switch (ty.specifier) { |
| 471 | .array, .static_array, .incomplete_array, .variable_len_array, .unspecified_variable_len_array => true, | 463 | .array, .static_array, .incomplete_array, .variable_len_array, .unspecified_variable_len_array => !ty.isDecayed(), |
| 472 | .typeof_type => ty.data.sub_type.isArray(), | 464 | .typeof_type => !ty.isDecayed() and ty.data.sub_type.isArray(), |
| 473 | .typeof_expr => ty.data.expr.ty.isArray(), | 465 | .typeof_expr => !ty.isDecayed() and ty.data.expr.ty.isArray(), |
| 474 | .attributed => ty.data.attributed.base.isArray(), | 466 | .attributed => !ty.isDecayed() and ty.data.attributed.base.isArray(), |
| 475 | else => false, | 467 | else => false, |
| 476 | }; | 468 | }; |
| 477 | } | 469 | } |
| ... | @@ -502,35 +494,22 @@ pub fn isScalarNonInt(ty: Type) bool { | ... | @@ -502,35 +494,22 @@ pub fn isScalarNonInt(ty: Type) bool { |
| 502 | } | 494 | } |
| 503 | 495 | ||
| 504 | pub fn isDecayed(ty: Type) bool { | 496 | pub fn isDecayed(ty: Type) bool { |
| 505 | const decayed = switch (ty.specifier) { | 497 | return ty.decayed; |
| 506 | .decayed_array, | ||
| 507 | .decayed_static_array, | ||
| 508 | .decayed_incomplete_array, | ||
| 509 | .decayed_variable_len_array, | ||
| 510 | .decayed_unspecified_variable_len_array, | ||
| 511 | .decayed_typeof_type, | ||
| 512 | .decayed_typeof_expr, | ||
| 513 | => true, | ||
| 514 | else => false, | ||
| 515 | }; | ||
| 516 | std.debug.assert(decayed or !std.mem.startsWith(u8, @tagName(ty.specifier), "decayed")); | ||
| 517 | return decayed; | ||
| 518 | } | 498 | } |
| 519 | 499 | ||
| 520 | pub fn isPtr(ty: Type) bool { | 500 | pub fn isPtr(ty: Type) bool { |
| 521 | return switch (ty.specifier) { | 501 | return switch (ty.specifier) { |
| 522 | .pointer, | 502 | .pointer => true, |
| 523 | .decayed_array, | 503 | |
| 524 | .decayed_static_array, | 504 | .array, |
| 525 | .decayed_incomplete_array, | 505 | .static_array, |
| 526 | .decayed_variable_len_array, | 506 | .incomplete_array, |
| 527 | .decayed_unspecified_variable_len_array, | 507 | .variable_len_array, |
| 528 | .decayed_typeof_type, | 508 | .unspecified_variable_len_array, |
| 529 | .decayed_typeof_expr, | 509 | => ty.isDecayed(), |
| 530 | => true, | 510 | .typeof_type => ty.isDecayed() or ty.data.sub_type.isPtr(), |
| 531 | .typeof_type => ty.data.sub_type.isPtr(), | 511 | .typeof_expr => ty.isDecayed() or ty.data.expr.ty.isPtr(), |
| 532 | .typeof_expr => ty.data.expr.ty.isPtr(), | 512 | .attributed => ty.isDecayed() or ty.data.attributed.base.isPtr(), |
| 533 | .attributed => ty.data.attributed.base.isPtr(), | ||
| 534 | else => false, | 513 | else => false, |
| 535 | }; | 514 | }; |
| 536 | } | 515 | } |
| ... | @@ -608,15 +587,15 @@ pub fn isVoidStar(ty: Type) bool { | ... | @@ -608,15 +587,15 @@ pub fn isVoidStar(ty: Type) bool { |
| 608 | 587 | ||
| 609 | pub fn isTypeof(ty: Type) bool { | 588 | pub fn isTypeof(ty: Type) bool { |
| 610 | return switch (ty.specifier) { | 589 | return switch (ty.specifier) { |
| 611 | .typeof_type, .typeof_expr, .decayed_typeof_type, .decayed_typeof_expr => true, | 590 | .typeof_type, .typeof_expr => true, |
| 612 | else => false, | 591 | else => false, |
| 613 | }; | 592 | }; |
| 614 | } | 593 | } |
| 615 | 594 | ||
| 616 | pub fn isConst(ty: Type) bool { | 595 | pub fn isConst(ty: Type) bool { |
| 617 | return switch (ty.specifier) { | 596 | return switch (ty.specifier) { |
| 618 | .typeof_type, .decayed_typeof_type => ty.qual.@"const" or ty.data.sub_type.isConst(), | 597 | .typeof_type => ty.qual.@"const" or ty.data.sub_type.isConst(), |
| 619 | .typeof_expr, .decayed_typeof_expr => ty.qual.@"const" or ty.data.expr.ty.isConst(), | 598 | .typeof_expr => ty.qual.@"const" or ty.data.expr.ty.isConst(), |
| 620 | .attributed => ty.data.attributed.base.isConst(), | 599 | .attributed => ty.data.attributed.base.isConst(), |
| 621 | else => ty.qual.@"const", | 600 | else => ty.qual.@"const", |
| 622 | }; | 601 | }; |
| ... | @@ -630,7 +609,7 @@ pub fn signedness(ty: Type, comp: *const Compilation) std.builtin.Signedness { | ... | @@ -630,7 +609,7 @@ pub fn signedness(ty: Type, comp: *const Compilation) std.builtin.Signedness { |
| 630 | return switch (ty.specifier) { | 609 | return switch (ty.specifier) { |
| 631 | // zig fmt: off | 610 | // zig fmt: off |
| 632 | .char, .complex_char => return comp.getCharSignedness(), | 611 | .char, .complex_char => return comp.getCharSignedness(), |
| 633 | .uchar, .ushort, .uint, .ulong, .ulong_long, .bool, .complex_uchar, .complex_ushort, | 612 | .uchar, .ushort, .uint, .ulong, .ulong_long, .uint128, .bool, .complex_uchar, .complex_ushort, |
| 634 | .complex_uint, .complex_ulong, .complex_ulong_long, .complex_uint128 => .unsigned, | 613 | .complex_uint, .complex_ulong, .complex_ulong_long, .complex_uint128 => .unsigned, |
| 635 | // zig fmt: on | 614 | // zig fmt: on |
| 636 | .bit_int, .complex_bit_int => ty.data.int.signedness, | 615 | .bit_int, .complex_bit_int => ty.data.int.signedness, |
| ... | @@ -678,16 +657,16 @@ pub fn isAnonymousRecord(ty: Type, comp: *const Compilation) bool { | ... | @@ -678,16 +657,16 @@ pub fn isAnonymousRecord(ty: Type, comp: *const Compilation) bool { |
| 678 | 657 | ||
| 679 | pub fn elemType(ty: Type) Type { | 658 | pub fn elemType(ty: Type) Type { |
| 680 | return switch (ty.specifier) { | 659 | return switch (ty.specifier) { |
| 681 | .pointer, .unspecified_variable_len_array, .decayed_unspecified_variable_len_array => ty.data.sub_type.*, | 660 | .pointer, .unspecified_variable_len_array => ty.data.sub_type.*, |
| 682 | .array, .static_array, .incomplete_array, .decayed_array, .decayed_static_array, .decayed_incomplete_array, .vector => ty.data.array.elem, | 661 | .array, .static_array, .incomplete_array, .vector => ty.data.array.elem, |
| 683 | .variable_len_array, .decayed_variable_len_array => ty.data.expr.ty, | 662 | .variable_len_array => ty.data.expr.ty, |
| 684 | .typeof_type, .decayed_typeof_type, .typeof_expr, .decayed_typeof_expr => { | 663 | .typeof_type, .typeof_expr => { |
| 685 | const unwrapped = ty.canonicalize(.preserve_quals); | 664 | const unwrapped = ty.canonicalize(.preserve_quals); |
| 686 | var elem = unwrapped.elemType(); | 665 | var elem = unwrapped.elemType(); |
| 687 | elem.qual = elem.qual.mergeAll(unwrapped.qual); | 666 | elem.qual = elem.qual.mergeAll(unwrapped.qual); |
| 688 | return elem; | 667 | return elem; |
| 689 | }, | 668 | }, |
| 690 | .attributed => ty.data.attributed.base, | 669 | .attributed => ty.data.attributed.base.elemType(), |
| 691 | .invalid => Type.invalid, | 670 | .invalid => Type.invalid, |
| 692 | // zig fmt: off | 671 | // zig fmt: off |
| 693 | .complex_float, .complex_double, .complex_long_double, .complex_float80, | 672 | .complex_float, .complex_double, .complex_long_double, .complex_float80, |
| ... | @@ -703,8 +682,8 @@ pub fn elemType(ty: Type) Type { | ... | @@ -703,8 +682,8 @@ pub fn elemType(ty: Type) Type { |
| 703 | pub fn returnType(ty: Type) Type { | 682 | pub fn returnType(ty: Type) Type { |
| 704 | return switch (ty.specifier) { | 683 | return switch (ty.specifier) { |
| 705 | .func, .var_args_func, .old_style_func => ty.data.func.return_type, | 684 | .func, .var_args_func, .old_style_func => ty.data.func.return_type, |
| 706 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.returnType(), | 685 | .typeof_type => ty.data.sub_type.returnType(), |
| 707 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.returnType(), | 686 | .typeof_expr => ty.data.expr.ty.returnType(), |
| 708 | .attributed => ty.data.attributed.base.returnType(), | 687 | .attributed => ty.data.attributed.base.returnType(), |
| 709 | .invalid => Type.invalid, | 688 | .invalid => Type.invalid, |
| 710 | else => unreachable, | 689 | else => unreachable, |
| ... | @@ -714,8 +693,8 @@ pub fn returnType(ty: Type) Type { | ... | @@ -714,8 +693,8 @@ pub fn returnType(ty: Type) Type { |
| 714 | pub fn params(ty: Type) []Func.Param { | 693 | pub fn params(ty: Type) []Func.Param { |
| 715 | return switch (ty.specifier) { | 694 | return switch (ty.specifier) { |
| 716 | .func, .var_args_func, .old_style_func => ty.data.func.params, | 695 | .func, .var_args_func, .old_style_func => ty.data.func.params, |
| 717 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.params(), | 696 | .typeof_type => ty.data.sub_type.params(), |
| 718 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.params(), | 697 | .typeof_expr => ty.data.expr.ty.params(), |
| 719 | .attributed => ty.data.attributed.base.params(), | 698 | .attributed => ty.data.attributed.base.params(), |
| 720 | .invalid => &.{}, | 699 | .invalid => &.{}, |
| 721 | else => unreachable, | 700 | else => unreachable, |
| ... | @@ -724,9 +703,9 @@ pub fn params(ty: Type) []Func.Param { | ... | @@ -724,9 +703,9 @@ pub fn params(ty: Type) []Func.Param { |
| 724 | 703 | ||
| 725 | pub fn arrayLen(ty: Type) ?u64 { | 704 | pub fn arrayLen(ty: Type) ?u64 { |
| 726 | return switch (ty.specifier) { | 705 | return switch (ty.specifier) { |
| 727 | .array, .static_array, .decayed_array, .decayed_static_array => ty.data.array.len, | 706 | .array, .static_array => ty.data.array.len, |
| 728 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.arrayLen(), | 707 | .typeof_type => ty.data.sub_type.arrayLen(), |
| 729 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.arrayLen(), | 708 | .typeof_expr => ty.data.expr.ty.arrayLen(), |
| 730 | .attributed => ty.data.attributed.base.arrayLen(), | 709 | .attributed => ty.data.attributed.base.arrayLen(), |
| 731 | else => null, | 710 | else => null, |
| 732 | }; | 711 | }; |
| ... | @@ -748,8 +727,8 @@ pub fn anyQual(ty: Type) bool { | ... | @@ -748,8 +727,8 @@ pub fn anyQual(ty: Type) bool { |
| 748 | pub fn getAttributes(ty: Type) []const Attribute { | 727 | pub fn getAttributes(ty: Type) []const Attribute { |
| 749 | return switch (ty.specifier) { | 728 | return switch (ty.specifier) { |
| 750 | .attributed => ty.data.attributed.attributes, | 729 | .attributed => ty.data.attributed.attributes, |
| 751 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.getAttributes(), | 730 | .typeof_type => ty.data.sub_type.getAttributes(), |
| 752 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.getAttributes(), | 731 | .typeof_expr => ty.data.expr.ty.getAttributes(), |
| 753 | else => &.{}, | 732 | else => &.{}, |
| 754 | }; | 733 | }; |
| 755 | } | 734 | } |
| ... | @@ -757,8 +736,8 @@ pub fn getAttributes(ty: Type) []const Attribute { | ... | @@ -757,8 +736,8 @@ pub fn getAttributes(ty: Type) []const Attribute { |
| 757 | pub fn getRecord(ty: Type) ?*const Type.Record { | 736 | pub fn getRecord(ty: Type) ?*const Type.Record { |
| 758 | return switch (ty.specifier) { | 737 | return switch (ty.specifier) { |
| 759 | .attributed => ty.data.attributed.base.getRecord(), | 738 | .attributed => ty.data.attributed.base.getRecord(), |
| 760 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.getRecord(), | 739 | .typeof_type => ty.data.sub_type.getRecord(), |
| 761 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.getRecord(), | 740 | .typeof_expr => ty.data.expr.ty.getRecord(), |
| 762 | .@"struct", .@"union" => ty.data.record, | 741 | .@"struct", .@"union" => ty.data.record, |
| 763 | else => null, | 742 | else => null, |
| 764 | }; | 743 | }; |
| ... | @@ -901,6 +880,7 @@ pub fn bitfieldPromotion(ty: Type, comp: *Compilation, width: u32) ?Type { | ... | @@ -901,6 +880,7 @@ pub fn bitfieldPromotion(ty: Type, comp: *Compilation, width: u32) ?Type { |
| 901 | } | 880 | } |
| 902 | 881 | ||
| 903 | pub fn hasIncompleteSize(ty: Type) bool { | 882 | pub fn hasIncompleteSize(ty: Type) bool { |
| 883 | if (ty.isDecayed()) return false; | ||
| 904 | return switch (ty.specifier) { | 884 | return switch (ty.specifier) { |
| 905 | .void, .incomplete_array => true, | 885 | .void, .incomplete_array => true, |
| 906 | .@"enum" => ty.data.@"enum".isIncomplete() and !ty.data.@"enum".fixed, | 886 | .@"enum" => ty.data.@"enum".isIncomplete() and !ty.data.@"enum".fixed, |
| ... | @@ -917,20 +897,14 @@ pub fn hasUnboundVLA(ty: Type) bool { | ... | @@ -917,20 +897,14 @@ pub fn hasUnboundVLA(ty: Type) bool { |
| 917 | var cur = ty; | 897 | var cur = ty; |
| 918 | while (true) { | 898 | while (true) { |
| 919 | switch (cur.specifier) { | 899 | switch (cur.specifier) { |
| 920 | .unspecified_variable_len_array, | 900 | .unspecified_variable_len_array => return true, |
| 921 | .decayed_unspecified_variable_len_array, | ||
| 922 | => return true, | ||
| 923 | .array, | 901 | .array, |
| 924 | .static_array, | 902 | .static_array, |
| 925 | .incomplete_array, | 903 | .incomplete_array, |
| 926 | .variable_len_array, | 904 | .variable_len_array, |
| 927 | .decayed_array, | ||
| 928 | .decayed_static_array, | ||
| 929 | .decayed_incomplete_array, | ||
| 930 | .decayed_variable_len_array, | ||
| 931 | => cur = cur.elemType(), | 905 | => cur = cur.elemType(), |
| 932 | .typeof_type, .decayed_typeof_type => cur = cur.data.sub_type.*, | 906 | .typeof_type => cur = cur.data.sub_type.*, |
| 933 | .typeof_expr, .decayed_typeof_expr => cur = cur.data.expr.ty, | 907 | .typeof_expr => cur = cur.data.expr.ty, |
| 934 | .attributed => cur = cur.data.attributed.base, | 908 | .attributed => cur = cur.data.attributed.base, |
| 935 | else => return false, | 909 | else => return false, |
| 936 | } | 910 | } |
| ... | @@ -1006,9 +980,11 @@ pub fn sizeCompare(a: Type, b: Type, comp: *Compilation) TypeSizeOrder { | ... | @@ -1006,9 +980,11 @@ pub fn sizeCompare(a: Type, b: Type, comp: *Compilation) TypeSizeOrder { |
| 1006 | 980 | ||
| 1007 | /// Size of type as reported by sizeof | 981 | /// Size of type as reported by sizeof |
| 1008 | pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 { | 982 | pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 { |
| 983 | if (ty.isPtr()) return comp.target.ptrBitWidth() / 8; | ||
| 984 | |||
| 1009 | return switch (ty.specifier) { | 985 | return switch (ty.specifier) { |
| 1010 | .auto_type, .c23_auto => unreachable, | 986 | .auto_type, .c23_auto => unreachable, |
| 1011 | .variable_len_array, .unspecified_variable_len_array => return null, | 987 | .variable_len_array, .unspecified_variable_len_array => null, |
| 1012 | .incomplete_array => return if (comp.langopts.emulate == .msvc) @as(?u64, 0) else null, | 988 | .incomplete_array => return if (comp.langopts.emulate == .msvc) @as(?u64, 0) else null, |
| 1013 | .func, .var_args_func, .old_style_func, .void, .bool => 1, | 989 | .func, .var_args_func, .old_style_func, .void, .bool => 1, |
| 1014 | .char, .schar, .uchar => 1, | 990 | .char, .schar, .uchar => 1, |
| ... | @@ -1037,14 +1013,7 @@ pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 { | ... | @@ -1037,14 +1013,7 @@ pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 { |
| 1037 | .complex_long_double, .complex_float80, .complex_float128, .complex_bit_int, | 1013 | .complex_long_double, .complex_float80, .complex_float128, .complex_bit_int, |
| 1038 | => return 2 * ty.makeReal().sizeof(comp).?, | 1014 | => return 2 * ty.makeReal().sizeof(comp).?, |
| 1039 | // zig fmt: on | 1015 | // zig fmt: on |
| 1040 | .pointer, | 1016 | .pointer => unreachable, |
| 1041 | .decayed_array, | ||
| 1042 | .decayed_static_array, | ||
| 1043 | .decayed_incomplete_array, | ||
| 1044 | .decayed_variable_len_array, | ||
| 1045 | .decayed_unspecified_variable_len_array, | ||
| 1046 | .decayed_typeof_type, | ||
| 1047 | .decayed_typeof_expr, | ||
| 1048 | .static_array, | 1017 | .static_array, |
| 1049 | .nullptr_t, | 1018 | .nullptr_t, |
| 1050 | => comp.target.ptrBitWidth() / 8, | 1019 | => comp.target.ptrBitWidth() / 8, |
| ... | @@ -1073,8 +1042,8 @@ pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 { | ... | @@ -1073,8 +1042,8 @@ pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 { |
| 1073 | pub fn bitSizeof(ty: Type, comp: *const Compilation) ?u64 { | 1042 | pub fn bitSizeof(ty: Type, comp: *const Compilation) ?u64 { |
| 1074 | return switch (ty.specifier) { | 1043 | return switch (ty.specifier) { |
| 1075 | .bool => if (comp.langopts.emulate == .msvc) @as(u64, 8) else 1, | 1044 | .bool => if (comp.langopts.emulate == .msvc) @as(u64, 8) else 1, |
| 1076 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.bitSizeof(comp), | 1045 | .typeof_type => ty.data.sub_type.bitSizeof(comp), |
| 1077 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.bitSizeof(comp), | 1046 | .typeof_expr => ty.data.expr.ty.bitSizeof(comp), |
| 1078 | .attributed => ty.data.attributed.base.bitSizeof(comp), | 1047 | .attributed => ty.data.attributed.base.bitSizeof(comp), |
| 1079 | .bit_int => return ty.data.int.bits, | 1048 | .bit_int => return ty.data.int.bits, |
| 1080 | .long_double => comp.target.c_type_bit_size(.longdouble), | 1049 | .long_double => comp.target.c_type_bit_size(.longdouble), |
| ... | @@ -1117,7 +1086,10 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { | ... | @@ -1117,7 +1086,10 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { |
| 1117 | .unspecified_variable_len_array, | 1086 | .unspecified_variable_len_array, |
| 1118 | .array, | 1087 | .array, |
| 1119 | .vector, | 1088 | .vector, |
| 1120 | => ty.elemType().alignof(comp), | 1089 | => if (ty.isPtr()) switch (comp.target.cpu.arch) { |
| 1090 | .avr => 1, | ||
| 1091 | else => comp.target.ptrBitWidth() / 8, | ||
| 1092 | } else ty.elemType().alignof(comp), | ||
| 1121 | .func, .var_args_func, .old_style_func => target_util.defaultFunctionAlignment(comp.target), | 1093 | .func, .var_args_func, .old_style_func => target_util.defaultFunctionAlignment(comp.target), |
| 1122 | .char, .schar, .uchar, .void, .bool => 1, | 1094 | .char, .schar, .uchar, .void, .bool => 1, |
| 1123 | 1095 | ||
| ... | @@ -1153,11 +1125,6 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { | ... | @@ -1153,11 +1125,6 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { |
| 1153 | 1125 | ||
| 1154 | .float80, .float128 => 16, | 1126 | .float80, .float128 => 16, |
| 1155 | .pointer, | 1127 | .pointer, |
| 1156 | .decayed_array, | ||
| 1157 | .decayed_static_array, | ||
| 1158 | .decayed_incomplete_array, | ||
| 1159 | .decayed_variable_len_array, | ||
| 1160 | .decayed_unspecified_variable_len_array, | ||
| 1161 | .static_array, | 1128 | .static_array, |
| 1162 | .nullptr_t, | 1129 | .nullptr_t, |
| 1163 | => switch (comp.target.cpu.arch) { | 1130 | => switch (comp.target.cpu.arch) { |
| ... | @@ -1166,8 +1133,8 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { | ... | @@ -1166,8 +1133,8 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { |
| 1166 | }, | 1133 | }, |
| 1167 | .@"struct", .@"union" => if (ty.data.record.isIncomplete()) 0 else @intCast(ty.data.record.type_layout.field_alignment_bits / 8), | 1134 | .@"struct", .@"union" => if (ty.data.record.isIncomplete()) 0 else @intCast(ty.data.record.type_layout.field_alignment_bits / 8), |
| 1168 | .@"enum" => if (ty.data.@"enum".isIncomplete() and !ty.data.@"enum".fixed) 0 else ty.data.@"enum".tag_ty.alignof(comp), | 1135 | .@"enum" => if (ty.data.@"enum".isIncomplete() and !ty.data.@"enum".fixed) 0 else ty.data.@"enum".tag_ty.alignof(comp), |
| 1169 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.alignof(comp), | 1136 | .typeof_type => ty.data.sub_type.alignof(comp), |
| 1170 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.alignof(comp), | 1137 | .typeof_expr => ty.data.expr.ty.alignof(comp), |
| 1171 | .attributed => ty.data.attributed.base.alignof(comp), | 1138 | .attributed => ty.data.attributed.base.alignof(comp), |
| 1172 | }; | 1139 | }; |
| 1173 | } | 1140 | } |
| ... | @@ -1179,7 +1146,10 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { | ... | @@ -1179,7 +1146,10 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { |
| 1179 | /// arrays and pointers. | 1146 | /// arrays and pointers. |
| 1180 | pub fn canonicalize(ty: Type, qual_handling: enum { standard, preserve_quals }) Type { | 1147 | pub fn canonicalize(ty: Type, qual_handling: enum { standard, preserve_quals }) Type { |
| 1181 | var cur = ty; | 1148 | var cur = ty; |
| 1182 | if (cur.specifier == .attributed) cur = cur.data.attributed.base; | 1149 | if (cur.specifier == .attributed) { |
| 1150 | cur = cur.data.attributed.base; | ||
| 1151 | cur.decayed = ty.decayed; | ||
| 1152 | } | ||
| 1183 | if (!cur.isTypeof()) return cur; | 1153 | if (!cur.isTypeof()) return cur; |
| 1184 | 1154 | ||
| 1185 | var qual = cur.qual; | 1155 | var qual = cur.qual; |
| ... | @@ -1187,14 +1157,6 @@ pub fn canonicalize(ty: Type, qual_handling: enum { standard, preserve_quals }) | ... | @@ -1187,14 +1157,6 @@ pub fn canonicalize(ty: Type, qual_handling: enum { standard, preserve_quals }) |
| 1187 | switch (cur.specifier) { | 1157 | switch (cur.specifier) { |
| 1188 | .typeof_type => cur = cur.data.sub_type.*, | 1158 | .typeof_type => cur = cur.data.sub_type.*, |
| 1189 | .typeof_expr => cur = cur.data.expr.ty, | 1159 | .typeof_expr => cur = cur.data.expr.ty, |
| 1190 | .decayed_typeof_type => { | ||
| 1191 | cur = cur.data.sub_type.*; | ||
| 1192 | cur.decayArray(); | ||
| 1193 | }, | ||
| 1194 | .decayed_typeof_expr => { | ||
| 1195 | cur = cur.data.expr.ty; | ||
| 1196 | cur.decayArray(); | ||
| 1197 | }, | ||
| 1198 | else => break, | 1160 | else => break, |
| 1199 | } | 1161 | } |
| 1200 | qual = qual.mergeAll(cur.qual); | 1162 | qual = qual.mergeAll(cur.qual); |
| ... | @@ -1204,6 +1166,7 @@ pub fn canonicalize(ty: Type, qual_handling: enum { standard, preserve_quals }) | ... | @@ -1204,6 +1166,7 @@ pub fn canonicalize(ty: Type, qual_handling: enum { standard, preserve_quals }) |
| 1204 | } else { | 1166 | } else { |
| 1205 | cur.qual = qual; | 1167 | cur.qual = qual; |
| 1206 | } | 1168 | } |
| 1169 | cur.decayed = ty.decayed; | ||
| 1207 | return cur; | 1170 | return cur; |
| 1208 | } | 1171 | } |
| 1209 | 1172 | ||
| ... | @@ -1219,8 +1182,8 @@ pub fn get(ty: *const Type, specifier: Specifier) ?*const Type { | ... | @@ -1219,8 +1182,8 @@ pub fn get(ty: *const Type, specifier: Specifier) ?*const Type { |
| 1219 | 1182 | ||
| 1220 | pub fn requestedAlignment(ty: Type, comp: *const Compilation) ?u29 { | 1183 | pub fn requestedAlignment(ty: Type, comp: *const Compilation) ?u29 { |
| 1221 | return switch (ty.specifier) { | 1184 | return switch (ty.specifier) { |
| 1222 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.requestedAlignment(comp), | 1185 | .typeof_type => ty.data.sub_type.requestedAlignment(comp), |
| 1223 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.requestedAlignment(comp), | 1186 | .typeof_expr => ty.data.expr.ty.requestedAlignment(comp), |
| 1224 | .attributed => annotationAlignment(comp, ty.data.attributed.attributes), | 1187 | .attributed => annotationAlignment(comp, ty.data.attributed.attributes), |
| 1225 | else => null, | 1188 | else => null, |
| 1226 | }; | 1189 | }; |
| ... | @@ -1265,14 +1228,11 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi | ... | @@ -1265,14 +1228,11 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi |
| 1265 | if (a.qual.@"volatile" != b.qual.@"volatile") return false; | 1228 | if (a.qual.@"volatile" != b.qual.@"volatile") return false; |
| 1266 | } | 1229 | } |
| 1267 | 1230 | ||
| 1231 | if (a.isPtr()) { | ||
| 1232 | return a_param.elemType().eql(b_param.elemType(), comp, check_qualifiers); | ||
| 1233 | } | ||
| 1268 | switch (a.specifier) { | 1234 | switch (a.specifier) { |
| 1269 | .pointer, | 1235 | .pointer => unreachable, |
| 1270 | .decayed_array, | ||
| 1271 | .decayed_static_array, | ||
| 1272 | .decayed_incomplete_array, | ||
| 1273 | .decayed_variable_len_array, | ||
| 1274 | .decayed_unspecified_variable_len_array, | ||
| 1275 | => if (!a_param.elemType().eql(b_param.elemType(), comp, check_qualifiers)) return false, | ||
| 1276 | 1236 | ||
| 1277 | .func, | 1237 | .func, |
| 1278 | .var_args_func, | 1238 | .var_args_func, |
| ... | @@ -1293,8 +1253,9 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi | ... | @@ -1293,8 +1253,9 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi |
| 1293 | } | 1253 | } |
| 1294 | if (!a.elemType().eql(b.elemType(), comp, false)) return false; | 1254 | if (!a.elemType().eql(b.elemType(), comp, false)) return false; |
| 1295 | }, | 1255 | }, |
| 1296 | .variable_len_array => if (!a.elemType().eql(b.elemType(), comp, check_qualifiers)) return false, | 1256 | .variable_len_array => { |
| 1297 | 1257 | if (!a.elemType().eql(b.elemType(), comp, check_qualifiers)) return false; | |
| 1258 | }, | ||
| 1298 | .@"struct", .@"union" => if (a.data.record != b.data.record) return false, | 1259 | .@"struct", .@"union" => if (a.data.record != b.data.record) return false, |
| 1299 | .@"enum" => if (a.data.@"enum" != b.data.@"enum") return false, | 1260 | .@"enum" => if (a.data.@"enum" != b.data.@"enum") return false, |
| 1300 | .bit_int, .complex_bit_int => return a.data.int.bits == b.data.int.bits and a.data.int.signedness == b.data.int.signedness, | 1261 | .bit_int, .complex_bit_int => return a.data.int.bits == b.data.int.bits and a.data.int.signedness == b.data.int.signedness, |
| ... | @@ -1306,14 +1267,14 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi | ... | @@ -1306,14 +1267,14 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi |
| 1306 | 1267 | ||
| 1307 | /// Decays an array to a pointer | 1268 | /// Decays an array to a pointer |
| 1308 | pub fn decayArray(ty: *Type) void { | 1269 | pub fn decayArray(ty: *Type) void { |
| 1309 | // the decayed array type is the current specifier +1 | 1270 | std.debug.assert(ty.isArray()); |
| 1310 | ty.specifier = @enumFromInt(@intFromEnum(ty.specifier) + 1); | 1271 | ty.decayed = true; |
| 1311 | } | 1272 | } |
| 1312 | 1273 | ||
| 1313 | pub fn originalTypeOfDecayedArray(ty: Type) Type { | 1274 | pub fn originalTypeOfDecayedArray(ty: Type) Type { |
| 1314 | std.debug.assert(ty.isDecayed()); | 1275 | std.debug.assert(ty.isDecayed()); |
| 1315 | var copy = ty; | 1276 | var copy = ty; |
| 1316 | copy.specifier = @enumFromInt(@intFromEnum(ty.specifier) - 1); | 1277 | copy.decayed = false; |
| 1317 | return copy; | 1278 | return copy; |
| 1318 | } | 1279 | } |
| 1319 | 1280 | ||
| ... | @@ -1405,25 +1366,23 @@ pub fn combine(inner: *Type, outer: Type) Parser.Error!void { | ... | @@ -1405,25 +1366,23 @@ pub fn combine(inner: *Type, outer: Type) Parser.Error!void { |
| 1405 | switch (inner.specifier) { | 1366 | switch (inner.specifier) { |
| 1406 | .pointer => return inner.data.sub_type.combine(outer), | 1367 | .pointer => return inner.data.sub_type.combine(outer), |
| 1407 | .unspecified_variable_len_array => { | 1368 | .unspecified_variable_len_array => { |
| 1369 | std.debug.assert(!inner.isDecayed()); | ||
| 1408 | try inner.data.sub_type.combine(outer); | 1370 | try inner.data.sub_type.combine(outer); |
| 1409 | }, | 1371 | }, |
| 1410 | .variable_len_array => { | 1372 | .variable_len_array => { |
| 1373 | std.debug.assert(!inner.isDecayed()); | ||
| 1411 | try inner.data.expr.ty.combine(outer); | 1374 | try inner.data.expr.ty.combine(outer); |
| 1412 | }, | 1375 | }, |
| 1413 | .array, .static_array, .incomplete_array => { | 1376 | .array, .static_array, .incomplete_array => { |
| 1377 | std.debug.assert(!inner.isDecayed()); | ||
| 1414 | try inner.data.array.elem.combine(outer); | 1378 | try inner.data.array.elem.combine(outer); |
| 1415 | }, | 1379 | }, |
| 1416 | .func, .var_args_func, .old_style_func => { | 1380 | .func, .var_args_func, .old_style_func => { |
| 1417 | try inner.data.func.return_type.combine(outer); | 1381 | try inner.data.func.return_type.combine(outer); |
| 1418 | }, | 1382 | }, |
| 1419 | .decayed_array, | 1383 | .typeof_type, |
| 1420 | .decayed_static_array, | 1384 | .typeof_expr, |
| 1421 | .decayed_incomplete_array, | 1385 | => std.debug.assert(!inner.isDecayed()), |
| 1422 | .decayed_variable_len_array, | ||
| 1423 | .decayed_unspecified_variable_len_array, | ||
| 1424 | .decayed_typeof_type, | ||
| 1425 | .decayed_typeof_expr, | ||
| 1426 | => unreachable, // type should not be able to decay before being combined | ||
| 1427 | .void, .invalid => inner.* = outer, | 1386 | .void, .invalid => inner.* = outer, |
| 1428 | else => unreachable, | 1387 | else => unreachable, |
| 1429 | } | 1388 | } |
| ... | @@ -1474,8 +1433,8 @@ pub fn validateCombinedType(ty: Type, p: *Parser, source_tok: TokenIndex) Parser | ... | @@ -1474,8 +1433,8 @@ pub fn validateCombinedType(ty: Type, p: *Parser, source_tok: TokenIndex) Parser |
| 1474 | try p.errStr(.suggest_pointer_for_invalid_fp16, source_tok, "function return value"); | 1433 | try p.errStr(.suggest_pointer_for_invalid_fp16, source_tok, "function return value"); |
| 1475 | } | 1434 | } |
| 1476 | }, | 1435 | }, |
| 1477 | .typeof_type, .decayed_typeof_type => return ty.data.sub_type.validateCombinedType(p, source_tok), | 1436 | .typeof_type => return ty.data.sub_type.validateCombinedType(p, source_tok), |
| 1478 | .typeof_expr, .decayed_typeof_expr => return ty.data.expr.ty.validateCombinedType(p, source_tok), | 1437 | .typeof_expr => return ty.data.expr.ty.validateCombinedType(p, source_tok), |
| 1479 | .attributed => return ty.data.attributed.base.validateCombinedType(p, source_tok), | 1438 | .attributed => return ty.data.attributed.base.validateCombinedType(p, source_tok), |
| 1480 | else => {}, | 1439 | else => {}, |
| 1481 | } | 1440 | } |
| ... | @@ -1610,6 +1569,7 @@ pub const Builder = struct { | ... | @@ -1610,6 +1569,7 @@ pub const Builder = struct { |
| 1610 | decayed_typeof_expr: *Expr, | 1569 | decayed_typeof_expr: *Expr, |
| 1611 | 1570 | ||
| 1612 | attributed: *Attributed, | 1571 | attributed: *Attributed, |
| 1572 | decayed_attributed: *Attributed, | ||
| 1613 | 1573 | ||
| 1614 | pub fn str(spec: Builder.Specifier, langopts: LangOpts) ?[]const u8 { | 1574 | pub fn str(spec: Builder.Specifier, langopts: LangOpts) ?[]const u8 { |
| 1615 | return switch (spec) { | 1575 | return switch (spec) { |
| ... | @@ -1835,13 +1795,10 @@ pub const Builder = struct { | ... | @@ -1835,13 +1795,10 @@ pub const Builder = struct { |
| 1835 | ty.specifier = .pointer; | 1795 | ty.specifier = .pointer; |
| 1836 | ty.data = .{ .sub_type = data }; | 1796 | ty.data = .{ .sub_type = data }; |
| 1837 | }, | 1797 | }, |
| 1838 | .unspecified_variable_len_array => |data| { | 1798 | .unspecified_variable_len_array, .decayed_unspecified_variable_len_array => |data| { |
| 1839 | ty.specifier = .unspecified_variable_len_array; | 1799 | ty.specifier = .unspecified_variable_len_array; |
| 1840 | ty.data = .{ .sub_type = data }; | 1800 | ty.data = .{ .sub_type = data }; |
| 1841 | }, | 1801 | ty.decayed = b.specifier == .decayed_unspecified_variable_len_array; |
| 1842 | .decayed_unspecified_variable_len_array => |data| { | ||
| 1843 | ty.specifier = .decayed_unspecified_variable_len_array; | ||
| 1844 | ty.data = .{ .sub_type = data }; | ||
| 1845 | }, | 1802 | }, |
| 1846 | .func => |data| { | 1803 | .func => |data| { |
| 1847 | ty.specifier = .func; | 1804 | ty.specifier = .func; |
| ... | @@ -1855,41 +1812,29 @@ pub const Builder = struct { | ... | @@ -1855,41 +1812,29 @@ pub const Builder = struct { |
| 1855 | ty.specifier = .old_style_func; | 1812 | ty.specifier = .old_style_func; |
| 1856 | ty.data = .{ .func = data }; | 1813 | ty.data = .{ .func = data }; |
| 1857 | }, | 1814 | }, |
| 1858 | .array => |data| { | 1815 | .array, .decayed_array => |data| { |
| 1859 | ty.specifier = .array; | 1816 | ty.specifier = .array; |
| 1860 | ty.data = .{ .array = data }; | 1817 | ty.data = .{ .array = data }; |
| 1818 | ty.decayed = b.specifier == .decayed_array; | ||
| 1861 | }, | 1819 | }, |
| 1862 | .decayed_array => |data| { | 1820 | .static_array, .decayed_static_array => |data| { |
| 1863 | ty.specifier = .decayed_array; | ||
| 1864 | ty.data = .{ .array = data }; | ||
| 1865 | }, | ||
| 1866 | .static_array => |data| { | ||
| 1867 | ty.specifier = .static_array; | 1821 | ty.specifier = .static_array; |
| 1868 | ty.data = .{ .array = data }; | 1822 | ty.data = .{ .array = data }; |
| 1823 | ty.decayed = b.specifier == .decayed_static_array; | ||
| 1869 | }, | 1824 | }, |
| 1870 | .decayed_static_array => |data| { | 1825 | .incomplete_array, .decayed_incomplete_array => |data| { |
| 1871 | ty.specifier = .decayed_static_array; | ||
| 1872 | ty.data = .{ .array = data }; | ||
| 1873 | }, | ||
| 1874 | .incomplete_array => |data| { | ||
| 1875 | ty.specifier = .incomplete_array; | 1826 | ty.specifier = .incomplete_array; |
| 1876 | ty.data = .{ .array = data }; | 1827 | ty.data = .{ .array = data }; |
| 1877 | }, | 1828 | ty.decayed = b.specifier == .decayed_incomplete_array; |
| 1878 | .decayed_incomplete_array => |data| { | ||
| 1879 | ty.specifier = .decayed_incomplete_array; | ||
| 1880 | ty.data = .{ .array = data }; | ||
| 1881 | }, | 1829 | }, |
| 1882 | .vector => |data| { | 1830 | .vector => |data| { |
| 1883 | ty.specifier = .vector; | 1831 | ty.specifier = .vector; |
| 1884 | ty.data = .{ .array = data }; | 1832 | ty.data = .{ .array = data }; |
| 1885 | }, | 1833 | }, |
| 1886 | .variable_len_array => |data| { | 1834 | .variable_len_array, .decayed_variable_len_array => |data| { |
| 1887 | ty.specifier = .variable_len_array; | 1835 | ty.specifier = .variable_len_array; |
| 1888 | ty.data = .{ .expr = data }; | 1836 | ty.data = .{ .expr = data }; |
| 1889 | }, | 1837 | ty.decayed = b.specifier == .decayed_variable_len_array; |
| 1890 | .decayed_variable_len_array => |data| { | ||
| 1891 | ty.specifier = .decayed_variable_len_array; | ||
| 1892 | ty.data = .{ .expr = data }; | ||
| 1893 | }, | 1838 | }, |
| 1894 | .@"struct" => |data| { | 1839 | .@"struct" => |data| { |
| 1895 | ty.specifier = .@"struct"; | 1840 | ty.specifier = .@"struct"; |
| ... | @@ -1903,25 +1848,20 @@ pub const Builder = struct { | ... | @@ -1903,25 +1848,20 @@ pub const Builder = struct { |
| 1903 | ty.specifier = .@"enum"; | 1848 | ty.specifier = .@"enum"; |
| 1904 | ty.data = .{ .@"enum" = data }; | 1849 | ty.data = .{ .@"enum" = data }; |
| 1905 | }, | 1850 | }, |
| 1906 | .typeof_type => |data| { | 1851 | .typeof_type, .decayed_typeof_type => |data| { |
| 1907 | ty.specifier = .typeof_type; | 1852 | ty.specifier = .typeof_type; |
| 1908 | ty.data = .{ .sub_type = data }; | 1853 | ty.data = .{ .sub_type = data }; |
| 1854 | ty.decayed = b.specifier == .decayed_typeof_type; | ||
| 1909 | }, | 1855 | }, |
| 1910 | .decayed_typeof_type => |data| { | 1856 | .typeof_expr, .decayed_typeof_expr => |data| { |
| 1911 | ty.specifier = .decayed_typeof_type; | ||
| 1912 | ty.data = .{ .sub_type = data }; | ||
| 1913 | }, | ||
| 1914 | .typeof_expr => |data| { | ||
| 1915 | ty.specifier = .typeof_expr; | 1857 | ty.specifier = .typeof_expr; |
| 1916 | ty.data = .{ .expr = data }; | 1858 | ty.data = .{ .expr = data }; |
| 1859 | ty.decayed = b.specifier == .decayed_typeof_expr; | ||
| 1917 | }, | 1860 | }, |
| 1918 | .decayed_typeof_expr => |data| { | 1861 | .attributed, .decayed_attributed => |data| { |
| 1919 | ty.specifier = .decayed_typeof_expr; | ||
| 1920 | ty.data = .{ .expr = data }; | ||
| 1921 | }, | ||
| 1922 | .attributed => |data| { | ||
| 1923 | ty.specifier = .attributed; | 1862 | ty.specifier = .attributed; |
| 1924 | ty.data = .{ .attributed = data }; | 1863 | ty.data = .{ .attributed = data }; |
| 1864 | ty.decayed = b.specifier == .decayed_attributed; | ||
| 1925 | }, | 1865 | }, |
| 1926 | } | 1866 | } |
| 1927 | if (!ty.isReal() and ty.isInt()) { | 1867 | if (!ty.isReal() and ty.isInt()) { |
| ... | @@ -2359,30 +2299,47 @@ pub const Builder = struct { | ... | @@ -2359,30 +2299,47 @@ pub const Builder = struct { |
| 2359 | .complex_float128 => .complex_float128, | 2299 | .complex_float128 => .complex_float128, |
| 2360 | 2300 | ||
| 2361 | .pointer => .{ .pointer = ty.data.sub_type }, | 2301 | .pointer => .{ .pointer = ty.data.sub_type }, |
| 2362 | .unspecified_variable_len_array => .{ .unspecified_variable_len_array = ty.data.sub_type }, | 2302 | .unspecified_variable_len_array => if (ty.isDecayed()) |
| 2363 | .decayed_unspecified_variable_len_array => .{ .decayed_unspecified_variable_len_array = ty.data.sub_type }, | 2303 | .{ .decayed_unspecified_variable_len_array = ty.data.sub_type } |
| 2304 | else | ||
| 2305 | .{ .unspecified_variable_len_array = ty.data.sub_type }, | ||
| 2364 | .func => .{ .func = ty.data.func }, | 2306 | .func => .{ .func = ty.data.func }, |
| 2365 | .var_args_func => .{ .var_args_func = ty.data.func }, | 2307 | .var_args_func => .{ .var_args_func = ty.data.func }, |
| 2366 | .old_style_func => .{ .old_style_func = ty.data.func }, | 2308 | .old_style_func => .{ .old_style_func = ty.data.func }, |
| 2367 | .array => .{ .array = ty.data.array }, | 2309 | .array => if (ty.isDecayed()) |
| 2368 | .decayed_array => .{ .decayed_array = ty.data.array }, | 2310 | .{ .decayed_array = ty.data.array } |
| 2369 | .static_array => .{ .static_array = ty.data.array }, | 2311 | else |
| 2370 | .decayed_static_array => .{ .decayed_static_array = ty.data.array }, | 2312 | .{ .array = ty.data.array }, |
| 2371 | .incomplete_array => .{ .incomplete_array = ty.data.array }, | 2313 | .static_array => if (ty.isDecayed()) |
| 2372 | .decayed_incomplete_array => .{ .decayed_incomplete_array = ty.data.array }, | 2314 | .{ .decayed_static_array = ty.data.array } |
| 2315 | else | ||
| 2316 | .{ .static_array = ty.data.array }, | ||
| 2317 | .incomplete_array => if (ty.isDecayed()) | ||
| 2318 | .{ .decayed_incomplete_array = ty.data.array } | ||
| 2319 | else | ||
| 2320 | .{ .incomplete_array = ty.data.array }, | ||
| 2373 | .vector => .{ .vector = ty.data.array }, | 2321 | .vector => .{ .vector = ty.data.array }, |
| 2374 | .variable_len_array => .{ .variable_len_array = ty.data.expr }, | 2322 | .variable_len_array => if (ty.isDecayed()) |
| 2375 | .decayed_variable_len_array => .{ .decayed_variable_len_array = ty.data.expr }, | 2323 | .{ .decayed_variable_len_array = ty.data.expr } |
| 2324 | else | ||
| 2325 | .{ .variable_len_array = ty.data.expr }, | ||
| 2376 | .@"struct" => .{ .@"struct" = ty.data.record }, | 2326 | .@"struct" => .{ .@"struct" = ty.data.record }, |
| 2377 | .@"union" => .{ .@"union" = ty.data.record }, | 2327 | .@"union" => .{ .@"union" = ty.data.record }, |
| 2378 | .@"enum" => .{ .@"enum" = ty.data.@"enum" }, | 2328 | .@"enum" => .{ .@"enum" = ty.data.@"enum" }, |
| 2379 | 2329 | ||
| 2380 | .typeof_type => .{ .typeof_type = ty.data.sub_type }, | 2330 | .typeof_type => if (ty.isDecayed()) |
| 2381 | .decayed_typeof_type => .{ .decayed_typeof_type = ty.data.sub_type }, | 2331 | .{ .decayed_typeof_type = ty.data.sub_type } |
| 2382 | .typeof_expr => .{ .typeof_expr = ty.data.expr }, | 2332 | else |
| 2383 | .decayed_typeof_expr => .{ .decayed_typeof_expr = ty.data.expr }, | 2333 | .{ .typeof_type = ty.data.sub_type }, |
| 2334 | .typeof_expr => if (ty.isDecayed()) | ||
| 2335 | .{ .decayed_typeof_expr = ty.data.expr } | ||
| 2336 | else | ||
| 2337 | .{ .typeof_expr = ty.data.expr }, | ||
| 2384 | 2338 | ||
| 2385 | .attributed => .{ .attributed = ty.data.attributed }, | 2339 | .attributed => if (ty.isDecayed()) |
| 2340 | .{ .decayed_attributed = ty.data.attributed } | ||
| 2341 | else | ||
| 2342 | .{ .attributed = ty.data.attributed }, | ||
| 2386 | else => unreachable, | 2343 | else => unreachable, |
| 2387 | }; | 2344 | }; |
| 2388 | } | 2345 | } |
| ... | @@ -2472,24 +2429,17 @@ fn printPrologue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts | ... | @@ -2472,24 +2429,17 @@ fn printPrologue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts |
| 2472 | try w.writeAll(")"); | 2429 | try w.writeAll(")"); |
| 2473 | return true; | 2430 | return true; |
| 2474 | } | 2431 | } |
| 2432 | if (ty.isPtr()) { | ||
| 2433 | const elem_ty = ty.elemType(); | ||
| 2434 | const simple = try elem_ty.printPrologue(mapper, langopts, w); | ||
| 2435 | if (simple) try w.writeByte(' '); | ||
| 2436 | if (elem_ty.isFunc() or elem_ty.isArray()) try w.writeByte('('); | ||
| 2437 | try w.writeByte('*'); | ||
| 2438 | try ty.qual.dump(w); | ||
| 2439 | return false; | ||
| 2440 | } | ||
| 2475 | switch (ty.specifier) { | 2441 | switch (ty.specifier) { |
| 2476 | .pointer, | 2442 | .pointer => unreachable, |
| 2477 | .decayed_array, | ||
| 2478 | .decayed_static_array, | ||
| 2479 | .decayed_incomplete_array, | ||
| 2480 | .decayed_variable_len_array, | ||
| 2481 | .decayed_unspecified_variable_len_array, | ||
| 2482 | .decayed_typeof_type, | ||
| 2483 | .decayed_typeof_expr, | ||
| 2484 | => { | ||
| 2485 | const elem_ty = ty.elemType(); | ||
| 2486 | const simple = try elem_ty.printPrologue(mapper, langopts, w); | ||
| 2487 | if (simple) try w.writeByte(' '); | ||
| 2488 | if (elem_ty.isFunc() or elem_ty.isArray()) try w.writeByte('('); | ||
| 2489 | try w.writeByte('*'); | ||
| 2490 | try ty.qual.dump(w); | ||
| 2491 | return false; | ||
| 2492 | }, | ||
| 2493 | .func, .var_args_func, .old_style_func => { | 2443 | .func, .var_args_func, .old_style_func => { |
| 2494 | const ret_ty = ty.data.func.return_type; | 2444 | const ret_ty = ty.data.func.return_type; |
| 2495 | const simple = try ret_ty.printPrologue(mapper, langopts, w); | 2445 | const simple = try ret_ty.printPrologue(mapper, langopts, w); |
| ... | @@ -2541,20 +2491,14 @@ fn printPrologue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts | ... | @@ -2541,20 +2491,14 @@ fn printPrologue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts |
| 2541 | 2491 | ||
| 2542 | fn printEpilogue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { | 2492 | fn printEpilogue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { |
| 2543 | if (ty.qual.atomic) return; | 2493 | if (ty.qual.atomic) return; |
| 2494 | if (ty.isPtr()) { | ||
| 2495 | const elem_ty = ty.elemType(); | ||
| 2496 | if (elem_ty.isFunc() or elem_ty.isArray()) try w.writeByte(')'); | ||
| 2497 | try elem_ty.printEpilogue(mapper, langopts, w); | ||
| 2498 | return; | ||
| 2499 | } | ||
| 2544 | switch (ty.specifier) { | 2500 | switch (ty.specifier) { |
| 2545 | .pointer, | 2501 | .pointer => unreachable, // handled above |
| 2546 | .decayed_array, | ||
| 2547 | .decayed_static_array, | ||
| 2548 | .decayed_incomplete_array, | ||
| 2549 | .decayed_variable_len_array, | ||
| 2550 | .decayed_unspecified_variable_len_array, | ||
| 2551 | .decayed_typeof_type, | ||
| 2552 | .decayed_typeof_expr, | ||
| 2553 | => { | ||
| 2554 | const elem_ty = ty.elemType(); | ||
| 2555 | if (elem_ty.isFunc() or elem_ty.isArray()) try w.writeByte(')'); | ||
| 2556 | try elem_ty.printEpilogue(mapper, langopts, w); | ||
| 2557 | }, | ||
| 2558 | .func, .var_args_func, .old_style_func => { | 2502 | .func, .var_args_func, .old_style_func => { |
| 2559 | try w.writeByte('('); | 2503 | try w.writeByte('('); |
| 2560 | for (ty.data.func.params, 0..) |param, i| { | 2504 | for (ty.data.func.params, 0..) |param, i| { |
| ... | @@ -2637,10 +2581,10 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: | ... | @@ -2637,10 +2581,10 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: |
| 2637 | try w.writeAll(") "); | 2581 | try w.writeAll(") "); |
| 2638 | try ty.data.func.return_type.dump(mapper, langopts, w); | 2582 | try ty.data.func.return_type.dump(mapper, langopts, w); |
| 2639 | }, | 2583 | }, |
| 2640 | .array, .static_array, .decayed_array, .decayed_static_array => { | 2584 | .array, .static_array => { |
| 2641 | if (ty.specifier == .decayed_array or ty.specifier == .decayed_static_array) try w.writeAll("*d"); | 2585 | if (ty.isDecayed()) try w.writeAll("*d"); |
| 2642 | try w.writeByte('['); | 2586 | try w.writeByte('['); |
| 2643 | if (ty.specifier == .static_array or ty.specifier == .decayed_static_array) try w.writeAll("static "); | 2587 | if (ty.specifier == .static_array) try w.writeAll("static "); |
| 2644 | try w.print("{d}]", .{ty.data.array.len}); | 2588 | try w.print("{d}]", .{ty.data.array.len}); |
| 2645 | try ty.data.array.elem.dump(mapper, langopts, w); | 2589 | try ty.data.array.elem.dump(mapper, langopts, w); |
| 2646 | }, | 2590 | }, |
| ... | @@ -2649,8 +2593,8 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: | ... | @@ -2649,8 +2593,8 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: |
| 2649 | try ty.data.array.elem.dump(mapper, langopts, w); | 2593 | try ty.data.array.elem.dump(mapper, langopts, w); |
| 2650 | try w.writeAll(")"); | 2594 | try w.writeAll(")"); |
| 2651 | }, | 2595 | }, |
| 2652 | .incomplete_array, .decayed_incomplete_array => { | 2596 | .incomplete_array => { |
| 2653 | if (ty.specifier == .decayed_incomplete_array) try w.writeAll("*d"); | 2597 | if (ty.isDecayed()) try w.writeAll("*d"); |
| 2654 | try w.writeAll("[]"); | 2598 | try w.writeAll("[]"); |
| 2655 | try ty.data.array.elem.dump(mapper, langopts, w); | 2599 | try ty.data.array.elem.dump(mapper, langopts, w); |
| 2656 | }, | 2600 | }, |
| ... | @@ -2672,27 +2616,28 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: | ... | @@ -2672,27 +2616,28 @@ pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: |
| 2672 | try w.print("union {s}", .{mapper.lookup(ty.data.record.name)}); | 2616 | try w.print("union {s}", .{mapper.lookup(ty.data.record.name)}); |
| 2673 | if (dump_detailed_containers) try dumpRecord(ty.data.record, mapper, langopts, w); | 2617 | if (dump_detailed_containers) try dumpRecord(ty.data.record, mapper, langopts, w); |
| 2674 | }, | 2618 | }, |
| 2675 | .unspecified_variable_len_array, .decayed_unspecified_variable_len_array => { | 2619 | .unspecified_variable_len_array => { |
| 2676 | if (ty.specifier == .decayed_unspecified_variable_len_array) try w.writeAll("*d"); | 2620 | if (ty.isDecayed()) try w.writeAll("*d"); |
| 2677 | try w.writeAll("[*]"); | 2621 | try w.writeAll("[*]"); |
| 2678 | try ty.data.sub_type.dump(mapper, langopts, w); | 2622 | try ty.data.sub_type.dump(mapper, langopts, w); |
| 2679 | }, | 2623 | }, |
| 2680 | .variable_len_array, .decayed_variable_len_array => { | 2624 | .variable_len_array => { |
| 2681 | if (ty.specifier == .decayed_variable_len_array) try w.writeAll("*d"); | 2625 | if (ty.isDecayed()) try w.writeAll("*d"); |
| 2682 | try w.writeAll("[<expr>]"); | 2626 | try w.writeAll("[<expr>]"); |
| 2683 | try ty.data.expr.ty.dump(mapper, langopts, w); | 2627 | try ty.data.expr.ty.dump(mapper, langopts, w); |
| 2684 | }, | 2628 | }, |
| 2685 | .typeof_type, .decayed_typeof_type => { | 2629 | .typeof_type => { |
| 2686 | try w.writeAll("typeof("); | 2630 | try w.writeAll("typeof("); |
| 2687 | try ty.data.sub_type.dump(mapper, langopts, w); | 2631 | try ty.data.sub_type.dump(mapper, langopts, w); |
| 2688 | try w.writeAll(")"); | 2632 | try w.writeAll(")"); |
| 2689 | }, | 2633 | }, |
| 2690 | .typeof_expr, .decayed_typeof_expr => { | 2634 | .typeof_expr => { |
| 2691 | try w.writeAll("typeof(<expr>: "); | 2635 | try w.writeAll("typeof(<expr>: "); |
| 2692 | try ty.data.expr.ty.dump(mapper, langopts, w); | 2636 | try ty.data.expr.ty.dump(mapper, langopts, w); |
| 2693 | try w.writeAll(")"); | 2637 | try w.writeAll(")"); |
| 2694 | }, | 2638 | }, |
| 2695 | .attributed => { | 2639 | .attributed => { |
| 2640 | if (ty.isDecayed()) try w.writeAll("*d:"); | ||
| 2696 | try w.writeAll("attributed("); | 2641 | try w.writeAll("attributed("); |
| 2697 | try ty.data.attributed.base.dump(mapper, langopts, w); | 2642 | try ty.data.attributed.base.dump(mapper, langopts, w); |
| 2698 | try w.writeAll(")"); | 2643 | try w.writeAll(")"); |
deps/aro/aro/Value.zig+1-1| ... | @@ -215,7 +215,7 @@ pub fn intCast(v: *Value, dest_ty: Type, comp: *Compilation) !void { | ... | @@ -215,7 +215,7 @@ pub fn intCast(v: *Value, dest_ty: Type, comp: *Compilation) !void { |
| 215 | 215 | ||
| 216 | const limbs = try comp.gpa.alloc( | 216 | const limbs = try comp.gpa.alloc( |
| 217 | std.math.big.Limb, | 217 | std.math.big.Limb, |
| 218 | std.math.big.int.calcTwosCompLimbCount(bits), | 218 | std.math.big.int.calcTwosCompLimbCount(@max(big.bitCountTwosComp(), bits)), |
| 219 | ); | 219 | ); |
| 220 | defer comp.gpa.free(limbs); | 220 | defer comp.gpa.free(limbs); |
| 221 | var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined }; | 221 | var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
deps/aro/aro/number_affixes.zig deleted-169| ... | @@ -1,169 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const mem = std.mem; | ||
| 3 | |||
| 4 | pub const Prefix = enum(u8) { | ||
| 5 | binary = 2, | ||
| 6 | octal = 8, | ||
| 7 | decimal = 10, | ||
| 8 | hex = 16, | ||
| 9 | |||
| 10 | pub fn digitAllowed(prefix: Prefix, c: u8) bool { | ||
| 11 | return switch (c) { | ||
| 12 | '0', '1' => true, | ||
| 13 | '2'...'7' => prefix != .binary, | ||
| 14 | '8'...'9' => prefix == .decimal or prefix == .hex, | ||
| 15 | 'a'...'f', 'A'...'F' => prefix == .hex, | ||
| 16 | else => false, | ||
| 17 | }; | ||
| 18 | } | ||
| 19 | |||
| 20 | pub fn fromString(buf: []const u8) Prefix { | ||
| 21 | if (buf.len == 1) return .decimal; | ||
| 22 | // tokenizer enforces that first byte is a decimal digit or period | ||
| 23 | switch (buf[0]) { | ||
| 24 | '.', '1'...'9' => return .decimal, | ||
| 25 | '0' => {}, | ||
| 26 | else => unreachable, | ||
| 27 | } | ||
| 28 | switch (buf[1]) { | ||
| 29 | 'x', 'X' => return if (buf.len == 2) .decimal else .hex, | ||
| 30 | 'b', 'B' => return if (buf.len == 2) .decimal else .binary, | ||
| 31 | else => { | ||
| 32 | if (mem.indexOfAny(u8, buf, "eE.")) |_| { | ||
| 33 | // This is a decimal floating point number that happens to start with zero | ||
| 34 | return .decimal; | ||
| 35 | } else if (Suffix.fromString(buf[1..], .int)) |_| { | ||
| 36 | // This is `0` with a valid suffix | ||
| 37 | return .decimal; | ||
| 38 | } else { | ||
| 39 | return .octal; | ||
| 40 | } | ||
| 41 | }, | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | /// Length of this prefix as a string | ||
| 46 | pub fn stringLen(prefix: Prefix) usize { | ||
| 47 | return switch (prefix) { | ||
| 48 | .binary => 2, | ||
| 49 | .octal => 1, | ||
| 50 | .decimal => 0, | ||
| 51 | .hex => 2, | ||
| 52 | }; | ||
| 53 | } | ||
| 54 | }; | ||
| 55 | |||
| 56 | pub const Suffix = enum { | ||
| 57 | // zig fmt: off | ||
| 58 | |||
| 59 | // int and imaginary int | ||
| 60 | None, I, | ||
| 61 | |||
| 62 | // unsigned real integers | ||
| 63 | U, UL, ULL, | ||
| 64 | |||
| 65 | // unsigned imaginary integers | ||
| 66 | IU, IUL, IULL, | ||
| 67 | |||
| 68 | // long or long double, real and imaginary | ||
| 69 | L, IL, | ||
| 70 | |||
| 71 | // long long and imaginary long long | ||
| 72 | LL, ILL, | ||
| 73 | |||
| 74 | // float and imaginary float | ||
| 75 | F, IF, | ||
| 76 | |||
| 77 | // _Float16 | ||
| 78 | F16, | ||
| 79 | |||
| 80 | // Imaginary _Bitint | ||
| 81 | IWB, IUWB, | ||
| 82 | |||
| 83 | // _Bitint | ||
| 84 | WB, UWB, | ||
| 85 | |||
| 86 | // zig fmt: on | ||
| 87 | |||
| 88 | const Tuple = struct { Suffix, []const []const u8 }; | ||
| 89 | |||
| 90 | const IntSuffixes = &[_]Tuple{ | ||
| 91 | .{ .U, &.{"U"} }, | ||
| 92 | .{ .L, &.{"L"} }, | ||
| 93 | .{ .WB, &.{"WB"} }, | ||
| 94 | .{ .UL, &.{ "U", "L" } }, | ||
| 95 | .{ .UWB, &.{ "U", "WB" } }, | ||
| 96 | .{ .LL, &.{"LL"} }, | ||
| 97 | .{ .ULL, &.{ "U", "LL" } }, | ||
| 98 | |||
| 99 | .{ .I, &.{"I"} }, | ||
| 100 | |||
| 101 | .{ .IWB, &.{ "I", "WB" } }, | ||
| 102 | .{ .IU, &.{ "I", "U" } }, | ||
| 103 | .{ .IL, &.{ "I", "L" } }, | ||
| 104 | .{ .IUL, &.{ "I", "U", "L" } }, | ||
| 105 | .{ .IUWB, &.{ "I", "U", "WB" } }, | ||
| 106 | .{ .ILL, &.{ "I", "LL" } }, | ||
| 107 | .{ .IULL, &.{ "I", "U", "LL" } }, | ||
| 108 | }; | ||
| 109 | |||
| 110 | const FloatSuffixes = &[_]Tuple{ | ||
| 111 | .{ .F16, &.{"F16"} }, | ||
| 112 | .{ .F, &.{"F"} }, | ||
| 113 | .{ .L, &.{"L"} }, | ||
| 114 | |||
| 115 | .{ .I, &.{"I"} }, | ||
| 116 | .{ .IL, &.{ "I", "L" } }, | ||
| 117 | .{ .IF, &.{ "I", "F" } }, | ||
| 118 | }; | ||
| 119 | |||
| 120 | pub fn fromString(buf: []const u8, suffix_kind: enum { int, float }) ?Suffix { | ||
| 121 | if (buf.len == 0) return .None; | ||
| 122 | |||
| 123 | const suffixes = switch (suffix_kind) { | ||
| 124 | .float => FloatSuffixes, | ||
| 125 | .int => IntSuffixes, | ||
| 126 | }; | ||
| 127 | var scratch: [3]u8 = undefined; | ||
| 128 | top: for (suffixes) |candidate| { | ||
| 129 | const tag = candidate[0]; | ||
| 130 | const parts = candidate[1]; | ||
| 131 | var len: usize = 0; | ||
| 132 | for (parts) |part| len += part.len; | ||
| 133 | if (len != buf.len) continue; | ||
| 134 | |||
| 135 | for (parts) |part| { | ||
| 136 | const lower = std.ascii.lowerString(&scratch, part); | ||
| 137 | if (mem.indexOf(u8, buf, part) == null and mem.indexOf(u8, buf, lower) == null) continue :top; | ||
| 138 | } | ||
| 139 | return tag; | ||
| 140 | } | ||
| 141 | return null; | ||
| 142 | } | ||
| 143 | |||
| 144 | pub fn isImaginary(suffix: Suffix) bool { | ||
| 145 | return switch (suffix) { | ||
| 146 | .I, .IL, .IF, .IU, .IUL, .ILL, .IULL, .IWB, .IUWB => true, | ||
| 147 | .None, .L, .F16, .F, .U, .UL, .LL, .ULL, .WB, .UWB => false, | ||
| 148 | }; | ||
| 149 | } | ||
| 150 | |||
| 151 | pub fn isSignedInteger(suffix: Suffix) bool { | ||
| 152 | return switch (suffix) { | ||
| 153 | .None, .L, .LL, .I, .IL, .ILL, .WB, .IWB => true, | ||
| 154 | .U, .UL, .ULL, .IU, .IUL, .IULL, .UWB, .IUWB => false, | ||
| 155 | .F, .IF, .F16 => unreachable, | ||
| 156 | }; | ||
| 157 | } | ||
| 158 | |||
| 159 | pub fn signedness(suffix: Suffix) std.builtin.Signedness { | ||
| 160 | return if (suffix.isSignedInteger()) .signed else .unsigned; | ||
| 161 | } | ||
| 162 | |||
| 163 | pub fn isBitInt(suffix: Suffix) bool { | ||
| 164 | return switch (suffix) { | ||
| 165 | .WB, .UWB, .IWB, .IUWB => true, | ||
| 166 | else => false, | ||
| 167 | }; | ||
| 168 | } | ||
| 169 | }; | ||
deps/aro/aro/target.zig-1| ... | @@ -1,7 +1,6 @@ | ... | @@ -1,7 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const LangOpts = @import("LangOpts.zig"); | 2 | const LangOpts = @import("LangOpts.zig"); |
| 3 | const Type = @import("Type.zig"); | 3 | const Type = @import("Type.zig"); |
| 4 | const llvm = @import("root").codegen.llvm; | ||
| 5 | const TargetSet = @import("Builtins/Properties.zig").TargetSet; | 4 | const TargetSet = @import("Builtins/Properties.zig").TargetSet; |
| 6 | 5 | ||
| 7 | /// intmax_t for this target | 6 | /// intmax_t for this target |
lib/std/c.zig-8| ... | @@ -5,14 +5,6 @@ const page_size = std.mem.page_size; | ... | @@ -5,14 +5,6 @@ const page_size = std.mem.page_size; |
| 5 | const iovec = std.os.iovec; | 5 | const iovec = std.os.iovec; |
| 6 | const iovec_const = std.os.iovec_const; | 6 | const iovec_const = std.os.iovec_const; |
| 7 | 7 | ||
| 8 | test { | ||
| 9 | _ = tokenizer; | ||
| 10 | } | ||
| 11 | |||
| 12 | pub const tokenizer = @import("c/tokenizer.zig"); | ||
| 13 | pub const Token = tokenizer.Token; | ||
| 14 | pub const Tokenizer = tokenizer.Tokenizer; | ||
| 15 | |||
| 16 | /// The return type is `type` to force comptime function call execution. | 8 | /// The return type is `type` to force comptime function call execution. |
| 17 | /// TODO: https://github.com/ziglang/zig/issues/425 | 9 | /// TODO: https://github.com/ziglang/zig/issues/425 |
| 18 | /// If not linking libc, returns struct{pub const ok = false;} | 10 | /// If not linking libc, returns struct{pub const ok = false;} |
lib/std/c/tokenizer.zig deleted-1585| ... | @@ -1,1585 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub const Token = struct { | ||
| 4 | id: Id, | ||
| 5 | start: usize, | ||
| 6 | end: usize, | ||
| 7 | |||
| 8 | pub const Id = union(enum) { | ||
| 9 | Invalid, | ||
| 10 | Eof, | ||
| 11 | Nl, | ||
| 12 | Identifier, | ||
| 13 | |||
| 14 | /// special case for #include <...> | ||
| 15 | MacroString, | ||
| 16 | StringLiteral: StrKind, | ||
| 17 | CharLiteral: StrKind, | ||
| 18 | IntegerLiteral: NumSuffix, | ||
| 19 | FloatLiteral: NumSuffix, | ||
| 20 | Bang, | ||
| 21 | BangEqual, | ||
| 22 | Pipe, | ||
| 23 | PipePipe, | ||
| 24 | PipeEqual, | ||
| 25 | Equal, | ||
| 26 | EqualEqual, | ||
| 27 | LParen, | ||
| 28 | RParen, | ||
| 29 | LBrace, | ||
| 30 | RBrace, | ||
| 31 | LBracket, | ||
| 32 | RBracket, | ||
| 33 | Period, | ||
| 34 | Ellipsis, | ||
| 35 | Caret, | ||
| 36 | CaretEqual, | ||
| 37 | Plus, | ||
| 38 | PlusPlus, | ||
| 39 | PlusEqual, | ||
| 40 | Minus, | ||
| 41 | MinusMinus, | ||
| 42 | MinusEqual, | ||
| 43 | Asterisk, | ||
| 44 | AsteriskEqual, | ||
| 45 | Percent, | ||
| 46 | PercentEqual, | ||
| 47 | Arrow, | ||
| 48 | Colon, | ||
| 49 | Semicolon, | ||
| 50 | Slash, | ||
| 51 | SlashEqual, | ||
| 52 | Comma, | ||
| 53 | Ampersand, | ||
| 54 | AmpersandAmpersand, | ||
| 55 | AmpersandEqual, | ||
| 56 | QuestionMark, | ||
| 57 | AngleBracketLeft, | ||
| 58 | AngleBracketLeftEqual, | ||
| 59 | AngleBracketAngleBracketLeft, | ||
| 60 | AngleBracketAngleBracketLeftEqual, | ||
| 61 | AngleBracketRight, | ||
| 62 | AngleBracketRightEqual, | ||
| 63 | AngleBracketAngleBracketRight, | ||
| 64 | AngleBracketAngleBracketRightEqual, | ||
| 65 | Tilde, | ||
| 66 | LineComment, | ||
| 67 | MultiLineComment, | ||
| 68 | Hash, | ||
| 69 | HashHash, | ||
| 70 | |||
| 71 | Keyword_auto, | ||
| 72 | Keyword_break, | ||
| 73 | Keyword_case, | ||
| 74 | Keyword_char, | ||
| 75 | Keyword_const, | ||
| 76 | Keyword_continue, | ||
| 77 | Keyword_default, | ||
| 78 | Keyword_do, | ||
| 79 | Keyword_double, | ||
| 80 | Keyword_else, | ||
| 81 | Keyword_enum, | ||
| 82 | Keyword_extern, | ||
| 83 | Keyword_float, | ||
| 84 | Keyword_for, | ||
| 85 | Keyword_goto, | ||
| 86 | Keyword_if, | ||
| 87 | Keyword_int, | ||
| 88 | Keyword_long, | ||
| 89 | Keyword_register, | ||
| 90 | Keyword_return, | ||
| 91 | Keyword_short, | ||
| 92 | Keyword_signed, | ||
| 93 | Keyword_sizeof, | ||
| 94 | Keyword_static, | ||
| 95 | Keyword_struct, | ||
| 96 | Keyword_switch, | ||
| 97 | Keyword_typedef, | ||
| 98 | Keyword_union, | ||
| 99 | Keyword_unsigned, | ||
| 100 | Keyword_void, | ||
| 101 | Keyword_volatile, | ||
| 102 | Keyword_while, | ||
| 103 | |||
| 104 | // ISO C99 | ||
| 105 | Keyword_bool, | ||
| 106 | Keyword_complex, | ||
| 107 | Keyword_imaginary, | ||
| 108 | Keyword_inline, | ||
| 109 | Keyword_restrict, | ||
| 110 | |||
| 111 | // ISO C11 | ||
| 112 | Keyword_alignas, | ||
| 113 | Keyword_alignof, | ||
| 114 | Keyword_atomic, | ||
| 115 | Keyword_generic, | ||
| 116 | Keyword_noreturn, | ||
| 117 | Keyword_static_assert, | ||
| 118 | Keyword_thread_local, | ||
| 119 | |||
| 120 | // Preprocessor directives | ||
| 121 | Keyword_include, | ||
| 122 | Keyword_define, | ||
| 123 | Keyword_ifdef, | ||
| 124 | Keyword_ifndef, | ||
| 125 | Keyword_error, | ||
| 126 | Keyword_pragma, | ||
| 127 | |||
| 128 | pub fn symbol(id: Id) []const u8 { | ||
| 129 | return symbolName(id); | ||
| 130 | } | ||
| 131 | |||
| 132 | pub fn symbolName(id: std.meta.Tag(Id)) []const u8 { | ||
| 133 | return switch (id) { | ||
| 134 | .Invalid => "Invalid", | ||
| 135 | .Eof => "Eof", | ||
| 136 | .Nl => "NewLine", | ||
| 137 | .Identifier => "Identifier", | ||
| 138 | .MacroString => "MacroString", | ||
| 139 | .StringLiteral => "StringLiteral", | ||
| 140 | .CharLiteral => "CharLiteral", | ||
| 141 | .IntegerLiteral => "IntegerLiteral", | ||
| 142 | .FloatLiteral => "FloatLiteral", | ||
| 143 | .LineComment => "LineComment", | ||
| 144 | .MultiLineComment => "MultiLineComment", | ||
| 145 | |||
| 146 | .Bang => "!", | ||
| 147 | .BangEqual => "!=", | ||
| 148 | .Pipe => "|", | ||
| 149 | .PipePipe => "||", | ||
| 150 | .PipeEqual => "|=", | ||
| 151 | .Equal => "=", | ||
| 152 | .EqualEqual => "==", | ||
| 153 | .LParen => "(", | ||
| 154 | .RParen => ")", | ||
| 155 | .LBrace => "{", | ||
| 156 | .RBrace => "}", | ||
| 157 | .LBracket => "[", | ||
| 158 | .RBracket => "]", | ||
| 159 | .Period => ".", | ||
| 160 | .Ellipsis => "...", | ||
| 161 | .Caret => "^", | ||
| 162 | .CaretEqual => "^=", | ||
| 163 | .Plus => "+", | ||
| 164 | .PlusPlus => "++", | ||
| 165 | .PlusEqual => "+=", | ||
| 166 | .Minus => "-", | ||
| 167 | .MinusMinus => "--", | ||
| 168 | .MinusEqual => "-=", | ||
| 169 | .Asterisk => "*", | ||
| 170 | .AsteriskEqual => "*=", | ||
| 171 | .Percent => "%", | ||
| 172 | .PercentEqual => "%=", | ||
| 173 | .Arrow => "->", | ||
| 174 | .Colon => ":", | ||
| 175 | .Semicolon => ";", | ||
| 176 | .Slash => "/", | ||
| 177 | .SlashEqual => "/=", | ||
| 178 | .Comma => ",", | ||
| 179 | .Ampersand => "&", | ||
| 180 | .AmpersandAmpersand => "&&", | ||
| 181 | .AmpersandEqual => "&=", | ||
| 182 | .QuestionMark => "?", | ||
| 183 | .AngleBracketLeft => "<", | ||
| 184 | .AngleBracketLeftEqual => "<=", | ||
| 185 | .AngleBracketAngleBracketLeft => "<<", | ||
| 186 | .AngleBracketAngleBracketLeftEqual => "<<=", | ||
| 187 | .AngleBracketRight => ">", | ||
| 188 | .AngleBracketRightEqual => ">=", | ||
| 189 | .AngleBracketAngleBracketRight => ">>", | ||
| 190 | .AngleBracketAngleBracketRightEqual => ">>=", | ||
| 191 | .Tilde => "~", | ||
| 192 | .Hash => "#", | ||
| 193 | .HashHash => "##", | ||
| 194 | .Keyword_auto => "auto", | ||
| 195 | .Keyword_break => "break", | ||
| 196 | .Keyword_case => "case", | ||
| 197 | .Keyword_char => "char", | ||
| 198 | .Keyword_const => "const", | ||
| 199 | .Keyword_continue => "continue", | ||
| 200 | .Keyword_default => "default", | ||
| 201 | .Keyword_do => "do", | ||
| 202 | .Keyword_double => "double", | ||
| 203 | .Keyword_else => "else", | ||
| 204 | .Keyword_enum => "enum", | ||
| 205 | .Keyword_extern => "extern", | ||
| 206 | .Keyword_float => "float", | ||
| 207 | .Keyword_for => "for", | ||
| 208 | .Keyword_goto => "goto", | ||
| 209 | .Keyword_if => "if", | ||
| 210 | .Keyword_int => "int", | ||
| 211 | .Keyword_long => "long", | ||
| 212 | .Keyword_register => "register", | ||
| 213 | .Keyword_return => "return", | ||
| 214 | .Keyword_short => "short", | ||
| 215 | .Keyword_signed => "signed", | ||
| 216 | .Keyword_sizeof => "sizeof", | ||
| 217 | .Keyword_static => "static", | ||
| 218 | .Keyword_struct => "struct", | ||
| 219 | .Keyword_switch => "switch", | ||
| 220 | .Keyword_typedef => "typedef", | ||
| 221 | .Keyword_union => "union", | ||
| 222 | .Keyword_unsigned => "unsigned", | ||
| 223 | .Keyword_void => "void", | ||
| 224 | .Keyword_volatile => "volatile", | ||
| 225 | .Keyword_while => "while", | ||
| 226 | .Keyword_bool => "_Bool", | ||
| 227 | .Keyword_complex => "_Complex", | ||
| 228 | .Keyword_imaginary => "_Imaginary", | ||
| 229 | .Keyword_inline => "inline", | ||
| 230 | .Keyword_restrict => "restrict", | ||
| 231 | .Keyword_alignas => "_Alignas", | ||
| 232 | .Keyword_alignof => "_Alignof", | ||
| 233 | .Keyword_atomic => "_Atomic", | ||
| 234 | .Keyword_generic => "_Generic", | ||
| 235 | .Keyword_noreturn => "_Noreturn", | ||
| 236 | .Keyword_static_assert => "_Static_assert", | ||
| 237 | .Keyword_thread_local => "_Thread_local", | ||
| 238 | .Keyword_include => "include", | ||
| 239 | .Keyword_define => "define", | ||
| 240 | .Keyword_ifdef => "ifdef", | ||
| 241 | .Keyword_ifndef => "ifndef", | ||
| 242 | .Keyword_error => "error", | ||
| 243 | .Keyword_pragma => "pragma", | ||
| 244 | }; | ||
| 245 | } | ||
| 246 | }; | ||
| 247 | |||
| 248 | // TODO extensions | ||
| 249 | pub const keywords = std.ComptimeStringMap(Id, .{ | ||
| 250 | .{ "auto", .Keyword_auto }, | ||
| 251 | .{ "break", .Keyword_break }, | ||
| 252 | .{ "case", .Keyword_case }, | ||
| 253 | .{ "char", .Keyword_char }, | ||
| 254 | .{ "const", .Keyword_const }, | ||
| 255 | .{ "continue", .Keyword_continue }, | ||
| 256 | .{ "default", .Keyword_default }, | ||
| 257 | .{ "do", .Keyword_do }, | ||
| 258 | .{ "double", .Keyword_double }, | ||
| 259 | .{ "else", .Keyword_else }, | ||
| 260 | .{ "enum", .Keyword_enum }, | ||
| 261 | .{ "extern", .Keyword_extern }, | ||
| 262 | .{ "float", .Keyword_float }, | ||
| 263 | .{ "for", .Keyword_for }, | ||
| 264 | .{ "goto", .Keyword_goto }, | ||
| 265 | .{ "if", .Keyword_if }, | ||
| 266 | .{ "int", .Keyword_int }, | ||
| 267 | .{ "long", .Keyword_long }, | ||
| 268 | .{ "register", .Keyword_register }, | ||
| 269 | .{ "return", .Keyword_return }, | ||
| 270 | .{ "short", .Keyword_short }, | ||
| 271 | .{ "signed", .Keyword_signed }, | ||
| 272 | .{ "sizeof", .Keyword_sizeof }, | ||
| 273 | .{ "static", .Keyword_static }, | ||
| 274 | .{ "struct", .Keyword_struct }, | ||
| 275 | .{ "switch", .Keyword_switch }, | ||
| 276 | .{ "typedef", .Keyword_typedef }, | ||
| 277 | .{ "union", .Keyword_union }, | ||
| 278 | .{ "unsigned", .Keyword_unsigned }, | ||
| 279 | .{ "void", .Keyword_void }, | ||
| 280 | .{ "volatile", .Keyword_volatile }, | ||
| 281 | .{ "while", .Keyword_while }, | ||
| 282 | |||
| 283 | // ISO C99 | ||
| 284 | .{ "_Bool", .Keyword_bool }, | ||
| 285 | .{ "_Complex", .Keyword_complex }, | ||
| 286 | .{ "_Imaginary", .Keyword_imaginary }, | ||
| 287 | .{ "inline", .Keyword_inline }, | ||
| 288 | .{ "restrict", .Keyword_restrict }, | ||
| 289 | |||
| 290 | // ISO C11 | ||
| 291 | .{ "_Alignas", .Keyword_alignas }, | ||
| 292 | .{ "_Alignof", .Keyword_alignof }, | ||
| 293 | .{ "_Atomic", .Keyword_atomic }, | ||
| 294 | .{ "_Generic", .Keyword_generic }, | ||
| 295 | .{ "_Noreturn", .Keyword_noreturn }, | ||
| 296 | .{ "_Static_assert", .Keyword_static_assert }, | ||
| 297 | .{ "_Thread_local", .Keyword_thread_local }, | ||
| 298 | |||
| 299 | // Preprocessor directives | ||
| 300 | .{ "include", .Keyword_include }, | ||
| 301 | .{ "define", .Keyword_define }, | ||
| 302 | .{ "ifdef", .Keyword_ifdef }, | ||
| 303 | .{ "ifndef", .Keyword_ifndef }, | ||
| 304 | .{ "error", .Keyword_error }, | ||
| 305 | .{ "pragma", .Keyword_pragma }, | ||
| 306 | }); | ||
| 307 | |||
| 308 | // TODO do this in the preprocessor | ||
| 309 | pub fn getKeyword(bytes: []const u8, pp_directive: bool) ?Id { | ||
| 310 | if (keywords.get(bytes)) |id| { | ||
| 311 | switch (id) { | ||
| 312 | .Keyword_include, | ||
| 313 | .Keyword_define, | ||
| 314 | .Keyword_ifdef, | ||
| 315 | .Keyword_ifndef, | ||
| 316 | .Keyword_error, | ||
| 317 | .Keyword_pragma, | ||
| 318 | => if (!pp_directive) return null, | ||
| 319 | else => {}, | ||
| 320 | } | ||
| 321 | return id; | ||
| 322 | } | ||
| 323 | return null; | ||
| 324 | } | ||
| 325 | |||
| 326 | pub const NumSuffix = enum { | ||
| 327 | none, | ||
| 328 | f, | ||
| 329 | l, | ||
| 330 | u, | ||
| 331 | lu, | ||
| 332 | ll, | ||
| 333 | llu, | ||
| 334 | }; | ||
| 335 | |||
| 336 | pub const StrKind = enum { | ||
| 337 | none, | ||
| 338 | wide, | ||
| 339 | utf_8, | ||
| 340 | utf_16, | ||
| 341 | utf_32, | ||
| 342 | }; | ||
| 343 | }; | ||
| 344 | |||
| 345 | pub const Tokenizer = struct { | ||
| 346 | buffer: []const u8, | ||
| 347 | index: usize = 0, | ||
| 348 | prev_tok_id: std.meta.Tag(Token.Id) = .Invalid, | ||
| 349 | pp_directive: bool = false, | ||
| 350 | |||
| 351 | pub fn next(self: *Tokenizer) Token { | ||
| 352 | var result = Token{ | ||
| 353 | .id = .Eof, | ||
| 354 | .start = self.index, | ||
| 355 | .end = undefined, | ||
| 356 | }; | ||
| 357 | var state: enum { | ||
| 358 | Start, | ||
| 359 | Cr, | ||
| 360 | BackSlash, | ||
| 361 | BackSlashCr, | ||
| 362 | u, | ||
| 363 | u8, | ||
| 364 | U, | ||
| 365 | L, | ||
| 366 | StringLiteral, | ||
| 367 | CharLiteralStart, | ||
| 368 | CharLiteral, | ||
| 369 | EscapeSequence, | ||
| 370 | CrEscape, | ||
| 371 | OctalEscape, | ||
| 372 | HexEscape, | ||
| 373 | UnicodeEscape, | ||
| 374 | Identifier, | ||
| 375 | Equal, | ||
| 376 | Bang, | ||
| 377 | Pipe, | ||
| 378 | Percent, | ||
| 379 | Asterisk, | ||
| 380 | Plus, | ||
| 381 | |||
| 382 | /// special case for #include <...> | ||
| 383 | MacroString, | ||
| 384 | AngleBracketLeft, | ||
| 385 | AngleBracketAngleBracketLeft, | ||
| 386 | AngleBracketRight, | ||
| 387 | AngleBracketAngleBracketRight, | ||
| 388 | Caret, | ||
| 389 | Period, | ||
| 390 | Period2, | ||
| 391 | Minus, | ||
| 392 | Slash, | ||
| 393 | Ampersand, | ||
| 394 | Hash, | ||
| 395 | LineComment, | ||
| 396 | MultiLineComment, | ||
| 397 | MultiLineCommentAsterisk, | ||
| 398 | Zero, | ||
| 399 | IntegerLiteralOct, | ||
| 400 | IntegerLiteralBinary, | ||
| 401 | IntegerLiteralBinaryFirst, | ||
| 402 | IntegerLiteralHex, | ||
| 403 | IntegerLiteralHexFirst, | ||
| 404 | IntegerLiteral, | ||
| 405 | IntegerSuffix, | ||
| 406 | IntegerSuffixU, | ||
| 407 | IntegerSuffixL, | ||
| 408 | IntegerSuffixLL, | ||
| 409 | IntegerSuffixUL, | ||
| 410 | FloatFraction, | ||
| 411 | FloatFractionHex, | ||
| 412 | FloatExponent, | ||
| 413 | FloatExponentDigits, | ||
| 414 | FloatSuffix, | ||
| 415 | } = .Start; | ||
| 416 | var string = false; | ||
| 417 | var counter: u32 = 0; | ||
| 418 | while (self.index < self.buffer.len) : (self.index += 1) { | ||
| 419 | const c = self.buffer[self.index]; | ||
| 420 | switch (state) { | ||
| 421 | .Start => switch (c) { | ||
| 422 | '\n' => { | ||
| 423 | self.pp_directive = false; | ||
| 424 | result.id = .Nl; | ||
| 425 | self.index += 1; | ||
| 426 | break; | ||
| 427 | }, | ||
| 428 | '\r' => { | ||
| 429 | state = .Cr; | ||
| 430 | }, | ||
| 431 | '"' => { | ||
| 432 | result.id = .{ .StringLiteral = .none }; | ||
| 433 | state = .StringLiteral; | ||
| 434 | }, | ||
| 435 | '\'' => { | ||
| 436 | result.id = .{ .CharLiteral = .none }; | ||
| 437 | state = .CharLiteralStart; | ||
| 438 | }, | ||
| 439 | 'u' => { | ||
| 440 | state = .u; | ||
| 441 | }, | ||
| 442 | 'U' => { | ||
| 443 | state = .U; | ||
| 444 | }, | ||
| 445 | 'L' => { | ||
| 446 | state = .L; | ||
| 447 | }, | ||
| 448 | 'a'...'t', 'v'...'z', 'A'...'K', 'M'...'T', 'V'...'Z', '_', '$' => { | ||
| 449 | state = .Identifier; | ||
| 450 | }, | ||
| 451 | '=' => { | ||
| 452 | state = .Equal; | ||
| 453 | }, | ||
| 454 | '!' => { | ||
| 455 | state = .Bang; | ||
| 456 | }, | ||
| 457 | '|' => { | ||
| 458 | state = .Pipe; | ||
| 459 | }, | ||
| 460 | '(' => { | ||
| 461 | result.id = .LParen; | ||
| 462 | self.index += 1; | ||
| 463 | break; | ||
| 464 | }, | ||
| 465 | ')' => { | ||
| 466 | result.id = .RParen; | ||
| 467 | self.index += 1; | ||
| 468 | break; | ||
| 469 | }, | ||
| 470 | '[' => { | ||
| 471 | result.id = .LBracket; | ||
| 472 | self.index += 1; | ||
| 473 | break; | ||
| 474 | }, | ||
| 475 | ']' => { | ||
| 476 | result.id = .RBracket; | ||
| 477 | self.index += 1; | ||
| 478 | break; | ||
| 479 | }, | ||
| 480 | ';' => { | ||
| 481 | result.id = .Semicolon; | ||
| 482 | self.index += 1; | ||
| 483 | break; | ||
| 484 | }, | ||
| 485 | ',' => { | ||
| 486 | result.id = .Comma; | ||
| 487 | self.index += 1; | ||
| 488 | break; | ||
| 489 | }, | ||
| 490 | '?' => { | ||
| 491 | result.id = .QuestionMark; | ||
| 492 | self.index += 1; | ||
| 493 | break; | ||
| 494 | }, | ||
| 495 | ':' => { | ||
| 496 | result.id = .Colon; | ||
| 497 | self.index += 1; | ||
| 498 | break; | ||
| 499 | }, | ||
| 500 | '%' => { | ||
| 501 | state = .Percent; | ||
| 502 | }, | ||
| 503 | '*' => { | ||
| 504 | state = .Asterisk; | ||
| 505 | }, | ||
| 506 | '+' => { | ||
| 507 | state = .Plus; | ||
| 508 | }, | ||
| 509 | '<' => { | ||
| 510 | if (self.prev_tok_id == .Keyword_include) | ||
| 511 | state = .MacroString | ||
| 512 | else | ||
| 513 | state = .AngleBracketLeft; | ||
| 514 | }, | ||
| 515 | '>' => { | ||
| 516 | state = .AngleBracketRight; | ||
| 517 | }, | ||
| 518 | '^' => { | ||
| 519 | state = .Caret; | ||
| 520 | }, | ||
| 521 | '{' => { | ||
| 522 | result.id = .LBrace; | ||
| 523 | self.index += 1; | ||
| 524 | break; | ||
| 525 | }, | ||
| 526 | '}' => { | ||
| 527 | result.id = .RBrace; | ||
| 528 | self.index += 1; | ||
| 529 | break; | ||
| 530 | }, | ||
| 531 | '~' => { | ||
| 532 | result.id = .Tilde; | ||
| 533 | self.index += 1; | ||
| 534 | break; | ||
| 535 | }, | ||
| 536 | '.' => { | ||
| 537 | state = .Period; | ||
| 538 | }, | ||
| 539 | '-' => { | ||
| 540 | state = .Minus; | ||
| 541 | }, | ||
| 542 | '/' => { | ||
| 543 | state = .Slash; | ||
| 544 | }, | ||
| 545 | '&' => { | ||
| 546 | state = .Ampersand; | ||
| 547 | }, | ||
| 548 | '#' => { | ||
| 549 | state = .Hash; | ||
| 550 | }, | ||
| 551 | '0' => { | ||
| 552 | state = .Zero; | ||
| 553 | }, | ||
| 554 | '1'...'9' => { | ||
| 555 | state = .IntegerLiteral; | ||
| 556 | }, | ||
| 557 | '\\' => { | ||
| 558 | state = .BackSlash; | ||
| 559 | }, | ||
| 560 | '\t', '\x0B', '\x0C', ' ' => { | ||
| 561 | result.start = self.index + 1; | ||
| 562 | }, | ||
| 563 | else => { | ||
| 564 | // TODO handle invalid bytes better | ||
| 565 | result.id = .Invalid; | ||
| 566 | self.index += 1; | ||
| 567 | break; | ||
| 568 | }, | ||
| 569 | }, | ||
| 570 | .Cr => switch (c) { | ||
| 571 | '\n' => { | ||
| 572 | self.pp_directive = false; | ||
| 573 | result.id = .Nl; | ||
| 574 | self.index += 1; | ||
| 575 | break; | ||
| 576 | }, | ||
| 577 | else => { | ||
| 578 | result.id = .Invalid; | ||
| 579 | break; | ||
| 580 | }, | ||
| 581 | }, | ||
| 582 | .BackSlash => switch (c) { | ||
| 583 | '\n' => { | ||
| 584 | result.start = self.index + 1; | ||
| 585 | state = .Start; | ||
| 586 | }, | ||
| 587 | '\r' => { | ||
| 588 | state = .BackSlashCr; | ||
| 589 | }, | ||
| 590 | '\t', '\x0B', '\x0C', ' ' => { | ||
| 591 | // TODO warn | ||
| 592 | }, | ||
| 593 | else => { | ||
| 594 | result.id = .Invalid; | ||
| 595 | break; | ||
| 596 | }, | ||
| 597 | }, | ||
| 598 | .BackSlashCr => switch (c) { | ||
| 599 | '\n' => { | ||
| 600 | result.start = self.index + 1; | ||
| 601 | state = .Start; | ||
| 602 | }, | ||
| 603 | else => { | ||
| 604 | result.id = .Invalid; | ||
| 605 | break; | ||
| 606 | }, | ||
| 607 | }, | ||
| 608 | .u => switch (c) { | ||
| 609 | '8' => { | ||
| 610 | state = .u8; | ||
| 611 | }, | ||
| 612 | '\'' => { | ||
| 613 | result.id = .{ .CharLiteral = .utf_16 }; | ||
| 614 | state = .CharLiteralStart; | ||
| 615 | }, | ||
| 616 | '\"' => { | ||
| 617 | result.id = .{ .StringLiteral = .utf_16 }; | ||
| 618 | state = .StringLiteral; | ||
| 619 | }, | ||
| 620 | else => { | ||
| 621 | self.index -= 1; | ||
| 622 | state = .Identifier; | ||
| 623 | }, | ||
| 624 | }, | ||
| 625 | .u8 => switch (c) { | ||
| 626 | '\"' => { | ||
| 627 | result.id = .{ .StringLiteral = .utf_8 }; | ||
| 628 | state = .StringLiteral; | ||
| 629 | }, | ||
| 630 | else => { | ||
| 631 | self.index -= 1; | ||
| 632 | state = .Identifier; | ||
| 633 | }, | ||
| 634 | }, | ||
| 635 | .U => switch (c) { | ||
| 636 | '\'' => { | ||
| 637 | result.id = .{ .CharLiteral = .utf_32 }; | ||
| 638 | state = .CharLiteralStart; | ||
| 639 | }, | ||
| 640 | '\"' => { | ||
| 641 | result.id = .{ .StringLiteral = .utf_32 }; | ||
| 642 | state = .StringLiteral; | ||
| 643 | }, | ||
| 644 | else => { | ||
| 645 | self.index -= 1; | ||
| 646 | state = .Identifier; | ||
| 647 | }, | ||
| 648 | }, | ||
| 649 | .L => switch (c) { | ||
| 650 | '\'' => { | ||
| 651 | result.id = .{ .CharLiteral = .wide }; | ||
| 652 | state = .CharLiteralStart; | ||
| 653 | }, | ||
| 654 | '\"' => { | ||
| 655 | result.id = .{ .StringLiteral = .wide }; | ||
| 656 | state = .StringLiteral; | ||
| 657 | }, | ||
| 658 | else => { | ||
| 659 | self.index -= 1; | ||
| 660 | state = .Identifier; | ||
| 661 | }, | ||
| 662 | }, | ||
| 663 | .StringLiteral => switch (c) { | ||
| 664 | '\\' => { | ||
| 665 | string = true; | ||
| 666 | state = .EscapeSequence; | ||
| 667 | }, | ||
| 668 | '"' => { | ||
| 669 | self.index += 1; | ||
| 670 | break; | ||
| 671 | }, | ||
| 672 | '\n', '\r' => { | ||
| 673 | result.id = .Invalid; | ||
| 674 | break; | ||
| 675 | }, | ||
| 676 | else => {}, | ||
| 677 | }, | ||
| 678 | .CharLiteralStart => switch (c) { | ||
| 679 | '\\' => { | ||
| 680 | string = false; | ||
| 681 | state = .EscapeSequence; | ||
| 682 | }, | ||
| 683 | '\'', '\n' => { | ||
| 684 | result.id = .Invalid; | ||
| 685 | break; | ||
| 686 | }, | ||
| 687 | else => { | ||
| 688 | state = .CharLiteral; | ||
| 689 | }, | ||
| 690 | }, | ||
| 691 | .CharLiteral => switch (c) { | ||
| 692 | '\\' => { | ||
| 693 | string = false; | ||
| 694 | state = .EscapeSequence; | ||
| 695 | }, | ||
| 696 | '\'' => { | ||
| 697 | self.index += 1; | ||
| 698 | break; | ||
| 699 | }, | ||
| 700 | '\n' => { | ||
| 701 | result.id = .Invalid; | ||
| 702 | break; | ||
| 703 | }, | ||
| 704 | else => {}, | ||
| 705 | }, | ||
| 706 | .EscapeSequence => switch (c) { | ||
| 707 | '\'', '"', '?', '\\', 'a', 'b', 'f', 'n', 'r', 't', 'v', '\n' => { | ||
| 708 | state = if (string) .StringLiteral else .CharLiteral; | ||
| 709 | }, | ||
| 710 | '\r' => { | ||
| 711 | state = .CrEscape; | ||
| 712 | }, | ||
| 713 | '0'...'7' => { | ||
| 714 | counter = 1; | ||
| 715 | state = .OctalEscape; | ||
| 716 | }, | ||
| 717 | 'x' => { | ||
| 718 | state = .HexEscape; | ||
| 719 | }, | ||
| 720 | 'u' => { | ||
| 721 | counter = 4; | ||
| 722 | state = .OctalEscape; | ||
| 723 | }, | ||
| 724 | 'U' => { | ||
| 725 | counter = 8; | ||
| 726 | state = .OctalEscape; | ||
| 727 | }, | ||
| 728 | else => { | ||
| 729 | result.id = .Invalid; | ||
| 730 | break; | ||
| 731 | }, | ||
| 732 | }, | ||
| 733 | .CrEscape => switch (c) { | ||
| 734 | '\n' => { | ||
| 735 | state = if (string) .StringLiteral else .CharLiteral; | ||
| 736 | }, | ||
| 737 | else => { | ||
| 738 | result.id = .Invalid; | ||
| 739 | break; | ||
| 740 | }, | ||
| 741 | }, | ||
| 742 | .OctalEscape => switch (c) { | ||
| 743 | '0'...'7' => { | ||
| 744 | counter += 1; | ||
| 745 | if (counter == 3) { | ||
| 746 | state = if (string) .StringLiteral else .CharLiteral; | ||
| 747 | } | ||
| 748 | }, | ||
| 749 | else => { | ||
| 750 | self.index -= 1; | ||
| 751 | state = if (string) .StringLiteral else .CharLiteral; | ||
| 752 | }, | ||
| 753 | }, | ||
| 754 | .HexEscape => switch (c) { | ||
| 755 | '0'...'9', 'a'...'f', 'A'...'F' => {}, | ||
| 756 | else => { | ||
| 757 | self.index -= 1; | ||
| 758 | state = if (string) .StringLiteral else .CharLiteral; | ||
| 759 | }, | ||
| 760 | }, | ||
| 761 | .UnicodeEscape => switch (c) { | ||
| 762 | '0'...'9', 'a'...'f', 'A'...'F' => { | ||
| 763 | counter -= 1; | ||
| 764 | if (counter == 0) { | ||
| 765 | state = if (string) .StringLiteral else .CharLiteral; | ||
| 766 | } | ||
| 767 | }, | ||
| 768 | else => { | ||
| 769 | if (counter != 0) { | ||
| 770 | result.id = .Invalid; | ||
| 771 | break; | ||
| 772 | } | ||
| 773 | self.index -= 1; | ||
| 774 | state = if (string) .StringLiteral else .CharLiteral; | ||
| 775 | }, | ||
| 776 | }, | ||
| 777 | .Identifier => switch (c) { | ||
| 778 | 'a'...'z', 'A'...'Z', '_', '0'...'9', '$' => {}, | ||
| 779 | else => { | ||
| 780 | result.id = Token.getKeyword(self.buffer[result.start..self.index], self.prev_tok_id == .Hash and !self.pp_directive) orelse .Identifier; | ||
| 781 | if (self.prev_tok_id == .Hash) | ||
| 782 | self.pp_directive = true; | ||
| 783 | break; | ||
| 784 | }, | ||
| 785 | }, | ||
| 786 | .Equal => switch (c) { | ||
| 787 | '=' => { | ||
| 788 | result.id = .EqualEqual; | ||
| 789 | self.index += 1; | ||
| 790 | break; | ||
| 791 | }, | ||
| 792 | else => { | ||
| 793 | result.id = .Equal; | ||
| 794 | break; | ||
| 795 | }, | ||
| 796 | }, | ||
| 797 | .Bang => switch (c) { | ||
| 798 | '=' => { | ||
| 799 | result.id = .BangEqual; | ||
| 800 | self.index += 1; | ||
| 801 | break; | ||
| 802 | }, | ||
| 803 | else => { | ||
| 804 | result.id = .Bang; | ||
| 805 | break; | ||
| 806 | }, | ||
| 807 | }, | ||
| 808 | .Pipe => switch (c) { | ||
| 809 | '=' => { | ||
| 810 | result.id = .PipeEqual; | ||
| 811 | self.index += 1; | ||
| 812 | break; | ||
| 813 | }, | ||
| 814 | '|' => { | ||
| 815 | result.id = .PipePipe; | ||
| 816 | self.index += 1; | ||
| 817 | break; | ||
| 818 | }, | ||
| 819 | else => { | ||
| 820 | result.id = .Pipe; | ||
| 821 | break; | ||
| 822 | }, | ||
| 823 | }, | ||
| 824 | .Percent => switch (c) { | ||
| 825 | '=' => { | ||
| 826 | result.id = .PercentEqual; | ||
| 827 | self.index += 1; | ||
| 828 | break; | ||
| 829 | }, | ||
| 830 | else => { | ||
| 831 | result.id = .Percent; | ||
| 832 | break; | ||
| 833 | }, | ||
| 834 | }, | ||
| 835 | .Asterisk => switch (c) { | ||
| 836 | '=' => { | ||
| 837 | result.id = .AsteriskEqual; | ||
| 838 | self.index += 1; | ||
| 839 | break; | ||
| 840 | }, | ||
| 841 | else => { | ||
| 842 | result.id = .Asterisk; | ||
| 843 | break; | ||
| 844 | }, | ||
| 845 | }, | ||
| 846 | .Plus => switch (c) { | ||
| 847 | '=' => { | ||
| 848 | result.id = .PlusEqual; | ||
| 849 | self.index += 1; | ||
| 850 | break; | ||
| 851 | }, | ||
| 852 | '+' => { | ||
| 853 | result.id = .PlusPlus; | ||
| 854 | self.index += 1; | ||
| 855 | break; | ||
| 856 | }, | ||
| 857 | else => { | ||
| 858 | result.id = .Plus; | ||
| 859 | break; | ||
| 860 | }, | ||
| 861 | }, | ||
| 862 | .MacroString => switch (c) { | ||
| 863 | '>' => { | ||
| 864 | result.id = .MacroString; | ||
| 865 | self.index += 1; | ||
| 866 | break; | ||
| 867 | }, | ||
| 868 | else => {}, | ||
| 869 | }, | ||
| 870 | .AngleBracketLeft => switch (c) { | ||
| 871 | '<' => { | ||
| 872 | state = .AngleBracketAngleBracketLeft; | ||
| 873 | }, | ||
| 874 | '=' => { | ||
| 875 | result.id = .AngleBracketLeftEqual; | ||
| 876 | self.index += 1; | ||
| 877 | break; | ||
| 878 | }, | ||
| 879 | else => { | ||
| 880 | result.id = .AngleBracketLeft; | ||
| 881 | break; | ||
| 882 | }, | ||
| 883 | }, | ||
| 884 | .AngleBracketAngleBracketLeft => switch (c) { | ||
| 885 | '=' => { | ||
| 886 | result.id = .AngleBracketAngleBracketLeftEqual; | ||
| 887 | self.index += 1; | ||
| 888 | break; | ||
| 889 | }, | ||
| 890 | else => { | ||
| 891 | result.id = .AngleBracketAngleBracketLeft; | ||
| 892 | break; | ||
| 893 | }, | ||
| 894 | }, | ||
| 895 | .AngleBracketRight => switch (c) { | ||
| 896 | '>' => { | ||
| 897 | state = .AngleBracketAngleBracketRight; | ||
| 898 | }, | ||
| 899 | '=' => { | ||
| 900 | result.id = .AngleBracketRightEqual; | ||
| 901 | self.index += 1; | ||
| 902 | break; | ||
| 903 | }, | ||
| 904 | else => { | ||
| 905 | result.id = .AngleBracketRight; | ||
| 906 | break; | ||
| 907 | }, | ||
| 908 | }, | ||
| 909 | .AngleBracketAngleBracketRight => switch (c) { | ||
| 910 | '=' => { | ||
| 911 | result.id = .AngleBracketAngleBracketRightEqual; | ||
| 912 | self.index += 1; | ||
| 913 | break; | ||
| 914 | }, | ||
| 915 | else => { | ||
| 916 | result.id = .AngleBracketAngleBracketRight; | ||
| 917 | break; | ||
| 918 | }, | ||
| 919 | }, | ||
| 920 | .Caret => switch (c) { | ||
| 921 | '=' => { | ||
| 922 | result.id = .CaretEqual; | ||
| 923 | self.index += 1; | ||
| 924 | break; | ||
| 925 | }, | ||
| 926 | else => { | ||
| 927 | result.id = .Caret; | ||
| 928 | break; | ||
| 929 | }, | ||
| 930 | }, | ||
| 931 | .Period => switch (c) { | ||
| 932 | '.' => { | ||
| 933 | state = .Period2; | ||
| 934 | }, | ||
| 935 | '0'...'9' => { | ||
| 936 | state = .FloatFraction; | ||
| 937 | }, | ||
| 938 | else => { | ||
| 939 | result.id = .Period; | ||
| 940 | break; | ||
| 941 | }, | ||
| 942 | }, | ||
| 943 | .Period2 => switch (c) { | ||
| 944 | '.' => { | ||
| 945 | result.id = .Ellipsis; | ||
| 946 | self.index += 1; | ||
| 947 | break; | ||
| 948 | }, | ||
| 949 | else => { | ||
| 950 | result.id = .Period; | ||
| 951 | self.index -= 1; | ||
| 952 | break; | ||
| 953 | }, | ||
| 954 | }, | ||
| 955 | .Minus => switch (c) { | ||
| 956 | '>' => { | ||
| 957 | result.id = .Arrow; | ||
| 958 | self.index += 1; | ||
| 959 | break; | ||
| 960 | }, | ||
| 961 | '=' => { | ||
| 962 | result.id = .MinusEqual; | ||
| 963 | self.index += 1; | ||
| 964 | break; | ||
| 965 | }, | ||
| 966 | '-' => { | ||
| 967 | result.id = .MinusMinus; | ||
| 968 | self.index += 1; | ||
| 969 | break; | ||
| 970 | }, | ||
| 971 | else => { | ||
| 972 | result.id = .Minus; | ||
| 973 | break; | ||
| 974 | }, | ||
| 975 | }, | ||
| 976 | .Slash => switch (c) { | ||
| 977 | '/' => { | ||
| 978 | state = .LineComment; | ||
| 979 | }, | ||
| 980 | '*' => { | ||
| 981 | state = .MultiLineComment; | ||
| 982 | }, | ||
| 983 | '=' => { | ||
| 984 | result.id = .SlashEqual; | ||
| 985 | self.index += 1; | ||
| 986 | break; | ||
| 987 | }, | ||
| 988 | else => { | ||
| 989 | result.id = .Slash; | ||
| 990 | break; | ||
| 991 | }, | ||
| 992 | }, | ||
| 993 | .Ampersand => switch (c) { | ||
| 994 | '&' => { | ||
| 995 | result.id = .AmpersandAmpersand; | ||
| 996 | self.index += 1; | ||
| 997 | break; | ||
| 998 | }, | ||
| 999 | '=' => { | ||
| 1000 | result.id = .AmpersandEqual; | ||
| 1001 | self.index += 1; | ||
| 1002 | break; | ||
| 1003 | }, | ||
| 1004 | else => { | ||
| 1005 | result.id = .Ampersand; | ||
| 1006 | break; | ||
| 1007 | }, | ||
| 1008 | }, | ||
| 1009 | .Hash => switch (c) { | ||
| 1010 | '#' => { | ||
| 1011 | result.id = .HashHash; | ||
| 1012 | self.index += 1; | ||
| 1013 | break; | ||
| 1014 | }, | ||
| 1015 | else => { | ||
| 1016 | result.id = .Hash; | ||
| 1017 | break; | ||
| 1018 | }, | ||
| 1019 | }, | ||
| 1020 | .LineComment => switch (c) { | ||
| 1021 | '\n' => { | ||
| 1022 | result.id = .LineComment; | ||
| 1023 | break; | ||
| 1024 | }, | ||
| 1025 | else => {}, | ||
| 1026 | }, | ||
| 1027 | .MultiLineComment => switch (c) { | ||
| 1028 | '*' => { | ||
| 1029 | state = .MultiLineCommentAsterisk; | ||
| 1030 | }, | ||
| 1031 | else => {}, | ||
| 1032 | }, | ||
| 1033 | .MultiLineCommentAsterisk => switch (c) { | ||
| 1034 | '/' => { | ||
| 1035 | result.id = .MultiLineComment; | ||
| 1036 | self.index += 1; | ||
| 1037 | break; | ||
| 1038 | }, | ||
| 1039 | else => { | ||
| 1040 | state = .MultiLineComment; | ||
| 1041 | }, | ||
| 1042 | }, | ||
| 1043 | .Zero => switch (c) { | ||
| 1044 | '0'...'9' => { | ||
| 1045 | state = .IntegerLiteralOct; | ||
| 1046 | }, | ||
| 1047 | 'b', 'B' => { | ||
| 1048 | state = .IntegerLiteralBinaryFirst; | ||
| 1049 | }, | ||
| 1050 | 'x', 'X' => { | ||
| 1051 | state = .IntegerLiteralHexFirst; | ||
| 1052 | }, | ||
| 1053 | '.' => { | ||
| 1054 | state = .FloatFraction; | ||
| 1055 | }, | ||
| 1056 | else => { | ||
| 1057 | state = .IntegerSuffix; | ||
| 1058 | self.index -= 1; | ||
| 1059 | }, | ||
| 1060 | }, | ||
| 1061 | .IntegerLiteralOct => switch (c) { | ||
| 1062 | '0'...'7' => {}, | ||
| 1063 | else => { | ||
| 1064 | state = .IntegerSuffix; | ||
| 1065 | self.index -= 1; | ||
| 1066 | }, | ||
| 1067 | }, | ||
| 1068 | .IntegerLiteralBinaryFirst => switch (c) { | ||
| 1069 | '0'...'7' => state = .IntegerLiteralBinary, | ||
| 1070 | else => { | ||
| 1071 | result.id = .Invalid; | ||
| 1072 | break; | ||
| 1073 | }, | ||
| 1074 | }, | ||
| 1075 | .IntegerLiteralBinary => switch (c) { | ||
| 1076 | '0', '1' => {}, | ||
| 1077 | else => { | ||
| 1078 | state = .IntegerSuffix; | ||
| 1079 | self.index -= 1; | ||
| 1080 | }, | ||
| 1081 | }, | ||
| 1082 | .IntegerLiteralHexFirst => switch (c) { | ||
| 1083 | '0'...'9', 'a'...'f', 'A'...'F' => state = .IntegerLiteralHex, | ||
| 1084 | '.' => { | ||
| 1085 | state = .FloatFractionHex; | ||
| 1086 | }, | ||
| 1087 | 'p', 'P' => { | ||
| 1088 | state = .FloatExponent; | ||
| 1089 | }, | ||
| 1090 | else => { | ||
| 1091 | result.id = .Invalid; | ||
| 1092 | break; | ||
| 1093 | }, | ||
| 1094 | }, | ||
| 1095 | .IntegerLiteralHex => switch (c) { | ||
| 1096 | '0'...'9', 'a'...'f', 'A'...'F' => {}, | ||
| 1097 | '.' => { | ||
| 1098 | state = .FloatFractionHex; | ||
| 1099 | }, | ||
| 1100 | 'p', 'P' => { | ||
| 1101 | state = .FloatExponent; | ||
| 1102 | }, | ||
| 1103 | else => { | ||
| 1104 | state = .IntegerSuffix; | ||
| 1105 | self.index -= 1; | ||
| 1106 | }, | ||
| 1107 | }, | ||
| 1108 | .IntegerLiteral => switch (c) { | ||
| 1109 | '0'...'9' => {}, | ||
| 1110 | '.' => { | ||
| 1111 | state = .FloatFraction; | ||
| 1112 | }, | ||
| 1113 | 'e', 'E' => { | ||
| 1114 | state = .FloatExponent; | ||
| 1115 | }, | ||
| 1116 | else => { | ||
| 1117 | state = .IntegerSuffix; | ||
| 1118 | self.index -= 1; | ||
| 1119 | }, | ||
| 1120 | }, | ||
| 1121 | .IntegerSuffix => switch (c) { | ||
| 1122 | 'u', 'U' => { | ||
| 1123 | state = .IntegerSuffixU; | ||
| 1124 | }, | ||
| 1125 | 'l', 'L' => { | ||
| 1126 | state = .IntegerSuffixL; | ||
| 1127 | }, | ||
| 1128 | else => { | ||
| 1129 | result.id = .{ .IntegerLiteral = .none }; | ||
| 1130 | break; | ||
| 1131 | }, | ||
| 1132 | }, | ||
| 1133 | .IntegerSuffixU => switch (c) { | ||
| 1134 | 'l', 'L' => { | ||
| 1135 | state = .IntegerSuffixUL; | ||
| 1136 | }, | ||
| 1137 | else => { | ||
| 1138 | result.id = .{ .IntegerLiteral = .u }; | ||
| 1139 | break; | ||
| 1140 | }, | ||
| 1141 | }, | ||
| 1142 | .IntegerSuffixL => switch (c) { | ||
| 1143 | 'l', 'L' => { | ||
| 1144 | state = .IntegerSuffixLL; | ||
| 1145 | }, | ||
| 1146 | 'u', 'U' => { | ||
| 1147 | result.id = .{ .IntegerLiteral = .lu }; | ||
| 1148 | self.index += 1; | ||
| 1149 | break; | ||
| 1150 | }, | ||
| 1151 | else => { | ||
| 1152 | result.id = .{ .IntegerLiteral = .l }; | ||
| 1153 | break; | ||
| 1154 | }, | ||
| 1155 | }, | ||
| 1156 | .IntegerSuffixLL => switch (c) { | ||
| 1157 | 'u', 'U' => { | ||
| 1158 | result.id = .{ .IntegerLiteral = .llu }; | ||
| 1159 | self.index += 1; | ||
| 1160 | break; | ||
| 1161 | }, | ||
| 1162 | else => { | ||
| 1163 | result.id = .{ .IntegerLiteral = .ll }; | ||
| 1164 | break; | ||
| 1165 | }, | ||
| 1166 | }, | ||
| 1167 | .IntegerSuffixUL => switch (c) { | ||
| 1168 | 'l', 'L' => { | ||
| 1169 | result.id = .{ .IntegerLiteral = .llu }; | ||
| 1170 | self.index += 1; | ||
| 1171 | break; | ||
| 1172 | }, | ||
| 1173 | else => { | ||
| 1174 | result.id = .{ .IntegerLiteral = .lu }; | ||
| 1175 | break; | ||
| 1176 | }, | ||
| 1177 | }, | ||
| 1178 | .FloatFraction => switch (c) { | ||
| 1179 | '0'...'9' => {}, | ||
| 1180 | 'e', 'E' => { | ||
| 1181 | state = .FloatExponent; | ||
| 1182 | }, | ||
| 1183 | else => { | ||
| 1184 | self.index -= 1; | ||
| 1185 | state = .FloatSuffix; | ||
| 1186 | }, | ||
| 1187 | }, | ||
| 1188 | .FloatFractionHex => switch (c) { | ||
| 1189 | '0'...'9', 'a'...'f', 'A'...'F' => {}, | ||
| 1190 | 'p', 'P' => { | ||
| 1191 | state = .FloatExponent; | ||
| 1192 | }, | ||
| 1193 | else => { | ||
| 1194 | result.id = .Invalid; | ||
| 1195 | break; | ||
| 1196 | }, | ||
| 1197 | }, | ||
| 1198 | .FloatExponent => switch (c) { | ||
| 1199 | '+', '-' => { | ||
| 1200 | state = .FloatExponentDigits; | ||
| 1201 | }, | ||
| 1202 | else => { | ||
| 1203 | self.index -= 1; | ||
| 1204 | state = .FloatExponentDigits; | ||
| 1205 | }, | ||
| 1206 | }, | ||
| 1207 | .FloatExponentDigits => switch (c) { | ||
| 1208 | '0'...'9' => { | ||
| 1209 | counter += 1; | ||
| 1210 | }, | ||
| 1211 | else => { | ||
| 1212 | if (counter == 0) { | ||
| 1213 | result.id = .Invalid; | ||
| 1214 | break; | ||
| 1215 | } | ||
| 1216 | self.index -= 1; | ||
| 1217 | state = .FloatSuffix; | ||
| 1218 | }, | ||
| 1219 | }, | ||
| 1220 | .FloatSuffix => switch (c) { | ||
| 1221 | 'l', 'L' => { | ||
| 1222 | result.id = .{ .FloatLiteral = .l }; | ||
| 1223 | self.index += 1; | ||
| 1224 | break; | ||
| 1225 | }, | ||
| 1226 | 'f', 'F' => { | ||
| 1227 | result.id = .{ .FloatLiteral = .f }; | ||
| 1228 | self.index += 1; | ||
| 1229 | break; | ||
| 1230 | }, | ||
| 1231 | else => { | ||
| 1232 | result.id = .{ .FloatLiteral = .none }; | ||
| 1233 | break; | ||
| 1234 | }, | ||
| 1235 | }, | ||
| 1236 | } | ||
| 1237 | } else if (self.index == self.buffer.len) { | ||
| 1238 | switch (state) { | ||
| 1239 | .Start => {}, | ||
| 1240 | .u, .u8, .U, .L, .Identifier => { | ||
| 1241 | result.id = Token.getKeyword(self.buffer[result.start..self.index], self.prev_tok_id == .Hash and !self.pp_directive) orelse .Identifier; | ||
| 1242 | }, | ||
| 1243 | |||
| 1244 | .Cr, | ||
| 1245 | .BackSlash, | ||
| 1246 | .BackSlashCr, | ||
| 1247 | .Period2, | ||
| 1248 | .StringLiteral, | ||
| 1249 | .CharLiteralStart, | ||
| 1250 | .CharLiteral, | ||
| 1251 | .EscapeSequence, | ||
| 1252 | .CrEscape, | ||
| 1253 | .OctalEscape, | ||
| 1254 | .HexEscape, | ||
| 1255 | .UnicodeEscape, | ||
| 1256 | .MultiLineComment, | ||
| 1257 | .MultiLineCommentAsterisk, | ||
| 1258 | .FloatExponent, | ||
| 1259 | .MacroString, | ||
| 1260 | .IntegerLiteralBinaryFirst, | ||
| 1261 | .IntegerLiteralHexFirst, | ||
| 1262 | => result.id = .Invalid, | ||
| 1263 | |||
| 1264 | .FloatExponentDigits => result.id = if (counter == 0) .Invalid else .{ .FloatLiteral = .none }, | ||
| 1265 | |||
| 1266 | .FloatFraction, | ||
| 1267 | .FloatFractionHex, | ||
| 1268 | => result.id = .{ .FloatLiteral = .none }, | ||
| 1269 | |||
| 1270 | .IntegerLiteralOct, | ||
| 1271 | .IntegerLiteralBinary, | ||
| 1272 | .IntegerLiteralHex, | ||
| 1273 | .IntegerLiteral, | ||
| 1274 | .IntegerSuffix, | ||
| 1275 | .Zero, | ||
| 1276 | => result.id = .{ .IntegerLiteral = .none }, | ||
| 1277 | .IntegerSuffixU => result.id = .{ .IntegerLiteral = .u }, | ||
| 1278 | .IntegerSuffixL => result.id = .{ .IntegerLiteral = .l }, | ||
| 1279 | .IntegerSuffixLL => result.id = .{ .IntegerLiteral = .ll }, | ||
| 1280 | .IntegerSuffixUL => result.id = .{ .IntegerLiteral = .lu }, | ||
| 1281 | |||
| 1282 | .FloatSuffix => result.id = .{ .FloatLiteral = .none }, | ||
| 1283 | .Equal => result.id = .Equal, | ||
| 1284 | .Bang => result.id = .Bang, | ||
| 1285 | .Minus => result.id = .Minus, | ||
| 1286 | .Slash => result.id = .Slash, | ||
| 1287 | .Ampersand => result.id = .Ampersand, | ||
| 1288 | .Hash => result.id = .Hash, | ||
| 1289 | .Period => result.id = .Period, | ||
| 1290 | .Pipe => result.id = .Pipe, | ||
| 1291 | .AngleBracketAngleBracketRight => result.id = .AngleBracketAngleBracketRight, | ||
| 1292 | .AngleBracketRight => result.id = .AngleBracketRight, | ||
| 1293 | .AngleBracketAngleBracketLeft => result.id = .AngleBracketAngleBracketLeft, | ||
| 1294 | .AngleBracketLeft => result.id = .AngleBracketLeft, | ||
| 1295 | .Plus => result.id = .Plus, | ||
| 1296 | .Percent => result.id = .Percent, | ||
| 1297 | .Caret => result.id = .Caret, | ||
| 1298 | .Asterisk => result.id = .Asterisk, | ||
| 1299 | .LineComment => result.id = .LineComment, | ||
| 1300 | } | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | self.prev_tok_id = result.id; | ||
| 1304 | result.end = self.index; | ||
| 1305 | return result; | ||
| 1306 | } | ||
| 1307 | }; | ||
| 1308 | |||
| 1309 | test "operators" { | ||
| 1310 | try expectTokens( | ||
| 1311 | \\ ! != | || |= = == | ||
| 1312 | \\ ( ) { } [ ] . .. ... | ||
| 1313 | \\ ^ ^= + ++ += - -- -= | ||
| 1314 | \\ * *= % %= -> : ; / /= | ||
| 1315 | \\ , & && &= ? < <= << | ||
| 1316 | \\ <<= > >= >> >>= ~ # ## | ||
| 1317 | \\ | ||
| 1318 | , &[_]Token.Id{ | ||
| 1319 | .Bang, | ||
| 1320 | .BangEqual, | ||
| 1321 | .Pipe, | ||
| 1322 | .PipePipe, | ||
| 1323 | .PipeEqual, | ||
| 1324 | .Equal, | ||
| 1325 | .EqualEqual, | ||
| 1326 | .Nl, | ||
| 1327 | .LParen, | ||
| 1328 | .RParen, | ||
| 1329 | .LBrace, | ||
| 1330 | .RBrace, | ||
| 1331 | .LBracket, | ||
| 1332 | .RBracket, | ||
| 1333 | .Period, | ||
| 1334 | .Period, | ||
| 1335 | .Period, | ||
| 1336 | .Ellipsis, | ||
| 1337 | .Nl, | ||
| 1338 | .Caret, | ||
| 1339 | .CaretEqual, | ||
| 1340 | .Plus, | ||
| 1341 | .PlusPlus, | ||
| 1342 | .PlusEqual, | ||
| 1343 | .Minus, | ||
| 1344 | .MinusMinus, | ||
| 1345 | .MinusEqual, | ||
| 1346 | .Nl, | ||
| 1347 | .Asterisk, | ||
| 1348 | .AsteriskEqual, | ||
| 1349 | .Percent, | ||
| 1350 | .PercentEqual, | ||
| 1351 | .Arrow, | ||
| 1352 | .Colon, | ||
| 1353 | .Semicolon, | ||
| 1354 | .Slash, | ||
| 1355 | .SlashEqual, | ||
| 1356 | .Nl, | ||
| 1357 | .Comma, | ||
| 1358 | .Ampersand, | ||
| 1359 | .AmpersandAmpersand, | ||
| 1360 | .AmpersandEqual, | ||
| 1361 | .QuestionMark, | ||
| 1362 | .AngleBracketLeft, | ||
| 1363 | .AngleBracketLeftEqual, | ||
| 1364 | .AngleBracketAngleBracketLeft, | ||
| 1365 | .Nl, | ||
| 1366 | .AngleBracketAngleBracketLeftEqual, | ||
| 1367 | .AngleBracketRight, | ||
| 1368 | .AngleBracketRightEqual, | ||
| 1369 | .AngleBracketAngleBracketRight, | ||
| 1370 | .AngleBracketAngleBracketRightEqual, | ||
| 1371 | .Tilde, | ||
| 1372 | .Hash, | ||
| 1373 | .HashHash, | ||
| 1374 | .Nl, | ||
| 1375 | }); | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | test "keywords" { | ||
| 1379 | try expectTokens( | ||
| 1380 | \\auto break case char const continue default do | ||
| 1381 | \\double else enum extern float for goto if int | ||
| 1382 | \\long register return short signed sizeof static | ||
| 1383 | \\struct switch typedef union unsigned void volatile | ||
| 1384 | \\while _Bool _Complex _Imaginary inline restrict _Alignas | ||
| 1385 | \\_Alignof _Atomic _Generic _Noreturn _Static_assert _Thread_local | ||
| 1386 | \\ | ||
| 1387 | , &[_]Token.Id{ | ||
| 1388 | .Keyword_auto, | ||
| 1389 | .Keyword_break, | ||
| 1390 | .Keyword_case, | ||
| 1391 | .Keyword_char, | ||
| 1392 | .Keyword_const, | ||
| 1393 | .Keyword_continue, | ||
| 1394 | .Keyword_default, | ||
| 1395 | .Keyword_do, | ||
| 1396 | .Nl, | ||
| 1397 | .Keyword_double, | ||
| 1398 | .Keyword_else, | ||
| 1399 | .Keyword_enum, | ||
| 1400 | .Keyword_extern, | ||
| 1401 | .Keyword_float, | ||
| 1402 | .Keyword_for, | ||
| 1403 | .Keyword_goto, | ||
| 1404 | .Keyword_if, | ||
| 1405 | .Keyword_int, | ||
| 1406 | .Nl, | ||
| 1407 | .Keyword_long, | ||
| 1408 | .Keyword_register, | ||
| 1409 | .Keyword_return, | ||
| 1410 | .Keyword_short, | ||
| 1411 | .Keyword_signed, | ||
| 1412 | .Keyword_sizeof, | ||
| 1413 | .Keyword_static, | ||
| 1414 | .Nl, | ||
| 1415 | .Keyword_struct, | ||
| 1416 | .Keyword_switch, | ||
| 1417 | .Keyword_typedef, | ||
| 1418 | .Keyword_union, | ||
| 1419 | .Keyword_unsigned, | ||
| 1420 | .Keyword_void, | ||
| 1421 | .Keyword_volatile, | ||
| 1422 | .Nl, | ||
| 1423 | .Keyword_while, | ||
| 1424 | .Keyword_bool, | ||
| 1425 | .Keyword_complex, | ||
| 1426 | .Keyword_imaginary, | ||
| 1427 | .Keyword_inline, | ||
| 1428 | .Keyword_restrict, | ||
| 1429 | .Keyword_alignas, | ||
| 1430 | .Nl, | ||
| 1431 | .Keyword_alignof, | ||
| 1432 | .Keyword_atomic, | ||
| 1433 | .Keyword_generic, | ||
| 1434 | .Keyword_noreturn, | ||
| 1435 | .Keyword_static_assert, | ||
| 1436 | .Keyword_thread_local, | ||
| 1437 | .Nl, | ||
| 1438 | }); | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | test "preprocessor keywords" { | ||
| 1442 | try expectTokens( | ||
| 1443 | \\#include <test> | ||
| 1444 | \\#define #include <1 | ||
| 1445 | \\#ifdef | ||
| 1446 | \\#ifndef | ||
| 1447 | \\#error | ||
| 1448 | \\#pragma | ||
| 1449 | \\ | ||
| 1450 | , &[_]Token.Id{ | ||
| 1451 | .Hash, | ||
| 1452 | .Keyword_include, | ||
| 1453 | .MacroString, | ||
| 1454 | .Nl, | ||
| 1455 | .Hash, | ||
| 1456 | .Keyword_define, | ||
| 1457 | .Hash, | ||
| 1458 | .Identifier, | ||
| 1459 | .AngleBracketLeft, | ||
| 1460 | .{ .IntegerLiteral = .none }, | ||
| 1461 | .Nl, | ||
| 1462 | .Hash, | ||
| 1463 | .Keyword_ifdef, | ||
| 1464 | .Nl, | ||
| 1465 | .Hash, | ||
| 1466 | .Keyword_ifndef, | ||
| 1467 | .Nl, | ||
| 1468 | .Hash, | ||
| 1469 | .Keyword_error, | ||
| 1470 | .Nl, | ||
| 1471 | .Hash, | ||
| 1472 | .Keyword_pragma, | ||
| 1473 | .Nl, | ||
| 1474 | }); | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | test "line continuation" { | ||
| 1478 | try expectTokens( | ||
| 1479 | \\#define foo \ | ||
| 1480 | \\ bar | ||
| 1481 | \\"foo\ | ||
| 1482 | \\ bar" | ||
| 1483 | \\#define "foo" | ||
| 1484 | \\ "bar" | ||
| 1485 | \\#define "foo" \ | ||
| 1486 | \\ "bar" | ||
| 1487 | , &[_]Token.Id{ | ||
| 1488 | .Hash, | ||
| 1489 | .Keyword_define, | ||
| 1490 | .Identifier, | ||
| 1491 | .Identifier, | ||
| 1492 | .Nl, | ||
| 1493 | .{ .StringLiteral = .none }, | ||
| 1494 | .Nl, | ||
| 1495 | .Hash, | ||
| 1496 | .Keyword_define, | ||
| 1497 | .{ .StringLiteral = .none }, | ||
| 1498 | .Nl, | ||
| 1499 | .{ .StringLiteral = .none }, | ||
| 1500 | .Nl, | ||
| 1501 | .Hash, | ||
| 1502 | .Keyword_define, | ||
| 1503 | .{ .StringLiteral = .none }, | ||
| 1504 | .{ .StringLiteral = .none }, | ||
| 1505 | }); | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | test "string prefix" { | ||
| 1509 | try expectTokens( | ||
| 1510 | \\"foo" | ||
| 1511 | \\u"foo" | ||
| 1512 | \\u8"foo" | ||
| 1513 | \\U"foo" | ||
| 1514 | \\L"foo" | ||
| 1515 | \\'foo' | ||
| 1516 | \\u'foo' | ||
| 1517 | \\U'foo' | ||
| 1518 | \\L'foo' | ||
| 1519 | \\ | ||
| 1520 | , &[_]Token.Id{ | ||
| 1521 | .{ .StringLiteral = .none }, | ||
| 1522 | .Nl, | ||
| 1523 | .{ .StringLiteral = .utf_16 }, | ||
| 1524 | .Nl, | ||
| 1525 | .{ .StringLiteral = .utf_8 }, | ||
| 1526 | .Nl, | ||
| 1527 | .{ .StringLiteral = .utf_32 }, | ||
| 1528 | .Nl, | ||
| 1529 | .{ .StringLiteral = .wide }, | ||
| 1530 | .Nl, | ||
| 1531 | .{ .CharLiteral = .none }, | ||
| 1532 | .Nl, | ||
| 1533 | .{ .CharLiteral = .utf_16 }, | ||
| 1534 | .Nl, | ||
| 1535 | .{ .CharLiteral = .utf_32 }, | ||
| 1536 | .Nl, | ||
| 1537 | .{ .CharLiteral = .wide }, | ||
| 1538 | .Nl, | ||
| 1539 | }); | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | test "num suffixes" { | ||
| 1543 | try expectTokens( | ||
| 1544 | \\ 1.0f 1.0L 1.0 .0 1. | ||
| 1545 | \\ 0l 0lu 0ll 0llu 0 | ||
| 1546 | \\ 1u 1ul 1ull 1 | ||
| 1547 | \\ 0x 0b | ||
| 1548 | \\ | ||
| 1549 | , &[_]Token.Id{ | ||
| 1550 | .{ .FloatLiteral = .f }, | ||
| 1551 | .{ .FloatLiteral = .l }, | ||
| 1552 | .{ .FloatLiteral = .none }, | ||
| 1553 | .{ .FloatLiteral = .none }, | ||
| 1554 | .{ .FloatLiteral = .none }, | ||
| 1555 | .Nl, | ||
| 1556 | .{ .IntegerLiteral = .l }, | ||
| 1557 | .{ .IntegerLiteral = .lu }, | ||
| 1558 | .{ .IntegerLiteral = .ll }, | ||
| 1559 | .{ .IntegerLiteral = .llu }, | ||
| 1560 | .{ .IntegerLiteral = .none }, | ||
| 1561 | .Nl, | ||
| 1562 | .{ .IntegerLiteral = .u }, | ||
| 1563 | .{ .IntegerLiteral = .lu }, | ||
| 1564 | .{ .IntegerLiteral = .llu }, | ||
| 1565 | .{ .IntegerLiteral = .none }, | ||
| 1566 | .Nl, | ||
| 1567 | .Invalid, | ||
| 1568 | .Invalid, | ||
| 1569 | .Nl, | ||
| 1570 | }); | ||
| 1571 | } | ||
| 1572 | |||
| 1573 | fn expectTokens(source: []const u8, expected_tokens: []const Token.Id) !void { | ||
| 1574 | var tokenizer = Tokenizer{ | ||
| 1575 | .buffer = source, | ||
| 1576 | }; | ||
| 1577 | for (expected_tokens) |expected_token_id| { | ||
| 1578 | const token = tokenizer.next(); | ||
| 1579 | if (!std.meta.eql(token.id, expected_token_id)) { | ||
| 1580 | std.debug.panic("expected {s}, found {s}\n", .{ @tagName(expected_token_id), @tagName(token.id) }); | ||
| 1581 | } | ||
| 1582 | } | ||
| 1583 | const last_token = tokenizer.next(); | ||
| 1584 | try std.testing.expect(last_token.id == .Eof); | ||
| 1585 | } | ||
lib/std/zig/c_translation.zig+3-3| ... | @@ -252,7 +252,7 @@ test "sizeof" { | ... | @@ -252,7 +252,7 @@ test "sizeof" { |
| 252 | try testing.expect(sizeof(anyopaque) == 1); | 252 | try testing.expect(sizeof(anyopaque) == 1); |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | pub const CIntLiteralBase = enum { decimal, octal, hexadecimal }; | 255 | pub const CIntLiteralBase = enum { decimal, octal, hex }; |
| 256 | 256 | ||
| 257 | /// Deprecated: use `CIntLiteralBase` | 257 | /// Deprecated: use `CIntLiteralBase` |
| 258 | pub const CIntLiteralRadix = CIntLiteralBase; | 258 | pub const CIntLiteralRadix = CIntLiteralBase; |
| ... | @@ -289,13 +289,13 @@ pub fn promoteIntLiteral( | ... | @@ -289,13 +289,13 @@ pub fn promoteIntLiteral( |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | test "promoteIntLiteral" { | 291 | test "promoteIntLiteral" { |
| 292 | const signed_hex = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .hexadecimal); | 292 | const signed_hex = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .hex); |
| 293 | try testing.expectEqual(c_uint, @TypeOf(signed_hex)); | 293 | try testing.expectEqual(c_uint, @TypeOf(signed_hex)); |
| 294 | 294 | ||
| 295 | if (math.maxInt(c_longlong) == math.maxInt(c_int)) return; | 295 | if (math.maxInt(c_longlong) == math.maxInt(c_int)) return; |
| 296 | 296 | ||
| 297 | const signed_decimal = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .decimal); | 297 | const signed_decimal = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .decimal); |
| 298 | const unsigned = promoteIntLiteral(c_uint, math.maxInt(c_uint) + 1, .hexadecimal); | 298 | const unsigned = promoteIntLiteral(c_uint, math.maxInt(c_uint) + 1, .hex); |
| 299 | 299 | ||
| 300 | if (math.maxInt(c_long) > math.maxInt(c_int)) { | 300 | if (math.maxInt(c_long) > math.maxInt(c_int)) { |
| 301 | try testing.expectEqual(c_long, @TypeOf(signed_decimal)); | 301 | try testing.expectEqual(c_long, @TypeOf(signed_decimal)); |
src/Compilation.zig+1-1| ... | @@ -4205,7 +4205,7 @@ pub const CImportResult = struct { | ... | @@ -4205,7 +4205,7 @@ pub const CImportResult = struct { |
| 4205 | /// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked | 4205 | /// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked |
| 4206 | /// a bit when we want to start using it from self-hosted. | 4206 | /// a bit when we want to start using it from self-hosted. |
| 4207 | pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { | 4207 | pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { |
| 4208 | if (build_options.only_c) unreachable; // @cImport is not needed for bootstrapping | 4208 | if (build_options.only_core_functionality) @panic("@cImport is not available in a zig2.c build"); |
| 4209 | const tracy_trace = trace(@src()); | 4209 | const tracy_trace = trace(@src()); |
| 4210 | defer tracy_trace.end(); | 4210 | defer tracy_trace.end(); |
| 4211 | 4211 |
src/main.zig+1-1| ... | @@ -4293,7 +4293,7 @@ fn updateModule(comp: *Compilation) !void { | ... | @@ -4293,7 +4293,7 @@ fn updateModule(comp: *Compilation) !void { |
| 4293 | } | 4293 | } |
| 4294 | 4294 | ||
| 4295 | fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilation.CImportResult) !void { | 4295 | fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilation.CImportResult) !void { |
| 4296 | if (build_options.only_c) unreachable; // translate-c is not needed for bootstrapping | 4296 | if (build_options.only_core_functionality) @panic("@translate-c is not available in a zig2.c build"); |
| 4297 | assert(comp.c_source_files.len == 1); | 4297 | assert(comp.c_source_files.len == 1); |
| 4298 | const c_source_file = comp.c_source_files[0]; | 4298 | const c_source_file = comp.c_source_files[0]; |
| 4299 | 4299 |
src/stubs/aro_builtins.zig+3-1| ... | @@ -22,7 +22,9 @@ pub fn with(comptime Properties: type) type { | ... | @@ -22,7 +22,9 @@ pub fn with(comptime Properties: type) type { |
| 22 | return .{}; | 22 | return .{}; |
| 23 | } | 23 | } |
| 24 | pub fn tagFromName(name: []const u8) ?Tag { | 24 | pub fn tagFromName(name: []const u8) ?Tag { |
| 25 | return @enumFromInt(name.len); | 25 | var res: u16 = 0; |
| 26 | for (name) |c| res +%= c; | ||
| 27 | return @enumFromInt(res); | ||
| 26 | } | 28 | } |
| 27 | pub const NameBuf = struct { | 29 | pub const NameBuf = struct { |
| 28 | pub fn span(_: *const NameBuf) []const u8 { | 30 | pub fn span(_: *const NameBuf) []const u8 { |
src/translate_c.zig+305-261| ... | @@ -1,13 +1,13 @@ | ... | @@ -1,13 +1,13 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const testing = std.testing; | 2 | const testing = std.testing; |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const clang = @import("clang.zig"); | ||
| 5 | const ctok = std.c.tokenizer; | ||
| 6 | const CToken = std.c.Token; | ||
| 7 | const mem = std.mem; | 4 | const mem = std.mem; |
| 8 | const math = std.math; | 5 | const math = std.math; |
| 9 | const meta = std.meta; | 6 | const meta = std.meta; |
| 10 | const CallingConvention = std.builtin.CallingConvention; | 7 | const CallingConvention = std.builtin.CallingConvention; |
| 8 | const clang = @import("clang.zig"); | ||
| 9 | const aro = @import("aro"); | ||
| 10 | const CToken = aro.Tokenizer.Token; | ||
| 11 | const ast = @import("translate_c/ast.zig"); | 11 | const ast = @import("translate_c/ast.zig"); |
| 12 | const Node = ast.Node; | 12 | const Node = ast.Node; |
| 13 | const Tag = Node.Tag; | 13 | const Tag = Node.Tag; |
| ... | @@ -190,19 +190,21 @@ pub fn translate( | ... | @@ -190,19 +190,21 @@ pub fn translate( |
| 190 | 190 | ||
| 191 | /// Determines whether macro is of the form: `#define FOO FOO` (Possibly with trailing tokens) | 191 | /// Determines whether macro is of the form: `#define FOO FOO` (Possibly with trailing tokens) |
| 192 | /// Macros of this form will not be translated. | 192 | /// Macros of this form will not be translated. |
| 193 | fn isSelfDefinedMacro(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) bool { | 193 | fn isSelfDefinedMacro(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) !bool { |
| 194 | const source = getMacroText(unit, c, macro); | 194 | const source = try getMacroText(unit, c, macro); |
| 195 | var tokenizer = std.c.Tokenizer{ | 195 | var tokenizer: aro.Tokenizer = .{ |
| 196 | .buffer = source, | 196 | .buf = source, |
| 197 | .source = .unused, | ||
| 198 | .langopts = .{}, | ||
| 197 | }; | 199 | }; |
| 198 | const name_tok = tokenizer.next(); | 200 | const name_tok = tokenizer.nextNoWS(); |
| 199 | const name = source[name_tok.start..name_tok.end]; | 201 | const name = source[name_tok.start..name_tok.end]; |
| 200 | 202 | ||
| 201 | const first_tok = tokenizer.next(); | 203 | const first_tok = tokenizer.nextNoWS(); |
| 202 | // We do not just check for `.Identifier` below because keyword tokens are preferentially matched first by | 204 | // We do not just check for `.Identifier` below because keyword tokens are preferentially matched first by |
| 203 | // the tokenizer. | 205 | // the tokenizer. |
| 204 | // In other words we would miss `#define inline inline` (`inline` is a valid c89 identifier) | 206 | // In other words we would miss `#define inline inline` (`inline` is a valid c89 identifier) |
| 205 | if (first_tok.id == .Eof) return false; | 207 | if (first_tok.id == .eof) return false; |
| 206 | return mem.eql(u8, name, source[first_tok.start..first_tok.end]); | 208 | return mem.eql(u8, name, source[first_tok.start..first_tok.end]); |
| 207 | } | 209 | } |
| 208 | 210 | ||
| ... | @@ -223,7 +225,7 @@ fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void { | ... | @@ -223,7 +225,7 @@ fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void { |
| 223 | const raw_name = macro.getName_getNameStart(); | 225 | const raw_name = macro.getName_getNameStart(); |
| 224 | const name = try c.str(raw_name); | 226 | const name = try c.str(raw_name); |
| 225 | 227 | ||
| 226 | if (!isSelfDefinedMacro(ast_unit, c, macro)) { | 228 | if (!try isSelfDefinedMacro(ast_unit, c, macro)) { |
| 227 | try c.global_names.put(c.gpa, name, {}); | 229 | try c.global_names.put(c.gpa, name, {}); |
| 228 | } | 230 | } |
| 229 | }, | 231 | }, |
| ... | @@ -5159,16 +5161,16 @@ pub const PatternList = struct { | ... | @@ -5159,16 +5161,16 @@ pub const PatternList = struct { |
| 5159 | /// Assumes that `ms` represents a tokenized function-like macro. | 5161 | /// Assumes that `ms` represents a tokenized function-like macro. |
| 5160 | fn buildArgsHash(allocator: mem.Allocator, ms: MacroSlicer, hash: *ArgsPositionMap) MacroProcessingError!void { | 5162 | fn buildArgsHash(allocator: mem.Allocator, ms: MacroSlicer, hash: *ArgsPositionMap) MacroProcessingError!void { |
| 5161 | assert(ms.tokens.len > 2); | 5163 | assert(ms.tokens.len > 2); |
| 5162 | assert(ms.tokens[0].id == .Identifier); | 5164 | assert(ms.tokens[0].id == .identifier or ms.tokens[0].id == .extended_identifier); |
| 5163 | assert(ms.tokens[1].id == .LParen); | 5165 | assert(ms.tokens[1].id == .l_paren); |
| 5164 | 5166 | ||
| 5165 | var i: usize = 2; | 5167 | var i: usize = 2; |
| 5166 | while (true) : (i += 1) { | 5168 | while (true) : (i += 1) { |
| 5167 | const token = ms.tokens[i]; | 5169 | const token = ms.tokens[i]; |
| 5168 | switch (token.id) { | 5170 | switch (token.id) { |
| 5169 | .RParen => break, | 5171 | .r_paren => break, |
| 5170 | .Comma => continue, | 5172 | .comma => continue, |
| 5171 | .Identifier => { | 5173 | .identifier, .extended_identifier => { |
| 5172 | const identifier = ms.slice(token); | 5174 | const identifier = ms.slice(token); |
| 5173 | try hash.put(allocator, identifier, i); | 5175 | try hash.put(allocator, identifier, i); |
| 5174 | }, | 5176 | }, |
| ... | @@ -5220,18 +5222,18 @@ pub const PatternList = struct { | ... | @@ -5220,18 +5222,18 @@ pub const PatternList = struct { |
| 5220 | if (args_hash.count() != self.args_hash.count()) return false; | 5222 | if (args_hash.count() != self.args_hash.count()) return false; |
| 5221 | 5223 | ||
| 5222 | var i: usize = 2; | 5224 | var i: usize = 2; |
| 5223 | while (self.tokens[i].id != .RParen) : (i += 1) {} | 5225 | while (self.tokens[i].id != .r_paren) : (i += 1) {} |
| 5224 | 5226 | ||
| 5225 | const pattern_slicer = MacroSlicer{ .source = self.source, .tokens = self.tokens }; | 5227 | const pattern_slicer = MacroSlicer{ .source = self.source, .tokens = self.tokens }; |
| 5226 | while (i < self.tokens.len) : (i += 1) { | 5228 | while (i < self.tokens.len) : (i += 1) { |
| 5227 | const pattern_token = self.tokens[i]; | 5229 | const pattern_token = self.tokens[i]; |
| 5228 | const macro_token = ms.tokens[i]; | 5230 | const macro_token = ms.tokens[i]; |
| 5229 | if (meta.activeTag(pattern_token.id) != meta.activeTag(macro_token.id)) return false; | 5231 | if (pattern_token.id != macro_token.id) return false; |
| 5230 | 5232 | ||
| 5231 | const pattern_bytes = pattern_slicer.slice(pattern_token); | 5233 | const pattern_bytes = pattern_slicer.slice(pattern_token); |
| 5232 | const macro_bytes = ms.slice(macro_token); | 5234 | const macro_bytes = ms.slice(macro_token); |
| 5233 | switch (pattern_token.id) { | 5235 | switch (pattern_token.id) { |
| 5234 | .Identifier => { | 5236 | .identifier, .extended_identifier => { |
| 5235 | const pattern_arg_index = self.args_hash.get(pattern_bytes); | 5237 | const pattern_arg_index = self.args_hash.get(pattern_bytes); |
| 5236 | const macro_arg_index = args_hash.get(macro_bytes); | 5238 | const macro_arg_index = args_hash.get(macro_bytes); |
| 5237 | 5239 | ||
| ... | @@ -5243,7 +5245,7 @@ pub const PatternList = struct { | ... | @@ -5243,7 +5245,7 @@ pub const PatternList = struct { |
| 5243 | return false; | 5245 | return false; |
| 5244 | } | 5246 | } |
| 5245 | }, | 5247 | }, |
| 5246 | .MacroString, .StringLiteral, .CharLiteral, .IntegerLiteral, .FloatLiteral => { | 5248 | .string_literal, .char_literal, .pp_num => { |
| 5247 | if (!mem.eql(u8, pattern_bytes, macro_bytes)) return false; | 5249 | if (!mem.eql(u8, pattern_bytes, macro_bytes)) return false; |
| 5248 | }, | 5250 | }, |
| 5249 | else => { | 5251 | else => { |
| ... | @@ -5359,13 +5361,13 @@ const MacroCtx = struct { | ... | @@ -5359,13 +5361,13 @@ const MacroCtx = struct { |
| 5359 | return self.list[self.i].id; | 5361 | return self.list[self.i].id; |
| 5360 | } | 5362 | } |
| 5361 | 5363 | ||
| 5362 | fn skip(self: *MacroCtx, c: *Context, expected_id: std.meta.Tag(CToken.Id)) ParseError!void { | 5364 | fn skip(self: *MacroCtx, c: *Context, expected_id: CToken.Id) ParseError!void { |
| 5363 | const next_id = self.next().?; | 5365 | const next_id = self.next().?; |
| 5364 | if (next_id != expected_id) { | 5366 | if (next_id != expected_id and !(expected_id == .identifier and next_id == .extended_identifier)) { |
| 5365 | try self.fail( | 5367 | try self.fail( |
| 5366 | c, | 5368 | c, |
| 5367 | "unable to translate C expr: expected '{s}' instead got '{s}'", | 5369 | "unable to translate C expr: expected '{s}' instead got '{s}'", |
| 5368 | .{ CToken.Id.symbolName(expected_id), next_id.symbol() }, | 5370 | .{ expected_id.symbol(), next_id.symbol() }, |
| 5369 | ); | 5371 | ); |
| 5370 | return error.ParseError; | 5372 | return error.ParseError; |
| 5371 | } | 5373 | } |
| ... | @@ -5396,12 +5398,12 @@ const MacroCtx = struct { | ... | @@ -5396,12 +5398,12 @@ const MacroCtx = struct { |
| 5396 | while (i < self.list.len) : (i += 1) { | 5398 | while (i < self.list.len) : (i += 1) { |
| 5397 | const token = self.list[i]; | 5399 | const token = self.list[i]; |
| 5398 | switch (token.id) { | 5400 | switch (token.id) { |
| 5399 | .Period, .Arrow => i += 1, // skip next token since field identifiers can be unknown | 5401 | .period, .arrow => i += 1, // skip next token since field identifiers can be unknown |
| 5400 | .Keyword_struct, .Keyword_union, .Keyword_enum => if (!last_is_type_kw) { | 5402 | .keyword_struct, .keyword_union, .keyword_enum => if (!last_is_type_kw) { |
| 5401 | last_is_type_kw = true; | 5403 | last_is_type_kw = true; |
| 5402 | continue; | 5404 | continue; |
| 5403 | }, | 5405 | }, |
| 5404 | .Identifier => { | 5406 | .identifier, .extended_identifier => { |
| 5405 | const identifier = slicer.slice(token); | 5407 | const identifier = slicer.slice(token); |
| 5406 | const is_param = for (params) |param| { | 5408 | const is_param = for (params) |param| { |
| 5407 | if (param.name != null and mem.eql(u8, identifier, param.name.?)) break true; | 5409 | if (param.name != null and mem.eql(u8, identifier, param.name.?)) break true; |
| ... | @@ -5422,31 +5424,38 @@ const MacroCtx = struct { | ... | @@ -5422,31 +5424,38 @@ const MacroCtx = struct { |
| 5422 | }; | 5424 | }; |
| 5423 | 5425 | ||
| 5424 | fn tokenizeMacro(source: []const u8, tok_list: *std.ArrayList(CToken)) Error!void { | 5426 | fn tokenizeMacro(source: []const u8, tok_list: *std.ArrayList(CToken)) Error!void { |
| 5425 | var tokenizer = std.c.Tokenizer{ | 5427 | var tokenizer: aro.Tokenizer = .{ |
| 5426 | .buffer = source, | 5428 | .buf = source, |
| 5429 | .source = .unused, | ||
| 5430 | .langopts = .{}, | ||
| 5427 | }; | 5431 | }; |
| 5428 | while (true) { | 5432 | while (true) { |
| 5429 | const tok = tokenizer.next(); | 5433 | const tok = tokenizer.next(); |
| 5430 | switch (tok.id) { | 5434 | switch (tok.id) { |
| 5431 | .Nl, .Eof => { | 5435 | .whitespace => continue, |
| 5436 | .nl, .eof => { | ||
| 5432 | try tok_list.append(tok); | 5437 | try tok_list.append(tok); |
| 5433 | break; | 5438 | break; |
| 5434 | }, | 5439 | }, |
| 5435 | .LineComment, .MultiLineComment => continue, | ||
| 5436 | else => {}, | 5440 | else => {}, |
| 5437 | } | 5441 | } |
| 5438 | try tok_list.append(tok); | 5442 | try tok_list.append(tok); |
| 5439 | } | 5443 | } |
| 5440 | } | 5444 | } |
| 5441 | 5445 | ||
| 5442 | fn getMacroText(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) []const u8 { | 5446 | fn getMacroText(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) ![]const u8 { |
| 5443 | const begin_loc = macro.getSourceRange_getBegin(); | 5447 | const begin_loc = macro.getSourceRange_getBegin(); |
| 5444 | const end_loc = clang.Lexer.getLocForEndOfToken(macro.getSourceRange_getEnd(), c.source_manager, unit); | 5448 | const end_loc = clang.Lexer.getLocForEndOfToken(macro.getSourceRange_getEnd(), c.source_manager, unit); |
| 5445 | 5449 | ||
| 5446 | const begin_c = c.source_manager.getCharacterData(begin_loc); | 5450 | const begin_c = c.source_manager.getCharacterData(begin_loc); |
| 5447 | const end_c = c.source_manager.getCharacterData(end_loc); | 5451 | const end_c = c.source_manager.getCharacterData(end_loc); |
| 5448 | const slice_len = @intFromPtr(end_c) - @intFromPtr(begin_c); | 5452 | const slice_len = @intFromPtr(end_c) - @intFromPtr(begin_c); |
| 5449 | return begin_c[0..slice_len]; | 5453 | |
| 5454 | var comp = aro.Compilation.init(c.gpa); | ||
| 5455 | defer comp.deinit(); | ||
| 5456 | const result = comp.addSourceFromBuffer("", begin_c[0..slice_len]) catch return error.OutOfMemory; | ||
| 5457 | |||
| 5458 | return c.arena.dupe(u8, result.buf); | ||
| 5450 | } | 5459 | } |
| 5451 | 5460 | ||
| 5452 | fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { | 5461 | fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| ... | @@ -5471,7 +5480,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { | ... | @@ -5471,7 +5480,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5471 | continue; | 5480 | continue; |
| 5472 | } | 5481 | } |
| 5473 | 5482 | ||
| 5474 | const source = getMacroText(unit, c, macro); | 5483 | const source = try getMacroText(unit, c, macro); |
| 5475 | 5484 | ||
| 5476 | try tokenizeMacro(source, &tok_list); | 5485 | try tokenizeMacro(source, &tok_list); |
| 5477 | 5486 | ||
| ... | @@ -5485,7 +5494,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { | ... | @@ -5485,7 +5494,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5485 | 5494 | ||
| 5486 | var macro_fn = false; | 5495 | var macro_fn = false; |
| 5487 | switch (macro_ctx.peek().?) { | 5496 | switch (macro_ctx.peek().?) { |
| 5488 | .Identifier => { | 5497 | .identifier, .extended_identifier => { |
| 5489 | // if it equals itself, ignore. for example, from stdio.h: | 5498 | // if it equals itself, ignore. for example, from stdio.h: |
| 5490 | // #define stdin stdin | 5499 | // #define stdin stdin |
| 5491 | const tok = macro_ctx.list[1]; | 5500 | const tok = macro_ctx.list[1]; |
| ... | @@ -5494,7 +5503,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { | ... | @@ -5494,7 +5503,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5494 | continue; | 5503 | continue; |
| 5495 | } | 5504 | } |
| 5496 | }, | 5505 | }, |
| 5497 | .Nl, .Eof => { | 5506 | .nl, .eof => { |
| 5498 | // this means it is a macro without a value | 5507 | // this means it is a macro without a value |
| 5499 | // We define it as an empty string so that it can still be used with ++ | 5508 | // We define it as an empty string so that it can still be used with ++ |
| 5500 | const str_node = try Tag.string_literal.create(c.arena, "\"\""); | 5509 | const str_node = try Tag.string_literal.create(c.arena, "\"\""); |
| ... | @@ -5503,7 +5512,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { | ... | @@ -5503,7 +5512,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5503 | try c.global_scope.blank_macros.put(name, {}); | 5512 | try c.global_scope.blank_macros.put(name, {}); |
| 5504 | continue; | 5513 | continue; |
| 5505 | }, | 5514 | }, |
| 5506 | .LParen => { | 5515 | .l_paren => { |
| 5507 | // if the name is immediately followed by a '(' then it is a function | 5516 | // if the name is immediately followed by a '(' then it is a function |
| 5508 | macro_fn = macro_ctx.list[0].end == macro_ctx.list[1].start; | 5517 | macro_fn = macro_ctx.list[0].end == macro_ctx.list[1].start; |
| 5509 | }, | 5518 | }, |
| ... | @@ -5534,7 +5543,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5534,7 +5543,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5534 | // Check if the macro only uses other blank macros. | 5543 | // Check if the macro only uses other blank macros. |
| 5535 | while (true) { | 5544 | while (true) { |
| 5536 | switch (m.peek().?) { | 5545 | switch (m.peek().?) { |
| 5537 | .Identifier => { | 5546 | .identifier, .extended_identifier => { |
| 5538 | const tok = m.list[m.i + 1]; | 5547 | const tok = m.list[m.i + 1]; |
| 5539 | const slice = m.source[tok.start..tok.end]; | 5548 | const slice = m.source[tok.start..tok.end]; |
| 5540 | if (c.global_scope.blank_macros.contains(slice)) { | 5549 | if (c.global_scope.blank_macros.contains(slice)) { |
| ... | @@ -5542,7 +5551,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5542,7 +5551,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5542 | continue; | 5551 | continue; |
| 5543 | } | 5552 | } |
| 5544 | }, | 5553 | }, |
| 5545 | .Eof, .Nl => { | 5554 | .eof, .nl => { |
| 5546 | try c.global_scope.blank_macros.put(m.name, {}); | 5555 | try c.global_scope.blank_macros.put(m.name, {}); |
| 5547 | const init_node = try Tag.string_literal.create(c.arena, "\"\""); | 5556 | const init_node = try Tag.string_literal.create(c.arena, "\"\""); |
| 5548 | const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node }); | 5557 | const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node }); |
| ... | @@ -5556,7 +5565,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5556,7 +5565,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5556 | 5565 | ||
| 5557 | const init_node = try parseCExpr(c, m, scope); | 5566 | const init_node = try parseCExpr(c, m, scope); |
| 5558 | const last = m.next().?; | 5567 | const last = m.next().?; |
| 5559 | if (last != .Eof and last != .Nl) | 5568 | if (last != .eof and last != .nl) |
| 5560 | return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()}); | 5569 | return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()}); |
| 5561 | 5570 | ||
| 5562 | const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node }); | 5571 | const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node }); |
| ... | @@ -5578,14 +5587,16 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5578,14 +5587,16 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5578 | defer block_scope.deinit(); | 5587 | defer block_scope.deinit(); |
| 5579 | const scope = &block_scope.base; | 5588 | const scope = &block_scope.base; |
| 5580 | 5589 | ||
| 5581 | try m.skip(c, .LParen); | 5590 | try m.skip(c, .l_paren); |
| 5582 | 5591 | ||
| 5583 | var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa); | 5592 | var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa); |
| 5584 | defer fn_params.deinit(); | 5593 | defer fn_params.deinit(); |
| 5585 | 5594 | ||
| 5586 | while (true) { | 5595 | while (true) { |
| 5587 | if (m.peek().? != .Identifier) break; | 5596 | switch (m.peek().?) { |
| 5588 | _ = m.next(); | 5597 | .identifier, .extended_identifier => _ = m.next(), |
| 5598 | else => break, | ||
| 5599 | } | ||
| 5589 | 5600 | ||
| 5590 | const mangled_name = try block_scope.makeMangledName(c, m.slice()); | 5601 | const mangled_name = try block_scope.makeMangledName(c, m.slice()); |
| 5591 | try fn_params.append(.{ | 5602 | try fn_params.append(.{ |
| ... | @@ -5594,11 +5605,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5594,11 +5605,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5594 | .type = Tag.@"anytype".init(), | 5605 | .type = Tag.@"anytype".init(), |
| 5595 | }); | 5606 | }); |
| 5596 | try block_scope.discardVariable(c, mangled_name); | 5607 | try block_scope.discardVariable(c, mangled_name); |
| 5597 | if (m.peek().? != .Comma) break; | 5608 | if (m.peek().? != .comma) break; |
| 5598 | _ = m.next(); | 5609 | _ = m.next(); |
| 5599 | } | 5610 | } |
| 5600 | 5611 | ||
| 5601 | try m.skip(c, .RParen); | 5612 | try m.skip(c, .r_paren); |
| 5602 | 5613 | ||
| 5603 | if (m.checkTranslatableMacro(scope, fn_params.items)) |err| switch (err) { | 5614 | if (m.checkTranslatableMacro(scope, fn_params.items)) |err| switch (err) { |
| 5604 | .undefined_identifier => |ident| return m.fail(c, "unable to translate macro: undefined identifier `{s}`", .{ident}), | 5615 | .undefined_identifier => |ident| return m.fail(c, "unable to translate macro: undefined identifier `{s}`", .{ident}), |
| ... | @@ -5607,7 +5618,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { | ... | @@ -5607,7 +5618,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5607 | 5618 | ||
| 5608 | const expr = try parseCExpr(c, m, scope); | 5619 | const expr = try parseCExpr(c, m, scope); |
| 5609 | const last = m.next().?; | 5620 | const last = m.next().?; |
| 5610 | if (last != .Eof and last != .Nl) | 5621 | if (last != .eof and last != .nl) |
| 5611 | return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()}); | 5622 | return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()}); |
| 5612 | 5623 | ||
| 5613 | const typeof_arg = if (expr.castTag(.block)) |some| blk: { | 5624 | const typeof_arg = if (expr.castTag(.block)) |some| blk: { |
| ... | @@ -5644,7 +5655,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -5644,7 +5655,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5644 | defer block_scope.deinit(); | 5655 | defer block_scope.deinit(); |
| 5645 | 5656 | ||
| 5646 | const node = try parseCCondExpr(c, m, &block_scope.base); | 5657 | const node = try parseCCondExpr(c, m, &block_scope.base); |
| 5647 | if (m.next().? != .Comma) { | 5658 | if (m.next().? != .comma) { |
| 5648 | m.i -= 1; | 5659 | m.i -= 1; |
| 5649 | return node; | 5660 | return node; |
| 5650 | } | 5661 | } |
| ... | @@ -5656,7 +5667,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -5656,7 +5667,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5656 | try block_scope.statements.append(ignore); | 5667 | try block_scope.statements.append(ignore); |
| 5657 | 5668 | ||
| 5658 | last = try parseCCondExpr(c, m, &block_scope.base); | 5669 | last = try parseCCondExpr(c, m, &block_scope.base); |
| 5659 | if (m.next().? != .Comma) { | 5670 | if (m.next().? != .comma) { |
| 5660 | m.i -= 1; | 5671 | m.i -= 1; |
| 5661 | break; | 5672 | break; |
| 5662 | } | 5673 | } |
| ... | @@ -5670,118 +5681,135 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -5670,118 +5681,135 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5670 | return try block_scope.complete(c); | 5681 | return try block_scope.complete(c); |
| 5671 | } | 5682 | } |
| 5672 | 5683 | ||
| 5673 | fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { | 5684 | fn parseCNumLit(ctx: *Context, m: *MacroCtx) ParseError!Node { |
| 5674 | var lit_bytes = m.slice(); | 5685 | const lit_bytes = m.slice(); |
| 5686 | var bytes = try std.ArrayListUnmanaged(u8).initCapacity(ctx.arena, lit_bytes.len + 3); | ||
| 5675 | 5687 | ||
| 5676 | switch (m.list[m.i].id) { | 5688 | const prefix = aro.Tree.Token.NumberPrefix.fromString(lit_bytes); |
| 5677 | .IntegerLiteral => |suffix| { | 5689 | switch (prefix) { |
| 5678 | var base: []const u8 = "decimal"; | 5690 | .binary => bytes.appendSliceAssumeCapacity("0b"), |
| 5679 | if (lit_bytes.len >= 2 and lit_bytes[0] == '0') { | 5691 | .octal => bytes.appendSliceAssumeCapacity("0o"), |
| 5680 | switch (lit_bytes[1]) { | 5692 | .hex => bytes.appendSliceAssumeCapacity("0x"), |
| 5681 | '0'...'7' => { | 5693 | .decimal => {}, |
| 5682 | // Octal | 5694 | } |
| 5683 | lit_bytes = try std.fmt.allocPrint(c.arena, "0o{s}", .{lit_bytes[1..]}); | ||
| 5684 | base = "octal"; | ||
| 5685 | }, | ||
| 5686 | 'X' => { | ||
| 5687 | // Hexadecimal with capital X, valid in C but not in Zig | ||
| 5688 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]}); | ||
| 5689 | base = "hexadecimal"; | ||
| 5690 | }, | ||
| 5691 | 'x' => { | ||
| 5692 | base = "hexadecimal"; | ||
| 5693 | }, | ||
| 5694 | else => {}, | ||
| 5695 | } | ||
| 5696 | } | ||
| 5697 | |||
| 5698 | const type_node = try Tag.type.create(c.arena, switch (suffix) { | ||
| 5699 | .none => "c_int", | ||
| 5700 | .u => "c_uint", | ||
| 5701 | .l => "c_long", | ||
| 5702 | .lu => "c_ulong", | ||
| 5703 | .ll => "c_longlong", | ||
| 5704 | .llu => "c_ulonglong", | ||
| 5705 | .f => unreachable, | ||
| 5706 | }); | ||
| 5707 | lit_bytes = lit_bytes[0 .. lit_bytes.len - switch (suffix) { | ||
| 5708 | .none => @as(u8, 0), | ||
| 5709 | .u, .l => 1, | ||
| 5710 | .lu, .ll => 2, | ||
| 5711 | .llu => 3, | ||
| 5712 | .f => unreachable, | ||
| 5713 | }]; | ||
| 5714 | |||
| 5715 | const value = std.fmt.parseInt(i128, lit_bytes, 0) catch math.maxInt(i128); | ||
| 5716 | |||
| 5717 | // make the output less noisy by skipping promoteIntLiteral where | ||
| 5718 | // it's guaranteed to not be required because of C standard type constraints | ||
| 5719 | const guaranteed_to_fit = switch (suffix) { | ||
| 5720 | .none => math.cast(i16, value) != null, | ||
| 5721 | .u => math.cast(u16, value) != null, | ||
| 5722 | .l => math.cast(i32, value) != null, | ||
| 5723 | .lu => math.cast(u32, value) != null, | ||
| 5724 | .ll => math.cast(i64, value) != null, | ||
| 5725 | .llu => math.cast(u64, value) != null, | ||
| 5726 | .f => unreachable, | ||
| 5727 | }; | ||
| 5728 | |||
| 5729 | const literal_node = try transCreateNodeNumber(c, lit_bytes, .int); | ||
| 5730 | 5695 | ||
| 5731 | if (guaranteed_to_fit) { | 5696 | const after_prefix = lit_bytes[prefix.stringLen()..]; |
| 5732 | return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = literal_node }); | 5697 | const after_int = for (after_prefix, 0..) |c, i| switch (c) { |
| 5733 | } else { | 5698 | '.' => { |
| 5734 | return Tag.helpers_promoteIntLiteral.create(c.arena, .{ | 5699 | if (i == 0) { |
| 5735 | .type = type_node, | 5700 | bytes.appendAssumeCapacity('0'); |
| 5736 | .value = literal_node, | ||
| 5737 | .base = try Tag.enum_literal.create(c.arena, base), | ||
| 5738 | }); | ||
| 5739 | } | 5701 | } |
| 5702 | break after_prefix[i..]; | ||
| 5740 | }, | 5703 | }, |
| 5741 | .FloatLiteral => |suffix| { | 5704 | 'e', 'E' => { |
| 5742 | if (suffix != .none) lit_bytes = lit_bytes[0 .. lit_bytes.len - 1]; | 5705 | if (prefix != .hex) break after_prefix[i..]; |
| 5743 | 5706 | bytes.appendAssumeCapacity(c); | |
| 5744 | if (lit_bytes.len >= 2 and std.ascii.eqlIgnoreCase(lit_bytes[0..2], "0x")) { | 5707 | }, |
| 5745 | if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| { | 5708 | 'p', 'P' => break after_prefix[i..], |
| 5746 | if (dot_index == 2) { | 5709 | '0'...'9', 'a'...'d', 'A'...'D', 'f', 'F' => { |
| 5747 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x0{s}", .{lit_bytes[2..]}); | 5710 | if (!prefix.digitAllowed(c)) break after_prefix[i..]; |
| 5748 | } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isHex(lit_bytes[dot_index + 1])) { | 5711 | bytes.appendAssumeCapacity(c); |
| 5749 | // If the literal lacks a digit after the `.`, we need to | 5712 | }, |
| 5750 | // add one since `0x1.p10` would be invalid syntax in Zig. | 5713 | '\'' => { |
| 5751 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}0{s}", .{ | 5714 | bytes.appendAssumeCapacity('_'); |
| 5752 | lit_bytes[2 .. dot_index + 1], | 5715 | }, |
| 5753 | lit_bytes[dot_index + 1 ..], | 5716 | else => break after_prefix[i..], |
| 5754 | }); | 5717 | } else ""; |
| 5755 | } | ||
| 5756 | } | ||
| 5757 | 5718 | ||
| 5758 | if (lit_bytes[1] == 'X') { | 5719 | const after_frac = frac: { |
| 5759 | // Hexadecimal with capital X, valid in C but not in Zig | 5720 | if (after_int.len == 0 or after_int[0] != '.') break :frac after_int; |
| 5760 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]}); | 5721 | bytes.appendAssumeCapacity('.'); |
| 5761 | } | 5722 | for (after_int[1..], 1..) |c, i| { |
| 5762 | } else if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| { | 5723 | if (c == '\'') { |
| 5763 | if (dot_index == 0) { | 5724 | bytes.appendAssumeCapacity('_'); |
| 5764 | lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes}); | 5725 | continue; |
| 5765 | } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isDigit(lit_bytes[dot_index + 1])) { | ||
| 5766 | // If the literal lacks a digit after the `.`, we need to | ||
| 5767 | // add one since `1.` or `1.e10` would be invalid syntax in Zig. | ||
| 5768 | lit_bytes = try std.fmt.allocPrint(c.arena, "{s}0{s}", .{ | ||
| 5769 | lit_bytes[0 .. dot_index + 1], | ||
| 5770 | lit_bytes[dot_index + 1 ..], | ||
| 5771 | }); | ||
| 5772 | } | ||
| 5773 | } | 5726 | } |
| 5727 | if (!prefix.digitAllowed(c)) break :frac after_int[i..]; | ||
| 5728 | bytes.appendAssumeCapacity(c); | ||
| 5729 | } | ||
| 5730 | break :frac ""; | ||
| 5731 | }; | ||
| 5732 | |||
| 5733 | const suffix_str = exponent: { | ||
| 5734 | if (after_frac.len == 0) break :exponent after_frac; | ||
| 5735 | switch (after_frac[0]) { | ||
| 5736 | 'e', 'E' => {}, | ||
| 5737 | 'p', 'P' => if (prefix != .hex) break :exponent after_frac, | ||
| 5738 | else => break :exponent after_frac, | ||
| 5739 | } | ||
| 5740 | bytes.appendAssumeCapacity(after_frac[0]); | ||
| 5741 | for (after_frac[1..], 1..) |c, i| switch (c) { | ||
| 5742 | '+', '-', '0'...'9' => { | ||
| 5743 | bytes.appendAssumeCapacity(c); | ||
| 5744 | }, | ||
| 5745 | '\'' => { | ||
| 5746 | bytes.appendAssumeCapacity('_'); | ||
| 5747 | }, | ||
| 5748 | else => break :exponent after_frac[i..], | ||
| 5749 | }; | ||
| 5750 | break :exponent ""; | ||
| 5751 | }; | ||
| 5752 | |||
| 5753 | const is_float = after_int.len != suffix_str.len; | ||
| 5754 | const suffix = aro.Tree.Token.NumberSuffix.fromString(suffix_str, if (is_float) .float else .int) orelse { | ||
| 5755 | try m.fail(ctx, "invalid number suffix: '{s}'", .{suffix_str}); | ||
| 5756 | return error.ParseError; | ||
| 5757 | }; | ||
| 5758 | if (suffix.isImaginary()) { | ||
| 5759 | try m.fail(ctx, "TODO: imaginary literals", .{}); | ||
| 5760 | return error.ParseError; | ||
| 5761 | } | ||
| 5762 | if (suffix.isBitInt()) { | ||
| 5763 | try m.fail(ctx, "TODO: _BitInt literals", .{}); | ||
| 5764 | return error.ParseError; | ||
| 5765 | } | ||
| 5766 | |||
| 5767 | if (is_float) { | ||
| 5768 | const type_node = try Tag.type.create(ctx.arena, switch (suffix) { | ||
| 5769 | .F16 => "f16", | ||
| 5770 | .F => "f32", | ||
| 5771 | .None => "f64", | ||
| 5772 | .L => "c_longdouble", | ||
| 5773 | .W => "f80", | ||
| 5774 | .Q, .F128 => "f128", | ||
| 5775 | else => unreachable, | ||
| 5776 | }); | ||
| 5777 | const rhs = try Tag.float_literal.create(ctx.arena, bytes.items); | ||
| 5778 | return Tag.as.create(ctx.arena, .{ .lhs = type_node, .rhs = rhs }); | ||
| 5779 | } else { | ||
| 5780 | const type_node = try Tag.type.create(ctx.arena, switch (suffix) { | ||
| 5781 | .None => "c_int", | ||
| 5782 | .U => "c_uint", | ||
| 5783 | .L => "c_long", | ||
| 5784 | .UL => "c_ulong", | ||
| 5785 | .LL => "c_longlong", | ||
| 5786 | .ULL => "c_ulonglong", | ||
| 5787 | else => unreachable, | ||
| 5788 | }); | ||
| 5789 | const value = std.fmt.parseInt(i128, bytes.items, 0) catch math.maxInt(i128); | ||
| 5790 | |||
| 5791 | // make the output less noisy by skipping promoteIntLiteral where | ||
| 5792 | // it's guaranteed to not be required because of C standard type constraints | ||
| 5793 | const guaranteed_to_fit = switch (suffix) { | ||
| 5794 | .None => math.cast(i16, value) != null, | ||
| 5795 | .U => math.cast(u16, value) != null, | ||
| 5796 | .L => math.cast(i32, value) != null, | ||
| 5797 | .UL => math.cast(u32, value) != null, | ||
| 5798 | .LL => math.cast(i64, value) != null, | ||
| 5799 | .ULL => math.cast(u64, value) != null, | ||
| 5800 | else => unreachable, | ||
| 5801 | }; | ||
| 5774 | 5802 | ||
| 5775 | const type_node = try Tag.type.create(c.arena, switch (suffix) { | 5803 | const literal_node = try Tag.integer_literal.create(ctx.arena, bytes.items); |
| 5776 | .f => "f32", | 5804 | if (guaranteed_to_fit) { |
| 5777 | .none => "f64", | 5805 | return Tag.as.create(ctx.arena, .{ .lhs = type_node, .rhs = literal_node }); |
| 5778 | .l => "c_longdouble", | 5806 | } else { |
| 5779 | else => unreachable, | 5807 | return Tag.helpers_promoteIntLiteral.create(ctx.arena, .{ |
| 5808 | .type = type_node, | ||
| 5809 | .value = literal_node, | ||
| 5810 | .base = try Tag.enum_literal.create(ctx.arena, @tagName(prefix)), | ||
| 5780 | }); | 5811 | }); |
| 5781 | const rhs = try transCreateNodeNumber(c, lit_bytes, .float); | 5812 | } |
| 5782 | return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs }); | ||
| 5783 | }, | ||
| 5784 | else => unreachable, | ||
| 5785 | } | 5813 | } |
| 5786 | } | 5814 | } |
| 5787 | 5815 | ||
| ... | @@ -5800,17 +5828,17 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5800,17 +5828,17 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5800 | } else return source; | 5828 | } else return source; |
| 5801 | var bytes = try ctx.arena.alloc(u8, source.len * 2); | 5829 | var bytes = try ctx.arena.alloc(u8, source.len * 2); |
| 5802 | var state: enum { | 5830 | var state: enum { |
| 5803 | Start, | 5831 | start, |
| 5804 | Escape, | 5832 | escape, |
| 5805 | Hex, | 5833 | hex, |
| 5806 | Octal, | 5834 | octal, |
| 5807 | } = .Start; | 5835 | } = .start; |
| 5808 | var i: usize = 0; | 5836 | var i: usize = 0; |
| 5809 | var count: u8 = 0; | 5837 | var count: u8 = 0; |
| 5810 | var num: u8 = 0; | 5838 | var num: u8 = 0; |
| 5811 | for (source) |c| { | 5839 | for (source) |c| { |
| 5812 | switch (state) { | 5840 | switch (state) { |
| 5813 | .Escape => { | 5841 | .escape => { |
| 5814 | switch (c) { | 5842 | switch (c) { |
| 5815 | 'n', 'r', 't', '\\', '\'', '\"' => { | 5843 | 'n', 'r', 't', '\\', '\'', '\"' => { |
| 5816 | bytes[i] = c; | 5844 | bytes[i] = c; |
| ... | @@ -5818,11 +5846,11 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5818,11 +5846,11 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5818 | '0'...'7' => { | 5846 | '0'...'7' => { |
| 5819 | count += 1; | 5847 | count += 1; |
| 5820 | num += c - '0'; | 5848 | num += c - '0'; |
| 5821 | state = .Octal; | 5849 | state = .octal; |
| 5822 | bytes[i] = 'x'; | 5850 | bytes[i] = 'x'; |
| 5823 | }, | 5851 | }, |
| 5824 | 'x' => { | 5852 | 'x' => { |
| 5825 | state = .Hex; | 5853 | state = .hex; |
| 5826 | bytes[i] = 'x'; | 5854 | bytes[i] = 'x'; |
| 5827 | }, | 5855 | }, |
| 5828 | 'a' => { | 5856 | 'a' => { |
| ... | @@ -5867,10 +5895,10 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5867,10 +5895,10 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5867 | }, | 5895 | }, |
| 5868 | } | 5896 | } |
| 5869 | i += 1; | 5897 | i += 1; |
| 5870 | if (state == .Escape) | 5898 | if (state == .escape) |
| 5871 | state = .Start; | 5899 | state = .start; |
| 5872 | }, | 5900 | }, |
| 5873 | .Start => { | 5901 | .start => { |
| 5874 | if (c == '\t') { | 5902 | if (c == '\t') { |
| 5875 | bytes[i] = '\\'; | 5903 | bytes[i] = '\\'; |
| 5876 | i += 1; | 5904 | i += 1; |
| ... | @@ -5879,12 +5907,12 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5879,12 +5907,12 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5879 | continue; | 5907 | continue; |
| 5880 | } | 5908 | } |
| 5881 | if (c == '\\') { | 5909 | if (c == '\\') { |
| 5882 | state = .Escape; | 5910 | state = .escape; |
| 5883 | } | 5911 | } |
| 5884 | bytes[i] = c; | 5912 | bytes[i] = c; |
| 5885 | i += 1; | 5913 | i += 1; |
| 5886 | }, | 5914 | }, |
| 5887 | .Hex => { | 5915 | .hex => { |
| 5888 | switch (c) { | 5916 | switch (c) { |
| 5889 | '0'...'9' => { | 5917 | '0'...'9' => { |
| 5890 | num = std.math.mul(u8, num, 16) catch { | 5918 | num = std.math.mul(u8, num, 16) catch { |
| ... | @@ -5911,15 +5939,15 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5911,15 +5939,15 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5911 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); | 5939 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); |
| 5912 | num = 0; | 5940 | num = 0; |
| 5913 | if (c == '\\') | 5941 | if (c == '\\') |
| 5914 | state = .Escape | 5942 | state = .escape |
| 5915 | else | 5943 | else |
| 5916 | state = .Start; | 5944 | state = .start; |
| 5917 | bytes[i] = c; | 5945 | bytes[i] = c; |
| 5918 | i += 1; | 5946 | i += 1; |
| 5919 | }, | 5947 | }, |
| 5920 | } | 5948 | } |
| 5921 | }, | 5949 | }, |
| 5922 | .Octal => { | 5950 | .octal => { |
| 5923 | const accept_digit = switch (c) { | 5951 | const accept_digit = switch (c) { |
| 5924 | // The maximum length of a octal literal is 3 digits | 5952 | // The maximum length of a octal literal is 3 digits |
| 5925 | '0'...'7' => count < 3, | 5953 | '0'...'7' => count < 3, |
| ... | @@ -5938,16 +5966,16 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5938,16 +5966,16 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5938 | num = 0; | 5966 | num = 0; |
| 5939 | count = 0; | 5967 | count = 0; |
| 5940 | if (c == '\\') | 5968 | if (c == '\\') |
| 5941 | state = .Escape | 5969 | state = .escape |
| 5942 | else | 5970 | else |
| 5943 | state = .Start; | 5971 | state = .start; |
| 5944 | bytes[i] = c; | 5972 | bytes[i] = c; |
| 5945 | i += 1; | 5973 | i += 1; |
| 5946 | } | 5974 | } |
| 5947 | }, | 5975 | }, |
| 5948 | } | 5976 | } |
| 5949 | } | 5977 | } |
| 5950 | if (state == .Hex or state == .Octal) | 5978 | if (state == .hex or state == .octal) |
| 5951 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); | 5979 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); |
| 5952 | return bytes[0..i]; | 5980 | return bytes[0..i]; |
| 5953 | } | 5981 | } |
| ... | @@ -5972,7 +6000,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N | ... | @@ -5972,7 +6000,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5972 | const tok = m.next().?; | 6000 | const tok = m.next().?; |
| 5973 | const slice = m.slice(); | 6001 | const slice = m.slice(); |
| 5974 | switch (tok) { | 6002 | switch (tok) { |
| 5975 | .CharLiteral => { | 6003 | .char_literal, |
| 6004 | .char_literal_utf_8, | ||
| 6005 | .char_literal_utf_16, | ||
| 6006 | .char_literal_utf_32, | ||
| 6007 | .char_literal_wide, | ||
| 6008 | => { | ||
| 5976 | if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) { | 6009 | if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) { |
| 5977 | return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m)); | 6010 | return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m)); |
| 5978 | } else { | 6011 | } else { |
| ... | @@ -5980,13 +6013,18 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N | ... | @@ -5980,13 +6013,18 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5980 | return Tag.integer_literal.create(c.arena, str); | 6013 | return Tag.integer_literal.create(c.arena, str); |
| 5981 | } | 6014 | } |
| 5982 | }, | 6015 | }, |
| 5983 | .StringLiteral => { | 6016 | .string_literal, |
| 6017 | .string_literal_utf_16, | ||
| 6018 | .string_literal_utf_8, | ||
| 6019 | .string_literal_utf_32, | ||
| 6020 | .string_literal_wide, | ||
| 6021 | => { | ||
| 5984 | return Tag.string_literal.create(c.arena, try escapeUnprintables(c, m)); | 6022 | return Tag.string_literal.create(c.arena, try escapeUnprintables(c, m)); |
| 5985 | }, | 6023 | }, |
| 5986 | .IntegerLiteral, .FloatLiteral => { | 6024 | .pp_num => { |
| 5987 | return parseCNumLit(c, m); | 6025 | return parseCNumLit(c, m); |
| 5988 | }, | 6026 | }, |
| 5989 | .Identifier => { | 6027 | .identifier, .extended_identifier => { |
| 5990 | if (c.global_scope.blank_macros.contains(slice)) { | 6028 | if (c.global_scope.blank_macros.contains(slice)) { |
| 5991 | return parseCPrimaryExprInner(c, m, scope); | 6029 | return parseCPrimaryExprInner(c, m, scope); |
| 5992 | } | 6030 | } |
| ... | @@ -5996,10 +6034,10 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N | ... | @@ -5996,10 +6034,10 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5996 | scope.skipVariableDiscard(identifier.castTag(.identifier).?.data); | 6034 | scope.skipVariableDiscard(identifier.castTag(.identifier).?.data); |
| 5997 | return identifier; | 6035 | return identifier; |
| 5998 | }, | 6036 | }, |
| 5999 | .LParen => { | 6037 | .l_paren => { |
| 6000 | const inner_node = try parseCExpr(c, m, scope); | 6038 | const inner_node = try parseCExpr(c, m, scope); |
| 6001 | 6039 | ||
| 6002 | try m.skip(c, .RParen); | 6040 | try m.skip(c, .r_paren); |
| 6003 | return inner_node; | 6041 | return inner_node; |
| 6004 | }, | 6042 | }, |
| 6005 | else => { | 6043 | else => { |
| ... | @@ -6022,8 +6060,13 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6022,8 +6060,13 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6022 | // after a primary expression. | 6060 | // after a primary expression. |
| 6023 | while (true) { | 6061 | while (true) { |
| 6024 | switch (m.peek().?) { | 6062 | switch (m.peek().?) { |
| 6025 | .StringLiteral => {}, | 6063 | .string_literal, |
| 6026 | .Identifier => { | 6064 | .string_literal_utf_16, |
| 6065 | .string_literal_utf_8, | ||
| 6066 | .string_literal_utf_32, | ||
| 6067 | .string_literal_wide, | ||
| 6068 | => {}, | ||
| 6069 | .identifier, .extended_identifier => { | ||
| 6027 | const tok = m.list[m.i + 1]; | 6070 | const tok = m.list[m.i + 1]; |
| 6028 | const slice = m.source[tok.start..tok.end]; | 6071 | const slice = m.source[tok.start..tok.end]; |
| 6029 | if (c.global_scope.blank_macros.contains(slice)) { | 6072 | if (c.global_scope.blank_macros.contains(slice)) { |
| ... | @@ -6057,20 +6100,20 @@ fn macroIntToBool(c: *Context, node: Node) !Node { | ... | @@ -6057,20 +6100,20 @@ fn macroIntToBool(c: *Context, node: Node) !Node { |
| 6057 | 6100 | ||
| 6058 | fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6101 | fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6059 | const node = try parseCOrExpr(c, m, scope); | 6102 | const node = try parseCOrExpr(c, m, scope); |
| 6060 | if (m.peek().? != .QuestionMark) { | 6103 | if (m.peek().? != .question_mark) { |
| 6061 | return node; | 6104 | return node; |
| 6062 | } | 6105 | } |
| 6063 | _ = m.next(); | 6106 | _ = m.next(); |
| 6064 | 6107 | ||
| 6065 | const then_body = try parseCOrExpr(c, m, scope); | 6108 | const then_body = try parseCOrExpr(c, m, scope); |
| 6066 | try m.skip(c, .Colon); | 6109 | try m.skip(c, .colon); |
| 6067 | const else_body = try parseCCondExpr(c, m, scope); | 6110 | const else_body = try parseCCondExpr(c, m, scope); |
| 6068 | return Tag.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body }); | 6111 | return Tag.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body }); |
| 6069 | } | 6112 | } |
| 6070 | 6113 | ||
| 6071 | fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6114 | fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6072 | var node = try parseCAndExpr(c, m, scope); | 6115 | var node = try parseCAndExpr(c, m, scope); |
| 6073 | while (m.next().? == .PipePipe) { | 6116 | while (m.next().? == .pipe_pipe) { |
| 6074 | const lhs = try macroIntToBool(c, node); | 6117 | const lhs = try macroIntToBool(c, node); |
| 6075 | const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope)); | 6118 | const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope)); |
| 6076 | node = try Tag.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6119 | node = try Tag.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6081,7 +6124,7 @@ fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6081,7 +6124,7 @@ fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6081 | 6124 | ||
| 6082 | fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6125 | fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6083 | var node = try parseCBitOrExpr(c, m, scope); | 6126 | var node = try parseCBitOrExpr(c, m, scope); |
| 6084 | while (m.next().? == .AmpersandAmpersand) { | 6127 | while (m.next().? == .ampersand_ampersand) { |
| 6085 | const lhs = try macroIntToBool(c, node); | 6128 | const lhs = try macroIntToBool(c, node); |
| 6086 | const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope)); | 6129 | const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope)); |
| 6087 | node = try Tag.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6130 | node = try Tag.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6092,7 +6135,7 @@ fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6092,7 +6135,7 @@ fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6092 | 6135 | ||
| 6093 | fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6136 | fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6094 | var node = try parseCBitXorExpr(c, m, scope); | 6137 | var node = try parseCBitXorExpr(c, m, scope); |
| 6095 | while (m.next().? == .Pipe) { | 6138 | while (m.next().? == .pipe) { |
| 6096 | const lhs = try macroIntFromBool(c, node); | 6139 | const lhs = try macroIntFromBool(c, node); |
| 6097 | const rhs = try macroIntFromBool(c, try parseCBitXorExpr(c, m, scope)); | 6140 | const rhs = try macroIntFromBool(c, try parseCBitXorExpr(c, m, scope)); |
| 6098 | node = try Tag.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6141 | node = try Tag.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6103,7 +6146,7 @@ fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6103,7 +6146,7 @@ fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6103 | 6146 | ||
| 6104 | fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6147 | fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6105 | var node = try parseCBitAndExpr(c, m, scope); | 6148 | var node = try parseCBitAndExpr(c, m, scope); |
| 6106 | while (m.next().? == .Caret) { | 6149 | while (m.next().? == .caret) { |
| 6107 | const lhs = try macroIntFromBool(c, node); | 6150 | const lhs = try macroIntFromBool(c, node); |
| 6108 | const rhs = try macroIntFromBool(c, try parseCBitAndExpr(c, m, scope)); | 6151 | const rhs = try macroIntFromBool(c, try parseCBitAndExpr(c, m, scope)); |
| 6109 | node = try Tag.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6152 | node = try Tag.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6114,7 +6157,7 @@ fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6114,7 +6157,7 @@ fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6114 | 6157 | ||
| 6115 | fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6158 | fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6116 | var node = try parseCEqExpr(c, m, scope); | 6159 | var node = try parseCEqExpr(c, m, scope); |
| 6117 | while (m.next().? == .Ampersand) { | 6160 | while (m.next().? == .ampersand) { |
| 6118 | const lhs = try macroIntFromBool(c, node); | 6161 | const lhs = try macroIntFromBool(c, node); |
| 6119 | const rhs = try macroIntFromBool(c, try parseCEqExpr(c, m, scope)); | 6162 | const rhs = try macroIntFromBool(c, try parseCEqExpr(c, m, scope)); |
| 6120 | node = try Tag.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6163 | node = try Tag.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6127,13 +6170,13 @@ fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6127,13 +6170,13 @@ fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6127 | var node = try parseCRelExpr(c, m, scope); | 6170 | var node = try parseCRelExpr(c, m, scope); |
| 6128 | while (true) { | 6171 | while (true) { |
| 6129 | switch (m.peek().?) { | 6172 | switch (m.peek().?) { |
| 6130 | .BangEqual => { | 6173 | .bang_equal => { |
| 6131 | _ = m.next(); | 6174 | _ = m.next(); |
| 6132 | const lhs = try macroIntFromBool(c, node); | 6175 | const lhs = try macroIntFromBool(c, node); |
| 6133 | const rhs = try macroIntFromBool(c, try parseCRelExpr(c, m, scope)); | 6176 | const rhs = try macroIntFromBool(c, try parseCRelExpr(c, m, scope)); |
| 6134 | node = try Tag.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6177 | node = try Tag.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6135 | }, | 6178 | }, |
| 6136 | .EqualEqual => { | 6179 | .equal_equal => { |
| 6137 | _ = m.next(); | 6180 | _ = m.next(); |
| 6138 | const lhs = try macroIntFromBool(c, node); | 6181 | const lhs = try macroIntFromBool(c, node); |
| 6139 | const rhs = try macroIntFromBool(c, try parseCRelExpr(c, m, scope)); | 6182 | const rhs = try macroIntFromBool(c, try parseCRelExpr(c, m, scope)); |
| ... | @@ -6148,25 +6191,25 @@ fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6148,25 +6191,25 @@ fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6148 | var node = try parseCShiftExpr(c, m, scope); | 6191 | var node = try parseCShiftExpr(c, m, scope); |
| 6149 | while (true) { | 6192 | while (true) { |
| 6150 | switch (m.peek().?) { | 6193 | switch (m.peek().?) { |
| 6151 | .AngleBracketRight => { | 6194 | .angle_bracket_right => { |
| 6152 | _ = m.next(); | 6195 | _ = m.next(); |
| 6153 | const lhs = try macroIntFromBool(c, node); | 6196 | const lhs = try macroIntFromBool(c, node); |
| 6154 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); | 6197 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| 6155 | node = try Tag.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6198 | node = try Tag.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6156 | }, | 6199 | }, |
| 6157 | .AngleBracketRightEqual => { | 6200 | .angle_bracket_right_equal => { |
| 6158 | _ = m.next(); | 6201 | _ = m.next(); |
| 6159 | const lhs = try macroIntFromBool(c, node); | 6202 | const lhs = try macroIntFromBool(c, node); |
| 6160 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); | 6203 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| 6161 | node = try Tag.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6204 | node = try Tag.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6162 | }, | 6205 | }, |
| 6163 | .AngleBracketLeft => { | 6206 | .angle_bracket_left => { |
| 6164 | _ = m.next(); | 6207 | _ = m.next(); |
| 6165 | const lhs = try macroIntFromBool(c, node); | 6208 | const lhs = try macroIntFromBool(c, node); |
| 6166 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); | 6209 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| 6167 | node = try Tag.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6210 | node = try Tag.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6168 | }, | 6211 | }, |
| 6169 | .AngleBracketLeftEqual => { | 6212 | .angle_bracket_left_equal => { |
| 6170 | _ = m.next(); | 6213 | _ = m.next(); |
| 6171 | const lhs = try macroIntFromBool(c, node); | 6214 | const lhs = try macroIntFromBool(c, node); |
| 6172 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); | 6215 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| ... | @@ -6181,13 +6224,13 @@ fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6181,13 +6224,13 @@ fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6181 | var node = try parseCAddSubExpr(c, m, scope); | 6224 | var node = try parseCAddSubExpr(c, m, scope); |
| 6182 | while (true) { | 6225 | while (true) { |
| 6183 | switch (m.peek().?) { | 6226 | switch (m.peek().?) { |
| 6184 | .AngleBracketAngleBracketLeft => { | 6227 | .angle_bracket_angle_bracket_left => { |
| 6185 | _ = m.next(); | 6228 | _ = m.next(); |
| 6186 | const lhs = try macroIntFromBool(c, node); | 6229 | const lhs = try macroIntFromBool(c, node); |
| 6187 | const rhs = try macroIntFromBool(c, try parseCAddSubExpr(c, m, scope)); | 6230 | const rhs = try macroIntFromBool(c, try parseCAddSubExpr(c, m, scope)); |
| 6188 | node = try Tag.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6231 | node = try Tag.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6189 | }, | 6232 | }, |
| 6190 | .AngleBracketAngleBracketRight => { | 6233 | .angle_bracket_angle_bracket_right => { |
| 6191 | _ = m.next(); | 6234 | _ = m.next(); |
| 6192 | const lhs = try macroIntFromBool(c, node); | 6235 | const lhs = try macroIntFromBool(c, node); |
| 6193 | const rhs = try macroIntFromBool(c, try parseCAddSubExpr(c, m, scope)); | 6236 | const rhs = try macroIntFromBool(c, try parseCAddSubExpr(c, m, scope)); |
| ... | @@ -6202,13 +6245,13 @@ fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6202,13 +6245,13 @@ fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6202 | var node = try parseCMulExpr(c, m, scope); | 6245 | var node = try parseCMulExpr(c, m, scope); |
| 6203 | while (true) { | 6246 | while (true) { |
| 6204 | switch (m.peek().?) { | 6247 | switch (m.peek().?) { |
| 6205 | .Plus => { | 6248 | .plus => { |
| 6206 | _ = m.next(); | 6249 | _ = m.next(); |
| 6207 | const lhs = try macroIntFromBool(c, node); | 6250 | const lhs = try macroIntFromBool(c, node); |
| 6208 | const rhs = try macroIntFromBool(c, try parseCMulExpr(c, m, scope)); | 6251 | const rhs = try macroIntFromBool(c, try parseCMulExpr(c, m, scope)); |
| 6209 | node = try Tag.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6252 | node = try Tag.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6210 | }, | 6253 | }, |
| 6211 | .Minus => { | 6254 | .minus => { |
| 6212 | _ = m.next(); | 6255 | _ = m.next(); |
| 6213 | const lhs = try macroIntFromBool(c, node); | 6256 | const lhs = try macroIntFromBool(c, node); |
| 6214 | const rhs = try macroIntFromBool(c, try parseCMulExpr(c, m, scope)); | 6257 | const rhs = try macroIntFromBool(c, try parseCMulExpr(c, m, scope)); |
| ... | @@ -6223,17 +6266,17 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6223,17 +6266,17 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6223 | var node = try parseCCastExpr(c, m, scope); | 6266 | var node = try parseCCastExpr(c, m, scope); |
| 6224 | while (true) { | 6267 | while (true) { |
| 6225 | switch (m.next().?) { | 6268 | switch (m.next().?) { |
| 6226 | .Asterisk => { | 6269 | .asterisk => { |
| 6227 | const lhs = try macroIntFromBool(c, node); | 6270 | const lhs = try macroIntFromBool(c, node); |
| 6228 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); | 6271 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6229 | node = try Tag.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); | 6272 | node = try Tag.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6230 | }, | 6273 | }, |
| 6231 | .Slash => { | 6274 | .slash => { |
| 6232 | const lhs = try macroIntFromBool(c, node); | 6275 | const lhs = try macroIntFromBool(c, node); |
| 6233 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); | 6276 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6234 | node = try Tag.macro_arithmetic.create(c.arena, .{ .op = .div, .lhs = lhs, .rhs = rhs }); | 6277 | node = try Tag.macro_arithmetic.create(c.arena, .{ .op = .div, .lhs = lhs, .rhs = rhs }); |
| 6235 | }, | 6278 | }, |
| 6236 | .Percent => { | 6279 | .percent => { |
| 6237 | const lhs = try macroIntFromBool(c, node); | 6280 | const lhs = try macroIntFromBool(c, node); |
| 6238 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); | 6281 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6239 | node = try Tag.macro_arithmetic.create(c.arena, .{ .op = .rem, .lhs = lhs, .rhs = rhs }); | 6282 | node = try Tag.macro_arithmetic.create(c.arena, .{ .op = .rem, .lhs = lhs, .rhs = rhs }); |
| ... | @@ -6248,17 +6291,18 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6248,17 +6291,18 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6248 | 6291 | ||
| 6249 | fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6292 | fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6250 | switch (m.next().?) { | 6293 | switch (m.next().?) { |
| 6251 | .LParen => { | 6294 | .l_paren => { |
| 6252 | if (try parseCTypeName(c, m, scope, true)) |type_name| { | 6295 | if (try parseCTypeName(c, m, scope, true)) |type_name| { |
| 6253 | while (true) { | 6296 | while (true) { |
| 6254 | const next_token = m.next().?; | 6297 | const next_token = m.next().?; |
| 6255 | switch (next_token) { | 6298 | switch (next_token) { |
| 6256 | .RParen => break, | 6299 | .r_paren => break, |
| 6257 | else => |next_tag| { | 6300 | else => |next_tag| { |
| 6258 | // Skip trailing blank defined before the RParen. | 6301 | // Skip trailing blank defined before the RParen. |
| 6259 | if (next_tag == .Identifier and c.global_scope.blank_macros.contains(m.slice())) { | 6302 | if ((next_tag == .identifier or next_tag == .extended_identifier) and |
| 6303 | c.global_scope.blank_macros.contains(m.slice())) | ||
| 6260 | continue; | 6304 | continue; |
| 6261 | } | 6305 | |
| 6262 | try m.fail( | 6306 | try m.fail( |
| 6263 | c, | 6307 | c, |
| 6264 | "unable to translate C expr: expected ')' instead got '{s}'", | 6308 | "unable to translate C expr: expected ')' instead got '{s}'", |
| ... | @@ -6268,7 +6312,7 @@ fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | ... | @@ -6268,7 +6312,7 @@ fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6268 | }, | 6312 | }, |
| 6269 | } | 6313 | } |
| 6270 | } | 6314 | } |
| 6271 | if (m.peek().? == .LBrace) { | 6315 | if (m.peek().? == .l_brace) { |
| 6272 | // initializer list | 6316 | // initializer list |
| 6273 | return parseCPostfixExpr(c, m, scope, type_name); | 6317 | return parseCPostfixExpr(c, m, scope, type_name); |
| 6274 | } | 6318 | } |
| ... | @@ -6294,7 +6338,7 @@ fn parseCTypeName(c: *Context, m: *MacroCtx, scope: *Scope, allow_fail: bool) Pa | ... | @@ -6294,7 +6338,7 @@ fn parseCTypeName(c: *Context, m: *MacroCtx, scope: *Scope, allow_fail: bool) Pa |
| 6294 | fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_fail: bool) ParseError!?Node { | 6338 | fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_fail: bool) ParseError!?Node { |
| 6295 | const tok = m.next().?; | 6339 | const tok = m.next().?; |
| 6296 | switch (tok) { | 6340 | switch (tok) { |
| 6297 | .Identifier => { | 6341 | .identifier, .extended_identifier => { |
| 6298 | if (c.global_scope.blank_macros.contains(m.slice())) { | 6342 | if (c.global_scope.blank_macros.contains(m.slice())) { |
| 6299 | return try parseCSpecifierQualifierList(c, m, scope, allow_fail); | 6343 | return try parseCSpecifierQualifierList(c, m, scope, allow_fail); |
| 6300 | } | 6344 | } |
| ... | @@ -6304,25 +6348,25 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_ | ... | @@ -6304,25 +6348,25 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_ |
| 6304 | return try Tag.identifier.create(c.arena, mangled_name); | 6348 | return try Tag.identifier.create(c.arena, mangled_name); |
| 6305 | } | 6349 | } |
| 6306 | }, | 6350 | }, |
| 6307 | .Keyword_void => return try Tag.type.create(c.arena, "anyopaque"), | 6351 | .keyword_void => return try Tag.type.create(c.arena, "anyopaque"), |
| 6308 | .Keyword_bool => return try Tag.type.create(c.arena, "bool"), | 6352 | .keyword_bool => return try Tag.type.create(c.arena, "bool"), |
| 6309 | .Keyword_char, | 6353 | .keyword_char, |
| 6310 | .Keyword_int, | 6354 | .keyword_int, |
| 6311 | .Keyword_short, | 6355 | .keyword_short, |
| 6312 | .Keyword_long, | 6356 | .keyword_long, |
| 6313 | .Keyword_float, | 6357 | .keyword_float, |
| 6314 | .Keyword_double, | 6358 | .keyword_double, |
| 6315 | .Keyword_signed, | 6359 | .keyword_signed, |
| 6316 | .Keyword_unsigned, | 6360 | .keyword_unsigned, |
| 6317 | .Keyword_complex, | 6361 | .keyword_complex, |
| 6318 | => { | 6362 | => { |
| 6319 | m.i -= 1; | 6363 | m.i -= 1; |
| 6320 | return try parseCNumericType(c, m); | 6364 | return try parseCNumericType(c, m); |
| 6321 | }, | 6365 | }, |
| 6322 | .Keyword_enum, .Keyword_struct, .Keyword_union => { | 6366 | .keyword_enum, .keyword_struct, .keyword_union => { |
| 6323 | // struct Foo will be declared as struct_Foo by transRecordDecl | 6367 | // struct Foo will be declared as struct_Foo by transRecordDecl |
| 6324 | const slice = m.slice(); | 6368 | const slice = m.slice(); |
| 6325 | try m.skip(c, .Identifier); | 6369 | try m.skip(c, .identifier); |
| 6326 | 6370 | ||
| 6327 | const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() }); | 6371 | const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() }); |
| 6328 | return try Tag.identifier.create(c.arena, name); | 6372 | return try Tag.identifier.create(c.arena, name); |
| ... | @@ -6364,15 +6408,15 @@ fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { | ... | @@ -6364,15 +6408,15 @@ fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { |
| 6364 | var i: u8 = 0; | 6408 | var i: u8 = 0; |
| 6365 | while (i < math.maxInt(u8)) : (i += 1) { | 6409 | while (i < math.maxInt(u8)) : (i += 1) { |
| 6366 | switch (m.next().?) { | 6410 | switch (m.next().?) { |
| 6367 | .Keyword_double => kw.double += 1, | 6411 | .keyword_double => kw.double += 1, |
| 6368 | .Keyword_long => kw.long += 1, | 6412 | .keyword_long => kw.long += 1, |
| 6369 | .Keyword_int => kw.int += 1, | 6413 | .keyword_int => kw.int += 1, |
| 6370 | .Keyword_float => kw.float += 1, | 6414 | .keyword_float => kw.float += 1, |
| 6371 | .Keyword_short => kw.short += 1, | 6415 | .keyword_short => kw.short += 1, |
| 6372 | .Keyword_char => kw.char += 1, | 6416 | .keyword_char => kw.char += 1, |
| 6373 | .Keyword_unsigned => kw.unsigned += 1, | 6417 | .keyword_unsigned => kw.unsigned += 1, |
| 6374 | .Keyword_signed => kw.signed += 1, | 6418 | .keyword_signed => kw.signed += 1, |
| 6375 | .Keyword_complex => kw.complex += 1, | 6419 | .keyword_complex => kw.complex += 1, |
| 6376 | else => { | 6420 | else => { |
| 6377 | m.i -= 1; | 6421 | m.i -= 1; |
| 6378 | break; | 6422 | break; |
| ... | @@ -6442,11 +6486,11 @@ fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { | ... | @@ -6442,11 +6486,11 @@ fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { |
| 6442 | 6486 | ||
| 6443 | fn parseCAbstractDeclarator(c: *Context, m: *MacroCtx, node: Node) ParseError!Node { | 6487 | fn parseCAbstractDeclarator(c: *Context, m: *MacroCtx, node: Node) ParseError!Node { |
| 6444 | switch (m.next().?) { | 6488 | switch (m.next().?) { |
| 6445 | .Asterisk => { | 6489 | .asterisk => { |
| 6446 | // last token of `node` | 6490 | // last token of `node` |
| 6447 | const prev_id = m.list[m.i - 1].id; | 6491 | const prev_id = m.list[m.i - 1].id; |
| 6448 | 6492 | ||
| 6449 | if (prev_id == .Keyword_void) { | 6493 | if (prev_id == .keyword_void) { |
| 6450 | const ptr = try Tag.single_pointer.create(c.arena, .{ | 6494 | const ptr = try Tag.single_pointer.create(c.arena, .{ |
| 6451 | .is_const = false, | 6495 | .is_const = false, |
| 6452 | .is_volatile = false, | 6496 | .is_volatile = false, |
| ... | @@ -6472,28 +6516,28 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6472,28 +6516,28 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6472 | var node = type_name orelse try parseCPrimaryExpr(c, m, scope); | 6516 | var node = type_name orelse try parseCPrimaryExpr(c, m, scope); |
| 6473 | while (true) { | 6517 | while (true) { |
| 6474 | switch (m.next().?) { | 6518 | switch (m.next().?) { |
| 6475 | .Period => { | 6519 | .period => { |
| 6476 | try m.skip(c, .Identifier); | 6520 | try m.skip(c, .identifier); |
| 6477 | 6521 | ||
| 6478 | node = try Tag.field_access.create(c.arena, .{ .lhs = node, .field_name = m.slice() }); | 6522 | node = try Tag.field_access.create(c.arena, .{ .lhs = node, .field_name = m.slice() }); |
| 6479 | }, | 6523 | }, |
| 6480 | .Arrow => { | 6524 | .arrow => { |
| 6481 | try m.skip(c, .Identifier); | 6525 | try m.skip(c, .identifier); |
| 6482 | 6526 | ||
| 6483 | const deref = try Tag.deref.create(c.arena, node); | 6527 | const deref = try Tag.deref.create(c.arena, node); |
| 6484 | node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .field_name = m.slice() }); | 6528 | node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .field_name = m.slice() }); |
| 6485 | }, | 6529 | }, |
| 6486 | .LBracket => { | 6530 | .l_bracket => { |
| 6487 | const index_val = try macroIntFromBool(c, try parseCExpr(c, m, scope)); | 6531 | const index_val = try macroIntFromBool(c, try parseCExpr(c, m, scope)); |
| 6488 | const index = try Tag.as.create(c.arena, .{ | 6532 | const index = try Tag.as.create(c.arena, .{ |
| 6489 | .lhs = try Tag.type.create(c.arena, "usize"), | 6533 | .lhs = try Tag.type.create(c.arena, "usize"), |
| 6490 | .rhs = try Tag.int_cast.create(c.arena, index_val), | 6534 | .rhs = try Tag.int_cast.create(c.arena, index_val), |
| 6491 | }); | 6535 | }); |
| 6492 | node = try Tag.array_access.create(c.arena, .{ .lhs = node, .rhs = index }); | 6536 | node = try Tag.array_access.create(c.arena, .{ .lhs = node, .rhs = index }); |
| 6493 | try m.skip(c, .RBracket); | 6537 | try m.skip(c, .r_bracket); |
| 6494 | }, | 6538 | }, |
| 6495 | .LParen => { | 6539 | .l_paren => { |
| 6496 | if (m.peek().? == .RParen) { | 6540 | if (m.peek().? == .r_paren) { |
| 6497 | m.i += 1; | 6541 | m.i += 1; |
| 6498 | node = try Tag.call.create(c.arena, .{ .lhs = node, .args = &[0]Node{} }); | 6542 | node = try Tag.call.create(c.arena, .{ .lhs = node, .args = &[0]Node{} }); |
| 6499 | } else { | 6543 | } else { |
| ... | @@ -6504,8 +6548,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6504,8 +6548,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6504 | try args.append(arg); | 6548 | try args.append(arg); |
| 6505 | const next_id = m.next().?; | 6549 | const next_id = m.next().?; |
| 6506 | switch (next_id) { | 6550 | switch (next_id) { |
| 6507 | .Comma => {}, | 6551 | .comma => {}, |
| 6508 | .RParen => break, | 6552 | .r_paren => break, |
| 6509 | else => { | 6553 | else => { |
| 6510 | try m.fail(c, "unable to translate C expr: expected ',' or ')' instead got '{s}'", .{next_id.symbol()}); | 6554 | try m.fail(c, "unable to translate C expr: expected ',' or ')' instead got '{s}'", .{next_id.symbol()}); |
| 6511 | return error.ParseError; | 6555 | return error.ParseError; |
| ... | @@ -6515,24 +6559,24 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6515,24 +6559,24 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6515 | node = try Tag.call.create(c.arena, .{ .lhs = node, .args = try c.arena.dupe(Node, args.items) }); | 6559 | node = try Tag.call.create(c.arena, .{ .lhs = node, .args = try c.arena.dupe(Node, args.items) }); |
| 6516 | } | 6560 | } |
| 6517 | }, | 6561 | }, |
| 6518 | .LBrace => { | 6562 | .l_brace => { |
| 6519 | // Check for designated field initializers | 6563 | // Check for designated field initializers |
| 6520 | if (m.peek().? == .Period) { | 6564 | if (m.peek().? == .period) { |
| 6521 | var init_vals = std.ArrayList(ast.Payload.ContainerInitDot.Initializer).init(c.gpa); | 6565 | var init_vals = std.ArrayList(ast.Payload.ContainerInitDot.Initializer).init(c.gpa); |
| 6522 | defer init_vals.deinit(); | 6566 | defer init_vals.deinit(); |
| 6523 | 6567 | ||
| 6524 | while (true) { | 6568 | while (true) { |
| 6525 | try m.skip(c, .Period); | 6569 | try m.skip(c, .period); |
| 6526 | try m.skip(c, .Identifier); | 6570 | try m.skip(c, .identifier); |
| 6527 | const name = m.slice(); | 6571 | const name = m.slice(); |
| 6528 | try m.skip(c, .Equal); | 6572 | try m.skip(c, .equal); |
| 6529 | 6573 | ||
| 6530 | const val = try parseCCondExpr(c, m, scope); | 6574 | const val = try parseCCondExpr(c, m, scope); |
| 6531 | try init_vals.append(.{ .name = name, .value = val }); | 6575 | try init_vals.append(.{ .name = name, .value = val }); |
| 6532 | const next_id = m.next().?; | 6576 | const next_id = m.next().?; |
| 6533 | switch (next_id) { | 6577 | switch (next_id) { |
| 6534 | .Comma => {}, | 6578 | .comma => {}, |
| 6535 | .RBrace => break, | 6579 | .r_brace => break, |
| 6536 | else => { | 6580 | else => { |
| 6537 | try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()}); | 6581 | try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()}); |
| 6538 | return error.ParseError; | 6582 | return error.ParseError; |
| ... | @@ -6552,8 +6596,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6552,8 +6596,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6552 | try init_vals.append(val); | 6596 | try init_vals.append(val); |
| 6553 | const next_id = m.next().?; | 6597 | const next_id = m.next().?; |
| 6554 | switch (next_id) { | 6598 | switch (next_id) { |
| 6555 | .Comma => {}, | 6599 | .comma => {}, |
| 6556 | .RBrace => break, | 6600 | .r_brace => break, |
| 6557 | else => { | 6601 | else => { |
| 6558 | try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()}); | 6602 | try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()}); |
| 6559 | return error.ParseError; | 6603 | return error.ParseError; |
| ... | @@ -6563,7 +6607,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6563,7 +6607,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6563 | const tuple_node = try Tag.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items)); | 6607 | const tuple_node = try Tag.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items)); |
| 6564 | node = try Tag.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node }); | 6608 | node = try Tag.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node }); |
| 6565 | }, | 6609 | }, |
| 6566 | .PlusPlus, .MinusMinus => { | 6610 | .plus_plus, .minus_minus => { |
| 6567 | try m.fail(c, "TODO postfix inc/dec expr", .{}); | 6611 | try m.fail(c, "TODO postfix inc/dec expr", .{}); |
| 6568 | return error.ParseError; | 6612 | return error.ParseError; |
| 6569 | }, | 6613 | }, |
| ... | @@ -6577,47 +6621,47 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) | ... | @@ -6577,47 +6621,47 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6577 | 6621 | ||
| 6578 | fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 6622 | fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6579 | switch (m.next().?) { | 6623 | switch (m.next().?) { |
| 6580 | .Bang => { | 6624 | .bang => { |
| 6581 | const operand = try macroIntToBool(c, try parseCCastExpr(c, m, scope)); | 6625 | const operand = try macroIntToBool(c, try parseCCastExpr(c, m, scope)); |
| 6582 | return Tag.not.create(c.arena, operand); | 6626 | return Tag.not.create(c.arena, operand); |
| 6583 | }, | 6627 | }, |
| 6584 | .Minus => { | 6628 | .minus => { |
| 6585 | const operand = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); | 6629 | const operand = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6586 | return Tag.negate.create(c.arena, operand); | 6630 | return Tag.negate.create(c.arena, operand); |
| 6587 | }, | 6631 | }, |
| 6588 | .Plus => return try parseCCastExpr(c, m, scope), | 6632 | .plus => return try parseCCastExpr(c, m, scope), |
| 6589 | .Tilde => { | 6633 | .tilde => { |
| 6590 | const operand = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); | 6634 | const operand = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6591 | return Tag.bit_not.create(c.arena, operand); | 6635 | return Tag.bit_not.create(c.arena, operand); |
| 6592 | }, | 6636 | }, |
| 6593 | .Asterisk => { | 6637 | .asterisk => { |
| 6594 | const operand = try parseCCastExpr(c, m, scope); | 6638 | const operand = try parseCCastExpr(c, m, scope); |
| 6595 | return Tag.deref.create(c.arena, operand); | 6639 | return Tag.deref.create(c.arena, operand); |
| 6596 | }, | 6640 | }, |
| 6597 | .Ampersand => { | 6641 | .ampersand => { |
| 6598 | const operand = try parseCCastExpr(c, m, scope); | 6642 | const operand = try parseCCastExpr(c, m, scope); |
| 6599 | return Tag.address_of.create(c.arena, operand); | 6643 | return Tag.address_of.create(c.arena, operand); |
| 6600 | }, | 6644 | }, |
| 6601 | .Keyword_sizeof => { | 6645 | .keyword_sizeof => { |
| 6602 | const operand = if (m.peek().? == .LParen) blk: { | 6646 | const operand = if (m.peek().? == .l_paren) blk: { |
| 6603 | _ = m.next(); | 6647 | _ = m.next(); |
| 6604 | const inner = (try parseCTypeName(c, m, scope, false)).?; | 6648 | const inner = (try parseCTypeName(c, m, scope, false)).?; |
| 6605 | try m.skip(c, .RParen); | 6649 | try m.skip(c, .r_paren); |
| 6606 | break :blk inner; | 6650 | break :blk inner; |
| 6607 | } else try parseCUnaryExpr(c, m, scope); | 6651 | } else try parseCUnaryExpr(c, m, scope); |
| 6608 | 6652 | ||
| 6609 | return Tag.helpers_sizeof.create(c.arena, operand); | 6653 | return Tag.helpers_sizeof.create(c.arena, operand); |
| 6610 | }, | 6654 | }, |
| 6611 | .Keyword_alignof => { | 6655 | .keyword_alignof => { |
| 6612 | // TODO this won't work if using <stdalign.h>'s | 6656 | // TODO this won't work if using <stdalign.h>'s |
| 6613 | // #define alignof _Alignof | 6657 | // #define alignof _Alignof |
| 6614 | try m.skip(c, .LParen); | 6658 | try m.skip(c, .l_paren); |
| 6615 | const operand = (try parseCTypeName(c, m, scope, false)).?; | 6659 | const operand = (try parseCTypeName(c, m, scope, false)).?; |
| 6616 | try m.skip(c, .RParen); | 6660 | try m.skip(c, .r_paren); |
| 6617 | 6661 | ||
| 6618 | return Tag.alignof.create(c.arena, operand); | 6662 | return Tag.alignof.create(c.arena, operand); |
| 6619 | }, | 6663 | }, |
| 6620 | .PlusPlus, .MinusMinus => { | 6664 | .plus_plus, .minus_minus => { |
| 6621 | try m.fail(c, "TODO unary inc/dec expr", .{}); | 6665 | try m.fail(c, "TODO unary inc/dec expr", .{}); |
| 6622 | return error.ParseError; | 6666 | return error.ParseError; |
| 6623 | }, | 6667 | }, |
test/translate_c.zig+7-7| ... | @@ -424,7 +424,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -424,7 +424,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 424 | \\ }); | 424 | \\ }); |
| 425 | \\} | 425 | \\} |
| 426 | , | 426 | , |
| 427 | \\pub const B = A(@as(f32, 0.0)); | 427 | \\pub const B = A(@as(f32, 0)); |
| 428 | }); | 428 | }); |
| 429 | 429 | ||
| 430 | cases.add("complex switch", | 430 | cases.add("complex switch", |
| ... | @@ -633,7 +633,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -633,7 +633,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 633 | cases.add("#define hex literal with capital X", | 633 | cases.add("#define hex literal with capital X", |
| 634 | \\#define VAL 0XF00D | 634 | \\#define VAL 0XF00D |
| 635 | , &[_][]const u8{ | 635 | , &[_][]const u8{ |
| 636 | \\pub const VAL = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0xF00D, .hexadecimal); | 636 | \\pub const VAL = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0xF00D, .hex); |
| 637 | }); | 637 | }); |
| 638 | 638 | ||
| 639 | cases.add("anonymous struct & unions", | 639 | cases.add("anonymous struct & unions", |
| ... | @@ -1243,12 +1243,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1243,12 +1243,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1243 | \\extern const long double my_extended_precision_longdouble = 1.0000000000000003l; | 1243 | \\extern const long double my_extended_precision_longdouble = 1.0000000000000003l; |
| 1244 | , &([_][]const u8{ | 1244 | , &([_][]const u8{ |
| 1245 | "pub const foo = @as(f32, 3.14);", | 1245 | "pub const foo = @as(f32, 3.14);", |
| 1246 | "pub const bar = @as(c_longdouble, 16.0e-2);", | 1246 | "pub const bar = @as(c_longdouble, 16.e-2);", |
| 1247 | "pub const FOO = @as(f64, 0.12345);", | 1247 | "pub const FOO = @as(f64, 0.12345);", |
| 1248 | "pub const BAR = @as(f64, 0.12345);", | 1248 | "pub const BAR = @as(f64, 0.12345);", |
| 1249 | "pub const baz = @as(f64, 1e1);", | 1249 | "pub const baz = @as(f64, 1e1);", |
| 1250 | "pub const BAZ = @as(f32, 42e-3);", | 1250 | "pub const BAZ = @as(f32, 42e-3);", |
| 1251 | "pub const foobar = -@as(c_longdouble, 73.0);", | 1251 | "pub const foobar = -@as(c_longdouble, 73);", |
| 1252 | "pub export const my_float: f32 = 1.0;", | 1252 | "pub export const my_float: f32 = 1.0;", |
| 1253 | "pub export const my_double: f64 = 1.0;", | 1253 | "pub export const my_double: f64 = 1.0;", |
| 1254 | "pub export const my_longdouble: c_longdouble = 1.0;", | 1254 | "pub export const my_longdouble: c_longdouble = 1.0;", |
| ... | @@ -1272,7 +1272,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1272,7 +1272,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1272 | "pub const BAR = -@as(f32, 0x8F.BP5);", | 1272 | "pub const BAR = -@as(f32, 0x8F.BP5);", |
| 1273 | "pub const FOOBAR = @as(f64, 0x0P+0);", | 1273 | "pub const FOOBAR = @as(f64, 0x0P+0);", |
| 1274 | "pub const BAZ = -@as(f64, 0x0.0a5dp+12);", | 1274 | "pub const BAZ = -@as(f64, 0x0.0a5dp+12);", |
| 1275 | "pub const FOOBAZ = @as(c_longdouble, 0xfE.0P-1);", | 1275 | "pub const FOOBAZ = @as(c_longdouble, 0xfE.P-1);", |
| 1276 | }); | 1276 | }); |
| 1277 | 1277 | ||
| 1278 | cases.add("comments", | 1278 | cases.add("comments", |
| ... | @@ -3730,7 +3730,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -3730,7 +3730,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3730 | , &[_][]const u8{ | 3730 | , &[_][]const u8{ |
| 3731 | \\pub const NULL = @import("std").zig.c_translation.cast(?*anyopaque, @as(c_int, 0)); | 3731 | \\pub const NULL = @import("std").zig.c_translation.cast(?*anyopaque, @as(c_int, 0)); |
| 3732 | , | 3732 | , |
| 3733 | \\pub const FOO = @import("std").zig.c_translation.cast(c_int, @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x8000, .hexadecimal)); | 3733 | \\pub const FOO = @import("std").zig.c_translation.cast(c_int, @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x8000, .hex)); |
| 3734 | }); | 3734 | }); |
| 3735 | 3735 | ||
| 3736 | if (builtin.abi == .msvc) { | 3736 | if (builtin.abi == .msvc) { |
| ... | @@ -3812,7 +3812,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -3812,7 +3812,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3812 | \\pub const MAY_NEED_PROMOTION_1 = @import("std").zig.c_translation.promoteIntLiteral(c_int, 10241024, .decimal); | 3812 | \\pub const MAY_NEED_PROMOTION_1 = @import("std").zig.c_translation.promoteIntLiteral(c_int, 10241024, .decimal); |
| 3813 | \\pub const MAY_NEED_PROMOTION_2 = @import("std").zig.c_translation.promoteIntLiteral(c_long, 307230723072, .decimal); | 3813 | \\pub const MAY_NEED_PROMOTION_2 = @import("std").zig.c_translation.promoteIntLiteral(c_long, 307230723072, .decimal); |
| 3814 | \\pub const MAY_NEED_PROMOTION_3 = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 819281928192, .decimal); | 3814 | \\pub const MAY_NEED_PROMOTION_3 = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 819281928192, .decimal); |
| 3815 | \\pub const MAY_NEED_PROMOTION_HEX = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x80000000, .hexadecimal); | 3815 | \\pub const MAY_NEED_PROMOTION_HEX = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x80000000, .hex); |
| 3816 | \\pub const MAY_NEED_PROMOTION_OCT = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0o20000000000, .octal); | 3816 | \\pub const MAY_NEED_PROMOTION_OCT = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0o20000000000, .octal); |
| 3817 | }); | 3817 | }); |
| 3818 | 3818 |