| author | |
| committer | |
| log | 7103088e4a51d4362e6665d5949a9677e18fb74a |
| tree | 858c52055896b6d6085b3810b6263eed3bafae0a |
| parent | 2ff707be789046a733d0d23c6fe42dd2b7210396 |
| parent | 74010fecc7bbeaf9de77c28dda5906c3c1f4a6df |
| signature |
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 | 218 | "${CMAKE_SOURCE_DIR}/lib/std/builtin.zig" |
| 219 | 219 | "${CMAKE_SOURCE_DIR}/lib/std/c.zig" |
| 220 | 220 | "${CMAKE_SOURCE_DIR}/lib/std/c/linux.zig" |
| 221 | "${CMAKE_SOURCE_DIR}/lib/std/c/tokenizer.zig" | |
| 222 | 221 | "${CMAKE_SOURCE_DIR}/lib/std/child_process.zig" |
| 223 | 222 | "${CMAKE_SOURCE_DIR}/lib/std/coff.zig" |
| 224 | 223 | "${CMAKE_SOURCE_DIR}/lib/std/comptime_string_map.zig" |
deps/aro/aro/Builtins/Builtin.def+152| ... | ... | @@ -17008,3 +17008,155 @@ wmemmove |
| 17008 | 17008 | .param_str = "w*w*wC*z" |
| 17009 | 17009 | .header = .wchar |
| 17010 | 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 | 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 | 422 | // types |
| 412 | 423 | if (comp.getCharSignedness() == .unsigned) try w.writeAll("#define __CHAR_UNSIGNED__ 1\n"); |
| 413 | 424 | try w.writeAll("#define __CHAR_BIT__ 8\n"); |
| ... | ... | @@ -445,6 +456,10 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { |
| 445 | 456 | try comp.generateSizeofType(w, "__SIZEOF_WCHAR_T__", comp.types.wchar); |
| 446 | 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 | 463 | // various int types |
| 449 | 464 | const mapper = comp.string_interner.getSlowTypeMapper(); |
| 450 | 465 | try generateTypeMacro(w, mapper, "__INTPTR_TYPE__", comp.types.intptr, comp.langopts); |
| ... | ... | @@ -461,6 +476,7 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { |
| 461 | 476 | try generateTypeMacro(w, mapper, "__WCHAR_TYPE__", comp.types.wchar, comp.langopts); |
| 462 | 477 | |
| 463 | 478 | try comp.generateExactWidthTypes(w, mapper); |
| 479 | try comp.generateFastAndLeastWidthTypes(w, mapper); | |
| 464 | 480 | |
| 465 | 481 | if (target_util.FPSemantics.halfPrecisionType(comp.target)) |half| { |
| 466 | 482 | try generateFloatMacros(w, "FLT16", half, "F16"); |
| ... | ... | @@ -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 | 519 | // standard macros |
| 501 | 520 | try buf.appendSlice( |
| 502 | \\#define __STDC__ 1 | |
| 503 | \\#define __STDC_HOSTED__ 1 | |
| 504 | 521 | \\#define __STDC_NO_ATOMICS__ 1 |
| 505 | 522 | \\#define __STDC_NO_COMPLEX__ 1 |
| 506 | 523 | \\#define __STDC_NO_THREADS__ 1 |
| ... | ... | @@ -678,6 +695,14 @@ fn generateBuiltinTypes(comp: *Compilation) !void { |
| 678 | 695 | |
| 679 | 696 | /// Smallest integer type with at least N bits |
| 680 | 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 | 706 | const candidates = switch (signedness) { |
| 682 | 707 | .signed => &[_]Type.Specifier{ .schar, .short, .int, .long, .long_long }, |
| 683 | 708 | .unsigned => &[_]Type.Specifier{ .uchar, .ushort, .uint, .ulong, .ulong_long }, |
| ... | ... | @@ -693,6 +718,52 @@ fn intSize(comp: *const Compilation, specifier: Type.Specifier) u64 { |
| 693 | 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 | 767 | fn generateExactWidthTypes(comp: *const Compilation, w: anytype, mapper: StrInt.TypeMapper) !void { |
| 697 | 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 | 236 | try d.addExtra(.{}, .{ |
| 237 | 237 | .tag = .unknown_warning, |
| 238 | 238 | .extra = .{ .str = name }, |
| 239 | }, &.{}); | |
| 239 | }, &.{}, true); | |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | 242 | pub fn init(gpa: Allocator) Diagnostics { |
| ... | ... | @@ -251,7 +251,7 @@ pub fn deinit(d: *Diagnostics) void { |
| 251 | 251 | } |
| 252 | 252 | |
| 253 | 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 | 257 | pub fn addExtra( |
| ... | ... | @@ -259,6 +259,7 @@ pub fn addExtra( |
| 259 | 259 | langopts: LangOpts, |
| 260 | 260 | msg: Message, |
| 261 | 261 | expansion_locs: []const Source.Location, |
| 262 | note_msg_loc: bool, | |
| 262 | 263 | ) Compilation.Error!void { |
| 263 | 264 | const kind = d.tagKind(msg.tag, langopts); |
| 264 | 265 | if (kind == .off) return; |
| ... | ... | @@ -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 | 306 | .tag = .expanded_from_here, |
| 306 | 307 | .kind = .note, |
| 307 | 308 | .loc = msg.loc, |
deps/aro/aro/Driver.zig+16| ... | ... | @@ -98,8 +98,10 @@ pub const usage = |
| 98 | 98 | \\ -fno-declspec Disable support for __declspec attributes |
| 99 | 99 | \\ -ffp-eval-method=[source|double|extended] |
| 100 | 100 | \\ Evaluation method to use for floating-point arithmetic |
| 101 | \\ -ffreestanding Compilation in a freestanding environment | |
| 101 | 102 | \\ -fgnu-inline-asm Enable GNU style inline asm (default: enabled) |
| 102 | 103 | \\ -fno-gnu-inline-asm Disable GNU style inline asm |
| 104 | \\ -fhosted Compilation in a hosted environment | |
| 103 | 105 | \\ -fms-extensions Enable support for Microsoft extensions |
| 104 | 106 | \\ -fno-ms-extensions Disable support for Microsoft extensions |
| 105 | 107 | \\ -fdollars-in-identifiers |
| ... | ... | @@ -177,6 +179,7 @@ pub fn parseArgs( |
| 177 | 179 | ) !bool { |
| 178 | 180 | var i: usize = 1; |
| 179 | 181 | var comment_arg: []const u8 = ""; |
| 182 | var hosted: ?bool = null; | |
| 180 | 183 | while (i < args.len) : (i += 1) { |
| 181 | 184 | const arg = args[i]; |
| 182 | 185 | if (mem.startsWith(u8, arg, "-") and arg.len > 1) { |
| ... | ... | @@ -277,6 +280,10 @@ pub fn parseArgs( |
| 277 | 280 | d.comp.langopts.declspec_attrs = true; |
| 278 | 281 | } else if (mem.eql(u8, arg, "-fno-declspec")) { |
| 279 | 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 | 287 | } else if (mem.eql(u8, arg, "-fms-extensions")) { |
| 281 | 288 | d.comp.langopts.enableMSExtensions(); |
| 282 | 289 | } else if (mem.eql(u8, arg, "-fno-ms-extensions")) { |
| ... | ... | @@ -440,6 +447,15 @@ pub fn parseArgs( |
| 440 | 447 | if (d.comp.langopts.preserve_comments and !d.only_preprocess) { |
| 441 | 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 | 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 | 121 | base: []const u8, |
| 122 | 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 | 125 | while (self.i < self.entries.len) { |
| 126 | 126 | const entry = self.entries[self.i]; |
| 127 | 127 | self.i += 1; |
| ... | ... | @@ -130,7 +130,7 @@ pub const Filesystem = union(enum) { |
| 130 | 130 | const remaining = entry.path[self.base.len + 1 ..]; |
| 131 | 131 | if (std.mem.indexOfScalar(u8, remaining, std.fs.path.sep) != null) continue; |
| 132 | 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 | 134 | return .{ .name = remaining, .kind = kind }; |
| 135 | 135 | } |
| 136 | 136 | } |
| ... | ... | @@ -139,18 +139,18 @@ pub const Filesystem = union(enum) { |
| 139 | 139 | }; |
| 140 | 140 | }; |
| 141 | 141 | |
| 142 | const IterableDir = union(enum) { | |
| 143 | dir: std.fs.IterableDir, | |
| 142 | const Dir = union(enum) { | |
| 143 | dir: std.fs.Dir, | |
| 144 | 144 | fake: FakeDir, |
| 145 | 145 | |
| 146 | pub fn iterate(self: IterableDir) Iterator { | |
| 146 | pub fn iterate(self: Dir) Iterator { | |
| 147 | 147 | return switch (self) { |
| 148 | 148 | .dir => |dir| .{ .iterator = dir.iterate() }, |
| 149 | 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 | 154 | switch (self.*) { |
| 155 | 155 | .dir => |*d| d.close(), |
| 156 | 156 | .fake => {}, |
| ... | ... | @@ -159,10 +159,10 @@ pub const Filesystem = union(enum) { |
| 159 | 159 | }; |
| 160 | 160 | |
| 161 | 161 | const Iterator = union(enum) { |
| 162 | iterator: std.fs.IterableDir.Iterator, | |
| 162 | iterator: std.fs.Dir.Iterator, | |
| 163 | 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 | 166 | return switch (self.*) { |
| 167 | 167 | .iterator => |*it| it.next(), |
| 168 | 168 | .fake => |*it| it.next(), |
| ... | ... | @@ -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 | 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 | 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 | 602 | const lib_suffix = std.fs.path.join(suffix_buf_fib.allocator(), &.{ base, candidate_triple }) catch continue; |
| 603 | 603 | |
| 604 | 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 | 606 | defer parent_dir.close(); |
| 607 | 607 | |
| 608 | 608 | var it = parent_dir.iterate(); |
deps/aro/aro/Parser.zig+79-32| ... | ... | @@ -9,6 +9,8 @@ const Tokenizer = @import("Tokenizer.zig"); |
| 9 | 9 | const Preprocessor = @import("Preprocessor.zig"); |
| 10 | 10 | const Tree = @import("Tree.zig"); |
| 11 | 11 | const Token = Tree.Token; |
| 12 | const NumberPrefix = Token.NumberPrefix; | |
| 13 | const NumberSuffix = Token.NumberSuffix; | |
| 12 | 14 | const TokenIndex = Tree.TokenIndex; |
| 13 | 15 | const NodeIndex = Tree.NodeIndex; |
| 14 | 16 | const Type = @import("Type.zig"); |
| ... | ... | @@ -24,9 +26,6 @@ const Symbol = SymbolStack.Symbol; |
| 24 | 26 | const record_layout = @import("record_layout.zig"); |
| 25 | 27 | const StrInt = @import("StringInterner.zig"); |
| 26 | 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 | 29 | const Builtins = @import("Builtins.zig"); |
| 31 | 30 | const Builtin = Builtins.Builtin; |
| 32 | 31 | const target_util = @import("target.zig"); |
| ... | ... | @@ -323,7 +322,7 @@ fn expectIdentifier(p: *Parser) Error!TokenIndex { |
| 323 | 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 | 328 | fn eatToken(p: *Parser, id: Token.Id) ?TokenIndex { |
| ... | ... | @@ -347,7 +346,7 @@ pub fn tokSlice(p: *Parser, tok: TokenIndex) []const u8 { |
| 347 | 346 | const loc = p.pp.tokens.items(.loc)[tok]; |
| 348 | 347 | var tmp_tokenizer = Tokenizer{ |
| 349 | 348 | .buf = p.comp.getSource(loc.id).buf, |
| 350 | .comp = p.comp, | |
| 349 | .langopts = p.comp.langopts, | |
| 351 | 350 | .index = loc.byte_offset, |
| 352 | 351 | .source = .generated, |
| 353 | 352 | }; |
| ... | ... | @@ -715,6 +714,9 @@ pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { |
| 715 | 714 | p.field_attr_buf.deinit(); |
| 716 | 715 | } |
| 717 | 716 | |
| 717 | try p.syms.pushScope(&p); | |
| 718 | defer p.syms.popScope(); | |
| 719 | ||
| 718 | 720 | // NodeIndex 0 must be invalid |
| 719 | 721 | _ = try p.addNode(.{ .tag = .invalid, .ty = undefined, .data = undefined }); |
| 720 | 722 | |
| ... | ... | @@ -1010,7 +1012,7 @@ fn decl(p: *Parser) Error!bool { |
| 1010 | 1012 | // Collect old style parameter declarations. |
| 1011 | 1013 | if (init_d.d.old_style_func != null) { |
| 1012 | 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 | 1016 | base_ty.specifier = .func; |
| 1015 | 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 | 1068 | d.ty = try Attribute.applyParameterAttributes(p, d.ty, attr_buf_top_declarator, .alignas_on_param); |
| 1067 | 1069 | |
| 1068 | 1070 | // bypass redefinition check to avoid duplicate errors |
| 1069 | try p.syms.syms.append(p.gpa, .{ | |
| 1071 | try p.syms.define(p.gpa, .{ | |
| 1070 | 1072 | .kind = .def, |
| 1071 | 1073 | .name = interned_name, |
| 1072 | 1074 | .tok = d.name, |
| ... | ... | @@ -1088,7 +1090,7 @@ fn decl(p: *Parser) Error!bool { |
| 1088 | 1090 | } |
| 1089 | 1091 | |
| 1090 | 1092 | // bypass redefinition check to avoid duplicate errors |
| 1091 | try p.syms.syms.append(p.gpa, .{ | |
| 1093 | try p.syms.define(p.gpa, .{ | |
| 1092 | 1094 | .kind = .def, |
| 1093 | 1095 | .name = param.name, |
| 1094 | 1096 | .tok = param.name_tok, |
| ... | ... | @@ -1428,12 +1430,14 @@ fn typeof(p: *Parser) Error!?Type { |
| 1428 | 1430 | .data = typeof_expr.ty.data, |
| 1429 | 1431 | .qual = if (unqual) .{} else typeof_expr.ty.qual.inheritFromTypeof(), |
| 1430 | 1432 | .specifier = typeof_expr.ty.specifier, |
| 1433 | .decayed = typeof_expr.ty.decayed, | |
| 1431 | 1434 | }, |
| 1432 | 1435 | }; |
| 1433 | 1436 | |
| 1434 | 1437 | return Type{ |
| 1435 | 1438 | .data = .{ .expr = inner }, |
| 1436 | 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 | 1818 | } else { |
| 1815 | 1819 | init_d.d.ty.specifier = init_d.initializer.ty.specifier; |
| 1816 | 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 | 1824 | if (apply_var_attributes) { |
| ... | ... | @@ -2105,7 +2110,7 @@ fn recordSpec(p: *Parser) Error!Type { |
| 2105 | 2110 | .specifier = if (is_struct) .@"struct" else .@"union", |
| 2106 | 2111 | .data = .{ .record = record_ty }, |
| 2107 | 2112 | }, attr_buf_top, null); |
| 2108 | try p.syms.syms.append(p.gpa, .{ | |
| 2113 | try p.syms.define(p.gpa, .{ | |
| 2109 | 2114 | .kind = if (is_struct) .@"struct" else .@"union", |
| 2110 | 2115 | .name = interned_name, |
| 2111 | 2116 | .tok = ident, |
| ... | ... | @@ -2151,10 +2156,8 @@ fn recordSpec(p: *Parser) Error!Type { |
| 2151 | 2156 | |
| 2152 | 2157 | // declare a symbol for the type |
| 2153 | 2158 | // We need to replace the symbol's type if it has attributes |
| 2154 | var symbol_index: ?usize = null; | |
| 2155 | 2159 | if (maybe_ident != null and !defined) { |
| 2156 | symbol_index = p.syms.syms.len; | |
| 2157 | try p.syms.syms.append(p.gpa, .{ | |
| 2160 | try p.syms.define(p.gpa, .{ | |
| 2158 | 2161 | .kind = if (is_struct) .@"struct" else .@"union", |
| 2159 | 2162 | .name = record_ty.name, |
| 2160 | 2163 | .tok = maybe_ident.?, |
| ... | ... | @@ -2216,8 +2219,11 @@ fn recordSpec(p: *Parser) Error!Type { |
| 2216 | 2219 | .specifier = if (is_struct) .@"struct" else .@"union", |
| 2217 | 2220 | .data = .{ .record = record_ty }, |
| 2218 | 2221 | }, attr_buf_top, null); |
| 2219 | if (ty.specifier == .attributed and symbol_index != null) { | |
| 2220 | p.syms.syms.items(.ty)[symbol_index.?] = ty; | |
| 2222 | if (ty.specifier == .attributed and maybe_ident != null) { | |
| 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 | 2229 | if (!ty.hasIncompleteSize()) { |
| ... | ... | @@ -2474,7 +2480,7 @@ fn enumSpec(p: *Parser) Error!Type { |
| 2474 | 2480 | .specifier = .@"enum", |
| 2475 | 2481 | .data = .{ .@"enum" = enum_ty }, |
| 2476 | 2482 | }, attr_buf_top, null); |
| 2477 | try p.syms.syms.append(p.gpa, .{ | |
| 2483 | try p.syms.define(p.gpa, .{ | |
| 2478 | 2484 | .kind = .@"enum", |
| 2479 | 2485 | .name = interned_name, |
| 2480 | 2486 | .tok = ident, |
| ... | ... | @@ -2525,7 +2531,6 @@ fn enumSpec(p: *Parser) Error!Type { |
| 2525 | 2531 | p.enum_buf.items.len = enum_buf_top; |
| 2526 | 2532 | } |
| 2527 | 2533 | |
| 2528 | const sym_stack_top = p.syms.syms.len; | |
| 2529 | 2534 | var e = Enumerator.init(fixed_ty); |
| 2530 | 2535 | while (try p.enumerator(&e)) |field_and_node| { |
| 2531 | 2536 | try p.enum_buf.append(field_and_node.field); |
| ... | ... | @@ -2551,13 +2556,12 @@ fn enumSpec(p: *Parser) Error!Type { |
| 2551 | 2556 | const field_nodes = p.list_buf.items[list_buf_top..]; |
| 2552 | 2557 | |
| 2553 | 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 | 2559 | for (enum_fields, 0..) |*field, i| { |
| 2558 | 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 | 2565 | const dest_ty = if (p.comp.fixedEnumTagSpecifier()) |some| |
| 2562 | 2566 | Type{ .specifier = some } |
| 2563 | 2567 | else if (try res.intFitsInType(p, Type.int)) |
| ... | ... | @@ -2567,8 +2571,9 @@ fn enumSpec(p: *Parser) Error!Type { |
| 2567 | 2571 | else |
| 2568 | 2572 | continue; |
| 2569 | 2573 | |
| 2570 | try vals[i].intCast(dest_ty, p.comp); | |
| 2571 | types[i] = dest_ty; | |
| 2574 | const symbol = p.syms.getPtr(field.name, .vars); | |
| 2575 | try symbol.val.intCast(dest_ty, p.comp); | |
| 2576 | symbol.ty = dest_ty; | |
| 2572 | 2577 | p.nodes.items(.ty)[@intFromEnum(field_nodes[i])] = dest_ty; |
| 2573 | 2578 | field.ty = dest_ty; |
| 2574 | 2579 | res.ty = dest_ty; |
| ... | ... | @@ -2585,7 +2590,7 @@ fn enumSpec(p: *Parser) Error!Type { |
| 2585 | 2590 | |
| 2586 | 2591 | // declare a symbol for the type |
| 2587 | 2592 | if (maybe_ident != null and !defined) { |
| 2588 | try p.syms.syms.append(p.gpa, .{ | |
| 2593 | try p.syms.define(p.gpa, .{ | |
| 2589 | 2594 | .kind = .@"enum", |
| 2590 | 2595 | .name = enum_ty.name, |
| 2591 | 2596 | .ty = ty, |
| ... | ... | @@ -2885,7 +2890,7 @@ fn declarator( |
| 2885 | 2890 | try res.ty.combine(outer); |
| 2886 | 2891 | try res.ty.validateCombinedType(p, suffix_start); |
| 2887 | 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 | 2894 | return res; |
| 2890 | 2895 | } |
| 2891 | 2896 | |
| ... | ... | @@ -4376,7 +4381,7 @@ fn stmt(p: *Parser) Error!NodeIndex { |
| 4376 | 4381 | /// | keyword_default ':' stmt |
| 4377 | 4382 | fn labeledStmt(p: *Parser) Error!?NodeIndex { |
| 4378 | 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 | 4385 | const str = p.tokSlice(name_tok); |
| 4381 | 4386 | if (p.findLabel(str)) |some| { |
| 4382 | 4387 | try p.errStr(.duplicate_label, name_tok, str); |
| ... | ... | @@ -4814,10 +4819,23 @@ const CallExpr = union(enum) { |
| 4814 | 4819 | /// of arguments, `paramCountOverride` is used to tell us how many arguments we should actually expect to see for |
| 4815 | 4820 | /// these custom-typechecked functions. |
| 4816 | 4821 | fn paramCountOverride(self: CallExpr) ?u32 { |
| 4822 | @setEvalBranchQuota(10_000); | |
| 4817 | 4823 | return switch (self) { |
| 4818 | 4824 | .standard => null, |
| 4819 | 4825 | .builtin => |builtin| switch (builtin.tag) { |
| 4820 | 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 | 4839 | else => null, |
| 4822 | 4840 | }, |
| 4823 | 4841 | }; |
| ... | ... | @@ -4827,10 +4845,25 @@ const CallExpr = union(enum) { |
| 4827 | 4845 | return switch (self) { |
| 4828 | 4846 | .standard => callable_ty.returnType(), |
| 4829 | 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 | 4859 | Builtin.tagFromName("__builtin_complex").? => { |
| 4860 | if (p.list_buf.items.len < 1) return Type.invalid; // not enough arguments; already an error | |
| 4831 | 4861 | const last_param = p.list_buf.items[p.list_buf.items.len - 1]; |
| 4832 | 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 | 4867 | else => callable_ty.returnType(), |
| 4835 | 4868 | }, |
| 4836 | 4869 | }; |
| ... | ... | @@ -7458,7 +7491,7 @@ fn primaryExpr(p: *Parser) Error!Result { |
| 7458 | 7491 | } |
| 7459 | 7492 | switch (p.tok_ids[p.tok_i]) { |
| 7460 | 7493 | .identifier, .extended_identifier => { |
| 7461 | const name_tok = p.expectIdentifier() catch unreachable; | |
| 7494 | const name_tok = try p.expectIdentifier(); | |
| 7462 | 7495 | const name = p.tokSlice(name_tok); |
| 7463 | 7496 | const interned_name = try StrInt.intern(p.comp, name); |
| 7464 | 7497 | if (p.syms.findSymbol(interned_name)) |sym| { |
| ... | ... | @@ -7938,6 +7971,8 @@ fn parseFloat(p: *Parser, buf: []const u8, suffix: NumberSuffix) !Result { |
| 7938 | 7971 | .F, .IF => .float, |
| 7939 | 7972 | .F16 => .float16, |
| 7940 | 7973 | .L, .IL => .long_double, |
| 7974 | .W, .IW => .float80, | |
| 7975 | .Q, .IQ, .F128, .IF128 => .float128, | |
| 7941 | 7976 | else => unreachable, |
| 7942 | 7977 | } }; |
| 7943 | 7978 | const val = try Value.intern(p.comp, key: { |
| ... | ... | @@ -7946,7 +7981,7 @@ fn parseFloat(p: *Parser, buf: []const u8, suffix: NumberSuffix) !Result { |
| 7946 | 7981 | const strings_top = p.strings.items.len; |
| 7947 | 7982 | defer p.strings.items.len = strings_top; |
| 7948 | 7983 | for (buf) |c| { |
| 7949 | if (c != '_') p.strings.appendAssumeCapacity(c); | |
| 7984 | if (c != '\'') p.strings.appendAssumeCapacity(c); | |
| 7950 | 7985 | } |
| 7951 | 7986 | |
| 7952 | 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 | 8006 | .I => .complex_double, |
| 7972 | 8007 | .IF => .complex_float, |
| 7973 | 8008 | .IL => .complex_long_double, |
| 8009 | .IW => .complex_float80, | |
| 8010 | .IQ, .IF128 => .complex_float128, | |
| 7974 | 8011 | else => unreachable, |
| 7975 | 8012 | } }; |
| 7976 | 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 | 8160 | var managed = try big.int.Managed.init(p.gpa); |
| 8124 | 8161 | defer managed.deinit(); |
| 8125 | 8162 | |
| 8126 | managed.setString(base, buf) catch |e| switch (e) { | |
| 8127 | error.InvalidBase => unreachable, // `base` is one of 2, 8, 10, 16 | |
| 8128 | error.InvalidCharacter => unreachable, // digits validated by Tokenizer | |
| 8129 | else => |er| return er, | |
| 8130 | }; | |
| 8163 | { | |
| 8164 | try p.strings.ensureUnusedCapacity(buf.len); | |
| 8165 | ||
| 8166 | const strings_top = p.strings.items.len; | |
| 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 | 8178 | const c = managed.toConst(); |
| 8132 | 8179 | const bits_needed: std.math.IntFittingRange(0, Compilation.bit_int_max_bits) = blk: { |
| 8133 | 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 | 315 | fn findIncludeGuard(pp: *Preprocessor, source: Source) ?[]const u8 { |
| 316 | 316 | var tokenizer = Tokenizer{ |
| 317 | 317 | .buf = source.buf, |
| 318 | .comp = pp.comp, | |
| 318 | .langopts = pp.comp.langopts, | |
| 319 | 319 | .source = source.id, |
| 320 | 320 | }; |
| 321 | 321 | var hash = tokenizer.nextNoWS(); |
| ... | ... | @@ -334,7 +334,7 @@ fn preprocessExtra(pp: *Preprocessor, source: Source) MacroError!Token { |
| 334 | 334 | pp.preprocess_count += 1; |
| 335 | 335 | var tokenizer = Tokenizer{ |
| 336 | 336 | .buf = source.buf, |
| 337 | .comp = pp.comp, | |
| 337 | .langopts = pp.comp.langopts, | |
| 338 | 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 | 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 | 761 | fn verboseLog(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args: anytype) void { |
| 751 | 762 | const source = pp.comp.getSource(raw.source); |
| 752 | 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 | 1196 | try pp.comp.generated_buf.appendSlice(pp.gpa, pp.char_buf.items); |
| 1186 | 1197 | var tmp_tokenizer = Tokenizer{ |
| 1187 | 1198 | .buf = pp.comp.generated_buf.items, |
| 1188 | .comp = pp.comp, | |
| 1199 | .langopts = pp.comp.langopts, | |
| 1189 | 1200 | .index = @intCast(start), |
| 1190 | 1201 | .source = .generated, |
| 1191 | 1202 | .line = pp.generated_line, |
| ... | ... | @@ -1864,7 +1875,7 @@ fn expandVaOpt( |
| 1864 | 1875 | .buf = source.buf, |
| 1865 | 1876 | .index = raw.start, |
| 1866 | 1877 | .source = raw.source, |
| 1867 | .comp = pp.comp, | |
| 1878 | .langopts = pp.comp.langopts, | |
| 1868 | 1879 | .line = raw.line, |
| 1869 | 1880 | }; |
| 1870 | 1881 | while (tokenizer.index < raw.end) { |
| ... | ... | @@ -2282,11 +2293,11 @@ fn expandMacro(pp: *Preprocessor, tokenizer: *Tokenizer, raw: RawToken) MacroErr |
| 2282 | 2293 | |
| 2283 | 2294 | fn expandedSliceExtra(pp: *const Preprocessor, tok: Token, macro_ws_handling: enum { single_macro_ws, preserve_macro_ws }) []const u8 { |
| 2284 | 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 | 2298 | var tmp_tokenizer = Tokenizer{ |
| 2288 | 2299 | .buf = pp.comp.getSource(tok.loc.id).buf, |
| 2289 | .comp = pp.comp, | |
| 2300 | .langopts = pp.comp.langopts, | |
| 2290 | 2301 | .index = tok.loc.byte_offset, |
| 2291 | 2302 | .source = .generated, |
| 2292 | 2303 | }; |
| ... | ... | @@ -2340,7 +2351,7 @@ fn pasteTokens(pp: *Preprocessor, lhs_toks: *ExpandBuf, rhs_toks: []const Token) |
| 2340 | 2351 | // Try to tokenize the result. |
| 2341 | 2352 | var tmp_tokenizer = Tokenizer{ |
| 2342 | 2353 | .buf = pp.comp.generated_buf.items, |
| 2343 | .comp = pp.comp, | |
| 2354 | .langopts = pp.comp.langopts, | |
| 2344 | 2355 | .index = @intCast(start), |
| 2345 | 2356 | .source = .generated, |
| 2346 | 2357 | }; |
| ... | ... | @@ -2703,6 +2714,7 @@ fn embed(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!void { |
| 2703 | 2714 | error.InvalidInclude => return, |
| 2704 | 2715 | else => |e| return e, |
| 2705 | 2716 | }; |
| 2717 | defer Token.free(filename_tok.expansion_locs, pp.gpa); | |
| 2706 | 2718 | |
| 2707 | 2719 | // Check for empty filename. |
| 2708 | 2720 | const tok_slice = pp.expandedSliceExtra(filename_tok, .single_macro_ws); |
| ... | ... | @@ -2836,7 +2848,7 @@ fn embed(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!void { |
| 2836 | 2848 | } |
| 2837 | 2849 | |
| 2838 | 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 | 2852 | defer pp.comp.gpa.free(embed_bytes); |
| 2841 | 2853 | |
| 2842 | 2854 | try Range.expand(prefix, pp, tokenizer); |
| ... | ... | @@ -2984,8 +2996,6 @@ fn findIncludeFilenameToken( |
| 2984 | 2996 | tokenizer: *Tokenizer, |
| 2985 | 2997 | trailing_token_behavior: enum { ignore_trailing_tokens, expect_nl_eof }, |
| 2986 | 2998 | ) !Token { |
| 2987 | const start = pp.tokens.len; | |
| 2988 | defer pp.tokens.len = start; | |
| 2989 | 2999 | var first = first_token; |
| 2990 | 3000 | |
| 2991 | 3001 | if (first.id == .angle_bracket_left) to_end: { |
| ... | ... | @@ -3008,35 +3018,60 @@ fn findIncludeFilenameToken( |
| 3008 | 3018 | }, &.{}); |
| 3009 | 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. | |
| 3015 | const filename_tok = pp.tokens.get(start); | |
| 3016 | switch (filename_tok.id) { | |
| 3017 | .string_literal, .macro_string => {}, | |
| 3018 | else => { | |
| 3019 | try pp.err(first, .expected_filename); | |
| 3020 | try pp.expectNl(tokenizer); | |
| 3021 | return error.InvalidInclude; | |
| 3022 | const source_tok = tokFromRaw(first); | |
| 3023 | const filename_tok, const expanded_trailing = switch (source_tok.id) { | |
| 3024 | .string_literal, .macro_string => .{ source_tok, false }, | |
| 3025 | else => expanded: { | |
| 3026 | // Try to expand if the argument is a macro. | |
| 3027 | pp.top_expansion_buf.items.len = 0; | |
| 3028 | defer for (pp.top_expansion_buf.items) |tok| Token.free(tok.expansion_locs, pp.gpa); | |
| 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 | 3050 | switch (trailing_token_behavior) { |
| 3025 | 3051 | .expect_nl_eof => { |
| 3026 | 3052 | // Error on extra tokens. |
| 3027 | 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 | 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 | 3069 | return filename_tok; |
| 3036 | 3070 | } |
| 3037 | 3071 | |
| 3038 | 3072 | fn findIncludeSource(pp: *Preprocessor, tokenizer: *Tokenizer, first: RawToken, which: Compilation.WhichInclude) !Source { |
| 3039 | 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 | 3076 | // Check for empty filename. |
| 3042 | 3077 | const tok_slice = pp.expandedSliceExtra(filename_tok, .single_macro_ws); |
| ... | ... | @@ -3054,7 +3089,7 @@ fn findIncludeSource(pp: *Preprocessor, tokenizer: *Tokenizer, first: RawToken, |
| 3054 | 3089 | }; |
| 3055 | 3090 | |
| 3056 | 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 | 3095 | fn printLinemarker( |
deps/aro/aro/SymbolStack.zig+201-184| ... | ... | @@ -11,6 +11,8 @@ const Parser = @import("Parser.zig"); |
| 11 | 11 | const Value = @import("Value.zig"); |
| 12 | 12 | const StringId = @import("StringInterner.zig").StringId; |
| 13 | 13 | |
| 14 | const SymbolStack = @This(); | |
| 15 | ||
| 14 | 16 | pub const Symbol = struct { |
| 15 | 17 | name: StringId, |
| 16 | 18 | ty: Type, |
| ... | ... | @@ -31,72 +33,74 @@ pub const Kind = enum { |
| 31 | 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) = .{}, | |
| 37 | scopes: std.ArrayListUnmanaged(u32) = .{}, | |
| 41 | const Scope = struct { | |
| 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 | 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 | 61 | s.scopes.deinit(gpa); |
| 42 | 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 | 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 | 75 | pub fn popScope(s: *SymbolStack) void { |
| 55 | s.syms.len = s.scopes.pop(); | |
| 76 | s.active_len -= 1; | |
| 56 | 77 | } |
| 57 | 78 | |
| 58 | 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); | |
| 60 | const names = s.syms.items(.name); | |
| 61 | var i = s.syms.len; | |
| 62 | while (i > 0) { | |
| 63 | i -= 1; | |
| 64 | switch (kinds[i]) { | |
| 65 | .typedef => if (names[i] == name) return s.syms.get(i), | |
| 66 | .@"struct" => if (names[i] == name) { | |
| 67 | if (no_type_yet) return null; | |
| 68 | try p.errStr(.must_use_struct, name_tok, p.tokSlice(name_tok)); | |
| 69 | return s.syms.get(i); | |
| 70 | }, | |
| 71 | .@"union" => if (names[i] == name) { | |
| 72 | if (no_type_yet) return null; | |
| 73 | try p.errStr(.must_use_union, name_tok, p.tokSlice(name_tok)); | |
| 74 | return s.syms.get(i); | |
| 75 | }, | |
| 76 | .@"enum" => if (names[i] == name) { | |
| 77 | if (no_type_yet) 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 | } | |
| 80 | const prev = s.lookup(name, .vars) orelse s.lookup(name, .tags) orelse return null; | |
| 81 | switch (prev.kind) { | |
| 82 | .typedef => return prev, | |
| 83 | .@"struct" => { | |
| 84 | if (no_type_yet) return null; | |
| 85 | try p.errStr(.must_use_struct, name_tok, p.tokSlice(name_tok)); | |
| 86 | return prev; | |
| 87 | }, | |
| 88 | .@"union" => { | |
| 89 | if (no_type_yet) return null; | |
| 90 | try p.errStr(.must_use_union, name_tok, p.tokSlice(name_tok)); | |
| 91 | return prev; | |
| 92 | }, | |
| 93 | .@"enum" => { | |
| 94 | if (no_type_yet) return null; | |
| 95 | try p.errStr(.must_use_enum, name_tok, p.tokSlice(name_tok)); | |
| 96 | return prev; | |
| 97 | }, | |
| 98 | else => return null, | |
| 84 | 99 | } |
| 85 | return null; | |
| 86 | 100 | } |
| 87 | 101 | |
| 88 | 102 | pub fn findSymbol(s: *SymbolStack, name: StringId) ?Symbol { |
| 89 | const kinds = s.syms.items(.kind); | |
| 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; | |
| 103 | return s.lookup(name, .vars); | |
| 100 | 104 | } |
| 101 | 105 | |
| 102 | 106 | pub fn findTag( |
| ... | ... | @@ -107,36 +111,62 @@ pub fn findTag( |
| 107 | 111 | name_tok: TokenIndex, |
| 108 | 112 | next_tok_id: Token.Id, |
| 109 | 113 | ) !?Symbol { |
| 110 | const kinds = s.syms.items(.kind); | |
| 111 | const names = s.syms.items(.name); | |
| 112 | 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; | |
| 114 | var i = s.syms.len; | |
| 115 | while (i > end) { | |
| 115 | const prev = (if (next_tok_id == .semicolon) s.get(name, .tags) else s.lookup(name, .tags)) orelse return null; | |
| 116 | switch (prev.kind) { | |
| 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 | 148 | i -= 1; |
| 117 | switch (kinds[i]) { | |
| 118 | .@"enum" => if (names[i] == name) { | |
| 119 | if (kind == .keyword_enum) return s.syms.get(i); | |
| 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 => {}, | |
| 149 | switch (kind) { | |
| 150 | .vars => if (s.scopes.items[i].vars.get(name)) |sym| return sym, | |
| 151 | .tags => if (s.scopes.items[i].tags.get(name)) |sym| return sym, | |
| 131 | 152 | } |
| 132 | } else return null; | |
| 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]); | |
| 153 | } | |
| 137 | 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 | 170 | pub fn defineTypedef( |
| 141 | 171 | s: *SymbolStack, |
| 142 | 172 | p: *Parser, |
| ... | ... | @@ -145,25 +175,22 @@ pub fn defineTypedef( |
| 145 | 175 | tok: TokenIndex, |
| 146 | 176 | node: NodeIndex, |
| 147 | 177 | ) !void { |
| 148 | const kinds = s.syms.items(.kind); | |
| 149 | const names = s.syms.items(.name); | |
| 150 | const end = s.scopeEnd(); | |
| 151 | var i = s.syms.len; | |
| 152 | while (i > end) { | |
| 153 | i -= 1; | |
| 154 | switch (kinds[i]) { | |
| 155 | .typedef => if (names[i] == name) { | |
| 156 | const prev_ty = s.syms.items(.ty)[i]; | |
| 157 | if (ty.eql(prev_ty, p.comp, true)) break; | |
| 158 | try p.errStr(.redefinition_of_typedef, tok, try p.typePairStrExtra(ty, " vs ", prev_ty)); | |
| 159 | const previous_tok = s.syms.items(.tok)[i]; | |
| 160 | if (previous_tok != 0) try p.errTok(.previous_definition, previous_tok); | |
| 161 | break; | |
| 178 | if (s.get(name, .vars)) |prev| { | |
| 179 | switch (prev.kind) { | |
| 180 | .typedef => { | |
| 181 | if (!ty.eql(prev.ty, p.comp, true)) { | |
| 182 | try p.errStr(.redefinition_of_typedef, tok, try p.typePairStrExtra(ty, " vs ", prev.ty)); | |
| 183 | if (prev.tok != 0) try p.errTok(.previous_definition, prev.tok); | |
| 184 | } | |
| 185 | }, | |
| 186 | .enumeration, .decl, .def, .constexpr => { | |
| 187 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); | |
| 188 | try p.errTok(.previous_definition, prev.tok); | |
| 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 | 194 | .kind = .typedef, |
| 168 | 195 | .name = name, |
| 169 | 196 | .tok = tok, |
| ... | ... | @@ -183,35 +210,31 @@ pub fn defineSymbol( |
| 183 | 210 | val: Value, |
| 184 | 211 | constexpr: bool, |
| 185 | 212 | ) !void { |
| 186 | const kinds = s.syms.items(.kind); | |
| 187 | const names = s.syms.items(.name); | |
| 188 | const end = s.scopeEnd(); | |
| 189 | var i = s.syms.len; | |
| 190 | while (i > end) { | |
| 191 | i -= 1; | |
| 192 | switch (kinds[i]) { | |
| 193 | .enumeration => if (names[i] == name) { | |
| 213 | if (s.get(name, .vars)) |prev| { | |
| 214 | switch (prev.kind) { | |
| 215 | .enumeration => { | |
| 194 | 216 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); |
| 195 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | |
| 196 | break; | |
| 217 | try p.errTok(.previous_definition, prev.tok); | |
| 197 | 218 | }, |
| 198 | .decl => if (names[i] == name) { | |
| 199 | const prev_ty = s.syms.items(.ty)[i]; | |
| 200 | if (!ty.eql(prev_ty, p.comp, true)) { | |
| 219 | .decl => { | |
| 220 | if (!ty.eql(prev.ty, p.comp, true)) { | |
| 201 | 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 | 226 | try p.errStr(.redefinition, tok, p.tokSlice(tok)); |
| 208 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | |
| 209 | break; | |
| 227 | try p.errTok(.previous_definition, prev.tok); | |
| 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 | 238 | .kind = if (constexpr) .constexpr else .def, |
| 216 | 239 | .name = name, |
| 217 | 240 | .tok = tok, |
| ... | ... | @@ -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 | 256 | pub fn declareSymbol( |
| 225 | 257 | s: *SymbolStack, |
| 226 | 258 | p: *Parser, |
| ... | ... | @@ -229,39 +261,34 @@ pub fn declareSymbol( |
| 229 | 261 | tok: TokenIndex, |
| 230 | 262 | node: NodeIndex, |
| 231 | 263 | ) !void { |
| 232 | const kinds = s.syms.items(.kind); | |
| 233 | const names = s.syms.items(.name); | |
| 234 | const end = s.scopeEnd(); | |
| 235 | var i = s.syms.len; | |
| 236 | while (i > end) { | |
| 237 | i -= 1; | |
| 238 | switch (kinds[i]) { | |
| 239 | .enumeration => if (names[i] == name) { | |
| 264 | if (s.get(name, .vars)) |prev| { | |
| 265 | switch (prev.kind) { | |
| 266 | .enumeration => { | |
| 240 | 267 | try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); |
| 241 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | |
| 242 | break; | |
| 268 | try p.errTok(.previous_definition, prev.tok); | |
| 243 | 269 | }, |
| 244 | .decl => if (names[i] == name) { | |
| 245 | const prev_ty = s.syms.items(.ty)[i]; | |
| 246 | if (!ty.eql(prev_ty, p.comp, true)) { | |
| 270 | .decl => { | |
| 271 | if (!ty.eql(prev.ty, p.comp, true)) { | |
| 247 | 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) { | |
| 253 | const prev_ty = s.syms.items(.ty)[i]; | |
| 254 | if (!ty.eql(prev_ty, p.comp, true)) { | |
| 276 | .def, .constexpr => { | |
| 277 | if (!ty.eql(prev.ty, p.comp, true)) { | |
| 255 | 278 | try p.errStr(.redefinition_incompatible, tok, p.tokSlice(tok)); |
| 256 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | |
| 257 | break; | |
| 279 | try p.errTok(.previous_definition, prev.tok); | |
| 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 | 292 | .kind = .decl, |
| 266 | 293 | .name = name, |
| 267 | 294 | .tok = tok, |
| ... | ... | @@ -272,25 +299,23 @@ pub fn declareSymbol( |
| 272 | 299 | } |
| 273 | 300 | |
| 274 | 301 | pub fn defineParam(s: *SymbolStack, p: *Parser, name: StringId, ty: Type, tok: TokenIndex) !void { |
| 275 | const kinds = s.syms.items(.kind); | |
| 276 | const names = s.syms.items(.name); | |
| 277 | const end = s.scopeEnd(); | |
| 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) { | |
| 302 | if (s.get(name, .vars)) |prev| { | |
| 303 | switch (prev.kind) { | |
| 304 | .enumeration, .decl, .def, .constexpr => { | |
| 283 | 305 | try p.errStr(.redefinition_of_parameter, tok, p.tokSlice(tok)); |
| 284 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | |
| 285 | break; | |
| 306 | try p.errTok(.previous_definition, prev.tok); | |
| 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 | 315 | if (ty.is(.fp16) and !p.comp.hasHalfPrecisionFloatABI()) { |
| 291 | 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 | 319 | .kind = .def, |
| 295 | 320 | .name = name, |
| 296 | 321 | .tok = tok, |
| ... | ... | @@ -306,35 +331,28 @@ pub fn defineTag( |
| 306 | 331 | kind: Token.Id, |
| 307 | 332 | tok: TokenIndex, |
| 308 | 333 | ) !?Symbol { |
| 309 | const kinds = s.syms.items(.kind); | |
| 310 | const names = s.syms.items(.name); | |
| 311 | const end = s.scopeEnd(); | |
| 312 | var i = s.syms.len; | |
| 313 | while (i > end) { | |
| 314 | i -= 1; | |
| 315 | switch (kinds[i]) { | |
| 316 | .@"enum" => if (names[i] == name) { | |
| 317 | if (kind == .keyword_enum) return s.syms.get(i); | |
| 318 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); | |
| 319 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | |
| 320 | return null; | |
| 321 | }, | |
| 322 | .@"struct" => if (names[i] == name) { | |
| 323 | if (kind == .keyword_struct) return s.syms.get(i); | |
| 324 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); | |
| 325 | try p.errTok(.previous_definition, s.syms.items(.tok)[i]); | |
| 326 | return null; | |
| 327 | }, | |
| 328 | .@"union" => if (names[i] == name) { | |
| 329 | if (kind == .keyword_union) return s.syms.get(i); | |
| 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 | } | |
| 334 | const prev = s.get(name, .tags) orelse return null; | |
| 335 | switch (prev.kind) { | |
| 336 | .@"enum" => { | |
| 337 | if (kind == .keyword_enum) return prev; | |
| 338 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); | |
| 339 | try p.errTok(.previous_definition, prev.tok); | |
| 340 | return null; | |
| 341 | }, | |
| 342 | .@"struct" => { | |
| 343 | if (kind == .keyword_struct) return prev; | |
| 344 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); | |
| 345 | try p.errTok(.previous_definition, prev.tok); | |
| 346 | return null; | |
| 347 | }, | |
| 348 | .@"union" => { | |
| 349 | if (kind == .keyword_union) return prev; | |
| 350 | try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); | |
| 351 | try p.errTok(.previous_definition, prev.tok); | |
| 352 | return null; | |
| 353 | }, | |
| 354 | else => unreachable, | |
| 336 | 355 | } |
| 337 | return null; | |
| 338 | 356 | } |
| 339 | 357 | |
| 340 | 358 | pub fn defineEnumeration( |
| ... | ... | @@ -345,27 +363,26 @@ pub fn defineEnumeration( |
| 345 | 363 | tok: TokenIndex, |
| 346 | 364 | val: Value, |
| 347 | 365 | ) !void { |
| 348 | const kinds = s.syms.items(.kind); | |
| 349 | const names = s.syms.items(.name); | |
| 350 | const end = s.scopeEnd(); | |
| 351 | var i = s.syms.len; | |
| 352 | while (i > end) { | |
| 353 | i -= 1; | |
| 354 | switch (kinds[i]) { | |
| 355 | .enumeration => if (names[i] == name) { | |
| 366 | if (s.get(name, .vars)) |prev| { | |
| 367 | switch (prev.kind) { | |
| 368 | .enumeration => { | |
| 356 | 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 | 371 | return; |
| 359 | 372 | }, |
| 360 | .decl, .def, .constexpr => if (names[i] == name) { | |
| 373 | .decl, .def, .constexpr => { | |
| 361 | 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 | 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 | 386 | .kind = .enumeration, |
| 370 | 387 | .name = name, |
| 371 | 388 | .tok = tok, |
deps/aro/aro/Tokenizer.zig+26-23| ... | ... | @@ -749,12 +749,15 @@ pub const Token = struct { |
| 749 | 749 | .string_literal_utf_8, |
| 750 | 750 | .string_literal_utf_32, |
| 751 | 751 | .string_literal_wide, |
| 752 | .unterminated_string_literal, | |
| 752 | 753 | => "a string literal", |
| 753 | 754 | .char_literal, |
| 754 | 755 | .char_literal_utf_8, |
| 755 | 756 | .char_literal_utf_16, |
| 756 | 757 | .char_literal_utf_32, |
| 757 | 758 | .char_literal_wide, |
| 759 | .unterminated_char_literal, | |
| 760 | .empty_char_literal, | |
| 758 | 761 | => "a character literal", |
| 759 | 762 | .pp_num, .embed_byte => "A number", |
| 760 | 763 | else => id.lexeme().?, |
| ... | ... | @@ -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 | 805 | return switch (id) { |
| 803 | 806 | .l_bracket, |
| 804 | 807 | .r_bracket, |
| ... | ... | @@ -806,7 +809,7 @@ pub const Token = struct { |
| 806 | 809 | .r_brace, |
| 807 | 810 | .hash, |
| 808 | 811 | .hash_hash, |
| 809 | => comp.langopts.hasDigraphs(), | |
| 812 | => langopts.hasDigraphs(), | |
| 810 | 813 | else => false, |
| 811 | 814 | }; |
| 812 | 815 | } |
| ... | ... | @@ -829,15 +832,15 @@ pub const Token = struct { |
| 829 | 832 | /// double underscore and underscore + capital letter identifiers |
| 830 | 833 | /// belong to the implementation namespace, so we always convert them |
| 831 | 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 | 836 | const kw = all_kws.get(str) orelse return .identifier; |
| 834 | const standard = comp.langopts.standard; | |
| 837 | const standard = langopts.standard; | |
| 835 | 838 | return switch (kw) { |
| 836 | 839 | .keyword_inline => if (standard.isGNU() or standard.atLeast(.c99)) kw else .identifier, |
| 837 | 840 | .keyword_restrict => if (standard.atLeast(.c99)) kw else .identifier, |
| 838 | 841 | .keyword_typeof => if (standard.isGNU() or standard.atLeast(.c23)) kw else .identifier, |
| 839 | 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 | 845 | .keyword_c23_alignas, |
| 843 | 846 | .keyword_c23_alignof, |
| ... | ... | @@ -864,7 +867,7 @@ pub const Token = struct { |
| 864 | 867 | .keyword_stdcall2, |
| 865 | 868 | .keyword_thiscall2, |
| 866 | 869 | .keyword_vectorcall2, |
| 867 | => if (comp.langopts.ms_extensions) kw else .identifier, | |
| 870 | => if (langopts.ms_extensions) kw else .identifier, | |
| 868 | 871 | else => kw, |
| 869 | 872 | }; |
| 870 | 873 | } |
| ... | ... | @@ -1023,7 +1026,7 @@ const Tokenizer = @This(); |
| 1023 | 1026 | buf: []const u8, |
| 1024 | 1027 | index: u32 = 0, |
| 1025 | 1028 | source: Source.Id, |
| 1026 | comp: *const Compilation, | |
| 1029 | langopts: LangOpts, | |
| 1027 | 1030 | line: u32 = 1, |
| 1028 | 1031 | |
| 1029 | 1032 | pub fn next(self: *Tokenizer) Token { |
| ... | ... | @@ -1162,14 +1165,14 @@ pub fn next(self: *Tokenizer) Token { |
| 1162 | 1165 | '#' => state = .hash, |
| 1163 | 1166 | '0'...'9' => state = .pp_num, |
| 1164 | 1167 | '\t', '\x0B', '\x0C', ' ' => state = .whitespace, |
| 1165 | '$' => if (self.comp.langopts.dollars_in_identifiers) { | |
| 1168 | '$' => if (self.langopts.dollars_in_identifiers) { | |
| 1166 | 1169 | state = .extended_identifier; |
| 1167 | 1170 | } else { |
| 1168 | 1171 | id = .invalid; |
| 1169 | 1172 | self.index += 1; |
| 1170 | 1173 | break; |
| 1171 | 1174 | }, |
| 1172 | 0x1A => if (self.comp.langopts.ms_extensions) { | |
| 1175 | 0x1A => if (self.langopts.ms_extensions) { | |
| 1173 | 1176 | id = .eof; |
| 1174 | 1177 | break; |
| 1175 | 1178 | } else { |
| ... | ... | @@ -1306,15 +1309,15 @@ pub fn next(self: *Tokenizer) Token { |
| 1306 | 1309 | }, |
| 1307 | 1310 | .identifier, .extended_identifier => switch (c) { |
| 1308 | 1311 | 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, |
| 1309 | '$' => if (self.comp.langopts.dollars_in_identifiers) { | |
| 1312 | '$' => if (self.langopts.dollars_in_identifiers) { | |
| 1310 | 1313 | state = .extended_identifier; |
| 1311 | 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 | 1316 | break; |
| 1314 | 1317 | }, |
| 1315 | 1318 | 0x80...0xFF => state = .extended_identifier, |
| 1316 | 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 | 1321 | break; |
| 1319 | 1322 | }, |
| 1320 | 1323 | }, |
| ... | ... | @@ -1358,7 +1361,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1358 | 1361 | }, |
| 1359 | 1362 | .colon => switch (c) { |
| 1360 | 1363 | '>' => { |
| 1361 | if (self.comp.langopts.hasDigraphs()) { | |
| 1364 | if (self.langopts.hasDigraphs()) { | |
| 1362 | 1365 | id = .r_bracket; |
| 1363 | 1366 | self.index += 1; |
| 1364 | 1367 | } else { |
| ... | ... | @@ -1367,7 +1370,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1367 | 1370 | break; |
| 1368 | 1371 | }, |
| 1369 | 1372 | ':' => { |
| 1370 | if (self.comp.langopts.standard.atLeast(.c23)) { | |
| 1373 | if (self.langopts.standard.atLeast(.c23)) { | |
| 1371 | 1374 | id = .colon_colon; |
| 1372 | 1375 | self.index += 1; |
| 1373 | 1376 | break; |
| ... | ... | @@ -1388,7 +1391,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1388 | 1391 | break; |
| 1389 | 1392 | }, |
| 1390 | 1393 | '>' => { |
| 1391 | if (self.comp.langopts.hasDigraphs()) { | |
| 1394 | if (self.langopts.hasDigraphs()) { | |
| 1392 | 1395 | id = .r_brace; |
| 1393 | 1396 | self.index += 1; |
| 1394 | 1397 | } else { |
| ... | ... | @@ -1397,7 +1400,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1397 | 1400 | break; |
| 1398 | 1401 | }, |
| 1399 | 1402 | ':' => { |
| 1400 | if (self.comp.langopts.hasDigraphs()) { | |
| 1403 | if (self.langopts.hasDigraphs()) { | |
| 1401 | 1404 | state = .hash_digraph; |
| 1402 | 1405 | } else { |
| 1403 | 1406 | id = .percent; |
| ... | ... | @@ -1444,7 +1447,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1444 | 1447 | break; |
| 1445 | 1448 | }, |
| 1446 | 1449 | ':' => { |
| 1447 | if (self.comp.langopts.hasDigraphs()) { | |
| 1450 | if (self.langopts.hasDigraphs()) { | |
| 1448 | 1451 | id = .l_bracket; |
| 1449 | 1452 | self.index += 1; |
| 1450 | 1453 | } else { |
| ... | ... | @@ -1453,7 +1456,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1453 | 1456 | break; |
| 1454 | 1457 | }, |
| 1455 | 1458 | '%' => { |
| 1456 | if (self.comp.langopts.hasDigraphs()) { | |
| 1459 | if (self.langopts.hasDigraphs()) { | |
| 1457 | 1460 | id = .l_brace; |
| 1458 | 1461 | self.index += 1; |
| 1459 | 1462 | } else { |
| ... | ... | @@ -1613,7 +1616,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1613 | 1616 | }, |
| 1614 | 1617 | .line_comment => switch (c) { |
| 1615 | 1618 | '\n' => { |
| 1616 | if (self.comp.langopts.preserve_comments) { | |
| 1619 | if (self.langopts.preserve_comments) { | |
| 1617 | 1620 | id = .comment; |
| 1618 | 1621 | break; |
| 1619 | 1622 | } |
| ... | ... | @@ -1629,7 +1632,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1629 | 1632 | }, |
| 1630 | 1633 | .multi_line_comment_asterisk => switch (c) { |
| 1631 | 1634 | '/' => { |
| 1632 | if (self.comp.langopts.preserve_comments) { | |
| 1635 | if (self.langopts.preserve_comments) { | |
| 1633 | 1636 | self.index += 1; |
| 1634 | 1637 | id = .comment; |
| 1635 | 1638 | break; |
| ... | ... | @@ -1673,7 +1676,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1673 | 1676 | '.', |
| 1674 | 1677 | => {}, |
| 1675 | 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 | 1680 | state = .pp_num_digit_separator; |
| 1678 | 1681 | } else { |
| 1679 | 1682 | id = .pp_num; |
| ... | ... | @@ -1721,7 +1724,7 @@ pub fn next(self: *Tokenizer) Token { |
| 1721 | 1724 | } else if (self.index == self.buf.len) { |
| 1722 | 1725 | switch (state) { |
| 1723 | 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 | 1728 | .extended_identifier => id = .extended_identifier, |
| 1726 | 1729 | |
| 1727 | 1730 | .period2 => { |
| ... | ... | @@ -2149,7 +2152,7 @@ fn expectTokensExtra(contents: []const u8, expected_tokens: []const Token.Id, st |
| 2149 | 2152 | var tokenizer = Tokenizer{ |
| 2150 | 2153 | .buf = source.buf, |
| 2151 | 2154 | .source = source.id, |
| 2152 | .comp = &comp, | |
| 2155 | .langopts = comp.langopts, | |
| 2153 | 2156 | }; |
| 2154 | 2157 | var i: usize = 0; |
| 2155 | 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 | 183 | return tc.getProgramPath(default_linker, buf); |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | const TargetSpecificToolName = std.BoundedArray(u8, 64); | |
| 187 | ||
| 188 | 186 | /// If an explicit target is provided, also check the prefixed tool-specific name |
| 189 | 187 | /// TODO: this isn't exactly right since our target names don't necessarily match up |
| 190 | 188 | /// with GCC's. |
| 191 | 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 | 191 | var possible_names: std.BoundedArray([]const u8, 2) = .{}; |
| 194 | 192 | if (raw_triple) |triple| { |
| 195 | const w = target_specific.writer(); | |
| 196 | if (w.print("{s}-{s}", .{ triple, name })) { | |
| 197 | possible_names.appendAssumeCapacity(target_specific.constSlice()); | |
| 193 | if (std.fmt.bufPrint(buf, "{s}-{s}", .{ triple, name })) |res| { | |
| 194 | possible_names.appendAssumeCapacity(res); | |
| 198 | 195 | } else |_| {} |
| 199 | 196 | } |
| 200 | 197 | possible_names.appendAssumeCapacity(name); |
| ... | ... | @@ -227,8 +224,8 @@ fn getProgramPath(tc: *const Toolchain, name: []const u8, buf: []u8) []const u8 |
| 227 | 224 | var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; |
| 228 | 225 | var fib = std.heap.FixedBufferAllocator.init(&path_buf); |
| 229 | 226 | |
| 230 | var tool_specific_name: TargetSpecificToolName = .{}; | |
| 231 | const possible_names = possibleProgramNames(tc.driver.raw_target_triple, name, &tool_specific_name); | |
| 227 | var tool_specific_buf: [64]u8 = undefined; | |
| 228 | const possible_names = possibleProgramNames(tc.driver.raw_target_triple, name, &tool_specific_buf); | |
| 232 | 229 | |
| 233 | 230 | for (possible_names.constSlice()) |tool_name| { |
| 234 | 231 | for (tc.program_paths.items) |program_path| { |
deps/aro/aro/Tree.zig+7-4| ... | ... | @@ -1,11 +1,12 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const Interner = @import("backend").Interner; |
| 3 | const Type = @import("Type.zig"); | |
| 4 | const Tokenizer = @import("Tokenizer.zig"); | |
| 3 | const Attribute = @import("Attribute.zig"); | |
| 5 | 4 | const CodeGen = @import("CodeGen.zig"); |
| 6 | 5 | const Compilation = @import("Compilation.zig"); |
| 6 | const number_affixes = @import("Tree/number_affixes.zig"); | |
| 7 | 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 | 10 | const Value = @import("Value.zig"); |
| 10 | 11 | const StringInterner = @import("StringInterner.zig"); |
| 11 | 12 | |
| ... | ... | @@ -92,6 +93,8 @@ pub const Token = struct { |
| 92 | 93 | |
| 93 | 94 | pub const List = std.MultiArrayList(Token); |
| 94 | 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 | 100 | pub const TokenIndex = u32; |
| ... | ... | @@ -669,7 +672,7 @@ pub fn tokSlice(tree: *const Tree, tok_i: TokenIndex) []const u8 { |
| 669 | 672 | const loc = tree.tokens.items(.loc)[tok_i]; |
| 670 | 673 | var tmp_tokenizer = Tokenizer{ |
| 671 | 674 | .buf = tree.comp.getSource(loc.id).buf, |
| 672 | .comp = tree.comp, | |
| 675 | .langopts = tree.comp.langopts, | |
| 673 | 676 | .index = loc.byte_offset, |
| 674 | 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 | 363 | // data.sub_type |
| 364 | 364 | pointer, |
| 365 | 365 | unspecified_variable_len_array, |
| 366 | decayed_unspecified_variable_len_array, | |
| 367 | 366 | // data.func |
| 368 | 367 | /// int foo(int bar, char baz) and int (void) |
| 369 | 368 | func, |
| ... | ... | @@ -375,15 +374,11 @@ pub const Specifier = enum { |
| 375 | 374 | |
| 376 | 375 | // data.array |
| 377 | 376 | array, |
| 378 | decayed_array, | |
| 379 | 377 | static_array, |
| 380 | decayed_static_array, | |
| 381 | 378 | incomplete_array, |
| 382 | decayed_incomplete_array, | |
| 383 | 379 | vector, |
| 384 | 380 | // data.expr |
| 385 | 381 | variable_len_array, |
| 386 | decayed_variable_len_array, | |
| 387 | 382 | |
| 388 | 383 | // data.record |
| 389 | 384 | @"struct", |
| ... | ... | @@ -394,13 +389,9 @@ pub const Specifier = enum { |
| 394 | 389 | |
| 395 | 390 | /// typeof(type-name) |
| 396 | 391 | typeof_type, |
| 397 | /// decayed array created with typeof(type-name) | |
| 398 | decayed_typeof_type, | |
| 399 | 392 | |
| 400 | 393 | /// typeof(expression) |
| 401 | 394 | typeof_expr, |
| 402 | /// decayed array created with typeof(expression) | |
| 403 | decayed_typeof_expr, | |
| 404 | 395 | |
| 405 | 396 | /// data.attributed |
| 406 | 397 | attributed, |
| ... | ... | @@ -428,6 +419,7 @@ data: union { |
| 428 | 419 | } = .{ .none = {} }, |
| 429 | 420 | specifier: Specifier, |
| 430 | 421 | qual: Qualifiers = .{}, |
| 422 | decayed: bool = false, | |
| 431 | 423 | |
| 432 | 424 | pub const int = Type{ .specifier = .int }; |
| 433 | 425 | pub const invalid = Type{ .specifier = .invalid }; |
| ... | ... | @@ -442,7 +434,7 @@ pub fn is(ty: Type, specifier: Specifier) bool { |
| 442 | 434 | pub fn withAttributes(self: Type, allocator: std.mem.Allocator, attributes: []const Attribute) !Type { |
| 443 | 435 | if (attributes.len == 0) return self; |
| 444 | 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 | 440 | pub fn isCallable(ty: Type) ?Type { |
| ... | ... | @@ -468,10 +460,10 @@ pub fn isFunc(ty: Type) bool { |
| 468 | 460 | |
| 469 | 461 | pub fn isArray(ty: Type) bool { |
| 470 | 462 | return switch (ty.specifier) { |
| 471 | .array, .static_array, .incomplete_array, .variable_len_array, .unspecified_variable_len_array => true, | |
| 472 | .typeof_type => ty.data.sub_type.isArray(), | |
| 473 | .typeof_expr => ty.data.expr.ty.isArray(), | |
| 474 | .attributed => ty.data.attributed.base.isArray(), | |
| 463 | .array, .static_array, .incomplete_array, .variable_len_array, .unspecified_variable_len_array => !ty.isDecayed(), | |
| 464 | .typeof_type => !ty.isDecayed() and ty.data.sub_type.isArray(), | |
| 465 | .typeof_expr => !ty.isDecayed() and ty.data.expr.ty.isArray(), | |
| 466 | .attributed => !ty.isDecayed() and ty.data.attributed.base.isArray(), | |
| 475 | 467 | else => false, |
| 476 | 468 | }; |
| 477 | 469 | } |
| ... | ... | @@ -502,35 +494,22 @@ pub fn isScalarNonInt(ty: Type) bool { |
| 502 | 494 | } |
| 503 | 495 | |
| 504 | 496 | pub fn isDecayed(ty: Type) bool { |
| 505 | const decayed = switch (ty.specifier) { | |
| 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; | |
| 497 | return ty.decayed; | |
| 518 | 498 | } |
| 519 | 499 | |
| 520 | 500 | pub fn isPtr(ty: Type) bool { |
| 521 | 501 | return switch (ty.specifier) { |
| 522 | .pointer, | |
| 523 | .decayed_array, | |
| 524 | .decayed_static_array, | |
| 525 | .decayed_incomplete_array, | |
| 526 | .decayed_variable_len_array, | |
| 527 | .decayed_unspecified_variable_len_array, | |
| 528 | .decayed_typeof_type, | |
| 529 | .decayed_typeof_expr, | |
| 530 | => true, | |
| 531 | .typeof_type => ty.data.sub_type.isPtr(), | |
| 532 | .typeof_expr => ty.data.expr.ty.isPtr(), | |
| 533 | .attributed => ty.data.attributed.base.isPtr(), | |
| 502 | .pointer => true, | |
| 503 | ||
| 504 | .array, | |
| 505 | .static_array, | |
| 506 | .incomplete_array, | |
| 507 | .variable_len_array, | |
| 508 | .unspecified_variable_len_array, | |
| 509 | => ty.isDecayed(), | |
| 510 | .typeof_type => ty.isDecayed() or ty.data.sub_type.isPtr(), | |
| 511 | .typeof_expr => ty.isDecayed() or ty.data.expr.ty.isPtr(), | |
| 512 | .attributed => ty.isDecayed() or ty.data.attributed.base.isPtr(), | |
| 534 | 513 | else => false, |
| 535 | 514 | }; |
| 536 | 515 | } |
| ... | ... | @@ -608,15 +587,15 @@ pub fn isVoidStar(ty: Type) bool { |
| 608 | 587 | |
| 609 | 588 | pub fn isTypeof(ty: Type) bool { |
| 610 | 589 | return switch (ty.specifier) { |
| 611 | .typeof_type, .typeof_expr, .decayed_typeof_type, .decayed_typeof_expr => true, | |
| 590 | .typeof_type, .typeof_expr => true, | |
| 612 | 591 | else => false, |
| 613 | 592 | }; |
| 614 | 593 | } |
| 615 | 594 | |
| 616 | 595 | pub fn isConst(ty: Type) bool { |
| 617 | 596 | return switch (ty.specifier) { |
| 618 | .typeof_type, .decayed_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(), | |
| 597 | .typeof_type => ty.qual.@"const" or ty.data.sub_type.isConst(), | |
| 598 | .typeof_expr => ty.qual.@"const" or ty.data.expr.ty.isConst(), | |
| 620 | 599 | .attributed => ty.data.attributed.base.isConst(), |
| 621 | 600 | else => ty.qual.@"const", |
| 622 | 601 | }; |
| ... | ... | @@ -630,7 +609,7 @@ pub fn signedness(ty: Type, comp: *const Compilation) std.builtin.Signedness { |
| 630 | 609 | return switch (ty.specifier) { |
| 631 | 610 | // zig fmt: off |
| 632 | 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 | 613 | .complex_uint, .complex_ulong, .complex_ulong_long, .complex_uint128 => .unsigned, |
| 635 | 614 | // zig fmt: on |
| 636 | 615 | .bit_int, .complex_bit_int => ty.data.int.signedness, |
| ... | ... | @@ -678,16 +657,16 @@ pub fn isAnonymousRecord(ty: Type, comp: *const Compilation) bool { |
| 678 | 657 | |
| 679 | 658 | pub fn elemType(ty: Type) Type { |
| 680 | 659 | return switch (ty.specifier) { |
| 681 | .pointer, .unspecified_variable_len_array, .decayed_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, | |
| 683 | .variable_len_array, .decayed_variable_len_array => ty.data.expr.ty, | |
| 684 | .typeof_type, .decayed_typeof_type, .typeof_expr, .decayed_typeof_expr => { | |
| 660 | .pointer, .unspecified_variable_len_array => ty.data.sub_type.*, | |
| 661 | .array, .static_array, .incomplete_array, .vector => ty.data.array.elem, | |
| 662 | .variable_len_array => ty.data.expr.ty, | |
| 663 | .typeof_type, .typeof_expr => { | |
| 685 | 664 | const unwrapped = ty.canonicalize(.preserve_quals); |
| 686 | 665 | var elem = unwrapped.elemType(); |
| 687 | 666 | elem.qual = elem.qual.mergeAll(unwrapped.qual); |
| 688 | 667 | return elem; |
| 689 | 668 | }, |
| 690 | .attributed => ty.data.attributed.base, | |
| 669 | .attributed => ty.data.attributed.base.elemType(), | |
| 691 | 670 | .invalid => Type.invalid, |
| 692 | 671 | // zig fmt: off |
| 693 | 672 | .complex_float, .complex_double, .complex_long_double, .complex_float80, |
| ... | ... | @@ -703,8 +682,8 @@ pub fn elemType(ty: Type) Type { |
| 703 | 682 | pub fn returnType(ty: Type) Type { |
| 704 | 683 | return switch (ty.specifier) { |
| 705 | 684 | .func, .var_args_func, .old_style_func => ty.data.func.return_type, |
| 706 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.returnType(), | |
| 707 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.returnType(), | |
| 685 | .typeof_type => ty.data.sub_type.returnType(), | |
| 686 | .typeof_expr => ty.data.expr.ty.returnType(), | |
| 708 | 687 | .attributed => ty.data.attributed.base.returnType(), |
| 709 | 688 | .invalid => Type.invalid, |
| 710 | 689 | else => unreachable, |
| ... | ... | @@ -714,8 +693,8 @@ pub fn returnType(ty: Type) Type { |
| 714 | 693 | pub fn params(ty: Type) []Func.Param { |
| 715 | 694 | return switch (ty.specifier) { |
| 716 | 695 | .func, .var_args_func, .old_style_func => ty.data.func.params, |
| 717 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.params(), | |
| 718 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.params(), | |
| 696 | .typeof_type => ty.data.sub_type.params(), | |
| 697 | .typeof_expr => ty.data.expr.ty.params(), | |
| 719 | 698 | .attributed => ty.data.attributed.base.params(), |
| 720 | 699 | .invalid => &.{}, |
| 721 | 700 | else => unreachable, |
| ... | ... | @@ -724,9 +703,9 @@ pub fn params(ty: Type) []Func.Param { |
| 724 | 703 | |
| 725 | 704 | pub fn arrayLen(ty: Type) ?u64 { |
| 726 | 705 | return switch (ty.specifier) { |
| 727 | .array, .static_array, .decayed_array, .decayed_static_array => ty.data.array.len, | |
| 728 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.arrayLen(), | |
| 729 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.arrayLen(), | |
| 706 | .array, .static_array => ty.data.array.len, | |
| 707 | .typeof_type => ty.data.sub_type.arrayLen(), | |
| 708 | .typeof_expr => ty.data.expr.ty.arrayLen(), | |
| 730 | 709 | .attributed => ty.data.attributed.base.arrayLen(), |
| 731 | 710 | else => null, |
| 732 | 711 | }; |
| ... | ... | @@ -748,8 +727,8 @@ pub fn anyQual(ty: Type) bool { |
| 748 | 727 | pub fn getAttributes(ty: Type) []const Attribute { |
| 749 | 728 | return switch (ty.specifier) { |
| 750 | 729 | .attributed => ty.data.attributed.attributes, |
| 751 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.getAttributes(), | |
| 752 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.getAttributes(), | |
| 730 | .typeof_type => ty.data.sub_type.getAttributes(), | |
| 731 | .typeof_expr => ty.data.expr.ty.getAttributes(), | |
| 753 | 732 | else => &.{}, |
| 754 | 733 | }; |
| 755 | 734 | } |
| ... | ... | @@ -757,8 +736,8 @@ pub fn getAttributes(ty: Type) []const Attribute { |
| 757 | 736 | pub fn getRecord(ty: Type) ?*const Type.Record { |
| 758 | 737 | return switch (ty.specifier) { |
| 759 | 738 | .attributed => ty.data.attributed.base.getRecord(), |
| 760 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.getRecord(), | |
| 761 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.getRecord(), | |
| 739 | .typeof_type => ty.data.sub_type.getRecord(), | |
| 740 | .typeof_expr => ty.data.expr.ty.getRecord(), | |
| 762 | 741 | .@"struct", .@"union" => ty.data.record, |
| 763 | 742 | else => null, |
| 764 | 743 | }; |
| ... | ... | @@ -901,6 +880,7 @@ pub fn bitfieldPromotion(ty: Type, comp: *Compilation, width: u32) ?Type { |
| 901 | 880 | } |
| 902 | 881 | |
| 903 | 882 | pub fn hasIncompleteSize(ty: Type) bool { |
| 883 | if (ty.isDecayed()) return false; | |
| 904 | 884 | return switch (ty.specifier) { |
| 905 | 885 | .void, .incomplete_array => true, |
| 906 | 886 | .@"enum" => ty.data.@"enum".isIncomplete() and !ty.data.@"enum".fixed, |
| ... | ... | @@ -917,20 +897,14 @@ pub fn hasUnboundVLA(ty: Type) bool { |
| 917 | 897 | var cur = ty; |
| 918 | 898 | while (true) { |
| 919 | 899 | switch (cur.specifier) { |
| 920 | .unspecified_variable_len_array, | |
| 921 | .decayed_unspecified_variable_len_array, | |
| 922 | => return true, | |
| 900 | .unspecified_variable_len_array => return true, | |
| 923 | 901 | .array, |
| 924 | 902 | .static_array, |
| 925 | 903 | .incomplete_array, |
| 926 | 904 | .variable_len_array, |
| 927 | .decayed_array, | |
| 928 | .decayed_static_array, | |
| 929 | .decayed_incomplete_array, | |
| 930 | .decayed_variable_len_array, | |
| 931 | 905 | => cur = cur.elemType(), |
| 932 | .typeof_type, .decayed_typeof_type => cur = cur.data.sub_type.*, | |
| 933 | .typeof_expr, .decayed_typeof_expr => cur = cur.data.expr.ty, | |
| 906 | .typeof_type => cur = cur.data.sub_type.*, | |
| 907 | .typeof_expr => cur = cur.data.expr.ty, | |
| 934 | 908 | .attributed => cur = cur.data.attributed.base, |
| 935 | 909 | else => return false, |
| 936 | 910 | } |
| ... | ... | @@ -1006,9 +980,11 @@ pub fn sizeCompare(a: Type, b: Type, comp: *Compilation) TypeSizeOrder { |
| 1006 | 980 | |
| 1007 | 981 | /// Size of type as reported by sizeof |
| 1008 | 982 | pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 { |
| 983 | if (ty.isPtr()) return comp.target.ptrBitWidth() / 8; | |
| 984 | ||
| 1009 | 985 | return switch (ty.specifier) { |
| 1010 | 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 | 988 | .incomplete_array => return if (comp.langopts.emulate == .msvc) @as(?u64, 0) else null, |
| 1013 | 989 | .func, .var_args_func, .old_style_func, .void, .bool => 1, |
| 1014 | 990 | .char, .schar, .uchar => 1, |
| ... | ... | @@ -1037,14 +1013,7 @@ pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 { |
| 1037 | 1013 | .complex_long_double, .complex_float80, .complex_float128, .complex_bit_int, |
| 1038 | 1014 | => return 2 * ty.makeReal().sizeof(comp).?, |
| 1039 | 1015 | // zig fmt: on |
| 1040 | .pointer, | |
| 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, | |
| 1016 | .pointer => unreachable, | |
| 1048 | 1017 | .static_array, |
| 1049 | 1018 | .nullptr_t, |
| 1050 | 1019 | => comp.target.ptrBitWidth() / 8, |
| ... | ... | @@ -1073,8 +1042,8 @@ pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 { |
| 1073 | 1042 | pub fn bitSizeof(ty: Type, comp: *const Compilation) ?u64 { |
| 1074 | 1043 | return switch (ty.specifier) { |
| 1075 | 1044 | .bool => if (comp.langopts.emulate == .msvc) @as(u64, 8) else 1, |
| 1076 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.bitSizeof(comp), | |
| 1077 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.bitSizeof(comp), | |
| 1045 | .typeof_type => ty.data.sub_type.bitSizeof(comp), | |
| 1046 | .typeof_expr => ty.data.expr.ty.bitSizeof(comp), | |
| 1078 | 1047 | .attributed => ty.data.attributed.base.bitSizeof(comp), |
| 1079 | 1048 | .bit_int => return ty.data.int.bits, |
| 1080 | 1049 | .long_double => comp.target.c_type_bit_size(.longdouble), |
| ... | ... | @@ -1117,7 +1086,10 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { |
| 1117 | 1086 | .unspecified_variable_len_array, |
| 1118 | 1087 | .array, |
| 1119 | 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 | 1093 | .func, .var_args_func, .old_style_func => target_util.defaultFunctionAlignment(comp.target), |
| 1122 | 1094 | .char, .schar, .uchar, .void, .bool => 1, |
| 1123 | 1095 | |
| ... | ... | @@ -1153,11 +1125,6 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { |
| 1153 | 1125 | |
| 1154 | 1126 | .float80, .float128 => 16, |
| 1155 | 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 | 1128 | .static_array, |
| 1162 | 1129 | .nullptr_t, |
| 1163 | 1130 | => switch (comp.target.cpu.arch) { |
| ... | ... | @@ -1166,8 +1133,8 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { |
| 1166 | 1133 | }, |
| 1167 | 1134 | .@"struct", .@"union" => if (ty.data.record.isIncomplete()) 0 else @intCast(ty.data.record.type_layout.field_alignment_bits / 8), |
| 1168 | 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), | |
| 1170 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.alignof(comp), | |
| 1136 | .typeof_type => ty.data.sub_type.alignof(comp), | |
| 1137 | .typeof_expr => ty.data.expr.ty.alignof(comp), | |
| 1171 | 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 | 1146 | /// arrays and pointers. |
| 1180 | 1147 | pub fn canonicalize(ty: Type, qual_handling: enum { standard, preserve_quals }) Type { |
| 1181 | 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 | 1153 | if (!cur.isTypeof()) return cur; |
| 1184 | 1154 | |
| 1185 | 1155 | var qual = cur.qual; |
| ... | ... | @@ -1187,14 +1157,6 @@ pub fn canonicalize(ty: Type, qual_handling: enum { standard, preserve_quals }) |
| 1187 | 1157 | switch (cur.specifier) { |
| 1188 | 1158 | .typeof_type => cur = cur.data.sub_type.*, |
| 1189 | 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 | 1160 | else => break, |
| 1199 | 1161 | } |
| 1200 | 1162 | qual = qual.mergeAll(cur.qual); |
| ... | ... | @@ -1204,6 +1166,7 @@ pub fn canonicalize(ty: Type, qual_handling: enum { standard, preserve_quals }) |
| 1204 | 1166 | } else { |
| 1205 | 1167 | cur.qual = qual; |
| 1206 | 1168 | } |
| 1169 | cur.decayed = ty.decayed; | |
| 1207 | 1170 | return cur; |
| 1208 | 1171 | } |
| 1209 | 1172 | |
| ... | ... | @@ -1219,8 +1182,8 @@ pub fn get(ty: *const Type, specifier: Specifier) ?*const Type { |
| 1219 | 1182 | |
| 1220 | 1183 | pub fn requestedAlignment(ty: Type, comp: *const Compilation) ?u29 { |
| 1221 | 1184 | return switch (ty.specifier) { |
| 1222 | .typeof_type, .decayed_typeof_type => ty.data.sub_type.requestedAlignment(comp), | |
| 1223 | .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.requestedAlignment(comp), | |
| 1185 | .typeof_type => ty.data.sub_type.requestedAlignment(comp), | |
| 1186 | .typeof_expr => ty.data.expr.ty.requestedAlignment(comp), | |
| 1224 | 1187 | .attributed => annotationAlignment(comp, ty.data.attributed.attributes), |
| 1225 | 1188 | else => null, |
| 1226 | 1189 | }; |
| ... | ... | @@ -1265,14 +1228,11 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi |
| 1265 | 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 | 1234 | switch (a.specifier) { |
| 1269 | .pointer, | |
| 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, | |
| 1235 | .pointer => unreachable, | |
| 1276 | 1236 | |
| 1277 | 1237 | .func, |
| 1278 | 1238 | .var_args_func, |
| ... | ... | @@ -1293,8 +1253,9 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi |
| 1293 | 1253 | } |
| 1294 | 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, | |
| 1297 | ||
| 1256 | .variable_len_array => { | |
| 1257 | if (!a.elemType().eql(b.elemType(), comp, check_qualifiers)) return false; | |
| 1258 | }, | |
| 1298 | 1259 | .@"struct", .@"union" => if (a.data.record != b.data.record) return false, |
| 1299 | 1260 | .@"enum" => if (a.data.@"enum" != b.data.@"enum") return false, |
| 1300 | 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 | 1267 | |
| 1307 | 1268 | /// Decays an array to a pointer |
| 1308 | 1269 | pub fn decayArray(ty: *Type) void { |
| 1309 | // the decayed array type is the current specifier +1 | |
| 1310 | ty.specifier = @enumFromInt(@intFromEnum(ty.specifier) + 1); | |
| 1270 | std.debug.assert(ty.isArray()); | |
| 1271 | ty.decayed = true; | |
| 1311 | 1272 | } |
| 1312 | 1273 | |
| 1313 | 1274 | pub fn originalTypeOfDecayedArray(ty: Type) Type { |
| 1314 | 1275 | std.debug.assert(ty.isDecayed()); |
| 1315 | 1276 | var copy = ty; |
| 1316 | copy.specifier = @enumFromInt(@intFromEnum(ty.specifier) - 1); | |
| 1277 | copy.decayed = false; | |
| 1317 | 1278 | return copy; |
| 1318 | 1279 | } |
| 1319 | 1280 | |
| ... | ... | @@ -1405,25 +1366,23 @@ pub fn combine(inner: *Type, outer: Type) Parser.Error!void { |
| 1405 | 1366 | switch (inner.specifier) { |
| 1406 | 1367 | .pointer => return inner.data.sub_type.combine(outer), |
| 1407 | 1368 | .unspecified_variable_len_array => { |
| 1369 | std.debug.assert(!inner.isDecayed()); | |
| 1408 | 1370 | try inner.data.sub_type.combine(outer); |
| 1409 | 1371 | }, |
| 1410 | 1372 | .variable_len_array => { |
| 1373 | std.debug.assert(!inner.isDecayed()); | |
| 1411 | 1374 | try inner.data.expr.ty.combine(outer); |
| 1412 | 1375 | }, |
| 1413 | 1376 | .array, .static_array, .incomplete_array => { |
| 1377 | std.debug.assert(!inner.isDecayed()); | |
| 1414 | 1378 | try inner.data.array.elem.combine(outer); |
| 1415 | 1379 | }, |
| 1416 | 1380 | .func, .var_args_func, .old_style_func => { |
| 1417 | 1381 | try inner.data.func.return_type.combine(outer); |
| 1418 | 1382 | }, |
| 1419 | .decayed_array, | |
| 1420 | .decayed_static_array, | |
| 1421 | .decayed_incomplete_array, | |
| 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 | |
| 1383 | .typeof_type, | |
| 1384 | .typeof_expr, | |
| 1385 | => std.debug.assert(!inner.isDecayed()), | |
| 1427 | 1386 | .void, .invalid => inner.* = outer, |
| 1428 | 1387 | else => unreachable, |
| 1429 | 1388 | } |
| ... | ... | @@ -1474,8 +1433,8 @@ pub fn validateCombinedType(ty: Type, p: *Parser, source_tok: TokenIndex) Parser |
| 1474 | 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), | |
| 1478 | .typeof_expr, .decayed_typeof_expr => return ty.data.expr.ty.validateCombinedType(p, source_tok), | |
| 1436 | .typeof_type => return ty.data.sub_type.validateCombinedType(p, source_tok), | |
| 1437 | .typeof_expr => return ty.data.expr.ty.validateCombinedType(p, source_tok), | |
| 1479 | 1438 | .attributed => return ty.data.attributed.base.validateCombinedType(p, source_tok), |
| 1480 | 1439 | else => {}, |
| 1481 | 1440 | } |
| ... | ... | @@ -1610,6 +1569,7 @@ pub const Builder = struct { |
| 1610 | 1569 | decayed_typeof_expr: *Expr, |
| 1611 | 1570 | |
| 1612 | 1571 | attributed: *Attributed, |
| 1572 | decayed_attributed: *Attributed, | |
| 1613 | 1573 | |
| 1614 | 1574 | pub fn str(spec: Builder.Specifier, langopts: LangOpts) ?[]const u8 { |
| 1615 | 1575 | return switch (spec) { |
| ... | ... | @@ -1835,13 +1795,10 @@ pub const Builder = struct { |
| 1835 | 1795 | ty.specifier = .pointer; |
| 1836 | 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 | 1799 | ty.specifier = .unspecified_variable_len_array; |
| 1840 | 1800 | ty.data = .{ .sub_type = data }; |
| 1841 | }, | |
| 1842 | .decayed_unspecified_variable_len_array => |data| { | |
| 1843 | ty.specifier = .decayed_unspecified_variable_len_array; | |
| 1844 | ty.data = .{ .sub_type = data }; | |
| 1801 | ty.decayed = b.specifier == .decayed_unspecified_variable_len_array; | |
| 1845 | 1802 | }, |
| 1846 | 1803 | .func => |data| { |
| 1847 | 1804 | ty.specifier = .func; |
| ... | ... | @@ -1855,41 +1812,29 @@ pub const Builder = struct { |
| 1855 | 1812 | ty.specifier = .old_style_func; |
| 1856 | 1813 | ty.data = .{ .func = data }; |
| 1857 | 1814 | }, |
| 1858 | .array => |data| { | |
| 1815 | .array, .decayed_array => |data| { | |
| 1859 | 1816 | ty.specifier = .array; |
| 1860 | 1817 | ty.data = .{ .array = data }; |
| 1818 | ty.decayed = b.specifier == .decayed_array; | |
| 1861 | 1819 | }, |
| 1862 | .decayed_array => |data| { | |
| 1863 | ty.specifier = .decayed_array; | |
| 1864 | ty.data = .{ .array = data }; | |
| 1865 | }, | |
| 1866 | .static_array => |data| { | |
| 1820 | .static_array, .decayed_static_array => |data| { | |
| 1867 | 1821 | ty.specifier = .static_array; |
| 1868 | 1822 | ty.data = .{ .array = data }; |
| 1823 | ty.decayed = b.specifier == .decayed_static_array; | |
| 1869 | 1824 | }, |
| 1870 | .decayed_static_array => |data| { | |
| 1871 | ty.specifier = .decayed_static_array; | |
| 1872 | ty.data = .{ .array = data }; | |
| 1873 | }, | |
| 1874 | .incomplete_array => |data| { | |
| 1825 | .incomplete_array, .decayed_incomplete_array => |data| { | |
| 1875 | 1826 | ty.specifier = .incomplete_array; |
| 1876 | 1827 | ty.data = .{ .array = data }; |
| 1877 | }, | |
| 1878 | .decayed_incomplete_array => |data| { | |
| 1879 | ty.specifier = .decayed_incomplete_array; | |
| 1880 | ty.data = .{ .array = data }; | |
| 1828 | ty.decayed = b.specifier == .decayed_incomplete_array; | |
| 1881 | 1829 | }, |
| 1882 | 1830 | .vector => |data| { |
| 1883 | 1831 | ty.specifier = .vector; |
| 1884 | 1832 | ty.data = .{ .array = data }; |
| 1885 | 1833 | }, |
| 1886 | .variable_len_array => |data| { | |
| 1834 | .variable_len_array, .decayed_variable_len_array => |data| { | |
| 1887 | 1835 | ty.specifier = .variable_len_array; |
| 1888 | 1836 | ty.data = .{ .expr = data }; |
| 1889 | }, | |
| 1890 | .decayed_variable_len_array => |data| { | |
| 1891 | ty.specifier = .decayed_variable_len_array; | |
| 1892 | ty.data = .{ .expr = data }; | |
| 1837 | ty.decayed = b.specifier == .decayed_variable_len_array; | |
| 1893 | 1838 | }, |
| 1894 | 1839 | .@"struct" => |data| { |
| 1895 | 1840 | ty.specifier = .@"struct"; |
| ... | ... | @@ -1903,25 +1848,20 @@ pub const Builder = struct { |
| 1903 | 1848 | ty.specifier = .@"enum"; |
| 1904 | 1849 | ty.data = .{ .@"enum" = data }; |
| 1905 | 1850 | }, |
| 1906 | .typeof_type => |data| { | |
| 1851 | .typeof_type, .decayed_typeof_type => |data| { | |
| 1907 | 1852 | ty.specifier = .typeof_type; |
| 1908 | 1853 | ty.data = .{ .sub_type = data }; |
| 1854 | ty.decayed = b.specifier == .decayed_typeof_type; | |
| 1909 | 1855 | }, |
| 1910 | .decayed_typeof_type => |data| { | |
| 1911 | ty.specifier = .decayed_typeof_type; | |
| 1912 | ty.data = .{ .sub_type = data }; | |
| 1913 | }, | |
| 1914 | .typeof_expr => |data| { | |
| 1856 | .typeof_expr, .decayed_typeof_expr => |data| { | |
| 1915 | 1857 | ty.specifier = .typeof_expr; |
| 1916 | 1858 | ty.data = .{ .expr = data }; |
| 1859 | ty.decayed = b.specifier == .decayed_typeof_expr; | |
| 1917 | 1860 | }, |
| 1918 | .decayed_typeof_expr => |data| { | |
| 1919 | ty.specifier = .decayed_typeof_expr; | |
| 1920 | ty.data = .{ .expr = data }; | |
| 1921 | }, | |
| 1922 | .attributed => |data| { | |
| 1861 | .attributed, .decayed_attributed => |data| { | |
| 1923 | 1862 | ty.specifier = .attributed; |
| 1924 | 1863 | ty.data = .{ .attributed = data }; |
| 1864 | ty.decayed = b.specifier == .decayed_attributed; | |
| 1925 | 1865 | }, |
| 1926 | 1866 | } |
| 1927 | 1867 | if (!ty.isReal() and ty.isInt()) { |
| ... | ... | @@ -2359,30 +2299,47 @@ pub const Builder = struct { |
| 2359 | 2299 | .complex_float128 => .complex_float128, |
| 2360 | 2300 | |
| 2361 | 2301 | .pointer => .{ .pointer = ty.data.sub_type }, |
| 2362 | .unspecified_variable_len_array => .{ .unspecified_variable_len_array = ty.data.sub_type }, | |
| 2363 | .decayed_unspecified_variable_len_array => .{ .decayed_unspecified_variable_len_array = ty.data.sub_type }, | |
| 2302 | .unspecified_variable_len_array => if (ty.isDecayed()) | |
| 2303 | .{ .decayed_unspecified_variable_len_array = ty.data.sub_type } | |
| 2304 | else | |
| 2305 | .{ .unspecified_variable_len_array = ty.data.sub_type }, | |
| 2364 | 2306 | .func => .{ .func = ty.data.func }, |
| 2365 | 2307 | .var_args_func => .{ .var_args_func = ty.data.func }, |
| 2366 | 2308 | .old_style_func => .{ .old_style_func = ty.data.func }, |
| 2367 | .array => .{ .array = ty.data.array }, | |
| 2368 | .decayed_array => .{ .decayed_array = ty.data.array }, | |
| 2369 | .static_array => .{ .static_array = ty.data.array }, | |
| 2370 | .decayed_static_array => .{ .decayed_static_array = ty.data.array }, | |
| 2371 | .incomplete_array => .{ .incomplete_array = ty.data.array }, | |
| 2372 | .decayed_incomplete_array => .{ .decayed_incomplete_array = ty.data.array }, | |
| 2309 | .array => if (ty.isDecayed()) | |
| 2310 | .{ .decayed_array = ty.data.array } | |
| 2311 | else | |
| 2312 | .{ .array = ty.data.array }, | |
| 2313 | .static_array => if (ty.isDecayed()) | |
| 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 | 2321 | .vector => .{ .vector = ty.data.array }, |
| 2374 | .variable_len_array => .{ .variable_len_array = ty.data.expr }, | |
| 2375 | .decayed_variable_len_array => .{ .decayed_variable_len_array = ty.data.expr }, | |
| 2322 | .variable_len_array => if (ty.isDecayed()) | |
| 2323 | .{ .decayed_variable_len_array = ty.data.expr } | |
| 2324 | else | |
| 2325 | .{ .variable_len_array = ty.data.expr }, | |
| 2376 | 2326 | .@"struct" => .{ .@"struct" = ty.data.record }, |
| 2377 | 2327 | .@"union" => .{ .@"union" = ty.data.record }, |
| 2378 | 2328 | .@"enum" => .{ .@"enum" = ty.data.@"enum" }, |
| 2379 | 2329 | |
| 2380 | .typeof_type => .{ .typeof_type = ty.data.sub_type }, | |
| 2381 | .decayed_typeof_type => .{ .decayed_typeof_type = ty.data.sub_type }, | |
| 2382 | .typeof_expr => .{ .typeof_expr = ty.data.expr }, | |
| 2383 | .decayed_typeof_expr => .{ .decayed_typeof_expr = ty.data.expr }, | |
| 2330 | .typeof_type => if (ty.isDecayed()) | |
| 2331 | .{ .decayed_typeof_type = ty.data.sub_type } | |
| 2332 | else | |
| 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 | 2343 | else => unreachable, |
| 2387 | 2344 | }; |
| 2388 | 2345 | } |
| ... | ... | @@ -2472,24 +2429,17 @@ fn printPrologue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts |
| 2472 | 2429 | try w.writeAll(")"); |
| 2473 | 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 | 2441 | switch (ty.specifier) { |
| 2476 | .pointer, | |
| 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 | }, | |
| 2442 | .pointer => unreachable, | |
| 2493 | 2443 | .func, .var_args_func, .old_style_func => { |
| 2494 | 2444 | const ret_ty = ty.data.func.return_type; |
| 2495 | 2445 | const simple = try ret_ty.printPrologue(mapper, langopts, w); |
| ... | ... | @@ -2541,20 +2491,14 @@ fn printPrologue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts |
| 2541 | 2491 | |
| 2542 | 2492 | fn printEpilogue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { |
| 2543 | 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 | 2500 | switch (ty.specifier) { |
| 2545 | .pointer, | |
| 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 | }, | |
| 2501 | .pointer => unreachable, // handled above | |
| 2558 | 2502 | .func, .var_args_func, .old_style_func => { |
| 2559 | 2503 | try w.writeByte('('); |
| 2560 | 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 | 2581 | try w.writeAll(") "); |
| 2638 | 2582 | try ty.data.func.return_type.dump(mapper, langopts, w); |
| 2639 | 2583 | }, |
| 2640 | .array, .static_array, .decayed_array, .decayed_static_array => { | |
| 2641 | if (ty.specifier == .decayed_array or ty.specifier == .decayed_static_array) try w.writeAll("*d"); | |
| 2584 | .array, .static_array => { | |
| 2585 | if (ty.isDecayed()) try w.writeAll("*d"); | |
| 2642 | 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 | 2588 | try w.print("{d}]", .{ty.data.array.len}); |
| 2645 | 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 | 2593 | try ty.data.array.elem.dump(mapper, langopts, w); |
| 2650 | 2594 | try w.writeAll(")"); |
| 2651 | 2595 | }, |
| 2652 | .incomplete_array, .decayed_incomplete_array => { | |
| 2653 | if (ty.specifier == .decayed_incomplete_array) try w.writeAll("*d"); | |
| 2596 | .incomplete_array => { | |
| 2597 | if (ty.isDecayed()) try w.writeAll("*d"); | |
| 2654 | 2598 | try w.writeAll("[]"); |
| 2655 | 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 | 2616 | try w.print("union {s}", .{mapper.lookup(ty.data.record.name)}); |
| 2673 | 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 => { | |
| 2676 | if (ty.specifier == .decayed_unspecified_variable_len_array) try w.writeAll("*d"); | |
| 2619 | .unspecified_variable_len_array => { | |
| 2620 | if (ty.isDecayed()) try w.writeAll("*d"); | |
| 2677 | 2621 | try w.writeAll("[*]"); |
| 2678 | 2622 | try ty.data.sub_type.dump(mapper, langopts, w); |
| 2679 | 2623 | }, |
| 2680 | .variable_len_array, .decayed_variable_len_array => { | |
| 2681 | if (ty.specifier == .decayed_variable_len_array) try w.writeAll("*d"); | |
| 2624 | .variable_len_array => { | |
| 2625 | if (ty.isDecayed()) try w.writeAll("*d"); | |
| 2682 | 2626 | try w.writeAll("[<expr>]"); |
| 2683 | 2627 | try ty.data.expr.ty.dump(mapper, langopts, w); |
| 2684 | 2628 | }, |
| 2685 | .typeof_type, .decayed_typeof_type => { | |
| 2629 | .typeof_type => { | |
| 2686 | 2630 | try w.writeAll("typeof("); |
| 2687 | 2631 | try ty.data.sub_type.dump(mapper, langopts, w); |
| 2688 | 2632 | try w.writeAll(")"); |
| 2689 | 2633 | }, |
| 2690 | .typeof_expr, .decayed_typeof_expr => { | |
| 2634 | .typeof_expr => { | |
| 2691 | 2635 | try w.writeAll("typeof(<expr>: "); |
| 2692 | 2636 | try ty.data.expr.ty.dump(mapper, langopts, w); |
| 2693 | 2637 | try w.writeAll(")"); |
| 2694 | 2638 | }, |
| 2695 | 2639 | .attributed => { |
| 2640 | if (ty.isDecayed()) try w.writeAll("*d:"); | |
| 2696 | 2641 | try w.writeAll("attributed("); |
| 2697 | 2642 | try ty.data.attributed.base.dump(mapper, langopts, w); |
| 2698 | 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 | 215 | |
| 216 | 216 | const limbs = try comp.gpa.alloc( |
| 217 | 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 | 220 | defer comp.gpa.free(limbs); |
| 221 | 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 | 1 | const std = @import("std"); |
| 2 | 2 | const LangOpts = @import("LangOpts.zig"); |
| 3 | 3 | const Type = @import("Type.zig"); |
| 4 | const llvm = @import("root").codegen.llvm; | |
| 5 | 4 | const TargetSet = @import("Builtins/Properties.zig").TargetSet; |
| 6 | 5 | |
| 7 | 6 | /// intmax_t for this target |
lib/std/c.zig-8| ... | ... | @@ -5,14 +5,6 @@ const page_size = std.mem.page_size; |
| 5 | 5 | const iovec = std.os.iovec; |
| 6 | 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 | 8 | /// The return type is `type` to force comptime function call execution. |
| 17 | 9 | /// TODO: https://github.com/ziglang/zig/issues/425 |
| 18 | 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 | 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 | 257 | /// Deprecated: use `CIntLiteralBase` |
| 258 | 258 | pub const CIntLiteralRadix = CIntLiteralBase; |
| ... | ... | @@ -289,13 +289,13 @@ pub fn promoteIntLiteral( |
| 289 | 289 | } |
| 290 | 290 | |
| 291 | 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 | 293 | try testing.expectEqual(c_uint, @TypeOf(signed_hex)); |
| 294 | 294 | |
| 295 | 295 | if (math.maxInt(c_longlong) == math.maxInt(c_int)) return; |
| 296 | 296 | |
| 297 | 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 | 300 | if (math.maxInt(c_long) > math.maxInt(c_int)) { |
| 301 | 301 | try testing.expectEqual(c_long, @TypeOf(signed_decimal)); |
src/Compilation.zig+1-1| ... | ... | @@ -4205,7 +4205,7 @@ pub const CImportResult = struct { |
| 4205 | 4205 | /// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked |
| 4206 | 4206 | /// a bit when we want to start using it from self-hosted. |
| 4207 | 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 | 4209 | const tracy_trace = trace(@src()); |
| 4210 | 4210 | defer tracy_trace.end(); |
| 4211 | 4211 |
src/main.zig+1-1| ... | ... | @@ -4293,7 +4293,7 @@ fn updateModule(comp: *Compilation) !void { |
| 4293 | 4293 | } |
| 4294 | 4294 | |
| 4295 | 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 | 4297 | assert(comp.c_source_files.len == 1); |
| 4298 | 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 | 22 | return .{}; |
| 23 | 23 | } |
| 24 | 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 | 29 | pub const NameBuf = struct { |
| 28 | 30 | pub fn span(_: *const NameBuf) []const u8 { |
src/translate_c.zig+305-261| ... | ... | @@ -1,13 +1,13 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const testing = std.testing; |
| 3 | 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 | 4 | const mem = std.mem; |
| 8 | 5 | const math = std.math; |
| 9 | 6 | const meta = std.meta; |
| 10 | 7 | const CallingConvention = std.builtin.CallingConvention; |
| 8 | const clang = @import("clang.zig"); | |
| 9 | const aro = @import("aro"); | |
| 10 | const CToken = aro.Tokenizer.Token; | |
| 11 | 11 | const ast = @import("translate_c/ast.zig"); |
| 12 | 12 | const Node = ast.Node; |
| 13 | 13 | const Tag = Node.Tag; |
| ... | ... | @@ -190,19 +190,21 @@ pub fn translate( |
| 190 | 190 | |
| 191 | 191 | /// Determines whether macro is of the form: `#define FOO FOO` (Possibly with trailing tokens) |
| 192 | 192 | /// Macros of this form will not be translated. |
| 193 | fn isSelfDefinedMacro(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) bool { | |
| 194 | const source = getMacroText(unit, c, macro); | |
| 195 | var tokenizer = std.c.Tokenizer{ | |
| 196 | .buffer = source, | |
| 193 | fn isSelfDefinedMacro(unit: *const clang.ASTUnit, c: *const Context, macro: *const clang.MacroDefinitionRecord) !bool { | |
| 194 | const source = try getMacroText(unit, c, macro); | |
| 195 | var tokenizer: aro.Tokenizer = .{ | |
| 196 | .buf = source, | |
| 197 | .source = .unused, | |
| 198 | .langopts = .{}, | |
| 197 | 199 | }; |
| 198 | const name_tok = tokenizer.next(); | |
| 200 | const name_tok = tokenizer.nextNoWS(); | |
| 199 | 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 | 204 | // We do not just check for `.Identifier` below because keyword tokens are preferentially matched first by |
| 203 | 205 | // the tokenizer. |
| 204 | 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 | 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 | 225 | const raw_name = macro.getName_getNameStart(); |
| 224 | 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 | 229 | try c.global_names.put(c.gpa, name, {}); |
| 228 | 230 | } |
| 229 | 231 | }, |
| ... | ... | @@ -5159,16 +5161,16 @@ pub const PatternList = struct { |
| 5159 | 5161 | /// Assumes that `ms` represents a tokenized function-like macro. |
| 5160 | 5162 | fn buildArgsHash(allocator: mem.Allocator, ms: MacroSlicer, hash: *ArgsPositionMap) MacroProcessingError!void { |
| 5161 | 5163 | assert(ms.tokens.len > 2); |
| 5162 | assert(ms.tokens[0].id == .Identifier); | |
| 5163 | assert(ms.tokens[1].id == .LParen); | |
| 5164 | assert(ms.tokens[0].id == .identifier or ms.tokens[0].id == .extended_identifier); | |
| 5165 | assert(ms.tokens[1].id == .l_paren); | |
| 5164 | 5166 | |
| 5165 | 5167 | var i: usize = 2; |
| 5166 | 5168 | while (true) : (i += 1) { |
| 5167 | 5169 | const token = ms.tokens[i]; |
| 5168 | 5170 | switch (token.id) { |
| 5169 | .RParen => break, | |
| 5170 | .Comma => continue, | |
| 5171 | .Identifier => { | |
| 5171 | .r_paren => break, | |
| 5172 | .comma => continue, | |
| 5173 | .identifier, .extended_identifier => { | |
| 5172 | 5174 | const identifier = ms.slice(token); |
| 5173 | 5175 | try hash.put(allocator, identifier, i); |
| 5174 | 5176 | }, |
| ... | ... | @@ -5220,18 +5222,18 @@ pub const PatternList = struct { |
| 5220 | 5222 | if (args_hash.count() != self.args_hash.count()) return false; |
| 5221 | 5223 | |
| 5222 | 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 | 5227 | const pattern_slicer = MacroSlicer{ .source = self.source, .tokens = self.tokens }; |
| 5226 | 5228 | while (i < self.tokens.len) : (i += 1) { |
| 5227 | 5229 | const pattern_token = self.tokens[i]; |
| 5228 | 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 | 5233 | const pattern_bytes = pattern_slicer.slice(pattern_token); |
| 5232 | 5234 | const macro_bytes = ms.slice(macro_token); |
| 5233 | 5235 | switch (pattern_token.id) { |
| 5234 | .Identifier => { | |
| 5236 | .identifier, .extended_identifier => { | |
| 5235 | 5237 | const pattern_arg_index = self.args_hash.get(pattern_bytes); |
| 5236 | 5238 | const macro_arg_index = args_hash.get(macro_bytes); |
| 5237 | 5239 | |
| ... | ... | @@ -5243,7 +5245,7 @@ pub const PatternList = struct { |
| 5243 | 5245 | return false; |
| 5244 | 5246 | } |
| 5245 | 5247 | }, |
| 5246 | .MacroString, .StringLiteral, .CharLiteral, .IntegerLiteral, .FloatLiteral => { | |
| 5248 | .string_literal, .char_literal, .pp_num => { | |
| 5247 | 5249 | if (!mem.eql(u8, pattern_bytes, macro_bytes)) return false; |
| 5248 | 5250 | }, |
| 5249 | 5251 | else => { |
| ... | ... | @@ -5359,13 +5361,13 @@ const MacroCtx = struct { |
| 5359 | 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 | 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 | 5367 | try self.fail( |
| 5366 | 5368 | c, |
| 5367 | 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 | 5372 | return error.ParseError; |
| 5371 | 5373 | } |
| ... | ... | @@ -5396,12 +5398,12 @@ const MacroCtx = struct { |
| 5396 | 5398 | while (i < self.list.len) : (i += 1) { |
| 5397 | 5399 | const token = self.list[i]; |
| 5398 | 5400 | switch (token.id) { |
| 5399 | .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) { | |
| 5401 | .period, .arrow => i += 1, // skip next token since field identifiers can be unknown | |
| 5402 | .keyword_struct, .keyword_union, .keyword_enum => if (!last_is_type_kw) { | |
| 5401 | 5403 | last_is_type_kw = true; |
| 5402 | 5404 | continue; |
| 5403 | 5405 | }, |
| 5404 | .Identifier => { | |
| 5406 | .identifier, .extended_identifier => { | |
| 5405 | 5407 | const identifier = slicer.slice(token); |
| 5406 | 5408 | const is_param = for (params) |param| { |
| 5407 | 5409 | if (param.name != null and mem.eql(u8, identifier, param.name.?)) break true; |
| ... | ... | @@ -5422,31 +5424,38 @@ const MacroCtx = struct { |
| 5422 | 5424 | }; |
| 5423 | 5425 | |
| 5424 | 5426 | fn tokenizeMacro(source: []const u8, tok_list: *std.ArrayList(CToken)) Error!void { |
| 5425 | var tokenizer = std.c.Tokenizer{ | |
| 5426 | .buffer = source, | |
| 5427 | var tokenizer: aro.Tokenizer = .{ | |
| 5428 | .buf = source, | |
| 5429 | .source = .unused, | |
| 5430 | .langopts = .{}, | |
| 5427 | 5431 | }; |
| 5428 | 5432 | while (true) { |
| 5429 | 5433 | const tok = tokenizer.next(); |
| 5430 | 5434 | switch (tok.id) { |
| 5431 | .Nl, .Eof => { | |
| 5435 | .whitespace => continue, | |
| 5436 | .nl, .eof => { | |
| 5432 | 5437 | try tok_list.append(tok); |
| 5433 | 5438 | break; |
| 5434 | 5439 | }, |
| 5435 | .LineComment, .MultiLineComment => continue, | |
| 5436 | 5440 | else => {}, |
| 5437 | 5441 | } |
| 5438 | 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 | 5447 | const begin_loc = macro.getSourceRange_getBegin(); |
| 5444 | 5448 | const end_loc = clang.Lexer.getLocForEndOfToken(macro.getSourceRange_getEnd(), c.source_manager, unit); |
| 5445 | 5449 | |
| 5446 | 5450 | const begin_c = c.source_manager.getCharacterData(begin_loc); |
| 5447 | 5451 | const end_c = c.source_manager.getCharacterData(end_loc); |
| 5448 | 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 | 5461 | fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| ... | ... | @@ -5471,7 +5480,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5471 | 5480 | continue; |
| 5472 | 5481 | } |
| 5473 | 5482 | |
| 5474 | const source = getMacroText(unit, c, macro); | |
| 5483 | const source = try getMacroText(unit, c, macro); | |
| 5475 | 5484 | |
| 5476 | 5485 | try tokenizeMacro(source, &tok_list); |
| 5477 | 5486 | |
| ... | ... | @@ -5485,7 +5494,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5485 | 5494 | |
| 5486 | 5495 | var macro_fn = false; |
| 5487 | 5496 | switch (macro_ctx.peek().?) { |
| 5488 | .Identifier => { | |
| 5497 | .identifier, .extended_identifier => { | |
| 5489 | 5498 | // if it equals itself, ignore. for example, from stdio.h: |
| 5490 | 5499 | // #define stdin stdin |
| 5491 | 5500 | const tok = macro_ctx.list[1]; |
| ... | ... | @@ -5494,7 +5503,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5494 | 5503 | continue; |
| 5495 | 5504 | } |
| 5496 | 5505 | }, |
| 5497 | .Nl, .Eof => { | |
| 5506 | .nl, .eof => { | |
| 5498 | 5507 | // this means it is a macro without a value |
| 5499 | 5508 | // We define it as an empty string so that it can still be used with ++ |
| 5500 | 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 | 5512 | try c.global_scope.blank_macros.put(name, {}); |
| 5504 | 5513 | continue; |
| 5505 | 5514 | }, |
| 5506 | .LParen => { | |
| 5515 | .l_paren => { | |
| 5507 | 5516 | // if the name is immediately followed by a '(' then it is a function |
| 5508 | 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 | 5543 | // Check if the macro only uses other blank macros. |
| 5535 | 5544 | while (true) { |
| 5536 | 5545 | switch (m.peek().?) { |
| 5537 | .Identifier => { | |
| 5546 | .identifier, .extended_identifier => { | |
| 5538 | 5547 | const tok = m.list[m.i + 1]; |
| 5539 | 5548 | const slice = m.source[tok.start..tok.end]; |
| 5540 | 5549 | if (c.global_scope.blank_macros.contains(slice)) { |
| ... | ... | @@ -5542,7 +5551,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5542 | 5551 | continue; |
| 5543 | 5552 | } |
| 5544 | 5553 | }, |
| 5545 | .Eof, .Nl => { | |
| 5554 | .eof, .nl => { | |
| 5546 | 5555 | try c.global_scope.blank_macros.put(m.name, {}); |
| 5547 | 5556 | const init_node = try Tag.string_literal.create(c.arena, "\"\""); |
| 5548 | 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 | 5565 | |
| 5557 | 5566 | const init_node = try parseCExpr(c, m, scope); |
| 5558 | 5567 | const last = m.next().?; |
| 5559 | if (last != .Eof and last != .Nl) | |
| 5568 | if (last != .eof and last != .nl) | |
| 5560 | 5569 | return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()}); |
| 5561 | 5570 | |
| 5562 | 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 | 5587 | defer block_scope.deinit(); |
| 5579 | 5588 | const scope = &block_scope.base; |
| 5580 | 5589 | |
| 5581 | try m.skip(c, .LParen); | |
| 5590 | try m.skip(c, .l_paren); | |
| 5582 | 5591 | |
| 5583 | 5592 | var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa); |
| 5584 | 5593 | defer fn_params.deinit(); |
| 5585 | 5594 | |
| 5586 | 5595 | while (true) { |
| 5587 | if (m.peek().? != .Identifier) break; | |
| 5588 | _ = m.next(); | |
| 5596 | switch (m.peek().?) { | |
| 5597 | .identifier, .extended_identifier => _ = m.next(), | |
| 5598 | else => break, | |
| 5599 | } | |
| 5589 | 5600 | |
| 5590 | 5601 | const mangled_name = try block_scope.makeMangledName(c, m.slice()); |
| 5591 | 5602 | try fn_params.append(.{ |
| ... | ... | @@ -5594,11 +5605,11 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5594 | 5605 | .type = Tag.@"anytype".init(), |
| 5595 | 5606 | }); |
| 5596 | 5607 | try block_scope.discardVariable(c, mangled_name); |
| 5597 | if (m.peek().? != .Comma) break; | |
| 5608 | if (m.peek().? != .comma) break; | |
| 5598 | 5609 | _ = m.next(); |
| 5599 | 5610 | } |
| 5600 | 5611 | |
| 5601 | try m.skip(c, .RParen); | |
| 5612 | try m.skip(c, .r_paren); | |
| 5602 | 5613 | |
| 5603 | 5614 | if (m.checkTranslatableMacro(scope, fn_params.items)) |err| switch (err) { |
| 5604 | 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 | 5618 | |
| 5608 | 5619 | const expr = try parseCExpr(c, m, scope); |
| 5609 | 5620 | const last = m.next().?; |
| 5610 | if (last != .Eof and last != .Nl) | |
| 5621 | if (last != .eof and last != .nl) | |
| 5611 | 5622 | return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()}); |
| 5612 | 5623 | |
| 5613 | 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 | 5655 | defer block_scope.deinit(); |
| 5645 | 5656 | |
| 5646 | 5657 | const node = try parseCCondExpr(c, m, &block_scope.base); |
| 5647 | if (m.next().? != .Comma) { | |
| 5658 | if (m.next().? != .comma) { | |
| 5648 | 5659 | m.i -= 1; |
| 5649 | 5660 | return node; |
| 5650 | 5661 | } |
| ... | ... | @@ -5656,7 +5667,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5656 | 5667 | try block_scope.statements.append(ignore); |
| 5657 | 5668 | |
| 5658 | 5669 | last = try parseCCondExpr(c, m, &block_scope.base); |
| 5659 | if (m.next().? != .Comma) { | |
| 5670 | if (m.next().? != .comma) { | |
| 5660 | 5671 | m.i -= 1; |
| 5661 | 5672 | break; |
| 5662 | 5673 | } |
| ... | ... | @@ -5670,118 +5681,135 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5670 | 5681 | return try block_scope.complete(c); |
| 5671 | 5682 | } |
| 5672 | 5683 | |
| 5673 | fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { | |
| 5674 | var lit_bytes = m.slice(); | |
| 5684 | fn parseCNumLit(ctx: *Context, m: *MacroCtx) ParseError!Node { | |
| 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) { | |
| 5677 | .IntegerLiteral => |suffix| { | |
| 5678 | var base: []const u8 = "decimal"; | |
| 5679 | if (lit_bytes.len >= 2 and lit_bytes[0] == '0') { | |
| 5680 | switch (lit_bytes[1]) { | |
| 5681 | '0'...'7' => { | |
| 5682 | // Octal | |
| 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); | |
| 5688 | const prefix = aro.Tree.Token.NumberPrefix.fromString(lit_bytes); | |
| 5689 | switch (prefix) { | |
| 5690 | .binary => bytes.appendSliceAssumeCapacity("0b"), | |
| 5691 | .octal => bytes.appendSliceAssumeCapacity("0o"), | |
| 5692 | .hex => bytes.appendSliceAssumeCapacity("0x"), | |
| 5693 | .decimal => {}, | |
| 5694 | } | |
| 5730 | 5695 | |
| 5731 | if (guaranteed_to_fit) { | |
| 5732 | return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = literal_node }); | |
| 5733 | } else { | |
| 5734 | return Tag.helpers_promoteIntLiteral.create(c.arena, .{ | |
| 5735 | .type = type_node, | |
| 5736 | .value = literal_node, | |
| 5737 | .base = try Tag.enum_literal.create(c.arena, base), | |
| 5738 | }); | |
| 5696 | const after_prefix = lit_bytes[prefix.stringLen()..]; | |
| 5697 | const after_int = for (after_prefix, 0..) |c, i| switch (c) { | |
| 5698 | '.' => { | |
| 5699 | if (i == 0) { | |
| 5700 | bytes.appendAssumeCapacity('0'); | |
| 5739 | 5701 | } |
| 5702 | break after_prefix[i..]; | |
| 5740 | 5703 | }, |
| 5741 | .FloatLiteral => |suffix| { | |
| 5742 | if (suffix != .none) lit_bytes = lit_bytes[0 .. lit_bytes.len - 1]; | |
| 5743 | ||
| 5744 | if (lit_bytes.len >= 2 and std.ascii.eqlIgnoreCase(lit_bytes[0..2], "0x")) { | |
| 5745 | if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| { | |
| 5746 | if (dot_index == 2) { | |
| 5747 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x0{s}", .{lit_bytes[2..]}); | |
| 5748 | } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isHex(lit_bytes[dot_index + 1])) { | |
| 5749 | // If the literal lacks a digit after the `.`, we need to | |
| 5750 | // add one since `0x1.p10` would be invalid syntax in Zig. | |
| 5751 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}0{s}", .{ | |
| 5752 | lit_bytes[2 .. dot_index + 1], | |
| 5753 | lit_bytes[dot_index + 1 ..], | |
| 5754 | }); | |
| 5755 | } | |
| 5756 | } | |
| 5704 | 'e', 'E' => { | |
| 5705 | if (prefix != .hex) break after_prefix[i..]; | |
| 5706 | bytes.appendAssumeCapacity(c); | |
| 5707 | }, | |
| 5708 | 'p', 'P' => break after_prefix[i..], | |
| 5709 | '0'...'9', 'a'...'d', 'A'...'D', 'f', 'F' => { | |
| 5710 | if (!prefix.digitAllowed(c)) break after_prefix[i..]; | |
| 5711 | bytes.appendAssumeCapacity(c); | |
| 5712 | }, | |
| 5713 | '\'' => { | |
| 5714 | bytes.appendAssumeCapacity('_'); | |
| 5715 | }, | |
| 5716 | else => break after_prefix[i..], | |
| 5717 | } else ""; | |
| 5757 | 5718 | |
| 5758 | if (lit_bytes[1] == 'X') { | |
| 5759 | // Hexadecimal with capital X, valid in C but not in Zig | |
| 5760 | lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]}); | |
| 5761 | } | |
| 5762 | } else if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| { | |
| 5763 | if (dot_index == 0) { | |
| 5764 | lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes}); | |
| 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 | } | |
| 5719 | const after_frac = frac: { | |
| 5720 | if (after_int.len == 0 or after_int[0] != '.') break :frac after_int; | |
| 5721 | bytes.appendAssumeCapacity('.'); | |
| 5722 | for (after_int[1..], 1..) |c, i| { | |
| 5723 | if (c == '\'') { | |
| 5724 | bytes.appendAssumeCapacity('_'); | |
| 5725 | continue; | |
| 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) { | |
| 5776 | .f => "f32", | |
| 5777 | .none => "f64", | |
| 5778 | .l => "c_longdouble", | |
| 5779 | else => unreachable, | |
| 5803 | const literal_node = try Tag.integer_literal.create(ctx.arena, bytes.items); | |
| 5804 | if (guaranteed_to_fit) { | |
| 5805 | return Tag.as.create(ctx.arena, .{ .lhs = type_node, .rhs = literal_node }); | |
| 5806 | } else { | |
| 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); | |
| 5782 | return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs }); | |
| 5783 | }, | |
| 5784 | else => unreachable, | |
| 5812 | } | |
| 5785 | 5813 | } |
| 5786 | 5814 | } |
| 5787 | 5815 | |
| ... | ... | @@ -5800,17 +5828,17 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5800 | 5828 | } else return source; |
| 5801 | 5829 | var bytes = try ctx.arena.alloc(u8, source.len * 2); |
| 5802 | 5830 | var state: enum { |
| 5803 | Start, | |
| 5804 | Escape, | |
| 5805 | Hex, | |
| 5806 | Octal, | |
| 5807 | } = .Start; | |
| 5831 | start, | |
| 5832 | escape, | |
| 5833 | hex, | |
| 5834 | octal, | |
| 5835 | } = .start; | |
| 5808 | 5836 | var i: usize = 0; |
| 5809 | 5837 | var count: u8 = 0; |
| 5810 | 5838 | var num: u8 = 0; |
| 5811 | 5839 | for (source) |c| { |
| 5812 | 5840 | switch (state) { |
| 5813 | .Escape => { | |
| 5841 | .escape => { | |
| 5814 | 5842 | switch (c) { |
| 5815 | 5843 | 'n', 'r', 't', '\\', '\'', '\"' => { |
| 5816 | 5844 | bytes[i] = c; |
| ... | ... | @@ -5818,11 +5846,11 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5818 | 5846 | '0'...'7' => { |
| 5819 | 5847 | count += 1; |
| 5820 | 5848 | num += c - '0'; |
| 5821 | state = .Octal; | |
| 5849 | state = .octal; | |
| 5822 | 5850 | bytes[i] = 'x'; |
| 5823 | 5851 | }, |
| 5824 | 5852 | 'x' => { |
| 5825 | state = .Hex; | |
| 5853 | state = .hex; | |
| 5826 | 5854 | bytes[i] = 'x'; |
| 5827 | 5855 | }, |
| 5828 | 5856 | 'a' => { |
| ... | ... | @@ -5867,10 +5895,10 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5867 | 5895 | }, |
| 5868 | 5896 | } |
| 5869 | 5897 | i += 1; |
| 5870 | if (state == .Escape) | |
| 5871 | state = .Start; | |
| 5898 | if (state == .escape) | |
| 5899 | state = .start; | |
| 5872 | 5900 | }, |
| 5873 | .Start => { | |
| 5901 | .start => { | |
| 5874 | 5902 | if (c == '\t') { |
| 5875 | 5903 | bytes[i] = '\\'; |
| 5876 | 5904 | i += 1; |
| ... | ... | @@ -5879,12 +5907,12 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5879 | 5907 | continue; |
| 5880 | 5908 | } |
| 5881 | 5909 | if (c == '\\') { |
| 5882 | state = .Escape; | |
| 5910 | state = .escape; | |
| 5883 | 5911 | } |
| 5884 | 5912 | bytes[i] = c; |
| 5885 | 5913 | i += 1; |
| 5886 | 5914 | }, |
| 5887 | .Hex => { | |
| 5915 | .hex => { | |
| 5888 | 5916 | switch (c) { |
| 5889 | 5917 | '0'...'9' => { |
| 5890 | 5918 | num = std.math.mul(u8, num, 16) catch { |
| ... | ... | @@ -5911,15 +5939,15 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5911 | 5939 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); |
| 5912 | 5940 | num = 0; |
| 5913 | 5941 | if (c == '\\') |
| 5914 | state = .Escape | |
| 5942 | state = .escape | |
| 5915 | 5943 | else |
| 5916 | state = .Start; | |
| 5944 | state = .start; | |
| 5917 | 5945 | bytes[i] = c; |
| 5918 | 5946 | i += 1; |
| 5919 | 5947 | }, |
| 5920 | 5948 | } |
| 5921 | 5949 | }, |
| 5922 | .Octal => { | |
| 5950 | .octal => { | |
| 5923 | 5951 | const accept_digit = switch (c) { |
| 5924 | 5952 | // The maximum length of a octal literal is 3 digits |
| 5925 | 5953 | '0'...'7' => count < 3, |
| ... | ... | @@ -5938,16 +5966,16 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5938 | 5966 | num = 0; |
| 5939 | 5967 | count = 0; |
| 5940 | 5968 | if (c == '\\') |
| 5941 | state = .Escape | |
| 5969 | state = .escape | |
| 5942 | 5970 | else |
| 5943 | state = .Start; | |
| 5971 | state = .start; | |
| 5944 | 5972 | bytes[i] = c; |
| 5945 | 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 | 5979 | i += std.fmt.formatIntBuf(bytes[i..], num, 16, .lower, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); |
| 5952 | 5980 | return bytes[0..i]; |
| 5953 | 5981 | } |
| ... | ... | @@ -5972,7 +6000,12 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5972 | 6000 | const tok = m.next().?; |
| 5973 | 6001 | const slice = m.slice(); |
| 5974 | 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 | 6009 | if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) { |
| 5977 | 6010 | return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m)); |
| 5978 | 6011 | } else { |
| ... | ... | @@ -5980,13 +6013,18 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5980 | 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 | 6022 | return Tag.string_literal.create(c.arena, try escapeUnprintables(c, m)); |
| 5985 | 6023 | }, |
| 5986 | .IntegerLiteral, .FloatLiteral => { | |
| 6024 | .pp_num => { | |
| 5987 | 6025 | return parseCNumLit(c, m); |
| 5988 | 6026 | }, |
| 5989 | .Identifier => { | |
| 6027 | .identifier, .extended_identifier => { | |
| 5990 | 6028 | if (c.global_scope.blank_macros.contains(slice)) { |
| 5991 | 6029 | return parseCPrimaryExprInner(c, m, scope); |
| 5992 | 6030 | } |
| ... | ... | @@ -5996,10 +6034,10 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5996 | 6034 | scope.skipVariableDiscard(identifier.castTag(.identifier).?.data); |
| 5997 | 6035 | return identifier; |
| 5998 | 6036 | }, |
| 5999 | .LParen => { | |
| 6037 | .l_paren => { | |
| 6000 | 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 | 6041 | return inner_node; |
| 6004 | 6042 | }, |
| 6005 | 6043 | else => { |
| ... | ... | @@ -6022,8 +6060,13 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6022 | 6060 | // after a primary expression. |
| 6023 | 6061 | while (true) { |
| 6024 | 6062 | switch (m.peek().?) { |
| 6025 | .StringLiteral => {}, | |
| 6026 | .Identifier => { | |
| 6063 | .string_literal, | |
| 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 | 6070 | const tok = m.list[m.i + 1]; |
| 6028 | 6071 | const slice = m.source[tok.start..tok.end]; |
| 6029 | 6072 | if (c.global_scope.blank_macros.contains(slice)) { |
| ... | ... | @@ -6057,20 +6100,20 @@ fn macroIntToBool(c: *Context, node: Node) !Node { |
| 6057 | 6100 | |
| 6058 | 6101 | fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6059 | 6102 | const node = try parseCOrExpr(c, m, scope); |
| 6060 | if (m.peek().? != .QuestionMark) { | |
| 6103 | if (m.peek().? != .question_mark) { | |
| 6061 | 6104 | return node; |
| 6062 | 6105 | } |
| 6063 | 6106 | _ = m.next(); |
| 6064 | 6107 | |
| 6065 | 6108 | const then_body = try parseCOrExpr(c, m, scope); |
| 6066 | try m.skip(c, .Colon); | |
| 6109 | try m.skip(c, .colon); | |
| 6067 | 6110 | const else_body = try parseCCondExpr(c, m, scope); |
| 6068 | 6111 | return Tag.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body }); |
| 6069 | 6112 | } |
| 6070 | 6113 | |
| 6071 | 6114 | fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6072 | 6115 | var node = try parseCAndExpr(c, m, scope); |
| 6073 | while (m.next().? == .PipePipe) { | |
| 6116 | while (m.next().? == .pipe_pipe) { | |
| 6074 | 6117 | const lhs = try macroIntToBool(c, node); |
| 6075 | 6118 | const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope)); |
| 6076 | 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 | 6124 | |
| 6082 | 6125 | fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6083 | 6126 | var node = try parseCBitOrExpr(c, m, scope); |
| 6084 | while (m.next().? == .AmpersandAmpersand) { | |
| 6127 | while (m.next().? == .ampersand_ampersand) { | |
| 6085 | 6128 | const lhs = try macroIntToBool(c, node); |
| 6086 | 6129 | const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope)); |
| 6087 | 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 | 6135 | |
| 6093 | 6136 | fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6094 | 6137 | var node = try parseCBitXorExpr(c, m, scope); |
| 6095 | while (m.next().? == .Pipe) { | |
| 6138 | while (m.next().? == .pipe) { | |
| 6096 | 6139 | const lhs = try macroIntFromBool(c, node); |
| 6097 | 6140 | const rhs = try macroIntFromBool(c, try parseCBitXorExpr(c, m, scope)); |
| 6098 | 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 | 6146 | |
| 6104 | 6147 | fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6105 | 6148 | var node = try parseCBitAndExpr(c, m, scope); |
| 6106 | while (m.next().? == .Caret) { | |
| 6149 | while (m.next().? == .caret) { | |
| 6107 | 6150 | const lhs = try macroIntFromBool(c, node); |
| 6108 | 6151 | const rhs = try macroIntFromBool(c, try parseCBitAndExpr(c, m, scope)); |
| 6109 | 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 | 6157 | |
| 6115 | 6158 | fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6116 | 6159 | var node = try parseCEqExpr(c, m, scope); |
| 6117 | while (m.next().? == .Ampersand) { | |
| 6160 | while (m.next().? == .ampersand) { | |
| 6118 | 6161 | const lhs = try macroIntFromBool(c, node); |
| 6119 | 6162 | const rhs = try macroIntFromBool(c, try parseCEqExpr(c, m, scope)); |
| 6120 | 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 | 6170 | var node = try parseCRelExpr(c, m, scope); |
| 6128 | 6171 | while (true) { |
| 6129 | 6172 | switch (m.peek().?) { |
| 6130 | .BangEqual => { | |
| 6173 | .bang_equal => { | |
| 6131 | 6174 | _ = m.next(); |
| 6132 | 6175 | const lhs = try macroIntFromBool(c, node); |
| 6133 | 6176 | const rhs = try macroIntFromBool(c, try parseCRelExpr(c, m, scope)); |
| 6134 | 6177 | node = try Tag.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6135 | 6178 | }, |
| 6136 | .EqualEqual => { | |
| 6179 | .equal_equal => { | |
| 6137 | 6180 | _ = m.next(); |
| 6138 | 6181 | const lhs = try macroIntFromBool(c, node); |
| 6139 | 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 | 6191 | var node = try parseCShiftExpr(c, m, scope); |
| 6149 | 6192 | while (true) { |
| 6150 | 6193 | switch (m.peek().?) { |
| 6151 | .AngleBracketRight => { | |
| 6194 | .angle_bracket_right => { | |
| 6152 | 6195 | _ = m.next(); |
| 6153 | 6196 | const lhs = try macroIntFromBool(c, node); |
| 6154 | 6197 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| 6155 | 6198 | node = try Tag.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6156 | 6199 | }, |
| 6157 | .AngleBracketRightEqual => { | |
| 6200 | .angle_bracket_right_equal => { | |
| 6158 | 6201 | _ = m.next(); |
| 6159 | 6202 | const lhs = try macroIntFromBool(c, node); |
| 6160 | 6203 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| 6161 | 6204 | node = try Tag.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6162 | 6205 | }, |
| 6163 | .AngleBracketLeft => { | |
| 6206 | .angle_bracket_left => { | |
| 6164 | 6207 | _ = m.next(); |
| 6165 | 6208 | const lhs = try macroIntFromBool(c, node); |
| 6166 | 6209 | const rhs = try macroIntFromBool(c, try parseCShiftExpr(c, m, scope)); |
| 6167 | 6210 | node = try Tag.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6168 | 6211 | }, |
| 6169 | .AngleBracketLeftEqual => { | |
| 6212 | .angle_bracket_left_equal => { | |
| 6170 | 6213 | _ = m.next(); |
| 6171 | 6214 | const lhs = try macroIntFromBool(c, node); |
| 6172 | 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 | 6224 | var node = try parseCAddSubExpr(c, m, scope); |
| 6182 | 6225 | while (true) { |
| 6183 | 6226 | switch (m.peek().?) { |
| 6184 | .AngleBracketAngleBracketLeft => { | |
| 6227 | .angle_bracket_angle_bracket_left => { | |
| 6185 | 6228 | _ = m.next(); |
| 6186 | 6229 | const lhs = try macroIntFromBool(c, node); |
| 6187 | 6230 | const rhs = try macroIntFromBool(c, try parseCAddSubExpr(c, m, scope)); |
| 6188 | 6231 | node = try Tag.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6189 | 6232 | }, |
| 6190 | .AngleBracketAngleBracketRight => { | |
| 6233 | .angle_bracket_angle_bracket_right => { | |
| 6191 | 6234 | _ = m.next(); |
| 6192 | 6235 | const lhs = try macroIntFromBool(c, node); |
| 6193 | 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 | 6245 | var node = try parseCMulExpr(c, m, scope); |
| 6203 | 6246 | while (true) { |
| 6204 | 6247 | switch (m.peek().?) { |
| 6205 | .Plus => { | |
| 6248 | .plus => { | |
| 6206 | 6249 | _ = m.next(); |
| 6207 | 6250 | const lhs = try macroIntFromBool(c, node); |
| 6208 | 6251 | const rhs = try macroIntFromBool(c, try parseCMulExpr(c, m, scope)); |
| 6209 | 6252 | node = try Tag.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6210 | 6253 | }, |
| 6211 | .Minus => { | |
| 6254 | .minus => { | |
| 6212 | 6255 | _ = m.next(); |
| 6213 | 6256 | const lhs = try macroIntFromBool(c, node); |
| 6214 | 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 | 6266 | var node = try parseCCastExpr(c, m, scope); |
| 6224 | 6267 | while (true) { |
| 6225 | 6268 | switch (m.next().?) { |
| 6226 | .Asterisk => { | |
| 6269 | .asterisk => { | |
| 6227 | 6270 | const lhs = try macroIntFromBool(c, node); |
| 6228 | 6271 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6229 | 6272 | node = try Tag.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 6230 | 6273 | }, |
| 6231 | .Slash => { | |
| 6274 | .slash => { | |
| 6232 | 6275 | const lhs = try macroIntFromBool(c, node); |
| 6233 | 6276 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6234 | 6277 | node = try Tag.macro_arithmetic.create(c.arena, .{ .op = .div, .lhs = lhs, .rhs = rhs }); |
| 6235 | 6278 | }, |
| 6236 | .Percent => { | |
| 6279 | .percent => { | |
| 6237 | 6280 | const lhs = try macroIntFromBool(c, node); |
| 6238 | 6281 | const rhs = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6239 | 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 | 6291 | |
| 6249 | 6292 | fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6250 | 6293 | switch (m.next().?) { |
| 6251 | .LParen => { | |
| 6294 | .l_paren => { | |
| 6252 | 6295 | if (try parseCTypeName(c, m, scope, true)) |type_name| { |
| 6253 | 6296 | while (true) { |
| 6254 | 6297 | const next_token = m.next().?; |
| 6255 | 6298 | switch (next_token) { |
| 6256 | .RParen => break, | |
| 6299 | .r_paren => break, | |
| 6257 | 6300 | else => |next_tag| { |
| 6258 | 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 | 6304 | continue; |
| 6261 | } | |
| 6305 | ||
| 6262 | 6306 | try m.fail( |
| 6263 | 6307 | c, |
| 6264 | 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 | 6312 | }, |
| 6269 | 6313 | } |
| 6270 | 6314 | } |
| 6271 | if (m.peek().? == .LBrace) { | |
| 6315 | if (m.peek().? == .l_brace) { | |
| 6272 | 6316 | // initializer list |
| 6273 | 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 | 6338 | fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_fail: bool) ParseError!?Node { |
| 6295 | 6339 | const tok = m.next().?; |
| 6296 | 6340 | switch (tok) { |
| 6297 | .Identifier => { | |
| 6341 | .identifier, .extended_identifier => { | |
| 6298 | 6342 | if (c.global_scope.blank_macros.contains(m.slice())) { |
| 6299 | 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 | 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"), | |
| 6308 | .Keyword_bool => return try Tag.type.create(c.arena, "bool"), | |
| 6309 | .Keyword_char, | |
| 6310 | .Keyword_int, | |
| 6311 | .Keyword_short, | |
| 6312 | .Keyword_long, | |
| 6313 | .Keyword_float, | |
| 6314 | .Keyword_double, | |
| 6315 | .Keyword_signed, | |
| 6316 | .Keyword_unsigned, | |
| 6317 | .Keyword_complex, | |
| 6351 | .keyword_void => return try Tag.type.create(c.arena, "anyopaque"), | |
| 6352 | .keyword_bool => return try Tag.type.create(c.arena, "bool"), | |
| 6353 | .keyword_char, | |
| 6354 | .keyword_int, | |
| 6355 | .keyword_short, | |
| 6356 | .keyword_long, | |
| 6357 | .keyword_float, | |
| 6358 | .keyword_double, | |
| 6359 | .keyword_signed, | |
| 6360 | .keyword_unsigned, | |
| 6361 | .keyword_complex, | |
| 6318 | 6362 | => { |
| 6319 | 6363 | m.i -= 1; |
| 6320 | 6364 | return try parseCNumericType(c, m); |
| 6321 | 6365 | }, |
| 6322 | .Keyword_enum, .Keyword_struct, .Keyword_union => { | |
| 6366 | .keyword_enum, .keyword_struct, .keyword_union => { | |
| 6323 | 6367 | // struct Foo will be declared as struct_Foo by transRecordDecl |
| 6324 | 6368 | const slice = m.slice(); |
| 6325 | try m.skip(c, .Identifier); | |
| 6369 | try m.skip(c, .identifier); | |
| 6326 | 6370 | |
| 6327 | 6371 | const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() }); |
| 6328 | 6372 | return try Tag.identifier.create(c.arena, name); |
| ... | ... | @@ -6364,15 +6408,15 @@ fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { |
| 6364 | 6408 | var i: u8 = 0; |
| 6365 | 6409 | while (i < math.maxInt(u8)) : (i += 1) { |
| 6366 | 6410 | switch (m.next().?) { |
| 6367 | .Keyword_double => kw.double += 1, | |
| 6368 | .Keyword_long => kw.long += 1, | |
| 6369 | .Keyword_int => kw.int += 1, | |
| 6370 | .Keyword_float => kw.float += 1, | |
| 6371 | .Keyword_short => kw.short += 1, | |
| 6372 | .Keyword_char => kw.char += 1, | |
| 6373 | .Keyword_unsigned => kw.unsigned += 1, | |
| 6374 | .Keyword_signed => kw.signed += 1, | |
| 6375 | .Keyword_complex => kw.complex += 1, | |
| 6411 | .keyword_double => kw.double += 1, | |
| 6412 | .keyword_long => kw.long += 1, | |
| 6413 | .keyword_int => kw.int += 1, | |
| 6414 | .keyword_float => kw.float += 1, | |
| 6415 | .keyword_short => kw.short += 1, | |
| 6416 | .keyword_char => kw.char += 1, | |
| 6417 | .keyword_unsigned => kw.unsigned += 1, | |
| 6418 | .keyword_signed => kw.signed += 1, | |
| 6419 | .keyword_complex => kw.complex += 1, | |
| 6376 | 6420 | else => { |
| 6377 | 6421 | m.i -= 1; |
| 6378 | 6422 | break; |
| ... | ... | @@ -6442,11 +6486,11 @@ fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { |
| 6442 | 6486 | |
| 6443 | 6487 | fn parseCAbstractDeclarator(c: *Context, m: *MacroCtx, node: Node) ParseError!Node { |
| 6444 | 6488 | switch (m.next().?) { |
| 6445 | .Asterisk => { | |
| 6489 | .asterisk => { | |
| 6446 | 6490 | // last token of `node` |
| 6447 | 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 | 6494 | const ptr = try Tag.single_pointer.create(c.arena, .{ |
| 6451 | 6495 | .is_const = false, |
| 6452 | 6496 | .is_volatile = false, |
| ... | ... | @@ -6472,28 +6516,28 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6472 | 6516 | var node = type_name orelse try parseCPrimaryExpr(c, m, scope); |
| 6473 | 6517 | while (true) { |
| 6474 | 6518 | switch (m.next().?) { |
| 6475 | .Period => { | |
| 6476 | try m.skip(c, .Identifier); | |
| 6519 | .period => { | |
| 6520 | try m.skip(c, .identifier); | |
| 6477 | 6521 | |
| 6478 | 6522 | node = try Tag.field_access.create(c.arena, .{ .lhs = node, .field_name = m.slice() }); |
| 6479 | 6523 | }, |
| 6480 | .Arrow => { | |
| 6481 | try m.skip(c, .Identifier); | |
| 6524 | .arrow => { | |
| 6525 | try m.skip(c, .identifier); | |
| 6482 | 6526 | |
| 6483 | 6527 | const deref = try Tag.deref.create(c.arena, node); |
| 6484 | 6528 | node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .field_name = m.slice() }); |
| 6485 | 6529 | }, |
| 6486 | .LBracket => { | |
| 6530 | .l_bracket => { | |
| 6487 | 6531 | const index_val = try macroIntFromBool(c, try parseCExpr(c, m, scope)); |
| 6488 | 6532 | const index = try Tag.as.create(c.arena, .{ |
| 6489 | 6533 | .lhs = try Tag.type.create(c.arena, "usize"), |
| 6490 | 6534 | .rhs = try Tag.int_cast.create(c.arena, index_val), |
| 6491 | 6535 | }); |
| 6492 | 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 => { | |
| 6496 | if (m.peek().? == .RParen) { | |
| 6539 | .l_paren => { | |
| 6540 | if (m.peek().? == .r_paren) { | |
| 6497 | 6541 | m.i += 1; |
| 6498 | 6542 | node = try Tag.call.create(c.arena, .{ .lhs = node, .args = &[0]Node{} }); |
| 6499 | 6543 | } else { |
| ... | ... | @@ -6504,8 +6548,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6504 | 6548 | try args.append(arg); |
| 6505 | 6549 | const next_id = m.next().?; |
| 6506 | 6550 | switch (next_id) { |
| 6507 | .Comma => {}, | |
| 6508 | .RParen => break, | |
| 6551 | .comma => {}, | |
| 6552 | .r_paren => break, | |
| 6509 | 6553 | else => { |
| 6510 | 6554 | try m.fail(c, "unable to translate C expr: expected ',' or ')' instead got '{s}'", .{next_id.symbol()}); |
| 6511 | 6555 | return error.ParseError; |
| ... | ... | @@ -6515,24 +6559,24 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6515 | 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 | 6563 | // Check for designated field initializers |
| 6520 | if (m.peek().? == .Period) { | |
| 6564 | if (m.peek().? == .period) { | |
| 6521 | 6565 | var init_vals = std.ArrayList(ast.Payload.ContainerInitDot.Initializer).init(c.gpa); |
| 6522 | 6566 | defer init_vals.deinit(); |
| 6523 | 6567 | |
| 6524 | 6568 | while (true) { |
| 6525 | try m.skip(c, .Period); | |
| 6526 | try m.skip(c, .Identifier); | |
| 6569 | try m.skip(c, .period); | |
| 6570 | try m.skip(c, .identifier); | |
| 6527 | 6571 | const name = m.slice(); |
| 6528 | try m.skip(c, .Equal); | |
| 6572 | try m.skip(c, .equal); | |
| 6529 | 6573 | |
| 6530 | 6574 | const val = try parseCCondExpr(c, m, scope); |
| 6531 | 6575 | try init_vals.append(.{ .name = name, .value = val }); |
| 6532 | 6576 | const next_id = m.next().?; |
| 6533 | 6577 | switch (next_id) { |
| 6534 | .Comma => {}, | |
| 6535 | .RBrace => break, | |
| 6578 | .comma => {}, | |
| 6579 | .r_brace => break, | |
| 6536 | 6580 | else => { |
| 6537 | 6581 | try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()}); |
| 6538 | 6582 | return error.ParseError; |
| ... | ... | @@ -6552,8 +6596,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6552 | 6596 | try init_vals.append(val); |
| 6553 | 6597 | const next_id = m.next().?; |
| 6554 | 6598 | switch (next_id) { |
| 6555 | .Comma => {}, | |
| 6556 | .RBrace => break, | |
| 6599 | .comma => {}, | |
| 6600 | .r_brace => break, | |
| 6557 | 6601 | else => { |
| 6558 | 6602 | try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()}); |
| 6559 | 6603 | return error.ParseError; |
| ... | ... | @@ -6563,7 +6607,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6563 | 6607 | const tuple_node = try Tag.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items)); |
| 6564 | 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 | 6611 | try m.fail(c, "TODO postfix inc/dec expr", .{}); |
| 6568 | 6612 | return error.ParseError; |
| 6569 | 6613 | }, |
| ... | ... | @@ -6577,47 +6621,47 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) |
| 6577 | 6621 | |
| 6578 | 6622 | fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 6579 | 6623 | switch (m.next().?) { |
| 6580 | .Bang => { | |
| 6624 | .bang => { | |
| 6581 | 6625 | const operand = try macroIntToBool(c, try parseCCastExpr(c, m, scope)); |
| 6582 | 6626 | return Tag.not.create(c.arena, operand); |
| 6583 | 6627 | }, |
| 6584 | .Minus => { | |
| 6628 | .minus => { | |
| 6585 | 6629 | const operand = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6586 | 6630 | return Tag.negate.create(c.arena, operand); |
| 6587 | 6631 | }, |
| 6588 | .Plus => return try parseCCastExpr(c, m, scope), | |
| 6589 | .Tilde => { | |
| 6632 | .plus => return try parseCCastExpr(c, m, scope), | |
| 6633 | .tilde => { | |
| 6590 | 6634 | const operand = try macroIntFromBool(c, try parseCCastExpr(c, m, scope)); |
| 6591 | 6635 | return Tag.bit_not.create(c.arena, operand); |
| 6592 | 6636 | }, |
| 6593 | .Asterisk => { | |
| 6637 | .asterisk => { | |
| 6594 | 6638 | const operand = try parseCCastExpr(c, m, scope); |
| 6595 | 6639 | return Tag.deref.create(c.arena, operand); |
| 6596 | 6640 | }, |
| 6597 | .Ampersand => { | |
| 6641 | .ampersand => { | |
| 6598 | 6642 | const operand = try parseCCastExpr(c, m, scope); |
| 6599 | 6643 | return Tag.address_of.create(c.arena, operand); |
| 6600 | 6644 | }, |
| 6601 | .Keyword_sizeof => { | |
| 6602 | const operand = if (m.peek().? == .LParen) blk: { | |
| 6645 | .keyword_sizeof => { | |
| 6646 | const operand = if (m.peek().? == .l_paren) blk: { | |
| 6603 | 6647 | _ = m.next(); |
| 6604 | 6648 | const inner = (try parseCTypeName(c, m, scope, false)).?; |
| 6605 | try m.skip(c, .RParen); | |
| 6649 | try m.skip(c, .r_paren); | |
| 6606 | 6650 | break :blk inner; |
| 6607 | 6651 | } else try parseCUnaryExpr(c, m, scope); |
| 6608 | 6652 | |
| 6609 | 6653 | return Tag.helpers_sizeof.create(c.arena, operand); |
| 6610 | 6654 | }, |
| 6611 | .Keyword_alignof => { | |
| 6655 | .keyword_alignof => { | |
| 6612 | 6656 | // TODO this won't work if using <stdalign.h>'s |
| 6613 | 6657 | // #define alignof _Alignof |
| 6614 | try m.skip(c, .LParen); | |
| 6658 | try m.skip(c, .l_paren); | |
| 6615 | 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 | 6662 | return Tag.alignof.create(c.arena, operand); |
| 6619 | 6663 | }, |
| 6620 | .PlusPlus, .MinusMinus => { | |
| 6664 | .plus_plus, .minus_minus => { | |
| 6621 | 6665 | try m.fail(c, "TODO unary inc/dec expr", .{}); |
| 6622 | 6666 | return error.ParseError; |
| 6623 | 6667 | }, |
test/translate_c.zig+7-7| ... | ... | @@ -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 | 430 | cases.add("complex switch", |
| ... | ... | @@ -633,7 +633,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 633 | 633 | cases.add("#define hex literal with capital X", |
| 634 | 634 | \\#define VAL 0XF00D |
| 635 | 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 | 639 | cases.add("anonymous struct & unions", |
| ... | ... | @@ -1243,12 +1243,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1243 | 1243 | \\extern const long double my_extended_precision_longdouble = 1.0000000000000003l; |
| 1244 | 1244 | , &([_][]const u8{ |
| 1245 | 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 | 1247 | "pub const FOO = @as(f64, 0.12345);", |
| 1248 | 1248 | "pub const BAR = @as(f64, 0.12345);", |
| 1249 | 1249 | "pub const baz = @as(f64, 1e1);", |
| 1250 | 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 | 1252 | "pub export const my_float: f32 = 1.0;", |
| 1253 | 1253 | "pub export const my_double: f64 = 1.0;", |
| 1254 | 1254 | "pub export const my_longdouble: c_longdouble = 1.0;", |
| ... | ... | @@ -1272,7 +1272,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1272 | 1272 | "pub const BAR = -@as(f32, 0x8F.BP5);", |
| 1273 | 1273 | "pub const FOOBAR = @as(f64, 0x0P+0);", |
| 1274 | 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 | 1278 | cases.add("comments", |
| ... | ... | @@ -3730,7 +3730,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3730 | 3730 | , &[_][]const u8{ |
| 3731 | 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 | 3736 | if (builtin.abi == .msvc) { |
| ... | ... | @@ -3812,7 +3812,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3812 | 3812 | \\pub const MAY_NEED_PROMOTION_1 = @import("std").zig.c_translation.promoteIntLiteral(c_int, 10241024, .decimal); |
| 3813 | 3813 | \\pub const MAY_NEED_PROMOTION_2 = @import("std").zig.c_translation.promoteIntLiteral(c_long, 307230723072, .decimal); |
| 3814 | 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 | 3816 | \\pub const MAY_NEED_PROMOTION_OCT = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0o20000000000, .octal); |
| 3817 | 3817 | }); |
| 3818 | 3818 |