authorgravatar for leroycepearson@geemili.xyzLeRoyce Pearson <leroycepearson@geemili.xyz> 2020-03-23 21:39:10-06:00
committergravatar for leroycepearson@geemili.xyzLeRoyce Pearson <leroycepearson@geemili.xyz> 2020-03-23 21:39:16-06:00
log113b217593ab5b0369b76251b99a195f361cc220
tree9aa8e8d78304afcc51bef0ace49bb5b3017804f6
parent0b93932a2103b178d3ab5235c837df14173ed38c
parentdc44fe053c609f389e375f6857f96b6bb3794897

Merge branch 'master' into feature-file-locks


107 files changed, 10674 insertions(+), 1748 deletions(-)

CMakeLists.txt-1
......@@ -622,7 +622,6 @@ set(BUILD_LIBSTAGE2_ARGS "build-lib"
622622 --cache on
623623 --output-dir "${CMAKE_BINARY_DIR}"
624624 ${LIBSTAGE2_RELEASE_ARG}
625 --disable-gen-h
626625 --bundle-compiler-rt
627626 -fPIC
628627 -lc
build.zig+11-6
......@@ -134,7 +134,8 @@ pub fn build(b: *Builder) !void {
134134 test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
135135 test_step.dependOn(tests.addTranslateCTests(b, test_filter));
136136 test_step.dependOn(tests.addRunTranslatedCTests(b, test_filter));
137 test_step.dependOn(tests.addGenHTests(b, test_filter));
137 // tests for this feature are disabled until we have the self-hosted compiler available
138 //test_step.dependOn(tests.addGenHTests(b, test_filter));
138139 test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));
139140 test_step.dependOn(docs_step);
140141}
......@@ -298,10 +299,14 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
298299 dependOnLib(b, exe, ctx.llvm);
299300
300301 if (exe.target.getOsTag() == .linux) {
301 try addCxxKnownPath(b, ctx, exe, "libstdc++.a",
302 \\Unable to determine path to libstdc++.a
303 \\On Fedora, install libstdc++-static and try again.
304 );
302 // First we try to static link against gcc libstdc++. If that doesn't work,
303 // we fall back to -lc++ and cross our fingers.
304 addCxxKnownPath(b, ctx, exe, "libstdc++.a", "") catch |err| switch (err) {
305 error.RequiredLibraryNotFound => {
306 exe.linkSystemLibrary("c++");
307 },
308 else => |e| return e,
309 };
305310
306311 exe.linkSystemLibrary("pthread");
307312 } else if (exe.target.isFreeBSD()) {
......@@ -320,7 +325,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
320325 // System compiler, not gcc.
321326 exe.linkSystemLibrary("c++");
322327 },
323 else => return err,
328 else => |e| return e,
324329 }
325330 }
326331
ci/drone/linux_script+2-1
......@@ -26,7 +26,8 @@ make -j$(nproc) install
2626# TODO test-cli is hitting https://github.com/ziglang/zig/issues/3526
2727./zig build test-asm-link test-runtime-safety
2828# TODO test-translate-c is hitting https://github.com/ziglang/zig/issues/3526
29./zig build test-gen-h
29# TODO disabled until we are shipping self-hosted
30#./zig build test-gen-h
3031# TODO test-compile-errors is hitting https://github.com/ziglang/zig/issues/3526
3132# TODO building docs is hitting https://github.com/ziglang/zig/issues/3526
3233
ci/srht/freebsd_script+2-1
......@@ -42,7 +42,8 @@ release/bin/zig build test-asm-link
4242release/bin/zig build test-runtime-safety
4343release/bin/zig build test-translate-c
4444release/bin/zig build test-run-translated-c
45release/bin/zig build test-gen-h
45# TODO disabled until we are shipping self-hosted
46#release/bin/zig build test-gen-h
4647release/bin/zig build test-compile-errors
4748release/bin/zig build docs
4849
doc/docgen.zig+19-3
......@@ -48,7 +48,7 @@ pub fn main() !void {
4848 var toc = try genToc(allocator, &tokenizer);
4949
5050 try fs.cwd().makePath(tmp_dir_name);
51 defer fs.deleteTree(tmp_dir_name) catch {};
51 defer fs.cwd().deleteTree(tmp_dir_name) catch {};
5252
5353 try genHtml(allocator, &tokenizer, &toc, buffered_out_stream.outStream(), zig_exe);
5454 try buffered_out_stream.flush();
......@@ -1096,6 +1096,9 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
10961096 try build_args.append("-lc");
10971097 try out.print(" -lc", .{});
10981098 }
1099 const target = try std.zig.CrossTarget.parse(.{
1100 .arch_os_abi = code.target_str orelse "native",
1101 });
10991102 if (code.target_str) |triple| {
11001103 try build_args.appendSlice(&[_][]const u8{ "-target", triple });
11011104 if (!code.is_inline) {
......@@ -1150,7 +1153,15 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
11501153 }
11511154 }
11521155
1153 const path_to_exe = mem.trim(u8, exec_result.stdout, " \r\n");
1156 const path_to_exe_dir = mem.trim(u8, exec_result.stdout, " \r\n");
1157 const path_to_exe_basename = try std.fmt.allocPrint(allocator, "{}{}", .{
1158 code.name,
1159 target.exeFileExt(),
1160 });
1161 const path_to_exe = try fs.path.join(allocator, &[_][]const u8{
1162 path_to_exe_dir,
1163 path_to_exe_basename,
1164 });
11541165 const run_args = &[_][]const u8{path_to_exe};
11551166
11561167 var exited_with_signal = false;
......@@ -1486,7 +1497,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
14861497}
14871498
14881499fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u8) !ChildProcess.ExecResult {
1489 const result = try ChildProcess.exec(allocator, args, null, env_map, max_doc_file_size);
1500 const result = try ChildProcess.exec2(.{
1501 .allocator = allocator,
1502 .argv = args,
1503 .env_map = env_map,
1504 .max_output_bytes = max_doc_file_size,
1505 });
14901506 switch (result.term) {
14911507 .Exited => |exit_code| {
14921508 if (exit_code != 0) {
doc/langref.html.in+27-20
......@@ -885,6 +885,12 @@ const hex_int = 0xff;
885885const another_hex_int = 0xFF;
886886const octal_int = 0o755;
887887const binary_int = 0b11110000;
888
889// underscores may be placed between two digits as a visual separator
890const one_billion = 1_000_000_000;
891const binary_mask = 0b1_1111_1111;
892const permissions = 0o7_5_5;
893const big_address = 0xFF80_0000_0000_0000;
888894 {#code_end#}
889895 {#header_close#}
890896 {#header_open|Runtime Integer Values#}
......@@ -947,6 +953,11 @@ const yet_another = 123.0e+77;
947953const hex_floating_point = 0x103.70p-5;
948954const another_hex_float = 0x103.70;
949955const yet_another_hex_float = 0x103.70P-5;
956
957// underscores may be placed between two digits as a visual separator
958const lightspeed = 299_792_458.000_000;
959const nanosecond = 0.000_000_001;
960const more_hex = 0x1234_5678.9ABC_CDEFp-10;
950961 {#code_end#}
951962 <p>
952963 There is no syntax for NaN, infinity, or negative infinity. For these special values,
......@@ -2093,8 +2104,9 @@ var foo: u8 align(4) = 100;
20932104test "global variable alignment" {
20942105 assert(@TypeOf(&foo).alignment == 4);
20952106 assert(@TypeOf(&foo) == *align(4) u8);
2096 const slice = @as(*[1]u8, &foo)[0..];
2097 assert(@TypeOf(slice) == []align(4) u8);
2107 const as_pointer_to_array: *[1]u8 = &foo;
2108 const as_slice: []u8 = as_pointer_to_array;
2109 assert(@TypeOf(as_slice) == []align(4) u8);
20982110}
20992111
21002112fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; }
......@@ -2187,7 +2199,8 @@ test "basic slices" {
21872199 // a slice is that the array's length is part of the type and known at
21882200 // compile-time, whereas the slice's length is known at runtime.
21892201 // Both can be accessed with the `len` field.
2190 const slice = array[0..array.len];
2202 var known_at_runtime_zero: usize = 0;
2203 const slice = array[known_at_runtime_zero..array.len];
21912204 assert(&slice[0] == &array[0]);
21922205 assert(slice.len == array.len);
21932206
......@@ -2207,13 +2220,15 @@ test "basic slices" {
22072220 {#code_end#}
22082221 <p>This is one reason we prefer slices to pointers.</p>
22092222 {#code_begin|test|slices#}
2210const assert = @import("std").debug.assert;
2211const mem = @import("std").mem;
2212const fmt = @import("std").fmt;
2223const std = @import("std");
2224const assert = std.debug.assert;
2225const mem = std.mem;
2226const fmt = std.fmt;
22132227
22142228test "using slices for strings" {
2215 // Zig has no concept of strings. String literals are arrays of u8, and
2216 // in general the string type is []u8 (slice of u8).
2229 // Zig has no concept of strings. String literals are const pointers to
2230 // arrays of u8, and by convention parameters that are "strings" are
2231 // expected to be UTF-8 encoded slices of u8.
22172232 // Here we coerce [5]u8 to []const u8
22182233 const hello: []const u8 = "hello";
22192234 const world: []const u8 = "世界";
......@@ -2222,7 +2237,7 @@ test "using slices for strings" {
22222237 // You can use slice syntax on an array to convert an array into a slice.
22232238 const all_together_slice = all_together[0..];
22242239 // String concatenation example.
2225 const hello_world = try fmt.bufPrint(all_together_slice, "{} {}", .{hello, world});
2240 const hello_world = try fmt.bufPrint(all_together_slice, "{} {}", .{ hello, world });
22262241
22272242 // Generally, you can use UTF-8 and not worry about whether something is a
22282243 // string. If you don't need to deal with individual characters, no need
......@@ -2239,23 +2254,15 @@ test "slice pointer" {
22392254 slice[2] = 3;
22402255 assert(slice[2] == 3);
22412256 // The slice is mutable because we sliced a mutable pointer.
2242 assert(@TypeOf(slice) == []u8);
2257 // Furthermore, it is actually a pointer to an array, since the start
2258 // and end indexes were both comptime-known.
2259 assert(@TypeOf(slice) == *[5]u8);
22432260
22442261 // You can also slice a slice:
22452262 const slice2 = slice[2..3];
22462263 assert(slice2.len == 1);
22472264 assert(slice2[0] == 3);
22482265}
2249
2250test "slice widening" {
2251 // Zig supports slice widening and slice narrowing. Cast a slice of u8
2252 // to a slice of anything else, and Zig will perform the length conversion.
2253 const array align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 };
2254 const slice = mem.bytesAsSlice(u32, array[0..]);
2255 assert(slice.len == 2);
2256 assert(slice[0] == 0x12121212);
2257 assert(slice[1] == 0x13131313);
2258}
22592266 {#code_end#}
22602267 {#see_also|Pointers|for|Arrays#}
22612268
lib/libc/glibc/abi.txt+135
......@@ -193,6 +193,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
193193
194194
19519529
196
19619729
197198
19819929
......@@ -514,6 +515,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
51451529
51551629
51651729
51829
517519
51852029
519521
......@@ -697,6 +699,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
69769929
69870029
69970129
702
70070329
70170429
70270529
......@@ -819,6 +822,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
81982229
82082329
82182429
82529
822826
82382729
82482829
......@@ -904,6 +908,9 @@ aarch64-linux-gnu aarch64_be-linux-gnu
90490829
90590929
90691029
91129
912
913
90791429
90891529
90991629
......@@ -1004,6 +1011,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
1004101129
1005101229
1006101329
101429
10071015
1008101629
1009101729
......@@ -1033,6 +1041,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
1033104129
1034104229
1035104329
104429
10361045
1037104629
1038104729
......@@ -3920,6 +3929,7 @@ s390x-linux-gnu
39203929
39213930
392239315
3932
3923393327
39243934
3925393527
......@@ -4241,6 +4251,7 @@ s390x-linux-gnu
424142515
424242525
424342535
42545
4244425511
4245425627
42464257
......@@ -4424,6 +4435,7 @@ s390x-linux-gnu
4424443519
4425443619
442644375
4438
442744395
442844405
4429444128
......@@ -4543,6 +4555,7 @@ s390x-linux-gnu
4543455527
45444556
4545455716
4558
454645595
454745605
4548456115
......@@ -4631,6 +4644,9 @@ s390x-linux-gnu
4631464416
463246455
463346465
4647
4648
464912
463446505
463546515
463646525
......@@ -4731,6 +4747,7 @@ s390x-linux-gnu
473147475
473247485
473347495
47505
47344751
473547525
473647535
......@@ -4756,6 +4773,7 @@ s390x-linux-gnu
475647735
475747745
475847755
47765
4759477731 5
4760477824 5 12 16
4761477924 5 12 16
......@@ -7645,6 +7663,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
76457663
76467664
76477665
7666
76487667
76497668
7650766927
......@@ -7968,6 +7987,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
7968798716
7969798816
7970798916
799016
79717991
7972799227
79737993
......@@ -8151,6 +8171,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
8151817119
8152817219
8153817316
8174
8154817516
8155817616
8156817728
......@@ -8273,6 +8294,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
8273829416
8274829516
8275829616
829716
82768298
8277829916
8278830016
......@@ -8358,6 +8380,9 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
8358838016
8359838116
8360838216
838316
8384
8385
8361838616
8362838716
8363838816
......@@ -8458,6 +8483,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
8458848316
8459848416
8460848516
848616
84618487
8462848816
8463848916
......@@ -8484,6 +8510,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
8484851016
8485851116
8486851216
851316
8487851424 16
8488851524 16
8489851616
......@@ -11374,6 +11401,7 @@ sparc-linux-gnu sparcel-linux-gnu
1137411401
1137511402
11376114030
11404
113771140527
1137811406
113791140727
......@@ -11693,6 +11721,7 @@ sparc-linux-gnu sparcel-linux-gnu
11693117210
11694117220
11695117231
117241
11696117250
11697117260
11698117273 11
......@@ -11878,6 +11907,7 @@ sparc-linux-gnu sparcel-linux-gnu
118781190719
118791190819
11880119090
11910
11881119110
11882119121
118831191328
......@@ -11997,6 +12027,7 @@ sparc-linux-gnu sparcel-linux-gnu
119971202733
1199812028
119991202916
12030
12000120315
12001120320
120021203315
......@@ -12085,6 +12116,9 @@ sparc-linux-gnu sparcel-linux-gnu
120851211616
12086121170
12087121180
1211912
12120
12121
12088121221
12089121231
12090121241
......@@ -12183,6 +12217,7 @@ sparc-linux-gnu sparcel-linux-gnu
12183122171
12184122181
12185122191
122201
12186122210
12187122220
1218812223
......@@ -12207,6 +12242,7 @@ sparc-linux-gnu sparcel-linux-gnu
12207122420
12208122430
12209122440
122450
12210122465
12211122470
12212122480
......@@ -15101,6 +15137,7 @@ sparcv9-linux-gnu
15101151375
15102151385
1510315139
15140
151041514127
1510515142
151061514327
......@@ -15422,6 +15459,7 @@ sparcv9-linux-gnu
15422154595
15423154605
15424154615
154625
154251546311
154261546427
1542715465
......@@ -15605,6 +15643,7 @@ sparcv9-linux-gnu
156051564319
156061564419
15607156455
15646
15608156475
15609156485
156101564928
......@@ -15724,6 +15763,7 @@ sparcv9-linux-gnu
157241576327
1572515764
157261576516
15766
15727157675
15728157685
157291576915
......@@ -15812,6 +15852,9 @@ sparcv9-linux-gnu
158121585216
15813158535
15814158545
1585512
15856
15857
15815158585
15816158595
15817158605
......@@ -15912,6 +15955,7 @@ sparcv9-linux-gnu
15912159555
15913159565
15914159575
159585
1591515959
15916159605
15917159615
......@@ -15938,6 +15982,7 @@ sparcv9-linux-gnu
15938159825
15939159835
15940159845
159855
159411598624 28 5 12 16
159421598724 28 5 12 16
15943159885 14
......@@ -18828,6 +18873,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
1882818873
1882918874
18830188750
18876
188311887727
1883218878
188331887927
......@@ -19147,6 +19193,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
19147191930
19148191940
19149191955
191965
19150191970
19151191980
191521919911
......@@ -19332,6 +19379,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
193321937919
193331938019
19334193810
19382
19335193830
19336193845
193371938528
......@@ -19450,6 +19498,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
194501949827
194511949927
1945219500
1950116
194531950216
19454195035
19455195040
......@@ -19539,6 +19588,9 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
195391958816
19540195890
19541195900
1959112
19592
19593
19542195945
19543195955
19544195965
......@@ -19637,6 +19689,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
19637196895
19638196905
19639196915
196925
19640196930
19641196940
19642196950
......@@ -19661,6 +19714,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
19661197140
19662197150
19663197160
197170
19664197185
19665197190
19666197200
......@@ -22555,6 +22609,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
2255522609
2255622610
22557226110
22612
225582261327
2255922614
225602261527
......@@ -22874,6 +22929,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
22874229290
22875229300
22876229315
229325
22877229330
22878229340
228792293511
......@@ -23059,6 +23115,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
230592311519
230602311619
23061231170
23118
23062231190
23063231205
230642312128
......@@ -23177,6 +23234,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
231772323427
231782323527
2317923236
2323716
231802323816
23181232395
23182232400
......@@ -23266,6 +23324,9 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
232662332416
23267233250
23268233260
2332712
23328
23329
23269233305
23270233315
23271233325
......@@ -23364,6 +23425,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
23364234255
23365234265
23366234275
234285
23367234290
23368234300
23369234310
......@@ -23388,6 +23450,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
23388234500
23389234510
23390234520
234530
23391234545
23392234550
23393234560
......@@ -26282,6 +26345,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
2628226345
2628326346
26284263470
26348
262852634927
2628626350
262872635127
......@@ -26601,6 +26665,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
26601266650
26602266660
26603266675
266685
26604266690
26605266700
266062667111
......@@ -26786,6 +26851,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
267862685119
267872685219
26788268530
26854
26789268550
26790268565
267912685728
......@@ -26904,6 +26970,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
269042697027
2690526971
2690626972
2697316
269072697416
26908269755
26909269760
......@@ -26993,6 +27060,9 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
269932706016
26994270610
26995270620
2706312
27064
27065
26996270665
26997270675
26998270685
......@@ -27091,6 +27161,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
27091271615
27092271625
27093271635
271645
27094271650
27095271660
27096271670
......@@ -27115,6 +27186,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
27115271860
27116271870
27117271880
271890
27118271905
27119271910
27120271920
......@@ -30009,6 +30081,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
3000930081
3001030082
30011300830
30084
300123008527
3001330086
300143008727
......@@ -30328,6 +30401,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
30328304010
30329304020
30330304035
304045
30331304050
30332304060
303333040711
......@@ -30513,6 +30587,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
305133058719
305143058819
30515305890
30590
30516305910
30517305925
305183059328
......@@ -30631,6 +30706,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
306313070627
3063230707
3063330708
3070916
306343071016
30635307115
30636307120
......@@ -30720,6 +30796,9 @@ mipsel-linux-gnueabi mips-linux-gnueabi
307203079616
30721307970
30722307980
3079912
30800
30801
30723308025
30724308035
30725308045
......@@ -30818,6 +30897,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
30818308975
30819308985
30820308995
309005
30821309010
30822309020
30823309030
......@@ -30842,6 +30922,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
30842309220
30843309230
30844309240
309250
30845309265
30846309270
30847309280
......@@ -33734,6 +33815,7 @@ x86_64-linux-gnu
3373433815
3373533816
3373633817
33818
3373733819
3373833820
337393382127
......@@ -34057,6 +34139,7 @@ x86_64-linux-gnu
340573413910
340583414010
340593414110
3414210
340603414311
340613414427
340623414536
......@@ -34240,6 +34323,7 @@ x86_64-linux-gnu
342403432319
342413432419
342423432510
34326
342433432710
342443432810
342453432928
......@@ -34359,6 +34443,7 @@ x86_64-linux-gnu
343593444327
3436034444
343613444516
34446
343623444710
343633444810
343643444915
......@@ -34447,6 +34532,9 @@ x86_64-linux-gnu
344473453216
344483453310
344493453410
3453512
34536
34537
344503453810
344513453910
344523454010
......@@ -34547,6 +34635,7 @@ x86_64-linux-gnu
345473463510
345483463610
345493463710
3463810
3455034639
345513464010
345523464110
......@@ -34573,6 +34662,7 @@ x86_64-linux-gnu
345733466210
345743466310
345753466410
3466510
345763466624 10 12 16
345773466724 10 12 16
345783466810 14
......@@ -37461,6 +37551,7 @@ x86_64-linux-gnux32
3746137551
3746237552
3746337553
37554
3746437555
3746537556
374663755728
......@@ -37784,6 +37875,7 @@ x86_64-linux-gnux32
377843787528
377853787628
377863787728
3787828
3778737879
377883788028
377893788136
......@@ -37967,6 +38059,7 @@ x86_64-linux-gnux32
379673805928
379683806028
379693806128
38062
379703806328
379713806428
379723806528
......@@ -38086,6 +38179,7 @@ x86_64-linux-gnux32
380863817928
3808738180
380883818128
38182
380893818328
380903818428
380913818528
......@@ -38174,6 +38268,9 @@ x86_64-linux-gnux32
381743826828
381753826928
381763827028
3827128
38272
38273
381773827428
381783827528
381793827628
......@@ -38274,6 +38371,7 @@ x86_64-linux-gnux32
382743837128
382753837228
382763837328
3837428
3827738375
382783837628
382793837728
......@@ -38303,6 +38401,7 @@ x86_64-linux-gnux32
383033840128
383043840228
383053840328
3840428
3830638405
383073840628
383083840728
......@@ -41190,6 +41289,7 @@ i386-linux-gnu
4119041289
4119141290
41192412910
4129212
411934129327
411944129436
411954129527
......@@ -41509,6 +41609,7 @@ i386-linux-gnu
41509416090
41510416100
41511416111
416121
41512416130
41513416140
41514416153 11
......@@ -41694,6 +41795,7 @@ i386-linux-gnu
416944179519
416954179619
41696417970
41798
41697417990
41698418001
416994180128
......@@ -41813,6 +41915,7 @@ i386-linux-gnu
418134191527
4181441916
418154191716
41918
41816419195
41817419200
418184192115
......@@ -41901,6 +42004,9 @@ i386-linux-gnu
419014200416
41902420050
41903420060
4200712
42008
42009
41904420101
41905420111
41906420121
......@@ -41999,6 +42105,7 @@ i386-linux-gnu
41999421051
42000421061
42001421071
421081
42002421090
42003421100
4200442111
......@@ -42023,6 +42130,7 @@ i386-linux-gnu
42023421300
42024421310
42025421320
421330
42026421345
42027421350
42028421360
......@@ -44915,6 +45023,7 @@ powerpc64le-linux-gnu
4491545023
4491645024
4491745025
45026
4491845027
4491945028
449204502929
......@@ -45238,6 +45347,7 @@ powerpc64le-linux-gnu
452384534729
452394534829
452404534929
4535029
4524145351
452424535229
452434535336
......@@ -45421,6 +45531,7 @@ powerpc64le-linux-gnu
454214553129
454224553229
454234553329
4553433
454244553529
454254553629
454264553729
......@@ -45540,6 +45651,7 @@ powerpc64le-linux-gnu
455404565129
4554145652
455424565329
45654
455434565529
455444565629
455454565729
......@@ -45628,6 +45740,9 @@ powerpc64le-linux-gnu
456284574029
456294574129
456304574229
4574329
4574432
45745
456314574629
456324574729
456334574829
......@@ -45728,6 +45843,7 @@ powerpc64le-linux-gnu
457284584329
457294584429
457304584529
4584629
4573145847
457324584829
457334584929
......@@ -45757,6 +45873,7 @@ powerpc64le-linux-gnu
457574587329
457584587429
457594587529
4587629
4576045877
457614587829
457624587929
......@@ -48642,6 +48759,7 @@ powerpc64-linux-gnu
4864248759
4864348760
4864448761
48762
4864548763
4864648764
486474876527
......@@ -48965,6 +49083,7 @@ powerpc64-linux-gnu
489654908312
489664908412
489674908512
4908612
4896849087
489694908827
4897049089
......@@ -49148,6 +49267,7 @@ powerpc64-linux-gnu
491484926719
491494926819
491504926912
4927033
491514927112
491524927212
491534927328
......@@ -49267,6 +49387,7 @@ powerpc64-linux-gnu
492674938727
4926849388
492694938916
49390
492704939112
492714939212
492724939315
......@@ -49355,6 +49476,9 @@ powerpc64-linux-gnu
493554947616
493564947712
493574947812
4947912
4948032
49481
493584948212
493594948312
493604948412
......@@ -49455,6 +49579,7 @@ powerpc64-linux-gnu
494554957912
494564958012
494574958112
4958212
4945849583
494594958412
494604958512
......@@ -49480,6 +49605,7 @@ powerpc64-linux-gnu
494804960512
494814960612
494824960712
4960812
494834960912 15
494844961024 12 16
494854961124 12 16
......@@ -52369,6 +52495,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
5236952495
5237052496
5237152497
52498
5237252499
5237352500
523745250127
......@@ -52690,6 +52817,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
52690528170
52691528180
52692528191
528201
52693528210
52694528220
52695528233 11
......@@ -52875,6 +53003,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
528755300319
528765300419
52877530050
5300633
52878530070
52879530081
528805300928
......@@ -52994,6 +53123,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
529945312327
529955312413
529965312516
53126
52997531275
52998531280
529995312915
......@@ -53082,6 +53212,9 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
530825321216
53083532130
53084532140
5321512
5321632
53217
53085532181
53086532191
53087532201
......@@ -53180,6 +53313,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
53180533131
53181533141
53182533151
533161
53183533170
53184533180
5318553319
......@@ -53204,6 +53338,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
53204533380
53205533390
53206533400
533410
53207533425
53208533430
53209533440
lib/libc/glibc/fns.txt+9
......@@ -192,6 +192,7 @@ _Qp_uitoq c
192192_Qp_uxtoq c
193193_Qp_xtoq c
194194___brk_addr c
195___tls_get_addr ld
195196__acos_finite m
196197__acosf128_finite m
197198__acosf_finite m
......@@ -511,6 +512,7 @@ __libc_memalign c
511512__libc_pvalloc c
512513__libc_realloc c
513514__libc_sa_len c
515__libc_stack_end ld
514516__libc_start_main c
515517__libc_valloc c
516518__libpthread_version_placeholder pthread
......@@ -696,6 +698,7 @@ __open_2 c
696698__openat64_2 c
697699__openat_2 c
698700__overflow c
701__parse_hwcap_and_convert_at_platform ld
699702__pipe c
700703__poll c
701704__poll_chk c
......@@ -815,6 +818,7 @@ __sqrtf_finite m
815818__sqrtl_finite m
816819__sqrtsf2 c
817820__stack_chk_fail c
821__stack_chk_guard ld
818822__statfs c
819823__stpcpy c
820824__stpcpy_chk c
......@@ -903,6 +907,9 @@ __sysctl c
903907__syslog_chk c
904908__sysv_signal c
905909__timezone c
910__tls_get_addr ld
911__tls_get_addr_opt ld
912__tls_get_offset ld
906913__toascii_l c
907914__tolower_l c
908915__toupper_l c
......@@ -999,6 +1006,7 @@ __ynf128_finite m
9991006__ynf_finite m
10001007__ynl_finite m
10011008_authenticate c
1009_dl_mcount ld
10021010_dl_mcount_wrapper c
10031011_dl_mcount_wrapper_check c
10041012_environ c
......@@ -1024,6 +1032,7 @@ _pthread_cleanup_pop pthread
10241032_pthread_cleanup_pop_restore pthread
10251033_pthread_cleanup_push pthread
10261034_pthread_cleanup_push_defer pthread
1035_r_debug ld
10271036_res c
10281037_res_hconf c
10291038_rpc_dtablesize c
lib/std/build.zig+35-23
......@@ -377,7 +377,7 @@ pub const Builder = struct {
377377 if (self.verbose) {
378378 warn("rm {}\n", .{full_path});
379379 }
380 fs.deleteTree(full_path) catch {};
380 fs.cwd().deleteTree(full_path) catch {};
381381 }
382382
383383 // TODO remove empty directories
......@@ -847,7 +847,8 @@ pub const Builder = struct {
847847 if (self.verbose) {
848848 warn("cp {} {} ", .{ source_path, dest_path });
849849 }
850 const prev_status = try fs.updateFile(source_path, dest_path);
850 const cwd = fs.cwd();
851 const prev_status = try fs.Dir.updateFile(cwd, source_path, cwd, dest_path, .{});
851852 if (self.verbose) switch (prev_status) {
852853 .stale => warn("# installed\n", .{}),
853854 .fresh => warn("# up-to-date\n", .{}),
......@@ -1120,7 +1121,7 @@ pub const LibExeObjStep = struct {
11201121 emit_llvm_ir: bool = false,
11211122 emit_asm: bool = false,
11221123 emit_bin: bool = true,
1123 disable_gen_h: bool,
1124 emit_h: bool = false,
11241125 bundle_compiler_rt: bool,
11251126 disable_stack_probing: bool,
11261127 disable_sanitize_c: bool,
......@@ -1157,8 +1158,14 @@ pub const LibExeObjStep = struct {
11571158
11581159 valgrind_support: ?bool = null,
11591160
1161 /// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF
1162 /// file.
11601163 link_eh_frame_hdr: bool = false,
11611164
1165 /// Place every function in its own section so that unused ones may be
1166 /// safely garbage-collected during the linking phase.
1167 link_function_sections: bool = false,
1168
11621169 /// Uses system Wine installation to run cross compiled Windows build artifacts.
11631170 enable_wine: bool = false,
11641171
......@@ -1274,7 +1281,6 @@ pub const LibExeObjStep = struct {
12741281 .exec_cmd_args = null,
12751282 .name_prefix = "",
12761283 .filter = null,
1277 .disable_gen_h = false,
12781284 .bundle_compiler_rt = false,
12791285 .disable_stack_probing = false,
12801286 .disable_sanitize_c = false,
......@@ -1593,8 +1599,9 @@ pub const LibExeObjStep = struct {
15931599 self.main_pkg_path = dir_path;
15941600 }
15951601
1596 pub fn setDisableGenH(self: *LibExeObjStep, value: bool) void {
1597 self.disable_gen_h = value;
1602 /// Deprecated; just set the field directly.
1603 pub fn setDisableGenH(self: *LibExeObjStep, is_disabled: bool) void {
1604 self.emit_h = !is_disabled;
15981605 }
15991606
16001607 pub fn setLibCFile(self: *LibExeObjStep, libc_file: ?[]const u8) void {
......@@ -1625,7 +1632,7 @@ pub const LibExeObjStep = struct {
16251632 /// the make step, from a step that has declared a dependency on this one.
16261633 pub fn getOutputHPath(self: *LibExeObjStep) []const u8 {
16271634 assert(self.kind != Kind.Exe);
1628 assert(!self.disable_gen_h);
1635 assert(self.emit_h);
16291636 return fs.path.join(
16301637 self.builder.allocator,
16311638 &[_][]const u8{ self.output_dir.?, self.out_h_filename },
......@@ -1672,7 +1679,7 @@ pub const LibExeObjStep = struct {
16721679 }
16731680
16741681 pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void {
1675 const out = &std.io.BufferOutStream.init(&self.build_options_contents).stream;
1682 const out = self.build_options_contents.outStream();
16761683 out.print("pub const {} = {};\n", .{ name, value }) catch unreachable;
16771684 }
16781685
......@@ -1877,6 +1884,7 @@ pub const LibExeObjStep = struct {
18771884 if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir");
18781885 if (self.emit_asm) try zig_args.append("-femit-asm");
18791886 if (!self.emit_bin) try zig_args.append("-fno-emit-bin");
1887 if (self.emit_h) try zig_args.append("-femit-h");
18801888
18811889 if (self.strip) {
18821890 try zig_args.append("--strip");
......@@ -1884,7 +1892,9 @@ pub const LibExeObjStep = struct {
18841892 if (self.link_eh_frame_hdr) {
18851893 try zig_args.append("--eh-frame-hdr");
18861894 }
1887
1895 if (self.link_function_sections) {
1896 try zig_args.append("-ffunction-sections");
1897 }
18881898 if (self.single_threaded) {
18891899 try zig_args.append("--single-threaded");
18901900 }
......@@ -1920,9 +1930,6 @@ pub const LibExeObjStep = struct {
19201930 if (self.is_dynamic) {
19211931 try zig_args.append("-dynamic");
19221932 }
1923 if (self.disable_gen_h) {
1924 try zig_args.append("--disable-gen-h");
1925 }
19261933 if (self.bundle_compiler_rt) {
19271934 try zig_args.append("--bundle-compiler-rt");
19281935 }
......@@ -2060,7 +2067,7 @@ pub const LibExeObjStep = struct {
20602067 try zig_args.append("-isystem");
20612068 try zig_args.append(self.builder.pathFromRoot(include_path));
20622069 },
2063 .OtherStep => |other| if (!other.disable_gen_h) {
2070 .OtherStep => |other| if (other.emit_h) {
20642071 const h_path = other.getOutputHPath();
20652072 try zig_args.append("-isystem");
20662073 try zig_args.append(fs.path.dirname(h_path).?);
......@@ -2144,17 +2151,22 @@ pub const LibExeObjStep = struct {
21442151 try zig_args.append("--cache");
21452152 try zig_args.append("on");
21462153
2147 const output_path_nl = try builder.execFromStep(zig_args.toSliceConst(), &self.step);
2148 const output_path = mem.trimRight(u8, output_path_nl, "\r\n");
2154 const output_dir_nl = try builder.execFromStep(zig_args.toSliceConst(), &self.step);
2155 const build_output_dir = mem.trimRight(u8, output_dir_nl, "\r\n");
21492156
21502157 if (self.output_dir) |output_dir| {
2151 const full_dest = try fs.path.join(builder.allocator, &[_][]const u8{
2152 output_dir,
2153 fs.path.basename(output_path),
2154 });
2155 try builder.updateFile(output_path, full_dest);
2158 var src_dir = try std.fs.cwd().openDir(build_output_dir, .{ .iterate = true });
2159 defer src_dir.close();
2160
2161 var dest_dir = try std.fs.cwd().openDir(output_dir, .{});
2162 defer dest_dir.close();
2163
2164 var it = src_dir.iterate();
2165 while (try it.next()) |entry| {
2166 _ = try src_dir.updateFile(entry.name, dest_dir, entry.name, .{});
2167 }
21562168 } else {
2157 self.output_dir = fs.path.dirname(output_path).?;
2169 self.output_dir = build_output_dir;
21582170 }
21592171 }
21602172
......@@ -2195,7 +2207,7 @@ const InstallArtifactStep = struct {
21952207 break :blk InstallDir.Lib;
21962208 }
21972209 } else null,
2198 .h_dir = if (artifact.kind == .Lib and !artifact.disable_gen_h) .Header else null,
2210 .h_dir = if (artifact.kind == .Lib and artifact.emit_h) .Header else null,
21992211 };
22002212 self.step.dependOn(&artifact.step);
22012213 artifact.install_step = self;
......@@ -2352,7 +2364,7 @@ pub const RemoveDirStep = struct {
23522364 const self = @fieldParentPtr(RemoveDirStep, "step", step);
23532365
23542366 const full_path = self.builder.pathFromRoot(self.dir_path);
2355 fs.deleteTree(full_path) catch |err| {
2367 fs.cwd().deleteTree(full_path) catch |err| {
23562368 warn("Unable to remove {}: {}\n", .{ full_path, @errorName(err) });
23572369 return err;
23582370 };
lib/std/build/run.zig+3-1
......@@ -29,6 +29,8 @@ pub const RunStep = struct {
2929 stdout_action: StdIoAction = .inherit,
3030 stderr_action: StdIoAction = .inherit,
3131
32 stdin_behavior: std.ChildProcess.StdIo = .Inherit,
33
3234 expected_exit_code: u8 = 0,
3335
3436 pub const StdIoAction = union(enum) {
......@@ -159,7 +161,7 @@ pub const RunStep = struct {
159161 child.cwd = cwd;
160162 child.env_map = self.env_map orelse self.builder.env_map;
161163
162 child.stdin_behavior = .Ignore;
164 child.stdin_behavior = self.stdin_behavior;
163165 child.stdout_behavior = stdIoActionToBehavior(self.stdout_action);
164166 child.stderr_behavior = stdIoActionToBehavior(self.stderr_action);
165167
lib/std/build/write_file.zig+1-1
......@@ -78,7 +78,7 @@ pub const WriteFileStep = struct {
7878 warn("unable to make path {}: {}\n", .{ self.output_dir, @errorName(err) });
7979 return err;
8080 };
81 var dir = try fs.cwd().openDirTraverse(self.output_dir);
81 var dir = try fs.cwd().openDir(self.output_dir, .{});
8282 defer dir.close();
8383 for (self.files.toSliceConst()) |file| {
8484 dir.writeFile(file.basename, file.bytes) catch |err| {
lib/std/c.zig+1
......@@ -106,6 +106,7 @@ pub extern "c" fn mkdir(path: [*:0]const u8, mode: c_uint) c_int;
106106pub extern "c" fn mkdirat(dirfd: fd_t, path: [*:0]const u8, mode: u32) c_int;
107107pub extern "c" fn symlink(existing: [*:0]const u8, new: [*:0]const u8) c_int;
108108pub extern "c" fn rename(old: [*:0]const u8, new: [*:0]const u8) c_int;
109pub extern "c" fn renameat(olddirfd: fd_t, old: [*:0]const u8, newdirfd: fd_t, new: [*:0]const u8) c_int;
109110pub extern "c" fn chdir(path: [*:0]const u8) c_int;
110111pub extern "c" fn fchdir(fd: fd_t) c_int;
111112pub extern "c" fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) c_int;
lib/std/crypto/aes.zig+19-19
......@@ -15,10 +15,10 @@ fn rotw(w: u32) u32 {
1515
1616// Encrypt one block from src into dst, using the expanded key xk.
1717fn encryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {
18 var s0 = mem.readIntSliceBig(u32, src[0..4]);
19 var s1 = mem.readIntSliceBig(u32, src[4..8]);
20 var s2 = mem.readIntSliceBig(u32, src[8..12]);
21 var s3 = mem.readIntSliceBig(u32, src[12..16]);
18 var s0 = mem.readIntBig(u32, src[0..4]);
19 var s1 = mem.readIntBig(u32, src[4..8]);
20 var s2 = mem.readIntBig(u32, src[8..12]);
21 var s3 = mem.readIntBig(u32, src[12..16]);
2222
2323 // First round just XORs input with key.
2424 s0 ^= xk[0];
......@@ -58,18 +58,18 @@ fn encryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {
5858 s2 ^= xk[k + 2];
5959 s3 ^= xk[k + 3];
6060
61 mem.writeIntSliceBig(u32, dst[0..4], s0);
62 mem.writeIntSliceBig(u32, dst[4..8], s1);
63 mem.writeIntSliceBig(u32, dst[8..12], s2);
64 mem.writeIntSliceBig(u32, dst[12..16], s3);
61 mem.writeIntBig(u32, dst[0..4], s0);
62 mem.writeIntBig(u32, dst[4..8], s1);
63 mem.writeIntBig(u32, dst[8..12], s2);
64 mem.writeIntBig(u32, dst[12..16], s3);
6565}
6666
6767// Decrypt one block from src into dst, using the expanded key xk.
6868pub fn decryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {
69 var s0 = mem.readIntSliceBig(u32, src[0..4]);
70 var s1 = mem.readIntSliceBig(u32, src[4..8]);
71 var s2 = mem.readIntSliceBig(u32, src[8..12]);
72 var s3 = mem.readIntSliceBig(u32, src[12..16]);
69 var s0 = mem.readIntBig(u32, src[0..4]);
70 var s1 = mem.readIntBig(u32, src[4..8]);
71 var s2 = mem.readIntBig(u32, src[8..12]);
72 var s3 = mem.readIntBig(u32, src[12..16]);
7373
7474 // First round just XORs input with key.
7575 s0 ^= xk[0];
......@@ -109,10 +109,10 @@ pub fn decryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {
109109 s2 ^= xk[k + 2];
110110 s3 ^= xk[k + 3];
111111
112 mem.writeIntSliceBig(u32, dst[0..4], s0);
113 mem.writeIntSliceBig(u32, dst[4..8], s1);
114 mem.writeIntSliceBig(u32, dst[8..12], s2);
115 mem.writeIntSliceBig(u32, dst[12..16], s3);
112 mem.writeIntBig(u32, dst[0..4], s0);
113 mem.writeIntBig(u32, dst[4..8], s1);
114 mem.writeIntBig(u32, dst[8..12], s2);
115 mem.writeIntBig(u32, dst[12..16], s3);
116116}
117117
118118fn xorBytes(dst: []u8, a: []const u8, b: []const u8) usize {
......@@ -154,8 +154,8 @@ fn AES(comptime keysize: usize) type {
154154 var n: usize = 0;
155155 while (n < src.len) {
156156 ctx.encrypt(keystream[0..], ctrbuf[0..]);
157 var ctr_i = std.mem.readIntSliceBig(u128, ctrbuf[0..]);
158 std.mem.writeIntSliceBig(u128, ctrbuf[0..], ctr_i +% 1);
157 var ctr_i = std.mem.readIntBig(u128, ctrbuf[0..]);
158 std.mem.writeIntBig(u128, ctrbuf[0..], ctr_i +% 1);
159159
160160 n += xorBytes(dst[n..], src[n..], &keystream);
161161 }
......@@ -251,7 +251,7 @@ fn expandKey(key: []const u8, enc: []u32, dec: []u32) void {
251251 var i: usize = 0;
252252 var nk = key.len / 4;
253253 while (i < nk) : (i += 1) {
254 enc[i] = mem.readIntSliceBig(u32, key[4 * i .. 4 * i + 4]);
254 enc[i] = mem.readIntBig(u32, key[4 * i ..][0..4]);
255255 }
256256 while (i < enc.len) : (i += 1) {
257257 var t = enc[i - 1];
lib/std/crypto/blake2.zig+4-7
......@@ -123,8 +123,7 @@ fn Blake2s(comptime out_len: usize) type {
123123 const rr = d.h[0 .. out_len / 32];
124124
125125 for (rr) |s, j| {
126 // TODO https://github.com/ziglang/zig/issues/863
127 mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
126 mem.writeIntLittle(u32, out[4 * j ..][0..4], s);
128127 }
129128 }
130129
......@@ -135,8 +134,7 @@ fn Blake2s(comptime out_len: usize) type {
135134 var v: [16]u32 = undefined;
136135
137136 for (m) |*r, i| {
138 // TODO https://github.com/ziglang/zig/issues/863
139 r.* = mem.readIntSliceLittle(u32, b[4 * i .. 4 * i + 4]);
137 r.* = mem.readIntLittle(u32, b[4 * i ..][0..4]);
140138 }
141139
142140 var k: usize = 0;
......@@ -358,8 +356,7 @@ fn Blake2b(comptime out_len: usize) type {
358356 const rr = d.h[0 .. out_len / 64];
359357
360358 for (rr) |s, j| {
361 // TODO https://github.com/ziglang/zig/issues/863
362 mem.writeIntSliceLittle(u64, out[8 * j .. 8 * j + 8], s);
359 mem.writeIntLittle(u64, out[8 * j ..][0..8], s);
363360 }
364361 }
365362
......@@ -370,7 +367,7 @@ fn Blake2b(comptime out_len: usize) type {
370367 var v: [16]u64 = undefined;
371368
372369 for (m) |*r, i| {
373 r.* = mem.readIntSliceLittle(u64, b[8 * i .. 8 * i + 8]);
370 r.* = mem.readIntLittle(u64, b[8 * i ..][0..8]);
374371 }
375372
376373 var k: usize = 0;
lib/std/crypto/chacha20.zig+30-31
......@@ -61,8 +61,7 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
6161 }
6262
6363 for (x) |_, i| {
64 // TODO https://github.com/ziglang/zig/issues/863
65 mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]);
64 mem.writeIntLittle(u32, out[4 * i ..][0..4], x[i] +% input[i]);
6665 }
6766}
6867
......@@ -73,10 +72,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
7372
7473 const c = "expand 32-byte k";
7574 const constant_le = [_]u32{
76 mem.readIntSliceLittle(u32, c[0..4]),
77 mem.readIntSliceLittle(u32, c[4..8]),
78 mem.readIntSliceLittle(u32, c[8..12]),
79 mem.readIntSliceLittle(u32, c[12..16]),
75 mem.readIntLittle(u32, c[0..4]),
76 mem.readIntLittle(u32, c[4..8]),
77 mem.readIntLittle(u32, c[8..12]),
78 mem.readIntLittle(u32, c[12..16]),
8079 };
8180
8281 mem.copy(u32, ctx[0..], constant_le[0..4]);
......@@ -120,19 +119,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce:
120119 var k: [8]u32 = undefined;
121120 var c: [4]u32 = undefined;
122121
123 k[0] = mem.readIntSliceLittle(u32, key[0..4]);
124 k[1] = mem.readIntSliceLittle(u32, key[4..8]);
125 k[2] = mem.readIntSliceLittle(u32, key[8..12]);
126 k[3] = mem.readIntSliceLittle(u32, key[12..16]);
127 k[4] = mem.readIntSliceLittle(u32, key[16..20]);
128 k[5] = mem.readIntSliceLittle(u32, key[20..24]);
129 k[6] = mem.readIntSliceLittle(u32, key[24..28]);
130 k[7] = mem.readIntSliceLittle(u32, key[28..32]);
122 k[0] = mem.readIntLittle(u32, key[0..4]);
123 k[1] = mem.readIntLittle(u32, key[4..8]);
124 k[2] = mem.readIntLittle(u32, key[8..12]);
125 k[3] = mem.readIntLittle(u32, key[12..16]);
126 k[4] = mem.readIntLittle(u32, key[16..20]);
127 k[5] = mem.readIntLittle(u32, key[20..24]);
128 k[6] = mem.readIntLittle(u32, key[24..28]);
129 k[7] = mem.readIntLittle(u32, key[28..32]);
131130
132131 c[0] = counter;
133 c[1] = mem.readIntSliceLittle(u32, nonce[0..4]);
134 c[2] = mem.readIntSliceLittle(u32, nonce[4..8]);
135 c[3] = mem.readIntSliceLittle(u32, nonce[8..12]);
132 c[1] = mem.readIntLittle(u32, nonce[0..4]);
133 c[2] = mem.readIntLittle(u32, nonce[4..8]);
134 c[3] = mem.readIntLittle(u32, nonce[8..12]);
136135 chaCha20_internal(out, in, k, c);
137136}
138137
......@@ -147,19 +146,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
147146 var k: [8]u32 = undefined;
148147 var c: [4]u32 = undefined;
149148
150 k[0] = mem.readIntSliceLittle(u32, key[0..4]);
151 k[1] = mem.readIntSliceLittle(u32, key[4..8]);
152 k[2] = mem.readIntSliceLittle(u32, key[8..12]);
153 k[3] = mem.readIntSliceLittle(u32, key[12..16]);
154 k[4] = mem.readIntSliceLittle(u32, key[16..20]);
155 k[5] = mem.readIntSliceLittle(u32, key[20..24]);
156 k[6] = mem.readIntSliceLittle(u32, key[24..28]);
157 k[7] = mem.readIntSliceLittle(u32, key[28..32]);
149 k[0] = mem.readIntLittle(u32, key[0..4]);
150 k[1] = mem.readIntLittle(u32, key[4..8]);
151 k[2] = mem.readIntLittle(u32, key[8..12]);
152 k[3] = mem.readIntLittle(u32, key[12..16]);
153 k[4] = mem.readIntLittle(u32, key[16..20]);
154 k[5] = mem.readIntLittle(u32, key[20..24]);
155 k[6] = mem.readIntLittle(u32, key[24..28]);
156 k[7] = mem.readIntLittle(u32, key[28..32]);
158157
159158 c[0] = @truncate(u32, counter);
160159 c[1] = @truncate(u32, counter >> 32);
161 c[2] = mem.readIntSliceLittle(u32, nonce[0..4]);
162 c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);
160 c[2] = mem.readIntLittle(u32, nonce[0..4]);
161 c[3] = mem.readIntLittle(u32, nonce[4..8]);
163162
164163 const block_size = (1 << 6);
165164 // The full block size is greater than the address space on a 32bit machine
......@@ -463,8 +462,8 @@ pub fn chacha20poly1305Seal(dst: []u8, plaintext: []const u8, data: []const u8,
463462 mac.update(zeros[0..padding]);
464463 }
465464 var lens: [16]u8 = undefined;
466 mem.writeIntSliceLittle(u64, lens[0..8], data.len);
467 mem.writeIntSliceLittle(u64, lens[8..16], plaintext.len);
465 mem.writeIntLittle(u64, lens[0..8], data.len);
466 mem.writeIntLittle(u64, lens[8..16], plaintext.len);
468467 mac.update(lens[0..]);
469468 mac.final(dst[plaintext.len..]);
470469}
......@@ -500,8 +499,8 @@ pub fn chacha20poly1305Open(dst: []u8, msgAndTag: []const u8, data: []const u8,
500499 mac.update(zeros[0..padding]);
501500 }
502501 var lens: [16]u8 = undefined;
503 mem.writeIntSliceLittle(u64, lens[0..8], data.len);
504 mem.writeIntSliceLittle(u64, lens[8..16], ciphertext.len);
502 mem.writeIntLittle(u64, lens[0..8], data.len);
503 mem.writeIntLittle(u64, lens[8..16], ciphertext.len);
505504 mac.update(lens[0..]);
506505 var computedTag: [16]u8 = undefined;
507506 mac.final(computedTag[0..]);
lib/std/crypto/md5.zig+1-2
......@@ -112,8 +112,7 @@ pub const Md5 = struct {
112112 d.round(d.buf[0..]);
113113
114114 for (d.s) |s, j| {
115 // TODO https://github.com/ziglang/zig/issues/863
116 mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
115 mem.writeIntLittle(u32, out[4 * j ..][0..4], s);
117116 }
118117 }
119118
lib/std/crypto/poly1305.zig+14-15
......@@ -3,11 +3,11 @@
33// https://monocypher.org/
44
55const std = @import("../std.zig");
6const builtin = @import("builtin");
6const builtin = std.builtin;
77
88const Endian = builtin.Endian;
9const readIntSliceLittle = std.mem.readIntSliceLittle;
10const writeIntSliceLittle = std.mem.writeIntSliceLittle;
9const readIntLittle = std.mem.readIntLittle;
10const writeIntLittle = std.mem.writeIntLittle;
1111
1212pub const Poly1305 = struct {
1313 const Self = @This();
......@@ -59,19 +59,19 @@ pub const Poly1305 = struct {
5959 {
6060 var i: usize = 0;
6161 while (i < 1) : (i += 1) {
62 ctx.r[0] = readIntSliceLittle(u32, key[0..4]) & 0x0fffffff;
62 ctx.r[0] = readIntLittle(u32, key[0..4]) & 0x0fffffff;
6363 }
6464 }
6565 {
6666 var i: usize = 1;
6767 while (i < 4) : (i += 1) {
68 ctx.r[i] = readIntSliceLittle(u32, key[i * 4 .. i * 4 + 4]) & 0x0ffffffc;
68 ctx.r[i] = readIntLittle(u32, key[i * 4 ..][0..4]) & 0x0ffffffc;
6969 }
7070 }
7171 {
7272 var i: usize = 0;
7373 while (i < 4) : (i += 1) {
74 ctx.pad[i] = readIntSliceLittle(u32, key[i * 4 + 16 .. i * 4 + 16 + 4]);
74 ctx.pad[i] = readIntLittle(u32, key[i * 4 + 16 ..][0..4]);
7575 }
7676 }
7777
......@@ -168,10 +168,10 @@ pub const Poly1305 = struct {
168168 const nb_blocks = nmsg.len >> 4;
169169 var i: usize = 0;
170170 while (i < nb_blocks) : (i += 1) {
171 ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]);
172 ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]);
173 ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]);
174 ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]);
171 ctx.c[0] = readIntLittle(u32, nmsg[0..4]);
172 ctx.c[1] = readIntLittle(u32, nmsg[4..8]);
173 ctx.c[2] = readIntLittle(u32, nmsg[8..12]);
174 ctx.c[3] = readIntLittle(u32, nmsg[12..16]);
175175 polyBlock(ctx);
176176 nmsg = nmsg[16..];
177177 }
......@@ -210,11 +210,10 @@ pub const Poly1305 = struct {
210210 const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
211211 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
212212
213 // TODO https://github.com/ziglang/zig/issues/863
214 writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0));
215 writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1));
216 writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2));
217 writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3));
213 writeIntLittle(u32, out[0..4], @truncate(u32, uu0));
214 writeIntLittle(u32, out[4..8], @truncate(u32, uu1));
215 writeIntLittle(u32, out[8..12], @truncate(u32, uu2));
216 writeIntLittle(u32, out[12..16], @truncate(u32, uu3));
218217
219218 ctx.secureZero();
220219 }
lib/std/crypto/sha1.zig+1-2
......@@ -109,8 +109,7 @@ pub const Sha1 = struct {
109109 d.round(d.buf[0..]);
110110
111111 for (d.s) |s, j| {
112 // TODO https://github.com/ziglang/zig/issues/863
113 mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
112 mem.writeIntBig(u32, out[4 * j ..][0..4], s);
114113 }
115114 }
116115
lib/std/crypto/sha2.zig+2-4
......@@ -167,8 +167,7 @@ fn Sha2_32(comptime params: Sha2Params32) type {
167167 const rr = d.s[0 .. params.out_len / 32];
168168
169169 for (rr) |s, j| {
170 // TODO https://github.com/ziglang/zig/issues/863
171 mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
170 mem.writeIntBig(u32, out[4 * j ..][0..4], s);
172171 }
173172 }
174173
......@@ -509,8 +508,7 @@ fn Sha2_64(comptime params: Sha2Params64) type {
509508 const rr = d.s[0 .. params.out_len / 64];
510509
511510 for (rr) |s, j| {
512 // TODO https://github.com/ziglang/zig/issues/863
513 mem.writeIntSliceBig(u64, out[8 * j .. 8 * j + 8], s);
511 mem.writeIntBig(u64, out[8 * j ..][0..8], s);
514512 }
515513 }
516514
lib/std/crypto/sha3.zig+2-3
......@@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
120120 var c = [_]u64{0} ** 5;
121121
122122 for (s) |*r, i| {
123 r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]);
123 r.* = mem.readIntLittle(u64, d[8 * i ..][0..8]);
124124 }
125125
126126 comptime var x: usize = 0;
......@@ -167,8 +167,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
167167 }
168168
169169 for (s) |r, i| {
170 // TODO https://github.com/ziglang/zig/issues/863
171 mem.writeIntSliceLittle(u64, d[8 * i .. 8 * i + 8], r);
170 mem.writeIntLittle(u64, d[8 * i ..][0..8], r);
172171 }
173172}
174173
lib/std/crypto/x25519.zig+20-21
......@@ -7,8 +7,8 @@ const builtin = @import("builtin");
77const fmt = std.fmt;
88
99const Endian = builtin.Endian;
10const readIntSliceLittle = std.mem.readIntSliceLittle;
11const writeIntSliceLittle = std.mem.writeIntSliceLittle;
10const readIntLittle = std.mem.readIntLittle;
11const writeIntLittle = std.mem.writeIntLittle;
1212
1313// Based on Supercop's ref10 implementation.
1414pub const X25519 = struct {
......@@ -255,16 +255,16 @@ const Fe = struct {
255255
256256 var t: [10]i64 = undefined;
257257
258 t[0] = readIntSliceLittle(u32, s[0..4]);
259 t[1] = @as(u32, readIntSliceLittle(u24, s[4..7])) << 6;
260 t[2] = @as(u32, readIntSliceLittle(u24, s[7..10])) << 5;
261 t[3] = @as(u32, readIntSliceLittle(u24, s[10..13])) << 3;
262 t[4] = @as(u32, readIntSliceLittle(u24, s[13..16])) << 2;
263 t[5] = readIntSliceLittle(u32, s[16..20]);
264 t[6] = @as(u32, readIntSliceLittle(u24, s[20..23])) << 7;
265 t[7] = @as(u32, readIntSliceLittle(u24, s[23..26])) << 5;
266 t[8] = @as(u32, readIntSliceLittle(u24, s[26..29])) << 4;
267 t[9] = (@as(u32, readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2;
258 t[0] = readIntLittle(u32, s[0..4]);
259 t[1] = @as(u32, readIntLittle(u24, s[4..7])) << 6;
260 t[2] = @as(u32, readIntLittle(u24, s[7..10])) << 5;
261 t[3] = @as(u32, readIntLittle(u24, s[10..13])) << 3;
262 t[4] = @as(u32, readIntLittle(u24, s[13..16])) << 2;
263 t[5] = readIntLittle(u32, s[16..20]);
264 t[6] = @as(u32, readIntLittle(u24, s[20..23])) << 7;
265 t[7] = @as(u32, readIntLittle(u24, s[23..26])) << 5;
266 t[8] = @as(u32, readIntLittle(u24, s[26..29])) << 4;
267 t[9] = (@as(u32, readIntLittle(u24, s[29..32])) & 0x7fffff) << 2;
268268
269269 carry1(h, t[0..]);
270270 }
......@@ -544,15 +544,14 @@ const Fe = struct {
544544 ut[i] = @bitCast(u32, @intCast(i32, t[i]));
545545 }
546546
547 // TODO https://github.com/ziglang/zig/issues/863
548 writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));
549 writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));
550 writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));
551 writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));
552 writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));
553 writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));
554 writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));
555 writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6));
547 writeIntLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));
548 writeIntLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));
549 writeIntLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));
550 writeIntLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));
551 writeIntLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));
552 writeIntLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));
553 writeIntLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));
554 writeIntLittle(u32, s[28..32], (ut[8] >> 20) | (ut[9] << 6));
556555
557556 std.mem.secureZero(i64, t[0..]);
558557 }
lib/std/debug.zig+44-11
......@@ -235,9 +235,17 @@ pub fn panic(comptime format: []const u8, args: var) noreturn {
235235 panicExtra(null, first_trace_addr, format, args);
236236}
237237
238/// TODO multithreaded awareness
238/// Non-zero whenever the program triggered a panic.
239/// The counter is incremented/decremented atomically.
239240var panicking: u8 = 0;
240241
242// Locked to avoid interleaving panic messages from multiple threads.
243var panic_mutex = std.Mutex.init();
244
245/// Counts how many times the panic handler is invoked by this thread.
246/// This is used to catch and handle panics triggered by the panic handler.
247threadlocal var panic_stage: usize = 0;
248
241249pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: var) noreturn {
242250 @setCold(true);
243251
......@@ -247,25 +255,50 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c
247255 resetSegfaultHandler();
248256 }
249257
250 switch (@atomicRmw(u8, &panicking, .Add, 1, .SeqCst)) {
258 switch (panic_stage) {
251259 0 => {
252 const stderr = getStderrStream();
253 noasync stderr.print(format ++ "\n", args) catch os.abort();
254 if (trace) |t| {
255 dumpStackTrace(t.*);
260 panic_stage = 1;
261
262 _ = @atomicRmw(u8, &panicking, .Add, 1, .SeqCst);
263
264 // Make sure to release the mutex when done
265 {
266 const held = panic_mutex.acquire();
267 defer held.release();
268
269 const stderr = getStderrStream();
270 noasync stderr.print(format ++ "\n", args) catch os.abort();
271 if (trace) |t| {
272 dumpStackTrace(t.*);
273 }
274 dumpCurrentStackTrace(first_trace_addr);
275 }
276
277 if (@atomicRmw(u8, &panicking, .Sub, 1, .SeqCst) != 1) {
278 // Another thread is panicking, wait for the last one to finish
279 // and call abort()
280
281 // Sleep forever without hammering the CPU
282 var event = std.ResetEvent.init();
283 event.wait();
284
285 unreachable;
256286 }
257 dumpCurrentStackTrace(first_trace_addr);
258287 },
259288 1 => {
260 // TODO detect if a different thread caused the panic, because in that case
261 // we would want to return here instead of calling abort, so that the thread
262 // which first called panic can finish printing a stack trace.
263 warn("Panicked during a panic. Aborting.\n", .{});
289 panic_stage = 2;
290
291 // A panic happened while trying to print a previous panic message,
292 // we're still holding the mutex but that's fine as we're going to
293 // call abort()
294 const stderr = getStderrStream();
295 noasync stderr.print("Panicked during a panic. Aborting.\n", .{}) catch os.abort();
264296 },
265297 else => {
266298 // Panicked while printing "Panicked during a panic."
267299 },
268300 }
301
269302 os.abort();
270303}
271304
lib/std/dwarf.zig+1-2
......@@ -717,8 +717,7 @@ pub const DwarfInfo = struct {
717717 const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
718718
719719 const version = try in.readInt(u16, di.endian);
720 // TODO support 3 and 5
721 if (version != 2 and version != 4) return error.InvalidDebugInfo;
720 if (version < 2 or version > 4) return error.InvalidDebugInfo;
722721
723722 const prologue_length = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian);
724723 const prog_start_offset = (try seekable.getPos()) + prologue_length;
lib/std/fmt.zig+2-1
......@@ -1223,7 +1223,8 @@ test "slice" {
12231223 try testFmt("slice: abc\n", "slice: {}\n", .{value});
12241224 }
12251225 {
1226 const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
1226 var runtime_zero: usize = 0;
1227 const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[runtime_zero..runtime_zero];
12271228 try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
12281229 }
12291230
lib/std/fs.zig+233-311
......@@ -81,134 +81,74 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:
8181 }
8282}
8383
84// TODO fix enum literal not casting to error union
85const PrevStatus = enum {
84pub const PrevStatus = enum {
8685 stale,
8786 fresh,
8887};
8988
90pub fn updateFile(source_path: []const u8, dest_path: []const u8) !PrevStatus {
91 return updateFileMode(source_path, dest_path, null);
92}
89pub const CopyFileOptions = struct {
90 /// When this is `null` the mode is copied from the source file.
91 override_mode: ?File.Mode = null,
92};
9393
94/// Check the file size, mtime, and mode of `source_path` and `dest_path`. If they are equal, does nothing.
95/// Otherwise, atomically copies `source_path` to `dest_path`. The destination file gains the mtime,
96/// atime, and mode of the source file so that the next call to `updateFile` will not need a copy.
97/// Returns the previous status of the file before updating.
98/// If any of the directories do not exist for dest_path, they are created.
99/// TODO rework this to integrate with Dir
100pub fn updateFileMode(source_path: []const u8, dest_path: []const u8, mode: ?File.Mode) !PrevStatus {
94/// Same as `Dir.updateFile`, except asserts that both `source_path` and `dest_path`
95/// are absolute. See `Dir.updateFile` for a function that operates on both
96/// absolute and relative paths.
97pub fn updateFileAbsolute(
98 source_path: []const u8,
99 dest_path: []const u8,
100 args: CopyFileOptions,
101) !PrevStatus {
102 assert(path.isAbsolute(source_path));
103 assert(path.isAbsolute(dest_path));
101104 const my_cwd = cwd();
102
103 var src_file = try my_cwd.openFile(source_path, .{});
104 defer src_file.close();
105
106 const src_stat = try src_file.stat();
107 check_dest_stat: {
108 const dest_stat = blk: {
109 var dest_file = my_cwd.openFile(dest_path, .{}) catch |err| switch (err) {
110 error.FileNotFound => break :check_dest_stat,
111 else => |e| return e,
112 };
113 defer dest_file.close();
114
115 break :blk try dest_file.stat();
116 };
117
118 if (src_stat.size == dest_stat.size and
119 src_stat.mtime == dest_stat.mtime and
120 src_stat.mode == dest_stat.mode)
121 {
122 return PrevStatus.fresh;
123 }
124 }
125 const actual_mode = mode orelse src_stat.mode;
126
127 if (path.dirname(dest_path)) |dirname| {
128 try cwd().makePath(dirname);
129 }
130
131 var atomic_file = try AtomicFile.init(dest_path, actual_mode);
132 defer atomic_file.deinit();
133
134 try atomic_file.file.writeFileAll(src_file, .{ .in_len = src_stat.size });
135 try atomic_file.file.updateTimes(src_stat.atime, src_stat.mtime);
136 try atomic_file.finish();
137 return PrevStatus.stale;
105 return Dir.updateFile(my_cwd, source_path, my_cwd, dest_path, args);
138106}
139107
140/// Guaranteed to be atomic.
141/// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and readily available,
142/// there is a possibility of power loss or application termination leaving temporary files present
143/// in the same directory as dest_path.
144/// Destination file will have the same mode as the source file.
145/// TODO rework this to integrate with Dir
146pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
147 var in_file = try cwd().openFile(source_path, .{});
148 defer in_file.close();
149
150 const stat = try in_file.stat();
151
152 var atomic_file = try AtomicFile.init(dest_path, stat.mode);
153 defer atomic_file.deinit();
154
155 try atomic_file.file.writeFileAll(in_file, .{ .in_len = stat.size });
156 return atomic_file.finish();
157}
158
159/// Guaranteed to be atomic.
160/// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and readily available,
161/// there is a possibility of power loss or application termination leaving temporary files present
162/// in the same directory as dest_path.
163/// TODO rework this to integrate with Dir
164pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
165 var in_file = try cwd().openFile(source_path, .{});
166 defer in_file.close();
167
168 var atomic_file = try AtomicFile.init(dest_path, mode);
169 defer atomic_file.deinit();
170
171 try atomic_file.file.writeFileAll(in_file, .{});
172 return atomic_file.finish();
108/// Same as `Dir.copyFile`, except asserts that both `source_path` and `dest_path`
109/// are absolute. See `Dir.copyFile` for a function that operates on both
110/// absolute and relative paths.
111pub fn copyFileAbsolute(source_path: []const u8, dest_path: []const u8, args: CopyFileOptions) !void {
112 assert(path.isAbsolute(source_path));
113 assert(path.isAbsolute(dest_path));
114 const my_cwd = cwd();
115 return Dir.copyFile(my_cwd, source_path, my_cwd, dest_path, args);
173116}
174117
175/// TODO update this API to avoid a getrandom syscall for every operation. It
176/// should accept a random interface.
177/// TODO rework this to integrate with Dir
118/// TODO update this API to avoid a getrandom syscall for every operation.
178119pub const AtomicFile = struct {
179120 file: File,
180 tmp_path_buf: [MAX_PATH_BYTES]u8,
121 tmp_path_buf: [MAX_PATH_BYTES - 1:0]u8,
181122 dest_path: []const u8,
182 finished: bool,
123 file_open: bool,
124 file_exists: bool,
125 dir: Dir,
183126
184127 const InitError = File.OpenError;
185128
186 /// dest_path must remain valid for the lifetime of AtomicFile
187 /// call finish to atomically replace dest_path with contents
188 pub fn init(dest_path: []const u8, mode: File.Mode) InitError!AtomicFile {
129 /// TODO rename this. Callers should go through Dir API
130 pub fn init2(dest_path: []const u8, mode: File.Mode, dir: Dir) InitError!AtomicFile {
189131 const dirname = path.dirname(dest_path);
190132 var rand_buf: [12]u8 = undefined;
191133 const dirname_component_len = if (dirname) |d| d.len + 1 else 0;
192134 const encoded_rand_len = comptime base64.Base64Encoder.calcSize(rand_buf.len);
193135 const tmp_path_len = dirname_component_len + encoded_rand_len;
194 var tmp_path_buf: [MAX_PATH_BYTES]u8 = undefined;
195 if (tmp_path_len >= tmp_path_buf.len) return error.NameTooLong;
136 var tmp_path_buf: [MAX_PATH_BYTES - 1:0]u8 = undefined;
137 if (tmp_path_len > tmp_path_buf.len) return error.NameTooLong;
196138
197 if (dirname) |dir| {
198 mem.copy(u8, tmp_path_buf[0..], dir);
199 tmp_path_buf[dir.len] = path.sep;
139 if (dirname) |dn| {
140 mem.copy(u8, tmp_path_buf[0..], dn);
141 tmp_path_buf[dn.len] = path.sep;
200142 }
201143
202144 tmp_path_buf[tmp_path_len] = 0;
203145 const tmp_path_slice = tmp_path_buf[0..tmp_path_len :0];
204146
205 const my_cwd = cwd();
206
207147 while (true) {
208148 try crypto.randomBytes(rand_buf[0..]);
209149 base64_encoder.encode(tmp_path_slice[dirname_component_len..tmp_path_len], &rand_buf);
210150
211 const file = my_cwd.createFileC(
151 const file = dir.createFileC(
212152 tmp_path_slice,
213153 .{ .mode = mode, .exclusive = true },
214154 ) catch |err| switch (err) {
......@@ -220,33 +160,46 @@ pub const AtomicFile = struct {
220160 .file = file,
221161 .tmp_path_buf = tmp_path_buf,
222162 .dest_path = dest_path,
223 .finished = false,
163 .file_open = true,
164 .file_exists = true,
165 .dir = dir,
224166 };
225167 }
226168 }
227169
170 /// Deprecated. Use `Dir.atomicFile`.
171 pub fn init(dest_path: []const u8, mode: File.Mode) InitError!AtomicFile {
172 return init2(dest_path, mode, cwd());
173 }
174
228175 /// always call deinit, even after successful finish()
229176 pub fn deinit(self: *AtomicFile) void {
230 if (!self.finished) {
177 if (self.file_open) {
231178 self.file.close();
232 cwd().deleteFileC(@ptrCast([*:0]u8, &self.tmp_path_buf)) catch {};
233 self.finished = true;
179 self.file_open = false;
180 }
181 if (self.file_exists) {
182 self.dir.deleteFileC(&self.tmp_path_buf) catch {};
183 self.file_exists = false;
234184 }
185 self.* = undefined;
235186 }
236187
237188 pub fn finish(self: *AtomicFile) !void {
238 assert(!self.finished);
189 assert(self.file_exists);
190 if (self.file_open) {
191 self.file.close();
192 self.file_open = false;
193 }
239194 if (std.Target.current.os.tag == .windows) {
240195 const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
241 const tmp_path_w = try os.windows.cStrToPrefixedFileW(@ptrCast([*:0]u8, &self.tmp_path_buf));
242 self.file.close();
243 self.finished = true;
244 return os.renameW(&tmp_path_w, &dest_path_w);
196 const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
197 try os.renameatW(self.dir.fd, &tmp_path_w, self.dir.fd, &dest_path_w, os.windows.TRUE);
198 self.file_exists = false;
245199 } else {
246200 const dest_path_c = try os.toPosixPath(self.dest_path);
247 self.file.close();
248 self.finished = true;
249 return os.renameC(@ptrCast([*:0]u8, &self.tmp_path_buf), &dest_path_c);
201 try os.renameatZ(self.dir.fd, &self.tmp_path_buf, self.dir.fd, &dest_path_c);
202 self.file_exists = false;
250203 }
251204 }
252205};
......@@ -274,44 +227,21 @@ pub fn makeDirAbsoluteW(absolute_path_w: [*:0]const u16) !void {
274227 os.windows.CloseHandle(handle);
275228}
276229
277/// Returns `error.DirNotEmpty` if the directory is not empty.
278/// To delete a directory recursively, see `deleteTree`.
230/// Deprecated; use `Dir.deleteDir`.
279231pub fn deleteDir(dir_path: []const u8) !void {
280232 return os.rmdir(dir_path);
281233}
282234
283/// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.
235/// Deprecated; use `Dir.deleteDirC`.
284236pub fn deleteDirC(dir_path: [*:0]const u8) !void {
285237 return os.rmdirC(dir_path);
286238}
287239
288/// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.
240/// Deprecated; use `Dir.deleteDirW`.
289241pub fn deleteDirW(dir_path: [*:0]const u16) !void {
290242 return os.rmdirW(dir_path);
291243}
292244
293/// Removes a symlink, file, or directory.
294/// If `full_path` is relative, this is equivalent to `Dir.deleteTree` with the
295/// current working directory as the open directory handle.
296/// If `full_path` is absolute, this is equivalent to `Dir.deleteTree` with the
297/// base directory.
298pub fn deleteTree(full_path: []const u8) !void {
299 if (path.isAbsolute(full_path)) {
300 const dirname = path.dirname(full_path) orelse return error{
301 /// Attempt to remove the root file system path.
302 /// This error is unreachable if `full_path` is relative.
303 CannotDeleteRootDirectory,
304 }.CannotDeleteRootDirectory;
305
306 var dir = try cwd().openDirList(dirname);
307 defer dir.close();
308
309 return dir.deleteTree(path.basename(full_path));
310 } else {
311 return cwd().deleteTree(full_path);
312 }
313}
314
315245pub const Dir = struct {
316246 fd: os.fd_t,
317247
......@@ -368,7 +298,7 @@ pub const Dir = struct {
368298 if (rc == 0) return null;
369299 if (rc < 0) {
370300 switch (os.errno(rc)) {
371 os.EBADF => unreachable,
301 os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability
372302 os.EFAULT => unreachable,
373303 os.ENOTDIR => unreachable,
374304 os.EINVAL => unreachable,
......@@ -411,13 +341,13 @@ pub const Dir = struct {
411341 if (self.index >= self.end_index) {
412342 const rc = os.system.getdirentries(
413343 self.dir.fd,
414 self.buf[0..].ptr,
344 &self.buf,
415345 self.buf.len,
416346 &self.seek,
417347 );
418348 switch (os.errno(rc)) {
419349 0 => {},
420 os.EBADF => unreachable,
350 os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability
421351 os.EFAULT => unreachable,
422352 os.ENOTDIR => unreachable,
423353 os.EINVAL => unreachable,
......@@ -473,7 +403,7 @@ pub const Dir = struct {
473403 const rc = os.linux.getdents64(self.dir.fd, &self.buf, self.buf.len);
474404 switch (os.linux.getErrno(rc)) {
475405 0 => {},
476 os.EBADF => unreachable,
406 os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability
477407 os.EFAULT => unreachable,
478408 os.ENOTDIR => unreachable,
479409 os.EINVAL => unreachable,
......@@ -547,7 +477,8 @@ pub const Dir = struct {
547477 self.end_index = io.Information;
548478 switch (rc) {
549479 .SUCCESS => {},
550 .ACCESS_DENIED => return error.AccessDenied,
480 .ACCESS_DENIED => return error.AccessDenied, // Double-check that the Dir was opened with iteration ability
481
551482 else => return w.unexpectedStatus(rc),
552483 }
553484 }
......@@ -625,16 +556,6 @@ pub const Dir = struct {
625556 DeviceBusy,
626557 } || os.UnexpectedError;
627558
628 /// Deprecated; call `cwd().openDirList` directly.
629 pub fn open(dir_path: []const u8) OpenError!Dir {
630 return cwd().openDirList(dir_path);
631 }
632
633 /// Deprecated; call `cwd().openDirListC` directly.
634 pub fn openC(dir_path_c: [*:0]const u8) OpenError!Dir {
635 return cwd().openDirListC(dir_path_c);
636 }
637
638559 pub fn close(self: *Dir) void {
639560 if (need_async_thread) {
640561 std.event.Loop.instance.?.close(self.fd);
......@@ -696,7 +617,7 @@ pub const Dir = struct {
696617 var flock = mem.zeroes(os.Flock);
697618 flock.l_type = if (flags.write) os.F_WRLCK else os.F_RDLCK;
698619 flock.l_whence = os.SEEK_SET;
699 try os.fcntl(fd, os.F_SETLKW, &flock);
620 _ = try os.fcntl(fd, os.F_SETLKW, @ptrToInt(&flock));
700621 }
701622
702623 return File{
......@@ -721,7 +642,10 @@ pub const Dir = struct {
721642 (if (flags.write) @as(os.windows.ULONG, 0) else w.FILE_SHARE_READ)
722643 else
723644 null;
724 return self.openFileWindows(sub_path_w, access_mask, share_access, w.FILE_OPEN);
645 return @as(File, .{
646 .handle = try os.windows.OpenFileW(self.fd, sub_path_w, null, access_mask, share_access, w.FILE_OPEN),
647 .io_mode = .blocking,
648 });
725649 }
726650
727651 /// Creates, opens, or overwrites a file with write access.
......@@ -765,7 +689,7 @@ pub const Dir = struct {
765689 var flock = mem.zeroes(os.Flock);
766690 flock.l_type = os.F_WRLCK;
767691 flock.l_whence = os.SEEK_SET;
768 try os.fcntl(fd, os.F_SETLKW, &flock);
692 _ = try os.fcntl(fd, os.F_SETLKW, @ptrToInt(&flock));
769693 }
770694
771695 return File{ .handle = fd, .io_mode = .blocking };
......@@ -788,7 +712,10 @@ pub const Dir = struct {
788712 @as(os.windows.ULONG, w.FILE_SHARE_DELETE)
789713 else
790714 null;
791 return self.openFileWindows(sub_path_w, access_mask, share_access, creation);
715 return @as(File, .{
716 .handle = try os.windows.OpenFileW(self.fd, sub_path_w, null, access_mask, share_access, creation),
717 .io_mode = .blocking,
718 });
792719 }
793720
794721 /// Deprecated; call `openFile` directly.
......@@ -806,87 +733,6 @@ pub const Dir = struct {
806733 return self.openFileW(sub_path, .{});
807734 }
808735
809 pub fn openFileWindows(
810 self: Dir,
811 sub_path_w: [*:0]const u16,
812 access_mask: os.windows.ACCESS_MASK,
813 share_access_opt: ?os.windows.ULONG,
814 creation: os.windows.ULONG,
815 ) File.OpenError!File {
816 var delay: usize = 1;
817 while (true) {
818 const w = os.windows;
819
820 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
821 return error.IsDir;
822 }
823 if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
824 return error.IsDir;
825 }
826
827 var result = File{
828 .handle = undefined,
829 .io_mode = .blocking,
830 };
831
832 const path_len_bytes = math.cast(u16, mem.toSliceConst(u16, sub_path_w).len * 2) catch |err| switch (err) {
833 error.Overflow => return error.NameTooLong,
834 };
835 var nt_name = w.UNICODE_STRING{
836 .Length = path_len_bytes,
837 .MaximumLength = path_len_bytes,
838 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
839 };
840 var attr = w.OBJECT_ATTRIBUTES{
841 .Length = @sizeOf(w.OBJECT_ATTRIBUTES),
842 .RootDirectory = if (path.isAbsoluteWindowsW(sub_path_w)) null else self.fd,
843 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
844 .ObjectName = &nt_name,
845 .SecurityDescriptor = null,
846 .SecurityQualityOfService = null,
847 };
848 var io: w.IO_STATUS_BLOCK = undefined;
849 const share_access = share_access_opt orelse w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE;
850 const rc = w.ntdll.NtCreateFile(
851 &result.handle,
852 access_mask,
853 &attr,
854 &io,
855 null,
856 w.FILE_ATTRIBUTE_NORMAL,
857 share_access,
858 creation,
859 w.FILE_NON_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT,
860 null,
861 0,
862 );
863 switch (rc) {
864 .SUCCESS => return result,
865 .OBJECT_NAME_INVALID => unreachable,
866 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
867 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
868 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
869 .INVALID_PARAMETER => unreachable,
870 .SHARING_VIOLATION => {
871 // TODO: check if async or blocking
872 //return error.SharingViolation
873 // Sleep so we don't consume a ton of CPU waiting to get lock on file
874 std.time.sleep(delay);
875 // Increase sleep time as long as it is less than 5 seconds
876 if (delay < 5 * std.time.ns_per_s) {
877 delay *= 2;
878 }
879 continue;
880 },
881 .ACCESS_DENIED => return error.AccessDenied,
882 .PIPE_BUSY => return error.PipeBusy,
883 .OBJECT_PATH_SYNTAX_BAD => unreachable,
884 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
885 else => return w.unexpectedStatus(rc),
886 }
887 }
888 }
889
890736 pub fn makeDir(self: Dir, sub_path: []const u8) !void {
891737 try os.mkdirat(self.fd, sub_path, default_new_dir_mode);
892738 }
......@@ -945,77 +791,61 @@ pub const Dir = struct {
945791 try os.fchdir(self.fd);
946792 }
947793
948 /// Deprecated; call `openDirList` directly.
949 pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir {
950 return self.openDirList(sub_path);
951 }
952
953 /// Deprecated; call `openDirListC` directly.
954 pub fn openDirC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {
955 return self.openDirListC(sub_path_c);
956 }
957
958 /// Opens a directory at the given path with the ability to access subpaths
959 /// of the result. Calling `iterate` on the result is illegal behavior; to
960 /// list the contents of a directory, open it with `openDirList`.
961 ///
962 /// Call `close` on the result when done.
963 ///
964 /// Asserts that the path parameter has no null bytes.
965 pub fn openDirTraverse(self: Dir, sub_path: []const u8) OpenError!Dir {
966 if (builtin.os.tag == .windows) {
967 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
968 return self.openDirTraverseW(&sub_path_w);
969 }
794 pub const OpenDirOptions = struct {
795 /// `true` means the opened directory can be used as the `Dir` parameter
796 /// for functions which operate based on an open directory handle. When `false`,
797 /// such operations are Illegal Behavior.
798 access_sub_paths: bool = true,
970799
971 const sub_path_c = try os.toPosixPath(sub_path);
972 return self.openDirTraverseC(&sub_path_c);
973 }
800 /// `true` means the opened directory can be scanned for the files and sub-directories
801 /// of the result. It means the `iterate` function can be called.
802 iterate: bool = false,
803 };
974804
975 /// Opens a directory at the given path with the ability to access subpaths and list contents
976 /// of the result. If the ability to list contents is unneeded, `openDirTraverse` acts the
977 /// same and may be more efficient.
978 ///
979 /// Call `close` on the result when done.
805 /// Opens a directory at the given path. The directory is a system resource that remains
806 /// open until `close` is called on the result.
980807 ///
981808 /// Asserts that the path parameter has no null bytes.
982 pub fn openDirList(self: Dir, sub_path: []const u8) OpenError!Dir {
809 pub fn openDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir {
983810 if (builtin.os.tag == .windows) {
984811 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
985 return self.openDirListW(&sub_path_w);
812 return self.openDirW(&sub_path_w, args);
813 } else {
814 const sub_path_c = try os.toPosixPath(sub_path);
815 return self.openDirC(&sub_path_c, args);
986816 }
987
988 const sub_path_c = try os.toPosixPath(sub_path);
989 return self.openDirListC(&sub_path_c);
990817 }
991818
992 /// Same as `openDirTraverse` except the parameter is null-terminated.
993 pub fn openDirTraverseC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {
819 /// Same as `openDir` except the parameter is null-terminated.
820 pub fn openDirC(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions) OpenError!Dir {
994821 if (builtin.os.tag == .windows) {
995822 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
996 return self.openDirTraverseW(&sub_path_w);
997 } else {
823 return self.openDirW(&sub_path_w, args);
824 } else if (!args.iterate) {
998825 const O_PATH = if (@hasDecl(os, "O_PATH")) os.O_PATH else 0;
999 return self.openDirFlagsC(sub_path_c, os.O_RDONLY | os.O_CLOEXEC | O_PATH);
826 return self.openDirFlagsC(sub_path_c, os.O_DIRECTORY | os.O_RDONLY | os.O_CLOEXEC | O_PATH);
827 } else {
828 return self.openDirFlagsC(sub_path_c, os.O_DIRECTORY | os.O_RDONLY | os.O_CLOEXEC);
1000829 }
1001830 }
1002831
1003 /// Same as `openDirList` except the parameter is null-terminated.
1004 pub fn openDirListC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {
1005 if (builtin.os.tag == .windows) {
1006 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
1007 return self.openDirListW(&sub_path_w);
1008 } else {
1009 return self.openDirFlagsC(sub_path_c, os.O_RDONLY | os.O_CLOEXEC);
1010 }
832 /// Same as `openDir` except the path parameter is WTF-16 encoded, NT-prefixed.
833 /// This function asserts the target OS is Windows.
834 pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenDirOptions) OpenError!Dir {
835 const w = os.windows;
836 // TODO remove some of these flags if args.access_sub_paths is false
837 const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA |
838 w.SYNCHRONIZE | w.FILE_TRAVERSE;
839 const flags: u32 = if (args.iterate) base_flags | w.FILE_LIST_DIRECTORY else base_flags;
840 return self.openDirAccessMaskW(sub_path_w, flags);
1011841 }
1012842
843 /// `flags` must contain `os.O_DIRECTORY`.
1013844 fn openDirFlagsC(self: Dir, sub_path_c: [*:0]const u8, flags: u32) OpenError!Dir {
1014 const os_flags = flags | os.O_DIRECTORY;
1015845 const result = if (need_async_thread)
1016 std.event.Loop.instance.?.openatZ(self.fd, sub_path_c, os_flags, 0)
846 std.event.Loop.instance.?.openatZ(self.fd, sub_path_c, flags, 0)
1017847 else
1018 os.openatC(self.fd, sub_path_c, os_flags, 0);
848 os.openatC(self.fd, sub_path_c, flags, 0);
1019849 const fd = result catch |err| switch (err) {
1020850 error.FileTooBig => unreachable, // can't happen for directories
1021851 error.IsDir => unreachable, // we're providing O_DIRECTORY
......@@ -1026,22 +856,6 @@ pub const Dir = struct {
1026856 return Dir{ .fd = fd };
1027857 }
1028858
1029 /// Same as `openDirTraverse` except the path parameter is UTF16LE, NT-prefixed.
1030 /// This function is Windows-only.
1031 pub fn openDirTraverseW(self: Dir, sub_path_w: [*:0]const u16) OpenError!Dir {
1032 const w = os.windows;
1033
1034 return self.openDirAccessMaskW(sub_path_w, w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | w.SYNCHRONIZE | w.FILE_TRAVERSE);
1035 }
1036
1037 /// Same as `openDirList` except the path parameter is UTF16LE, NT-prefixed.
1038 /// This function is Windows-only.
1039 pub fn openDirListW(self: Dir, sub_path_w: [*:0]const u16) OpenError!Dir {
1040 const w = os.windows;
1041
1042 return self.openDirAccessMaskW(sub_path_w, w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | w.SYNCHRONIZE | w.FILE_TRAVERSE | w.FILE_LIST_DIRECTORY);
1043 }
1044
1045859 fn openDirAccessMaskW(self: Dir, sub_path_w: [*:0]const u16, access_mask: u32) OpenError!Dir {
1046860 const w = os.windows;
1047861
......@@ -1262,7 +1076,7 @@ pub const Dir = struct {
12621076 error.Unexpected,
12631077 => |e| return e,
12641078 }
1265 var dir = self.openDirList(sub_path) catch |err| switch (err) {
1079 var dir = self.openDir(sub_path, .{ .iterate = true }) catch |err| switch (err) {
12661080 error.NotDir => {
12671081 if (got_access_denied) {
12681082 return error.AccessDenied;
......@@ -1295,7 +1109,6 @@ pub const Dir = struct {
12951109
12961110 var dir_name_buf: [MAX_PATH_BYTES]u8 = undefined;
12971111 var dir_name: []const u8 = sub_path;
1298 var parent_dir = self;
12991112
13001113 // Here we must avoid recursion, in order to provide O(1) memory guarantee of this function.
13011114 // Go through each entry and if it is not a directory, delete it. If it is a directory,
......@@ -1327,7 +1140,7 @@ pub const Dir = struct {
13271140 => |e| return e,
13281141 }
13291142
1330 const new_dir = dir.openDirList(entry.name) catch |err| switch (err) {
1143 const new_dir = dir.openDir(entry.name, .{ .iterate = true }) catch |err| switch (err) {
13311144 error.NotDir => {
13321145 if (got_access_denied) {
13331146 return error.AccessDenied;
......@@ -1434,9 +1247,96 @@ pub const Dir = struct {
14341247 pub fn accessW(self: Dir, sub_path_w: [*:0]const u16, flags: File.OpenFlags) AccessError!void {
14351248 return os.faccessatW(self.fd, sub_path_w, 0, 0);
14361249 }
1250
1251 /// Check the file size, mtime, and mode of `source_path` and `dest_path`. If they are equal, does nothing.
1252 /// Otherwise, atomically copies `source_path` to `dest_path`. The destination file gains the mtime,
1253 /// atime, and mode of the source file so that the next call to `updateFile` will not need a copy.
1254 /// Returns the previous status of the file before updating.
1255 /// If any of the directories do not exist for dest_path, they are created.
1256 pub fn updateFile(
1257 source_dir: Dir,
1258 source_path: []const u8,
1259 dest_dir: Dir,
1260 dest_path: []const u8,
1261 options: CopyFileOptions,
1262 ) !PrevStatus {
1263 var src_file = try source_dir.openFile(source_path, .{});
1264 defer src_file.close();
1265
1266 const src_stat = try src_file.stat();
1267 const actual_mode = options.override_mode orelse src_stat.mode;
1268 check_dest_stat: {
1269 const dest_stat = blk: {
1270 var dest_file = dest_dir.openFile(dest_path, .{}) catch |err| switch (err) {
1271 error.FileNotFound => break :check_dest_stat,
1272 else => |e| return e,
1273 };
1274 defer dest_file.close();
1275
1276 break :blk try dest_file.stat();
1277 };
1278
1279 if (src_stat.size == dest_stat.size and
1280 src_stat.mtime == dest_stat.mtime and
1281 actual_mode == dest_stat.mode)
1282 {
1283 return PrevStatus.fresh;
1284 }
1285 }
1286
1287 if (path.dirname(dest_path)) |dirname| {
1288 try dest_dir.makePath(dirname);
1289 }
1290
1291 var atomic_file = try dest_dir.atomicFile(dest_path, .{ .mode = actual_mode });
1292 defer atomic_file.deinit();
1293
1294 try atomic_file.file.writeFileAll(src_file, .{ .in_len = src_stat.size });
1295 try atomic_file.file.updateTimes(src_stat.atime, src_stat.mtime);
1296 try atomic_file.finish();
1297 return PrevStatus.stale;
1298 }
1299
1300 /// Guaranteed to be atomic.
1301 /// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and readily available,
1302 /// there is a possibility of power loss or application termination leaving temporary files present
1303 /// in the same directory as dest_path.
1304 pub fn copyFile(
1305 source_dir: Dir,
1306 source_path: []const u8,
1307 dest_dir: Dir,
1308 dest_path: []const u8,
1309 options: CopyFileOptions,
1310 ) !void {
1311 var in_file = try source_dir.openFile(source_path, .{});
1312 defer in_file.close();
1313
1314 var size: ?u64 = null;
1315 const mode = options.override_mode orelse blk: {
1316 const stat = try in_file.stat();
1317 size = stat.size;
1318 break :blk stat.mode;
1319 };
1320
1321 var atomic_file = try dest_dir.atomicFile(dest_path, .{ .mode = mode });
1322 defer atomic_file.deinit();
1323
1324 try atomic_file.file.writeFileAll(in_file, .{ .in_len = size });
1325 return atomic_file.finish();
1326 }
1327
1328 pub const AtomicFileOptions = struct {
1329 mode: File.Mode = File.default_mode,
1330 };
1331
1332 /// `dest_path` must remain valid for the lifetime of `AtomicFile`.
1333 /// Call `AtomicFile.finish` to atomically replace `dest_path` with contents.
1334 pub fn atomicFile(self: Dir, dest_path: []const u8, options: AtomicFileOptions) !AtomicFile {
1335 return AtomicFile.init2(dest_path, options.mode, self);
1336 }
14371337};
14381338
1439/// Returns an handle to the current working directory that is open for traversal.
1339/// Returns an handle to the current working directory. It is not opened with iteration capability.
14401340/// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior.
14411341/// On POSIX targets, this function is comptime-callable.
14421342pub fn cwd() Dir {
......@@ -1514,6 +1414,25 @@ pub fn deleteFileAbsoluteW(absolute_path_w: [*:0]const u16) DeleteFileError!void
15141414 return cwd().deleteFileW(absolute_path_w);
15151415}
15161416
1417/// Removes a symlink, file, or directory.
1418/// This is equivalent to `Dir.deleteTree` with the base directory.
1419/// Asserts that the path is absolute. See `Dir.deleteTree` for a function that
1420/// operates on both absolute and relative paths.
1421/// Asserts that the path parameter has no null bytes.
1422pub fn deleteTreeAbsolute(absolute_path: []const u8) !void {
1423 assert(path.isAbsolute(absolute_path));
1424 const dirname = path.dirname(absolute_path) orelse return error{
1425 /// Attempt to remove the root file system path.
1426 /// This error is unreachable if `absolute_path` is relative.
1427 CannotDeleteRootDirectory,
1428 }.CannotDeleteRootDirectory;
1429
1430 var dir = try cwd().openDir(dirname, .{});
1431 defer dir.close();
1432
1433 return dir.deleteTree(path.basename(absolute_path));
1434}
1435
15171436pub const Walker = struct {
15181437 stack: std.ArrayList(StackItem),
15191438 name_buffer: std.Buffer,
......@@ -1548,7 +1467,7 @@ pub const Walker = struct {
15481467 try self.name_buffer.appendByte(path.sep);
15491468 try self.name_buffer.append(base.name);
15501469 if (base.kind == .Directory) {
1551 var new_dir = top.dir_it.dir.openDirList(base.name) catch |err| switch (err) {
1470 var new_dir = top.dir_it.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
15521471 error.NameTooLong => unreachable, // no path sep in base.name
15531472 else => |e| return e,
15541473 };
......@@ -1586,7 +1505,7 @@ pub const Walker = struct {
15861505pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker {
15871506 assert(!mem.endsWith(u8, dir_path, path.sep_str));
15881507
1589 var dir = try cwd().openDirList(dir_path);
1508 var dir = try cwd().openDir(dir_path, .{ .iterate = true });
15901509 errdefer dir.close();
15911510
15921511 var name_buffer = try std.Buffer.init(allocator, dir_path);
......@@ -1605,13 +1524,12 @@ pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker {
16051524 return walker;
16061525}
16071526
1608/// Read value of a symbolic link.
1609/// The return value is a slice of buffer, from index `0`.
1527/// Deprecated; use `Dir.readLink`.
16101528pub fn readLink(pathname: []const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
16111529 return os.readlink(pathname, buffer);
16121530}
16131531
1614/// Same as `readLink`, except the parameter is null-terminated.
1532/// Deprecated; use `Dir.readLinkC`.
16151533pub fn readLinkC(pathname_c: [*]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
16161534 return os.readlinkC(pathname_c, buffer);
16171535}
......@@ -1718,6 +1636,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]const
17181636}
17191637
17201638/// `realpath`, except caller must free the returned memory.
1639/// TODO integrate with `Dir`
17211640pub fn realpathAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
17221641 var buf: [MAX_PATH_BYTES]u8 = undefined;
17231642 return mem.dupe(allocator, u8, try os.realpath(pathname, &buf));
......@@ -1726,6 +1645,9 @@ pub fn realpathAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
17261645test "" {
17271646 _ = makeDirAbsolute;
17281647 _ = makeDirAbsoluteZ;
1648 _ = copyFileAbsolute;
1649 _ = updateFileAbsolute;
1650 _ = Dir.copyFile;
17291651 _ = @import("fs/path.zig");
17301652 _ = @import("fs/file.zig");
17311653 _ = @import("fs/get_app_data_dir.zig");
lib/std/fs/watch.zig+1-1
......@@ -619,7 +619,7 @@ test "write a file, watch it, write it again" {
619619 if (true) return error.SkipZigTest;
620620
621621 try fs.cwd().makePath(test_tmp_dir);
622 defer os.deleteTree(test_tmp_dir) catch {};
622 defer fs.cwd().deleteTree(test_tmp_dir) catch {};
623623
624624 const allocator = std.heap.page_allocator;
625625 return testFsWatch(&allocator);
lib/std/hash/auto_hash.zig+8-4
......@@ -40,7 +40,9 @@ pub fn hashPointer(hasher: var, key: var, comptime strat: HashStrategy) void {
4040 .DeepRecursive => hashArray(hasher, key, .DeepRecursive),
4141 },
4242
43 .Many, .C, => switch (strat) {
43 .Many,
44 .C,
45 => switch (strat) {
4446 .Shallow => hash(hasher, @ptrToInt(key), .Shallow),
4547 else => @compileError(
4648 \\ unknown-length pointers and C pointers cannot be hashed deeply.
......@@ -236,9 +238,11 @@ test "hash slice shallow" {
236238 defer std.testing.allocator.destroy(array1);
237239 array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 };
238240 const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 };
239 const a = array1[0..];
240 const b = array2[0..];
241 const c = array1[0..3];
241 // TODO audit deep/shallow - maybe it has the wrong behavior with respect to array pointers and slices
242 var runtime_zero: usize = 0;
243 const a = array1[runtime_zero..];
244 const b = array2[runtime_zero..];
245 const c = array1[runtime_zero..3];
242246 testing.expect(testHashShallow(a) == testHashShallow(a));
243247 testing.expect(testHashShallow(a) != testHashShallow(array1));
244248 testing.expect(testHashShallow(a) != testHashShallow(b));
lib/std/hash/siphash.zig+3-3
......@@ -39,8 +39,8 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round
3939 pub fn init(key: []const u8) Self {
4040 assert(key.len >= 16);
4141
42 const k0 = mem.readIntSliceLittle(u64, key[0..8]);
43 const k1 = mem.readIntSliceLittle(u64, key[8..16]);
42 const k0 = mem.readIntLittle(u64, key[0..8]);
43 const k1 = mem.readIntLittle(u64, key[8..16]);
4444
4545 var d = Self{
4646 .v0 = k0 ^ 0x736f6d6570736575,
......@@ -111,7 +111,7 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round
111111 fn round(self: *Self, b: []const u8) void {
112112 assert(b.len == 8);
113113
114 const m = mem.readIntSliceLittle(u64, b[0..]);
114 const m = mem.readIntLittle(u64, b[0..8]);
115115 self.v3 ^= m;
116116
117117 // TODO this is a workaround, should be able to supply the value without a separate variable
lib/std/hash/wyhash.zig+1-1
......@@ -11,7 +11,7 @@ const primes = [_]u64{
1111
1212fn read_bytes(comptime bytes: u8, data: []const u8) u64 {
1313 const T = std.meta.IntType(false, 8 * bytes);
14 return mem.readIntSliceLittle(T, data[0..bytes]);
14 return mem.readIntLittle(T, data[0..bytes]);
1515}
1616
1717fn read_8bytes_swapped(data: []const u8) u64 {
lib/std/io/serialization.zig+5-1
......@@ -1,6 +1,10 @@
11const std = @import("../std.zig");
22const builtin = std.builtin;
33const io = std.io;
4const assert = std.debug.assert;
5const math = std.math;
6const meta = std.meta;
7const trait = meta.trait;
48
59pub const Packing = enum {
610 /// Pack data to byte alignment
......@@ -252,7 +256,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
252256 byte.* = if (t_bit_count < u8_bit_count) v else @truncate(u8, v);
253257 }
254258
255 try self.out_stream.write(&buffer);
259 try self.out_stream.writeAll(&buffer);
256260 }
257261
258262 /// Serializes the passed value into the stream
lib/std/json.zig+16-7
......@@ -2249,11 +2249,16 @@ pub const StringifyOptions = struct {
22492249 // TODO: allow picking if []u8 is string or array?
22502250};
22512251
2252pub const StringifyError = error{
2253 TooMuchData,
2254 DifferentData,
2255};
2256
22522257pub fn stringify(
22532258 value: var,
22542259 options: StringifyOptions,
22552260 out_stream: var,
2256) !void {
2261) StringifyError!void {
22572262 const T = @TypeOf(value);
22582263 switch (@typeInfo(T)) {
22592264 .Float, .ComptimeFloat => {
......@@ -2320,9 +2325,15 @@ pub fn stringify(
23202325 return;
23212326 },
23222327 .Pointer => |ptr_info| switch (ptr_info.size) {
2323 .One => {
2324 // TODO: avoid loops?
2325 return try stringify(value.*, options, out_stream);
2328 .One => switch (@typeInfo(ptr_info.child)) {
2329 .Array => {
2330 const Slice = []const std.meta.Elem(ptr_info.child);
2331 return stringify(@as(Slice, value), options, out_stream);
2332 },
2333 else => {
2334 // TODO: avoid loops?
2335 return stringify(value.*, options, out_stream);
2336 },
23262337 },
23272338 // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
23282339 .Slice => {
......@@ -2381,9 +2392,7 @@ pub fn stringify(
23812392 },
23822393 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
23832394 },
2384 .Array => |info| {
2385 return try stringify(value[0..], options, out_stream);
2386 },
2395 .Array => return stringify(&value, options, out_stream),
23872396 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
23882397 }
23892398 unreachable;
lib/std/math/big/int.zig+25-4
......@@ -373,6 +373,7 @@ pub const Int = struct {
373373 const d = switch (ch) {
374374 '0'...'9' => ch - '0',
375375 'a'...'f' => (ch - 'a') + 0xa,
376 'A'...'F' => (ch - 'A') + 0xa,
376377 else => return error.InvalidCharForDigit,
377378 };
378379
......@@ -393,8 +394,9 @@ pub const Int = struct {
393394
394395 /// Set self from the string representation `value`.
395396 ///
396 /// value must contain only digits <= `base`. Base prefixes are not allowed (e.g. 0x43 should
397 /// simply be 43).
397 /// `value` must contain only digits <= `base` and is case insensitive. Base prefixes are
398 /// not allowed (e.g. 0x43 should simply be 43). Underscores in the input string are
399 /// ignored and can be used as digit separators.
398400 ///
399401 /// Returns an error if memory could not be allocated or `value` has invalid digits for the
400402 /// requested base.
......@@ -415,6 +417,9 @@ pub const Int = struct {
415417 try self.set(0);
416418
417419 for (value[i..]) |ch| {
420 if (ch == '_') {
421 continue;
422 }
418423 const d = try charToDigit(ch, base);
419424
420425 const ap_d = Int.initFixed(([_]Limb{d})[0..]);
......@@ -520,13 +525,13 @@ pub const Int = struct {
520525 comptime fmt: []const u8,
521526 options: std.fmt.FormatOptions,
522527 out_stream: var,
523 ) FmtError!void {
528 ) !void {
524529 self.assertWritable();
525530 // TODO look at fmt and support other bases
526531 // TODO support read-only fixed integers
527532 const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");
528533 defer self.allocator.?.free(str);
529 return out_stream.print(str);
534 return out_stream.writeAll(str);
530535 }
531536
532537 /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
......@@ -1582,6 +1587,22 @@ test "big.int string negative" {
15821587 testing.expect((try a.to(i32)) == -1023);
15831588}
15841589
1590test "big.int string set number with underscores" {
1591 var a = try Int.init(testing.allocator);
1592 defer a.deinit();
1593
1594 try a.setString(10, "__1_2_0_3_1_7_2_4_1_2_0_____9_1__2__4_7_8_1_2_4_1_2_9_0_8_4_7_1_2_4___");
1595 testing.expect((try a.to(u128)) == 120317241209124781241290847124);
1596}
1597
1598test "big.int string set case insensitive number" {
1599 var a = try Int.init(testing.allocator);
1600 defer a.deinit();
1601
1602 try a.setString(16, "aB_cD_eF");
1603 testing.expect((try a.to(u32)) == 0xabcdef);
1604}
1605
15851606test "big.int string set bad char error" {
15861607 var a = try Int.init(testing.allocator);
15871608 defer a.deinit();
lib/std/mem.zig+137-75
......@@ -116,7 +116,7 @@ pub const Allocator = struct {
116116 pub fn allocSentinel(self: *Allocator, comptime Elem: type, n: usize, comptime sentinel: Elem) Error![:sentinel]Elem {
117117 var ptr = try self.alloc(Elem, n + 1);
118118 ptr[n] = sentinel;
119 return ptr[0 .. n :sentinel];
119 return ptr[0..n :sentinel];
120120 }
121121
122122 pub fn alignedAlloc(
......@@ -496,14 +496,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
496496 return true;
497497}
498498
499/// Deprecated. Use `span`.
499/// Deprecated. Use `spanZ`.
500500pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T {
501 return ptr[0..len(ptr) :0];
501 return ptr[0..lenZ(ptr) :0];
502502}
503503
504/// Deprecated. Use `span`.
504/// Deprecated. Use `spanZ`.
505505pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T {
506 return ptr[0..len(ptr) :0];
506 return ptr[0..lenZ(ptr) :0];
507507}
508508
509509/// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and
......@@ -548,6 +548,9 @@ test "Span" {
548548/// returns a slice. If there is a sentinel on the input type, there will be a
549549/// sentinel on the output type. The constness of the output type matches
550550/// the constness of the input type.
551///
552/// When there is both a sentinel and an array length or slice length, the
553/// length value is used instead of the sentinel.
551554pub fn span(ptr: var) Span(@TypeOf(ptr)) {
552555 const Result = Span(@TypeOf(ptr));
553556 const l = len(ptr);
......@@ -560,20 +563,42 @@ pub fn span(ptr: var) Span(@TypeOf(ptr)) {
560563
561564test "span" {
562565 var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 };
563 const ptr = array[0..2 :3].ptr;
566 const ptr = @as([*:3]u16, array[0..2 :3]);
564567 testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 }));
565568 testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 }));
566569}
567570
571/// Same as `span`, except when there is both a sentinel and an array
572/// length or slice length, scans the memory for the sentinel value
573/// rather than using the length.
574pub fn spanZ(ptr: var) Span(@TypeOf(ptr)) {
575 const Result = Span(@TypeOf(ptr));
576 const l = lenZ(ptr);
577 if (@typeInfo(Result).Pointer.sentinel) |s| {
578 return ptr[0..l :s];
579 } else {
580 return ptr[0..l];
581 }
582}
583
584test "spanZ" {
585 var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 };
586 const ptr = @as([*:3]u16, array[0..2 :3]);
587 testing.expect(eql(u16, spanZ(ptr), &[_]u16{ 1, 2 }));
588 testing.expect(eql(u16, spanZ(&array), &[_]u16{ 1, 2, 3, 4, 5 }));
589}
590
568591/// Takes a pointer to an array, an array, a sentinel-terminated pointer,
569592/// or a slice, and returns the length.
593/// In the case of a sentinel-terminated array, it uses the array length.
594/// For C pointers it assumes it is a pointer-to-many with a 0 sentinel.
570595pub fn len(ptr: var) usize {
571596 return switch (@typeInfo(@TypeOf(ptr))) {
572597 .Array => |info| info.len,
573598 .Pointer => |info| switch (info.size) {
574599 .One => switch (@typeInfo(info.child)) {
575 .Array => |x| x.len,
576 else => @compileError("invalid type given to std.mem.length"),
600 .Array => ptr.len,
601 else => @compileError("invalid type given to std.mem.len"),
577602 },
578603 .Many => if (info.sentinel) |sentinel|
579604 indexOfSentinel(info.child, sentinel, ptr)
......@@ -582,7 +607,7 @@ pub fn len(ptr: var) usize {
582607 .C => indexOfSentinel(info.child, 0, ptr),
583608 .Slice => ptr.len,
584609 },
585 else => @compileError("invalid type given to std.mem.length"),
610 else => @compileError("invalid type given to std.mem.len"),
586611 };
587612}
588613
......@@ -594,9 +619,67 @@ test "len" {
594619 testing.expect(len(&array) == 5);
595620 testing.expect(len(array[0..3]) == 3);
596621 array[2] = 0;
597 const ptr = array[0..2 :0].ptr;
622 const ptr = @as([*:0]u16, array[0..2 :0]);
598623 testing.expect(len(ptr) == 2);
599624 }
625 {
626 var array: [5:0]u16 = [_:0]u16{ 1, 2, 3, 4, 5 };
627 testing.expect(len(&array) == 5);
628 array[2] = 0;
629 testing.expect(len(&array) == 5);
630 }
631}
632
633/// Takes a pointer to an array, an array, a sentinel-terminated pointer,
634/// or a slice, and returns the length.
635/// In the case of a sentinel-terminated array, it scans the array
636/// for a sentinel and uses that for the length, rather than using the array length.
637/// For C pointers it assumes it is a pointer-to-many with a 0 sentinel.
638pub fn lenZ(ptr: var) usize {
639 return switch (@typeInfo(@TypeOf(ptr))) {
640 .Array => |info| if (info.sentinel) |sentinel|
641 indexOfSentinel(info.child, sentinel, &ptr)
642 else
643 info.len,
644 .Pointer => |info| switch (info.size) {
645 .One => switch (@typeInfo(info.child)) {
646 .Array => |x| if (x.sentinel) |sentinel|
647 indexOfSentinel(x.child, sentinel, ptr)
648 else
649 ptr.len,
650 else => @compileError("invalid type given to std.mem.lenZ"),
651 },
652 .Many => if (info.sentinel) |sentinel|
653 indexOfSentinel(info.child, sentinel, ptr)
654 else
655 @compileError("length of pointer with no sentinel"),
656 .C => indexOfSentinel(info.child, 0, ptr),
657 .Slice => if (info.sentinel) |sentinel|
658 indexOfSentinel(info.child, sentinel, ptr.ptr)
659 else
660 ptr.len,
661 },
662 else => @compileError("invalid type given to std.mem.lenZ"),
663 };
664}
665
666test "lenZ" {
667 testing.expect(lenZ("aoeu") == 4);
668
669 {
670 var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 };
671 testing.expect(lenZ(&array) == 5);
672 testing.expect(lenZ(array[0..3]) == 3);
673 array[2] = 0;
674 const ptr = @as([*:0]u16, array[0..2 :0]);
675 testing.expect(lenZ(ptr) == 2);
676 }
677 {
678 var array: [5:0]u16 = [_:0]u16{ 1, 2, 3, 4, 5 };
679 testing.expect(lenZ(&array) == 5);
680 array[2] = 0;
681 testing.expect(lenZ(&array) == 2);
682 }
600683}
601684
602685pub fn indexOfSentinel(comptime Elem: type, comptime sentinel: Elem, ptr: [*:sentinel]const Elem) usize {
......@@ -810,8 +893,7 @@ pub const readIntBig = switch (builtin.endian) {
810893pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
811894 const n = @divExact(T.bit_count, 8);
812895 assert(bytes.len >= n);
813 // TODO https://github.com/ziglang/zig/issues/863
814 return readIntNative(T, @ptrCast(*const [n]u8, bytes.ptr));
896 return readIntNative(T, bytes[0..n]);
815897}
816898
817899/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
......@@ -849,8 +931,7 @@ pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, en
849931pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
850932 const n = @divExact(T.bit_count, 8);
851933 assert(bytes.len >= n);
852 // TODO https://github.com/ziglang/zig/issues/863
853 return readInt(T, @ptrCast(*const [n]u8, bytes.ptr), endian);
934 return readInt(T, bytes[0..n], endian);
854935}
855936
856937test "comptime read/write int" {
......@@ -1572,24 +1653,24 @@ pub fn nativeToBig(comptime T: type, x: T) T {
15721653}
15731654
15741655fn AsBytesReturnType(comptime P: type) type {
1575 if (comptime !trait.isSingleItemPtr(P))
1656 if (!trait.isSingleItemPtr(P))
15761657 @compileError("expected single item pointer, passed " ++ @typeName(P));
15771658
1578 const size = @as(usize, @sizeOf(meta.Child(P)));
1579 const alignment = comptime meta.alignment(P);
1659 const size = @sizeOf(meta.Child(P));
1660 const alignment = meta.alignment(P);
15801661
15811662 if (alignment == 0) {
1582 if (comptime trait.isConstPtr(P))
1663 if (trait.isConstPtr(P))
15831664 return *const [size]u8;
15841665 return *[size]u8;
15851666 }
15861667
1587 if (comptime trait.isConstPtr(P))
1668 if (trait.isConstPtr(P))
15881669 return *align(alignment) const [size]u8;
15891670 return *align(alignment) [size]u8;
15901671}
15911672
1592///Given a pointer to a single item, returns a slice of the underlying bytes, preserving constness.
1673/// Given a pointer to a single item, returns a slice of the underlying bytes, preserving constness.
15931674pub fn asBytes(ptr: var) AsBytesReturnType(@TypeOf(ptr)) {
15941675 const P = @TypeOf(ptr);
15951676 return @ptrCast(AsBytesReturnType(P), ptr);
......@@ -1736,34 +1817,50 @@ fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type {
17361817}
17371818
17381819pub fn bytesAsSlice(comptime T: type, bytes: var) BytesAsSliceReturnType(T, @TypeOf(bytes)) {
1739 const bytesSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(bytes))) bytes[0..] else bytes;
1740
17411820 // let's not give an undefined pointer to @ptrCast
17421821 // it may be equal to zero and fail a null check
1743 if (bytesSlice.len == 0) {
1822 if (bytes.len == 0) {
17441823 return &[0]T{};
17451824 }
17461825
1747 const bytesType = @TypeOf(bytesSlice);
1748 const alignment = comptime meta.alignment(bytesType);
1826 const Bytes = @TypeOf(bytes);
1827 const alignment = comptime meta.alignment(Bytes);
17491828
1750 const castTarget = if (comptime trait.isConstPtr(bytesType)) [*]align(alignment) const T else [*]align(alignment) T;
1829 const cast_target = if (comptime trait.isConstPtr(Bytes)) [*]align(alignment) const T else [*]align(alignment) T;
17511830
1752 return @ptrCast(castTarget, bytesSlice.ptr)[0..@divExact(bytes.len, @sizeOf(T))];
1831 return @ptrCast(cast_target, bytes)[0..@divExact(bytes.len, @sizeOf(T))];
17531832}
17541833
17551834test "bytesAsSlice" {
1756 const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };
1757 const slice = bytesAsSlice(u16, bytes[0..]);
1758 testing.expect(slice.len == 2);
1759 testing.expect(bigToNative(u16, slice[0]) == 0xDEAD);
1760 testing.expect(bigToNative(u16, slice[1]) == 0xBEEF);
1835 {
1836 const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };
1837 const slice = bytesAsSlice(u16, bytes[0..]);
1838 testing.expect(slice.len == 2);
1839 testing.expect(bigToNative(u16, slice[0]) == 0xDEAD);
1840 testing.expect(bigToNative(u16, slice[1]) == 0xBEEF);
1841 }
1842 {
1843 const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };
1844 var runtime_zero: usize = 0;
1845 const slice = bytesAsSlice(u16, bytes[runtime_zero..]);
1846 testing.expect(slice.len == 2);
1847 testing.expect(bigToNative(u16, slice[0]) == 0xDEAD);
1848 testing.expect(bigToNative(u16, slice[1]) == 0xBEEF);
1849 }
17611850}
17621851
17631852test "bytesAsSlice keeps pointer alignment" {
1764 var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 };
1765 const numbers = bytesAsSlice(u32, bytes[0..]);
1766 comptime testing.expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32);
1853 {
1854 var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 };
1855 const numbers = bytesAsSlice(u32, bytes[0..]);
1856 comptime testing.expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32);
1857 }
1858 {
1859 var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 };
1860 var runtime_zero: usize = 0;
1861 const numbers = bytesAsSlice(u32, bytes[runtime_zero..]);
1862 comptime testing.expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32);
1863 }
17671864}
17681865
17691866test "bytesAsSlice on a packed struct" {
......@@ -1799,21 +1896,19 @@ fn SliceAsBytesReturnType(comptime sliceType: type) type {
17991896}
18001897
18011898pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) {
1802 const actualSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(slice))) slice[0..] else slice;
1803 const actualSliceTypeInfo = @typeInfo(@TypeOf(actualSlice)).Pointer;
1899 const Slice = @TypeOf(slice);
18041900
18051901 // let's not give an undefined pointer to @ptrCast
18061902 // it may be equal to zero and fail a null check
1807 if (actualSlice.len == 0 and actualSliceTypeInfo.sentinel == null) {
1903 if (slice.len == 0 and comptime meta.sentinel(Slice) == null) {
18081904 return &[0]u8{};
18091905 }
18101906
1811 const sliceType = @TypeOf(actualSlice);
1812 const alignment = comptime meta.alignment(sliceType);
1907 const alignment = comptime meta.alignment(Slice);
18131908
1814 const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8;
1909 const cast_target = if (comptime trait.isConstPtr(Slice)) [*]align(alignment) const u8 else [*]align(alignment) u8;
18151910
1816 return @ptrCast(castTarget, actualSlice.ptr)[0 .. actualSlice.len * @sizeOf(comptime meta.Child(sliceType))];
1911 return @ptrCast(cast_target, slice)[0 .. slice.len * @sizeOf(meta.Elem(Slice))];
18171912}
18181913
18191914test "sliceAsBytes" {
......@@ -1883,39 +1978,6 @@ test "sliceAsBytes and bytesAsSlice back" {
18831978 testing.expect(bytes[11] == math.maxInt(u8));
18841979}
18851980
1886fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
1887 if (trait.isConstPtr(T))
1888 return *const [length]meta.Child(meta.Child(T));
1889 return *[length]meta.Child(meta.Child(T));
1890}
1891
1892/// Given a pointer to an array, returns a pointer to a portion of that array, preserving constness.
1893/// TODO this will be obsoleted by https://github.com/ziglang/zig/issues/863
1894pub fn subArrayPtr(
1895 ptr: var,
1896 comptime start: usize,
1897 comptime length: usize,
1898) SubArrayPtrReturnType(@TypeOf(ptr), length) {
1899 assert(start + length <= ptr.*.len);
1900
1901 const ReturnType = SubArrayPtrReturnType(@TypeOf(ptr), length);
1902 const T = meta.Child(meta.Child(@TypeOf(ptr)));
1903 return @ptrCast(ReturnType, &ptr[start]);
1904}
1905
1906test "subArrayPtr" {
1907 const a1: [6]u8 = "abcdef".*;
1908 const sub1 = subArrayPtr(&a1, 2, 3);
1909 testing.expect(eql(u8, sub1, "cde"));
1910
1911 var a2: [6]u8 = "abcdef".*;
1912 var sub2 = subArrayPtr(&a2, 2, 3);
1913
1914 testing.expect(eql(u8, sub2, "cde"));
1915 sub2[1] = 'X';
1916 testing.expect(eql(u8, &a2, "abcXef"));
1917}
1918
19191981/// Round an address up to the nearest aligned address
19201982/// The alignment must be a power of 2 and greater than 0.
19211983pub fn alignForward(addr: usize, alignment: usize) usize {
lib/std/meta.zig+50-15
......@@ -104,7 +104,7 @@ pub fn Child(comptime T: type) type {
104104 .Array => |info| info.child,
105105 .Pointer => |info| info.child,
106106 .Optional => |info| info.child,
107 else => @compileError("Expected pointer, optional, or array type, " ++ "found '" ++ @typeName(T) ++ "'"),
107 else => @compileError("Expected pointer, optional, or array type, found '" ++ @typeName(T) ++ "'"),
108108 };
109109}
110110
......@@ -115,30 +115,65 @@ test "std.meta.Child" {
115115 testing.expect(Child(?u8) == u8);
116116}
117117
118/// Given a type with a sentinel e.g. `[:0]u8`, returns the sentinel
119pub fn Sentinel(comptime T: type) Child(T) {
120 // comptime asserts that ptr has a sentinel
118/// Given a "memory span" type, returns the "element type".
119pub fn Elem(comptime T: type) type {
121120 switch (@typeInfo(T)) {
122 .Array => |arrayInfo| {
123 return comptime arrayInfo.sentinel.?;
121 .Array => |info| return info.child,
122 .Pointer => |info| switch (info.size) {
123 .One => switch (@typeInfo(info.child)) {
124 .Array => |array_info| return array_info.child,
125 else => {},
126 },
127 .Many, .C, .Slice => return info.child,
124128 },
125 .Pointer => |ptrInfo| {
126 switch (ptrInfo.size) {
127 .Many, .Slice => {
128 return comptime ptrInfo.sentinel.?;
129 else => {},
130 }
131 @compileError("Expected pointer, slice, or array, found '" ++ @typeName(T) ++ "'");
132}
133
134test "std.meta.Elem" {
135 testing.expect(Elem([1]u8) == u8);
136 testing.expect(Elem([*]u8) == u8);
137 testing.expect(Elem([]u8) == u8);
138 testing.expect(Elem(*[10]u8) == u8);
139}
140
141/// Given a type which can have a sentinel e.g. `[:0]u8`, returns the sentinel value,
142/// or `null` if there is not one.
143/// Types which cannot possibly have a sentinel will be a compile error.
144pub fn sentinel(comptime T: type) ?Elem(T) {
145 switch (@typeInfo(T)) {
146 .Array => |info| return info.sentinel,
147 .Pointer => |info| {
148 switch (info.size) {
149 .Many, .Slice => return info.sentinel,
150 .One => switch (@typeInfo(info.child)) {
151 .Array => |array_info| return array_info.sentinel,
152 else => {},
129153 },
130154 else => {},
131155 }
132156 },
133157 else => {},
134158 }
135 @compileError("not a sentinel type, found '" ++ @typeName(T) ++ "'");
159 @compileError("type '" ++ @typeName(T) ++ "' cannot possibly have a sentinel");
136160}
137161
138test "std.meta.Sentinel" {
139 testing.expectEqual(@as(u8, 0), Sentinel([:0]u8));
140 testing.expectEqual(@as(u8, 0), Sentinel([*:0]u8));
141 testing.expectEqual(@as(u8, 0), Sentinel([5:0]u8));
162test "std.meta.sentinel" {
163 testSentinel();
164 comptime testSentinel();
165}
166
167fn testSentinel() void {
168 testing.expectEqual(@as(u8, 0), sentinel([:0]u8).?);
169 testing.expectEqual(@as(u8, 0), sentinel([*:0]u8).?);
170 testing.expectEqual(@as(u8, 0), sentinel([5:0]u8).?);
171 testing.expectEqual(@as(u8, 0), sentinel(*const [5:0]u8).?);
172
173 testing.expect(sentinel([]u8) == null);
174 testing.expect(sentinel([*]u8) == null);
175 testing.expect(sentinel([5]u8) == null);
176 testing.expect(sentinel(*const [5]u8) == null);
142177}
143178
144179pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
lib/std/meta/trait.zig+7-5
......@@ -230,9 +230,10 @@ pub fn isSingleItemPtr(comptime T: type) bool {
230230
231231test "std.meta.trait.isSingleItemPtr" {
232232 const array = [_]u8{0} ** 10;
233 testing.expect(isSingleItemPtr(@TypeOf(&array[0])));
234 testing.expect(!isSingleItemPtr(@TypeOf(array)));
235 testing.expect(!isSingleItemPtr(@TypeOf(array[0..1])));
233 comptime testing.expect(isSingleItemPtr(@TypeOf(&array[0])));
234 comptime testing.expect(!isSingleItemPtr(@TypeOf(array)));
235 var runtime_zero: usize = 0;
236 testing.expect(!isSingleItemPtr(@TypeOf(array[runtime_zero..1])));
236237}
237238
238239pub fn isManyItemPtr(comptime T: type) bool {
......@@ -259,7 +260,8 @@ pub fn isSlice(comptime T: type) bool {
259260
260261test "std.meta.trait.isSlice" {
261262 const array = [_]u8{0} ** 10;
262 testing.expect(isSlice(@TypeOf(array[0..])));
263 var runtime_zero: usize = 0;
264 testing.expect(isSlice(@TypeOf(array[runtime_zero..])));
263265 testing.expect(!isSlice(@TypeOf(array)));
264266 testing.expect(!isSlice(@TypeOf(&array[0])));
265267}
......@@ -276,7 +278,7 @@ pub fn isIndexable(comptime T: type) bool {
276278
277279test "std.meta.trait.isIndexable" {
278280 const array = [_]u8{0} ** 10;
279 const slice = array[0..];
281 const slice = @as([]const u8, &array);
280282
281283 testing.expect(isIndexable(@TypeOf(array)));
282284 testing.expect(isIndexable(@TypeOf(&array)));
lib/std/net.zig+6-4
......@@ -612,8 +612,7 @@ fn linuxLookupName(
612612 } else {
613613 mem.copy(u8, &sa6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff");
614614 mem.copy(u8, &da6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff");
615 // TODO https://github.com/ziglang/zig/issues/863
616 mem.writeIntNative(u32, @ptrCast(*[4]u8, da6.addr[12..].ptr), addr.addr.in.addr);
615 mem.writeIntNative(u32, da6.addr[12..], addr.addr.in.addr);
617616 da4.addr = addr.addr.in.addr;
618617 da = @ptrCast(*os.sockaddr, &da4);
619618 dalen = @sizeOf(os.sockaddr_in);
......@@ -821,7 +820,7 @@ fn linuxLookupNameFromHosts(
821820 // Skip to the delimiter in the stream, to fix parsing
822821 try stream.skipUntilDelimiterOrEof('\n');
823822 // Use the truncated line. A truncated comment or hostname will be handled correctly.
824 break :blk line_buf[0..];
823 break :blk &line_buf;
825824 },
826825 else => |e| return e,
827826 }) |line| {
......@@ -958,7 +957,10 @@ fn linuxLookupNameFromDns(
958957 }
959958 }
960959
961 var ap = [2][]u8{ apbuf[0][0..0], apbuf[1][0..0] };
960 var ap = [2][]u8{ apbuf[0], apbuf[1] };
961 ap[0].len = 0;
962 ap[1].len = 0;
963
962964 try resMSendRc(qp[0..nq], ap[0..nq], apbuf[0..nq], rc);
963965
964966 var i: usize = 0;
lib/std/os.zig+143-23
......@@ -461,13 +461,11 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
461461 );
462462
463463 switch (rc) {
464 .SUCCESS => {},
464 .SUCCESS => return,
465465 .INVALID_HANDLE => unreachable, // Handle not open for writing
466466 .ACCESS_DENIED => return error.CannotTruncate,
467467 else => return windows.unexpectedStatus(rc),
468468 }
469
470 return;
471469 }
472470
473471 while (true) {
......@@ -852,6 +850,7 @@ pub const OpenError = error{
852850
853851/// Open and possibly create a file. Keeps trying if it gets interrupted.
854852/// See also `openC`.
853/// TODO support windows
855854pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {
856855 const file_path_c = try toPosixPath(file_path);
857856 return openC(&file_path_c, flags, perm);
......@@ -859,6 +858,7 @@ pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {
859858
860859/// Open and possibly create a file. Keeps trying if it gets interrupted.
861860/// See also `open`.
861/// TODO support windows
862862pub fn openC(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {
863863 while (true) {
864864 const rc = system.open(file_path, flags, perm);
......@@ -892,6 +892,7 @@ pub fn openC(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {
892892/// Open and possibly create a file. Keeps trying if it gets interrupted.
893893/// `file_path` is relative to the open directory handle `dir_fd`.
894894/// See also `openatC`.
895/// TODO support windows
895896pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) OpenError!fd_t {
896897 const file_path_c = try toPosixPath(file_path);
897898 return openatC(dir_fd, &file_path_c, flags, mode);
......@@ -900,6 +901,7 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) Ope
900901/// Open and possibly create a file. Keeps trying if it gets interrupted.
901902/// `file_path` is relative to the open directory handle `dir_fd`.
902903/// See also `openat`.
904/// TODO support windows
903905pub fn openatC(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: mode_t) OpenError!fd_t {
904906 while (true) {
905907 const rc = system.openat(dir_fd, file_path, flags, mode);
......@@ -1140,24 +1142,6 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8)
11401142 allocator.free(envp_buf);
11411143}
11421144
1143pub const FcntlError = error{
1144 /// The file is locked by another process
1145 FileLocked,
1146} || UnexpectedError;
1147
1148/// Attempts to get lock the file, blocking if the file is locked.
1149pub fn fcntl(fd: fd_t, cmd: i32, flock_p: *Flock) FcntlError!void {
1150 while (true) {
1151 switch (errno(system.fcntl(fd, cmd, flock_p))) {
1152 0 => return,
1153 EACCES => return error.FileLocked,
1154 EAGAIN => return error.FileLocked,
1155 EINTR => continue,
1156 else => |err| return unexpectedErrno(err),
1157 }
1158 }
1159}
1160
11611145/// Get an environment variable.
11621146/// See also `getenvZ`.
11631147pub fn getenv(key: []const u8) ?[]const u8 {
......@@ -1545,6 +1529,9 @@ const RenameError = error{
15451529 RenameAcrossMountPoints,
15461530 InvalidUtf8,
15471531 BadPathName,
1532 NoDevice,
1533 SharingViolation,
1534 PipeBusy,
15481535} || UnexpectedError;
15491536
15501537/// Change the name or location of a file.
......@@ -1598,6 +1585,113 @@ pub fn renameW(old_path: [*:0]const u16, new_path: [*:0]const u16) RenameError!v
15981585 return windows.MoveFileExW(old_path, new_path, flags);
15991586}
16001587
1588/// Change the name or location of a file based on an open directory handle.
1589pub fn renameat(
1590 old_dir_fd: fd_t,
1591 old_path: []const u8,
1592 new_dir_fd: fd_t,
1593 new_path: []const u8,
1594) RenameError!void {
1595 if (builtin.os.tag == .windows) {
1596 const old_path_w = try windows.sliceToPrefixedFileW(old_path);
1597 const new_path_w = try windows.sliceToPrefixedFileW(new_path);
1598 return renameatW(old_dir_fd, &old_path_w, new_dir_fd, &new_path_w, windows.TRUE);
1599 } else {
1600 const old_path_c = try toPosixPath(old_path);
1601 const new_path_c = try toPosixPath(new_path);
1602 return renameatZ(old_dir_fd, &old_path_c, new_dir_fd, &new_path_c);
1603 }
1604}
1605
1606/// Same as `renameat` except the parameters are null-terminated byte arrays.
1607pub fn renameatZ(
1608 old_dir_fd: fd_t,
1609 old_path: [*:0]const u8,
1610 new_dir_fd: fd_t,
1611 new_path: [*:0]const u8,
1612) RenameError!void {
1613 if (builtin.os.tag == .windows) {
1614 const old_path_w = try windows.cStrToPrefixedFileW(old_path);
1615 const new_path_w = try windows.cStrToPrefixedFileW(new_path);
1616 return renameatW(old_dir_fd, &old_path_w, new_dir_fd, &new_path_w, windows.TRUE);
1617 }
1618
1619 switch (errno(system.renameat(old_dir_fd, old_path, new_dir_fd, new_path))) {
1620 0 => return,
1621 EACCES => return error.AccessDenied,
1622 EPERM => return error.AccessDenied,
1623 EBUSY => return error.FileBusy,
1624 EDQUOT => return error.DiskQuota,
1625 EFAULT => unreachable,
1626 EINVAL => unreachable,
1627 EISDIR => return error.IsDir,
1628 ELOOP => return error.SymLinkLoop,
1629 EMLINK => return error.LinkQuotaExceeded,
1630 ENAMETOOLONG => return error.NameTooLong,
1631 ENOENT => return error.FileNotFound,
1632 ENOTDIR => return error.NotDir,
1633 ENOMEM => return error.SystemResources,
1634 ENOSPC => return error.NoSpaceLeft,
1635 EEXIST => return error.PathAlreadyExists,
1636 ENOTEMPTY => return error.PathAlreadyExists,
1637 EROFS => return error.ReadOnlyFileSystem,
1638 EXDEV => return error.RenameAcrossMountPoints,
1639 else => |err| return unexpectedErrno(err),
1640 }
1641}
1642
1643/// Same as `renameat` except the parameters are null-terminated UTF16LE encoded byte arrays.
1644/// Assumes target is Windows.
1645/// TODO these args can actually be slices when using ntdll. audit the rest of the W functions too.
1646pub fn renameatW(
1647 old_dir_fd: fd_t,
1648 old_path: [*:0]const u16,
1649 new_dir_fd: fd_t,
1650 new_path_w: [*:0]const u16,
1651 ReplaceIfExists: windows.BOOLEAN,
1652) RenameError!void {
1653 const access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE;
1654 const src_fd = try windows.OpenFileW(old_dir_fd, old_path, null, access_mask, windows.FILE_OPEN);
1655 defer windows.CloseHandle(src_fd);
1656
1657 const struct_buf_len = @sizeOf(windows.FILE_RENAME_INFORMATION) + (MAX_PATH_BYTES - 1);
1658 var rename_info_buf: [struct_buf_len]u8 align(@alignOf(windows.FILE_RENAME_INFORMATION)) = undefined;
1659 const new_path = mem.span(new_path_w);
1660 const struct_len = @sizeOf(windows.FILE_RENAME_INFORMATION) - 1 + new_path.len * 2;
1661 if (struct_len > struct_buf_len) return error.NameTooLong;
1662
1663 const rename_info = @ptrCast(*windows.FILE_RENAME_INFORMATION, &rename_info_buf);
1664
1665 rename_info.* = .{
1666 .ReplaceIfExists = ReplaceIfExists,
1667 .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(new_path_w)) null else new_dir_fd,
1668 .FileNameLength = @intCast(u32, new_path.len * 2), // already checked error.NameTooLong
1669 .FileName = undefined,
1670 };
1671 std.mem.copy(u16, @as([*]u16, &rename_info.FileName)[0..new_path.len], new_path);
1672
1673 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
1674
1675 const rc = windows.ntdll.NtSetInformationFile(
1676 src_fd,
1677 &io_status_block,
1678 rename_info,
1679 @intCast(u32, struct_len), // already checked for error.NameTooLong
1680 .FileRenameInformation,
1681 );
1682
1683 switch (rc) {
1684 .SUCCESS => return,
1685 .INVALID_HANDLE => unreachable,
1686 .INVALID_PARAMETER => unreachable,
1687 .OBJECT_PATH_SYNTAX_BAD => unreachable,
1688 .ACCESS_DENIED => return error.AccessDenied,
1689 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
1690 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
1691 else => return windows.unexpectedStatus(rc),
1692 }
1693}
1694
16011695pub const MakeDirError = error{
16021696 AccessDenied,
16031697 DiskQuota,
......@@ -2090,7 +2184,7 @@ const ListenError = error{
20902184 OperationNotSupported,
20912185} || UnexpectedError;
20922186
2093pub fn listen(sockfd: i32, backlog: u32) ListenError!void {
2187pub fn listen(sockfd: fd_t, backlog: u32) ListenError!void {
20942188 const rc = system.listen(sockfd, backlog);
20952189 switch (errno(rc)) {
20962190 0 => return,
......@@ -2381,7 +2475,7 @@ pub fn connect(sockfd: fd_t, sock_addr: *const sockaddr, len: socklen_t) Connect
23812475 }
23822476}
23832477
2384pub fn getsockoptError(sockfd: i32) ConnectError!void {
2478pub fn getsockoptError(sockfd: fd_t) ConnectError!void {
23852479 var err_code: u32 = undefined;
23862480 var size: u32 = @sizeOf(u32);
23872481 const rc = system.getsockopt(sockfd, SOL_SOCKET, SO_ERROR, @ptrCast([*]u8, &err_code), &size);
......@@ -3069,6 +3163,31 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
30693163 }
30703164}
30713165
3166pub const FcntlError = error{
3167 PermissionDenied,
3168 FileBusy,
3169 ProcessFdQuotaExceeded,
3170 Locked,
3171} || UnexpectedError;
3172
3173pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize {
3174 while (true) {
3175 const rc = system.fcntl(fd, cmd, arg);
3176 switch (errno(rc)) {
3177 0 => return @intCast(usize, rc),
3178 EINTR => continue,
3179 EACCES => return error.Locked,
3180 EBADF => unreachable,
3181 EBUSY => return error.FileBusy,
3182 EINVAL => unreachable, // invalid parameters
3183 EPERM => return error.PermissionDenied,
3184 EMFILE => return error.ProcessFdQuotaExceeded,
3185 ENOTDIR => unreachable, // invalid parameter
3186 else => |err| return unexpectedErrno(err),
3187 }
3188 }
3189}
3190
30723191pub const RealPathError = error{
30733192 FileNotFound,
30743193 AccessDenied,
......@@ -3143,6 +3262,7 @@ pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP
31433262}
31443263
31453264/// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded.
3265/// TODO use ntdll for better semantics
31463266pub fn realpathW(pathname: [*:0]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
31473267 const h_file = try windows.CreateFileW(
31483268 pathname,
lib/std/os/bits/dragonfly.zig+2
......@@ -283,6 +283,8 @@ pub const F_LOCK = 1;
283283pub const F_TLOCK = 2;
284284pub const F_TEST = 3;
285285
286pub const FD_CLOEXEC = 1;
287
286288pub const AT_FDCWD = -328243;
287289pub const AT_SYMLINK_NOFOLLOW = 1;
288290pub const AT_REMOVEDIR = 2;
lib/std/os/bits/freebsd.zig+2
......@@ -372,6 +372,8 @@ pub const F_GETOWN_EX = 16;
372372
373373pub const F_GETOWNER_UIDS = 17;
374374
375pub const FD_CLOEXEC = 1;
376
375377pub const SEEK_SET = 0;
376378pub const SEEK_CUR = 1;
377379pub const SEEK_END = 2;
lib/std/os/bits/linux.zig+2
......@@ -136,6 +136,8 @@ pub const MAP_FIXED_NOREPLACE = 0x100000;
136136/// For anonymous mmap, memory could be uninitialized
137137pub const MAP_UNINITIALIZED = 0x4000000;
138138
139pub const FD_CLOEXEC = 1;
140
139141pub const F_OK = 0;
140142pub const X_OK = 1;
141143pub const W_OK = 2;
lib/std/os/bits/netbsd.zig+2
......@@ -327,6 +327,8 @@ pub const F_RDLCK = 1;
327327pub const F_WRLCK = 3;
328328pub const F_UNLCK = 2;
329329
330pub const FD_CLOEXEC = 1;
331
330332pub const SEEK_SET = 0;
331333pub const SEEK_CUR = 1;
332334pub const SEEK_END = 2;
lib/std/os/linux.zig+8-8
......@@ -219,10 +219,6 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of
219219 }
220220}
221221
222pub fn fcntl(fd: fd_t, cmd: i32, arg: ?*c_void) usize {
223 return syscall3(SYS_fcntl, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, cmd)), @ptrToInt(arg));
224}
225
226222pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize {
227223 return syscall3(SYS_mprotect, @ptrToInt(address), length, protection);
228224}
......@@ -469,17 +465,17 @@ pub fn renameat(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const
469465 return syscall4(
470466 SYS_renameat,
471467 @bitCast(usize, @as(isize, oldfd)),
472 @ptrToInt(old),
468 @ptrToInt(oldpath),
473469 @bitCast(usize, @as(isize, newfd)),
474 @ptrToInt(new),
470 @ptrToInt(newpath),
475471 );
476472 } else {
477473 return syscall5(
478474 SYS_renameat2,
479475 @bitCast(usize, @as(isize, oldfd)),
480 @ptrToInt(old),
476 @ptrToInt(oldpath),
481477 @bitCast(usize, @as(isize, newfd)),
482 @ptrToInt(new),
478 @ptrToInt(newpath),
483479 0,
484480 );
485481 }
......@@ -592,6 +588,10 @@ pub fn waitpid(pid: pid_t, status: *u32, flags: u32) usize {
592588 return syscall4(SYS_wait4, @bitCast(usize, @as(isize, pid)), @ptrToInt(status), flags, 0);
593589}
594590
591pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize {
592 return syscall3(SYS_fcntl, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, cmd)), arg);
593}
594
595595var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);
596596
597597// We must follow the C calling convention when we call into the VDSO
lib/std/os/test.zig+44-12
......@@ -1,7 +1,8 @@
11const std = @import("../std.zig");
22const os = std.os;
33const testing = std.testing;
4const expect = std.testing.expect;
4const expect = testing.expect;
5const expectEqual = testing.expectEqual;
56const io = std.io;
67const fs = std.fs;
78const mem = std.mem;
......@@ -19,8 +20,8 @@ test "makePath, put some files in it, deleteTree" {
1920 try fs.cwd().makePath("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c");
2021 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c" ++ fs.path.sep_str ++ "file.txt", "nonsense");
2122 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "file2.txt", "blah");
22 try fs.deleteTree("os_test_tmp");
23 if (fs.cwd().openDirTraverse("os_test_tmp")) |dir| {
23 try fs.cwd().deleteTree("os_test_tmp");
24 if (fs.cwd().openDir("os_test_tmp", .{})) |dir| {
2425 @panic("expected error");
2526 } else |err| {
2627 expect(err == error.FileNotFound);
......@@ -37,7 +38,7 @@ test "access file" {
3738
3839 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", "");
3940 try os.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", os.F_OK);
40 try fs.deleteTree("os_test_tmp");
41 try fs.cwd().deleteTree("os_test_tmp");
4142}
4243
4344fn testThreadIdFn(thread_id: *Thread.Id) void {
......@@ -46,9 +47,9 @@ fn testThreadIdFn(thread_id: *Thread.Id) void {
4647
4748test "sendfile" {
4849 try fs.cwd().makePath("os_test_tmp");
49 defer fs.deleteTree("os_test_tmp") catch {};
50 defer fs.cwd().deleteTree("os_test_tmp") catch {};
5051
51 var dir = try fs.cwd().openDirList("os_test_tmp");
52 var dir = try fs.cwd().openDir("os_test_tmp", .{});
5253 defer dir.close();
5354
5455 const line1 = "line1\n";
......@@ -112,14 +113,16 @@ test "fs.copyFile" {
112113 const dest_file = "tmp_test_copy_file2.txt";
113114 const dest_file2 = "tmp_test_copy_file3.txt";
114115
115 try fs.cwd().writeFile(src_file, data);
116 defer fs.cwd().deleteFile(src_file) catch {};
116 const cwd = fs.cwd();
117117
118 try fs.copyFile(src_file, dest_file);
119 defer fs.cwd().deleteFile(dest_file) catch {};
118 try cwd.writeFile(src_file, data);
119 defer cwd.deleteFile(src_file) catch {};
120120
121 try fs.copyFileMode(src_file, dest_file2, File.default_mode);
122 defer fs.cwd().deleteFile(dest_file2) catch {};
121 try cwd.copyFile(src_file, cwd, dest_file, .{});
122 defer cwd.deleteFile(dest_file) catch {};
123
124 try cwd.copyFile(src_file, cwd, dest_file2, .{ .override_mode = File.default_mode });
125 defer cwd.deleteFile(dest_file2) catch {};
123126
124127 try expectFileContents(dest_file, data);
125128 try expectFileContents(dest_file2, data);
......@@ -446,3 +449,32 @@ test "getenv" {
446449 expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);
447450 }
448451}
452
453test "fcntl" {
454 if (builtin.os.tag == .windows)
455 return error.SkipZigTest;
456
457 const test_out_file = "os_tmp_test";
458
459 const file = try fs.cwd().createFile(test_out_file, .{});
460 defer {
461 file.close();
462 fs.cwd().deleteFile(test_out_file) catch {};
463 }
464
465 // Note: The test assumes createFile opens the file with O_CLOEXEC
466 {
467 const flags = try os.fcntl(file.handle, os.F_GETFD, 0);
468 expect((flags & os.FD_CLOEXEC) != 0);
469 }
470 {
471 _ = try os.fcntl(file.handle, os.F_SETFD, 0);
472 const flags = try os.fcntl(file.handle, os.F_GETFD, 0);
473 expect((flags & os.FD_CLOEXEC) == 0);
474 }
475 {
476 _ = try os.fcntl(file.handle, os.F_SETFD, os.FD_CLOEXEC);
477 const flags = try os.fcntl(file.handle, os.F_GETFD, 0);
478 expect((flags & os.FD_CLOEXEC) != 0);
479 }
480}
lib/std/os/windows.zig+85-1
......@@ -88,6 +88,82 @@ pub fn CreateFileW(
8888 return result;
8989}
9090
91pub const OpenError = error{
92 IsDir,
93 FileNotFound,
94 NoDevice,
95 SharingViolation,
96 AccessDenied,
97 PipeBusy,
98 PathAlreadyExists,
99 Unexpected,
100 NameTooLong,
101};
102
103/// TODO rename to CreateFileW
104/// TODO actually we don't need the path parameter to be null terminated
105pub fn OpenFileW(
106 dir: ?HANDLE,
107 sub_path_w: [*:0]const u16,
108 sa: ?*SECURITY_ATTRIBUTES,
109 access_mask: ACCESS_MASK,
110 creation: ULONG,
111) OpenError!HANDLE {
112 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
113 return error.IsDir;
114 }
115 if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
116 return error.IsDir;
117 }
118
119 var result: HANDLE = undefined;
120
121 const path_len_bytes = math.cast(u16, mem.toSliceConst(u16, sub_path_w).len * 2) catch |err| switch (err) {
122 error.Overflow => return error.NameTooLong,
123 };
124 var nt_name = UNICODE_STRING{
125 .Length = path_len_bytes,
126 .MaximumLength = path_len_bytes,
127 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
128 };
129 var attr = OBJECT_ATTRIBUTES{
130 .Length = @sizeOf(OBJECT_ATTRIBUTES),
131 .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w)) null else dir,
132 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
133 .ObjectName = &nt_name,
134 .SecurityDescriptor = if (sa) |ptr| ptr.lpSecurityDescriptor else null,
135 .SecurityQualityOfService = null,
136 };
137 var io: IO_STATUS_BLOCK = undefined;
138 const rc = ntdll.NtCreateFile(
139 &result,
140 access_mask,
141 &attr,
142 &io,
143 null,
144 FILE_ATTRIBUTE_NORMAL,
145 FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
146 creation,
147 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
148 null,
149 0,
150 );
151 switch (rc) {
152 .SUCCESS => return result,
153 .OBJECT_NAME_INVALID => unreachable,
154 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
155 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
156 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
157 .INVALID_PARAMETER => unreachable,
158 .SHARING_VIOLATION => return error.SharingViolation,
159 .ACCESS_DENIED => return error.AccessDenied,
160 .PIPE_BUSY => return error.PipeBusy,
161 .OBJECT_PATH_SYNTAX_BAD => unreachable,
162 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
163 else => return unexpectedStatus(rc),
164 }
165}
166
91167pub const CreatePipeError = error{Unexpected};
92168
93169pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) CreatePipeError!void {
......@@ -1200,7 +1276,15 @@ pub fn unexpectedError(err: Win32Error) std.os.UnexpectedError {
12001276 // 614 is the length of the longest windows error desciption
12011277 var buf_u16: [614]u16 = undefined;
12021278 var buf_u8: [614]u8 = undefined;
1203 var len = kernel32.FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, null, err, MAKELANGID(LANG.NEUTRAL, SUBLANG.DEFAULT), buf_u16[0..].ptr, buf_u16.len / @sizeOf(TCHAR), null);
1279 const len = kernel32.FormatMessageW(
1280 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
1281 null,
1282 err,
1283 MAKELANGID(LANG.NEUTRAL, SUBLANG.DEFAULT),
1284 &buf_u16,
1285 buf_u16.len / @sizeOf(TCHAR),
1286 null,
1287 );
12041288 _ = std.unicode.utf16leToUtf8(&buf_u8, buf_u16[0..len]) catch unreachable;
12051289 std.debug.warn("error.Unexpected: GetLastError({}): {}\n", .{ @enumToInt(err), buf_u8[0..len] });
12061290 std.debug.dumpCurrentStackTrace(null);
lib/std/os/windows/bits.zig+7
......@@ -242,6 +242,13 @@ pub const FILE_NAME_INFORMATION = extern struct {
242242 FileName: [1]WCHAR,
243243};
244244
245pub const FILE_RENAME_INFORMATION = extern struct {
246 ReplaceIfExists: BOOLEAN,
247 RootDirectory: ?HANDLE,
248 FileNameLength: ULONG,
249 FileName: [1]WCHAR,
250};
251
245252pub const IO_STATUS_BLOCK = extern struct {
246253 // "DUMMYUNIONNAME" expands to "u"
247254 u: extern union {
lib/std/rand.zig+1-1
......@@ -5,7 +5,7 @@
55// ```
66// var buf: [8]u8 = undefined;
77// try std.crypto.randomBytes(buf[0..]);
8// const seed = mem.readIntSliceLittle(u64, buf[0..8]);
8// const seed = mem.readIntLittle(u64, buf[0..8]);
99//
1010// var r = DefaultPrng.init(seed);
1111//
lib/std/special/compiler_rt/floatundisf.zig+19-19
......@@ -69,23 +69,23 @@ test "floatundisf" {
6969 test__floatundisf(0, 0.0);
7070 test__floatundisf(1, 1.0);
7171 test__floatundisf(2, 2.0);
72 test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62F);
73 test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62F);
74 test__floatundisf(0x8000008000000000, 0x1p+63F);
75 test__floatundisf(0x8000010000000000, 0x1.000002p+63F);
76 test__floatundisf(0x8000000000000000, 0x1p+63F);
77 test__floatundisf(0x8000000000000001, 0x1p+63F);
78 test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64F);
79 test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64F);
80 test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50F);
81 test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50F);
82 test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50F);
83 test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50F);
84 test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50F);
85 test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50F);
86 test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50F);
87 test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50F);
88 test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50F);
89 test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50F);
90 test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50F);
72 test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
73 test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
74 test__floatundisf(0x8000008000000000, 0x1p+63);
75 test__floatundisf(0x8000010000000000, 0x1.000002p+63);
76 test__floatundisf(0x8000000000000000, 0x1p+63);
77 test__floatundisf(0x8000000000000001, 0x1p+63);
78 test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64);
79 test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64);
80 test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
81 test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
82 test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
83 test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
84 test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
85 test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
86 test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
87 test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
88 test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
89 test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
90 test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
9191}
lib/std/start.zig+4
......@@ -41,6 +41,10 @@ fn _DllMainCRTStartup(
4141 fdwReason: std.os.windows.DWORD,
4242 lpReserved: std.os.windows.LPVOID,
4343) callconv(.Stdcall) std.os.windows.BOOL {
44 if (!builtin.single_threaded) {
45 _ = @import("start_windows_tls.zig");
46 }
47
4448 if (@hasDecl(root, "DllMain")) {
4549 return root.DllMain(hinstDLL, fdwReason, lpReserved);
4650 }
lib/std/thread.zig+45-6
......@@ -6,6 +6,8 @@ const windows = std.os.windows;
66const c = std.c;
77const assert = std.debug.assert;
88
9const bad_startfn_ret = "expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'";
10
911pub const Thread = struct {
1012 data: Data,
1113
......@@ -158,15 +160,34 @@ pub const Thread = struct {
158160 };
159161 fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {
160162 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
163
161164 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
162 .Int => {
163 return startFn(arg);
165 .NoReturn => {
166 startFn(arg);
164167 },
165168 .Void => {
166169 startFn(arg);
167170 return 0;
168171 },
169 else => @compileError("expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"),
172 .Int => |info| {
173 if (info.bits != 8) {
174 @compileError(bad_startfn_ret);
175 }
176 return startFn(arg);
177 },
178 .ErrorUnion => |info| {
179 if (info.payload != void) {
180 @compileError(bad_startfn_ret);
181 }
182 startFn(arg) catch |err| {
183 std.debug.warn("error: {}\n", .{@errorName(err)});
184 if (@errorReturnTrace()) |trace| {
185 std.debug.dumpStackTrace(trace.*);
186 }
187 };
188 return 0;
189 },
190 else => @compileError(bad_startfn_ret),
170191 }
171192 }
172193 };
......@@ -202,14 +223,32 @@ pub const Thread = struct {
202223 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;
203224
204225 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
205 .Int => {
206 return startFn(arg);
226 .NoReturn => {
227 startFn(arg);
207228 },
208229 .Void => {
209230 startFn(arg);
210231 return 0;
211232 },
212 else => @compileError("expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"),
233 .Int => |info| {
234 if (info.bits != 8) {
235 @compileError(bad_startfn_ret);
236 }
237 return startFn(arg);
238 },
239 .ErrorUnion => |info| {
240 if (info.payload != void) {
241 @compileError(bad_startfn_ret);
242 }
243 startFn(arg) catch |err| {
244 std.debug.warn("error: {}\n", .{@errorName(err)});
245 if (@errorReturnTrace()) |trace| {
246 std.debug.dumpStackTrace(trace.*);
247 }
248 };
249 return 0;
250 },
251 else => @compileError(bad_startfn_ret),
213252 }
214253 }
215254 fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void {
lib/std/unicode.zig+10-10
......@@ -251,12 +251,12 @@ pub const Utf16LeIterator = struct {
251251 pub fn nextCodepoint(it: *Utf16LeIterator) !?u21 {
252252 assert(it.i <= it.bytes.len);
253253 if (it.i == it.bytes.len) return null;
254 const c0: u21 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
254 const c0: u21 = mem.readIntLittle(u16, it.bytes[it.i..][0..2]);
255255 if (c0 & ~@as(u21, 0x03ff) == 0xd800) {
256256 // surrogate pair
257257 it.i += 2;
258258 if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;
259 const c1: u21 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
259 const c1: u21 = mem.readIntLittle(u16, it.bytes[it.i..][0..2]);
260260 if (c1 & ~@as(u21, 0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;
261261 it.i += 2;
262262 return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));
......@@ -630,11 +630,11 @@ test "utf8ToUtf16LeWithNull" {
630630 }
631631}
632632
633/// Converts a UTF-8 string literal into a UTF-16LE string literal.
634pub fn utf8ToUtf16LeStringLiteral(comptime utf8: []const u8) *const [calcUtf16LeLen(utf8) :0] u16 {
633/// Converts a UTF-8 string literal into a UTF-16LE string literal.
634pub fn utf8ToUtf16LeStringLiteral(comptime utf8: []const u8) *const [calcUtf16LeLen(utf8):0]u16 {
635635 comptime {
636636 const len: usize = calcUtf16LeLen(utf8);
637 var utf16le: [len :0]u16 = [_ :0]u16{0} ** len;
637 var utf16le: [len:0]u16 = [_:0]u16{0} ** len;
638638 const utf16le_len = utf8ToUtf16Le(&utf16le, utf8[0..]) catch |err| @compileError(err);
639639 assert(len == utf16le_len);
640640 return &utf16le;
......@@ -660,8 +660,8 @@ fn calcUtf16LeLen(utf8: []const u8) usize {
660660}
661661
662662test "utf8ToUtf16LeStringLiteral" {
663{
664 const bytes = [_:0]u16{ 0x41 };
663 {
664 const bytes = [_:0]u16{0x41};
665665 const utf16 = utf8ToUtf16LeStringLiteral("A");
666666 testing.expectEqualSlices(u16, &bytes, utf16);
667667 testing.expect(utf16[1] == 0);
......@@ -673,19 +673,19 @@ test "utf8ToUtf16LeStringLiteral" {
673673 testing.expect(utf16[2] == 0);
674674 }
675675 {
676 const bytes = [_:0]u16{ 0x02FF };
676 const bytes = [_:0]u16{0x02FF};
677677 const utf16 = utf8ToUtf16LeStringLiteral("\u{02FF}");
678678 testing.expectEqualSlices(u16, &bytes, utf16);
679679 testing.expect(utf16[1] == 0);
680680 }
681681 {
682 const bytes = [_:0]u16{ 0x7FF };
682 const bytes = [_:0]u16{0x7FF};
683683 const utf16 = utf8ToUtf16LeStringLiteral("\u{7FF}");
684684 testing.expectEqualSlices(u16, &bytes, utf16);
685685 testing.expect(utf16[1] == 0);
686686 }
687687 {
688 const bytes = [_:0]u16{ 0x801 };
688 const bytes = [_:0]u16{0x801};
689689 const utf16 = utf8ToUtf16LeStringLiteral("\u{801}");
690690 testing.expectEqualSlices(u16, &bytes, utf16);
691691 testing.expect(utf16[1] == 0);
lib/std/zig/ast.zig+65-92
......@@ -740,11 +740,11 @@ pub const Node = struct {
740740 var i = index;
741741
742742 switch (self.init_arg_expr) {
743 InitArg.Type => |t| {
743 .Type => |t| {
744744 if (i < 1) return t;
745745 i -= 1;
746746 },
747 InitArg.None, InitArg.Enum => {},
747 .None, .Enum => {},
748748 }
749749
750750 if (i < self.fields_and_decls.len) return self.fields_and_decls.at(i).*;
......@@ -904,12 +904,7 @@ pub const Node = struct {
904904 }
905905
906906 switch (self.return_type) {
907 // TODO allow this and next prong to share bodies since the types are the same
908 ReturnType.Explicit => |node| {
909 if (i < 1) return node;
910 i -= 1;
911 },
912 ReturnType.InferErrorSet => |node| {
907 .Explicit, .InferErrorSet => |node| {
913908 if (i < 1) return node;
914909 i -= 1;
915910 },
......@@ -934,9 +929,7 @@ pub const Node = struct {
934929 pub fn lastToken(self: *const FnProto) TokenIndex {
935930 if (self.body_node) |body_node| return body_node.lastToken();
936931 switch (self.return_type) {
937 // TODO allow this and next prong to share bodies since the types are the same
938 ReturnType.Explicit => |node| return node.lastToken(),
939 ReturnType.InferErrorSet => |node| return node.lastToken(),
932 .Explicit, .InferErrorSet => |node| return node.lastToken(),
940933 }
941934 }
942935 };
......@@ -1039,6 +1032,7 @@ pub const Node = struct {
10391032 pub const Defer = struct {
10401033 base: Node = Node{ .id = .Defer },
10411034 defer_token: TokenIndex,
1035 payload: ?*Node,
10421036 expr: *Node,
10431037
10441038 pub fn iterate(self: *Defer, index: usize) ?*Node {
......@@ -1512,55 +1506,55 @@ pub const Node = struct {
15121506 i -= 1;
15131507
15141508 switch (self.op) {
1515 Op.Catch => |maybe_payload| {
1509 .Catch => |maybe_payload| {
15161510 if (maybe_payload) |payload| {
15171511 if (i < 1) return payload;
15181512 i -= 1;
15191513 }
15201514 },
15211515
1522 Op.Add,
1523 Op.AddWrap,
1524 Op.ArrayCat,
1525 Op.ArrayMult,
1526 Op.Assign,
1527 Op.AssignBitAnd,
1528 Op.AssignBitOr,
1529 Op.AssignBitShiftLeft,
1530 Op.AssignBitShiftRight,
1531 Op.AssignBitXor,
1532 Op.AssignDiv,
1533 Op.AssignSub,
1534 Op.AssignSubWrap,
1535 Op.AssignMod,
1536 Op.AssignAdd,
1537 Op.AssignAddWrap,
1538 Op.AssignMul,
1539 Op.AssignMulWrap,
1540 Op.BangEqual,
1541 Op.BitAnd,
1542 Op.BitOr,
1543 Op.BitShiftLeft,
1544 Op.BitShiftRight,
1545 Op.BitXor,
1546 Op.BoolAnd,
1547 Op.BoolOr,
1548 Op.Div,
1549 Op.EqualEqual,
1550 Op.ErrorUnion,
1551 Op.GreaterOrEqual,
1552 Op.GreaterThan,
1553 Op.LessOrEqual,
1554 Op.LessThan,
1555 Op.MergeErrorSets,
1556 Op.Mod,
1557 Op.Mul,
1558 Op.MulWrap,
1559 Op.Period,
1560 Op.Range,
1561 Op.Sub,
1562 Op.SubWrap,
1563 Op.UnwrapOptional,
1516 .Add,
1517 .AddWrap,
1518 .ArrayCat,
1519 .ArrayMult,
1520 .Assign,
1521 .AssignBitAnd,
1522 .AssignBitOr,
1523 .AssignBitShiftLeft,
1524 .AssignBitShiftRight,
1525 .AssignBitXor,
1526 .AssignDiv,
1527 .AssignSub,
1528 .AssignSubWrap,
1529 .AssignMod,
1530 .AssignAdd,
1531 .AssignAddWrap,
1532 .AssignMul,
1533 .AssignMulWrap,
1534 .BangEqual,
1535 .BitAnd,
1536 .BitOr,
1537 .BitShiftLeft,
1538 .BitShiftRight,
1539 .BitXor,
1540 .BoolAnd,
1541 .BoolOr,
1542 .Div,
1543 .EqualEqual,
1544 .ErrorUnion,
1545 .GreaterOrEqual,
1546 .GreaterThan,
1547 .LessOrEqual,
1548 .LessThan,
1549 .MergeErrorSets,
1550 .Mod,
1551 .Mul,
1552 .MulWrap,
1553 .Period,
1554 .Range,
1555 .Sub,
1556 .SubWrap,
1557 .UnwrapOptional,
15641558 => {},
15651559 }
15661560
......@@ -1591,7 +1585,6 @@ pub const Node = struct {
15911585 Await,
15921586 BitNot,
15931587 BoolNot,
1594 Cancel,
15951588 OptionalType,
15961589 Negation,
15971590 NegationWrap,
......@@ -1628,8 +1621,7 @@ pub const Node = struct {
16281621 var i = index;
16291622
16301623 switch (self.op) {
1631 // TODO https://github.com/ziglang/zig/issues/1107
1632 Op.SliceType => |addr_of_info| {
1624 .PtrType, .SliceType => |addr_of_info| {
16331625 if (addr_of_info.sentinel) |sentinel| {
16341626 if (i < 1) return sentinel;
16351627 i -= 1;
......@@ -1641,14 +1633,7 @@ pub const Node = struct {
16411633 }
16421634 },
16431635
1644 Op.PtrType => |addr_of_info| {
1645 if (addr_of_info.align_info) |align_info| {
1646 if (i < 1) return align_info.node;
1647 i -= 1;
1648 }
1649 },
1650
1651 Op.ArrayType => |array_info| {
1636 .ArrayType => |array_info| {
16521637 if (i < 1) return array_info.len_expr;
16531638 i -= 1;
16541639 if (array_info.sentinel) |sentinel| {
......@@ -1657,16 +1642,15 @@ pub const Node = struct {
16571642 }
16581643 },
16591644
1660 Op.AddressOf,
1661 Op.Await,
1662 Op.BitNot,
1663 Op.BoolNot,
1664 Op.Cancel,
1665 Op.OptionalType,
1666 Op.Negation,
1667 Op.NegationWrap,
1668 Op.Try,
1669 Op.Resume,
1645 .AddressOf,
1646 .Await,
1647 .BitNot,
1648 .BoolNot,
1649 .OptionalType,
1650 .Negation,
1651 .NegationWrap,
1652 .Try,
1653 .Resume,
16701654 => {},
16711655 }
16721656
......@@ -1850,19 +1834,13 @@ pub const Node = struct {
18501834 var i = index;
18511835
18521836 switch (self.kind) {
1853 Kind.Break => |maybe_label| {
1854 if (maybe_label) |label| {
1855 if (i < 1) return label;
1856 i -= 1;
1857 }
1858 },
1859 Kind.Continue => |maybe_label| {
1837 .Break, .Continue => |maybe_label| {
18601838 if (maybe_label) |label| {
18611839 if (i < 1) return label;
18621840 i -= 1;
18631841 }
18641842 },
1865 Kind.Return => {},
1843 .Return => {},
18661844 }
18671845
18681846 if (self.rhs) |rhs| {
......@@ -1883,17 +1861,12 @@ pub const Node = struct {
18831861 }
18841862
18851863 switch (self.kind) {
1886 Kind.Break => |maybe_label| {
1887 if (maybe_label) |label| {
1888 return label.lastToken();
1889 }
1890 },
1891 Kind.Continue => |maybe_label| {
1864 .Break, .Continue => |maybe_label| {
18921865 if (maybe_label) |label| {
18931866 return label.lastToken();
18941867 }
18951868 },
1896 Kind.Return => return self.ltoken,
1869 .Return => return self.ltoken,
18971870 }
18981871
18991872 return self.ltoken;
......@@ -2134,11 +2107,11 @@ pub const Node = struct {
21342107 i -= 1;
21352108
21362109 switch (self.kind) {
2137 Kind.Variable => |variable_name| {
2110 .Variable => |variable_name| {
21382111 if (i < 1) return &variable_name.base;
21392112 i -= 1;
21402113 },
2141 Kind.Return => |return_type| {
2114 .Return => |return_type| {
21422115 if (i < 1) return return_type;
21432116 i -= 1;
21442117 },
lib/std/zig/parse.zig+342-352
......@@ -23,7 +23,7 @@ pub fn parse(allocator: *Allocator, source: []const u8) Allocator.Error!*Tree {
2323 var arena = std.heap.ArenaAllocator.init(allocator);
2424 errdefer arena.deinit();
2525 const tree = try arena.allocator.create(ast.Tree);
26 tree.* = ast.Tree{
26 tree.* = .{
2727 .source = source,
2828 .root_node = undefined,
2929 .arena_allocator = arena,
......@@ -66,10 +66,10 @@ pub fn parse(allocator: *Allocator, source: []const u8) Allocator.Error!*Tree {
6666/// Root <- skip ContainerMembers eof
6767fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!*Node.Root {
6868 const node = try arena.create(Node.Root);
69 node.* = Node.Root{
69 node.* = .{
7070 .decls = try parseContainerMembers(arena, it, tree),
7171 .eof_token = eatToken(it, .Eof) orelse {
72 try tree.errors.push(AstError{
72 try tree.errors.push(.{
7373 .ExpectedContainerMembers = .{ .token = it.index },
7474 });
7575 return error.ParseError;
......@@ -139,8 +139,8 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No
139139 }
140140
141141 if (visib_token != null) {
142 try tree.errors.push(AstError{
143 .ExpectedPubItem = AstError.ExpectedPubItem{ .token = it.index },
142 try tree.errors.push(.{
143 .ExpectedPubItem = .{ .token = it.index },
144144 });
145145 return error.ParseError;
146146 }
......@@ -157,8 +157,8 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No
157157
158158 // Dangling doc comment
159159 if (doc_comments != null) {
160 try tree.errors.push(AstError{
161 .UnattachedDocComment = AstError.UnattachedDocComment{ .token = doc_comments.?.firstToken() },
160 try tree.errors.push(.{
161 .UnattachedDocComment = .{ .token = doc_comments.?.firstToken() },
162162 });
163163 }
164164 break;
......@@ -177,7 +177,7 @@ fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree)
177177 if (lines.len == 0) return null;
178178
179179 const node = try arena.create(Node.DocComment);
180 node.* = Node.DocComment{
180 node.* = .{
181181 .lines = lines,
182182 };
183183 return &node.base;
......@@ -186,15 +186,15 @@ fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree)
186186/// TestDecl <- KEYWORD_test STRINGLITERALSINGLE Block
187187fn parseTestDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
188188 const test_token = eatToken(it, .Keyword_test) orelse return null;
189 const name_node = try expectNode(arena, it, tree, parseStringLiteralSingle, AstError{
190 .ExpectedStringLiteral = AstError.ExpectedStringLiteral{ .token = it.index },
189 const name_node = try expectNode(arena, it, tree, parseStringLiteralSingle, .{
190 .ExpectedStringLiteral = .{ .token = it.index },
191191 });
192 const block_node = try expectNode(arena, it, tree, parseBlock, AstError{
193 .ExpectedLBrace = AstError.ExpectedLBrace{ .token = it.index },
192 const block_node = try expectNode(arena, it, tree, parseBlock, .{
193 .ExpectedLBrace = .{ .token = it.index },
194194 });
195195
196196 const test_node = try arena.create(Node.TestDecl);
197 test_node.* = Node.TestDecl{
197 test_node.* = .{
198198 .doc_comments = null,
199199 .test_token = test_token,
200200 .name = name_node,
......@@ -211,12 +211,12 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*
211211 return null;
212212 };
213213 putBackToken(it, lbrace);
214 const block_node = try expectNode(arena, it, tree, parseBlockExpr, AstError{
215 .ExpectedLabelOrLBrace = AstError.ExpectedLabelOrLBrace{ .token = it.index },
214 const block_node = try expectNode(arena, it, tree, parseBlockExpr, .{
215 .ExpectedLabelOrLBrace = .{ .token = it.index },
216216 });
217217
218218 const comptime_node = try arena.create(Node.Comptime);
219 comptime_node.* = Node.Comptime{
219 comptime_node.* = .{
220220 .doc_comments = null,
221221 .comptime_token = tok,
222222 .expr = block_node,
......@@ -250,8 +250,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
250250 fn_node.body_node = body_node;
251251 return node;
252252 }
253 try tree.errors.push(AstError{
254 .ExpectedSemiOrLBrace = AstError.ExpectedSemiOrLBrace{ .token = it.index },
253 try tree.errors.push(.{
254 .ExpectedSemiOrLBrace = .{ .token = it.index },
255255 });
256256 return null;
257257 }
......@@ -277,8 +277,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
277277 }
278278
279279 if (thread_local_token != null) {
280 try tree.errors.push(AstError{
281 .ExpectedVarDecl = AstError.ExpectedVarDecl{ .token = it.index },
280 try tree.errors.push(.{
281 .ExpectedVarDecl = .{ .token = it.index },
282282 });
283283 return error.ParseError;
284284 }
......@@ -291,8 +291,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
291291 }
292292
293293 const use_node = (try parseUse(arena, it, tree)) orelse return null;
294 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
295 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
294 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
295 .ExpectedExpr = .{ .token = it.index },
296296 });
297297 const semicolon_token = try expectToken(it, tree, .Semicolon);
298298 const use_node_raw = use_node.cast(Node.Use).?;
......@@ -310,7 +310,7 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
310310 if (fnCC == .Extern) {
311311 putBackToken(it, fnCC.Extern); // 'extern' is also used in ContainerDecl
312312 } else {
313 try tree.errors.push(AstError{
313 try tree.errors.push(.{
314314 .ExpectedToken = .{ .token = it.index, .expected_id = .Keyword_fn },
315315 });
316316 return error.ParseError;
......@@ -328,16 +328,16 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
328328 const exclamation_token = eatToken(it, .Bang);
329329
330330 const return_type_expr = (try parseVarType(arena, it, tree)) orelse
331 try expectNode(arena, it, tree, parseTypeExpr, AstError{
332 .ExpectedReturnType = AstError.ExpectedReturnType{ .token = it.index },
331 try expectNode(arena, it, tree, parseTypeExpr, .{
332 .ExpectedReturnType = .{ .token = it.index },
333333 });
334334
335 const return_type = if (exclamation_token != null)
336 Node.FnProto.ReturnType{
335 const return_type: Node.FnProto.ReturnType = if (exclamation_token != null)
336 .{
337337 .InferErrorSet = return_type_expr,
338338 }
339339 else
340 Node.FnProto.ReturnType{
340 .{
341341 .Explicit = return_type_expr,
342342 };
343343
......@@ -347,7 +347,7 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
347347 null;
348348
349349 const fn_proto_node = try arena.create(Node.FnProto);
350 fn_proto_node.* = Node.FnProto{
350 fn_proto_node.* = .{
351351 .doc_comments = null,
352352 .visib_token = null,
353353 .fn_token = fn_token,
......@@ -382,8 +382,8 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
382382
383383 const name_token = try expectToken(it, tree, .Identifier);
384384 const type_node = if (eatToken(it, .Colon) != null)
385 try expectNode(arena, it, tree, parseTypeExpr, AstError{
386 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
385 try expectNode(arena, it, tree, parseTypeExpr, .{
386 .ExpectedTypeExpr = .{ .token = it.index },
387387 })
388388 else
389389 null;
......@@ -391,14 +391,14 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
391391 const section_node = try parseLinkSection(arena, it, tree);
392392 const eq_token = eatToken(it, .Equal);
393393 const init_node = if (eq_token != null) blk: {
394 break :blk try expectNode(arena, it, tree, parseExpr, AstError{
395 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
394 break :blk try expectNode(arena, it, tree, parseExpr, .{
395 .ExpectedExpr = .{ .token = it.index },
396396 });
397397 } else null;
398398 const semicolon_token = try expectToken(it, tree, .Semicolon);
399399
400400 const node = try arena.create(Node.VarDecl);
401 node.* = Node.VarDecl{
401 node.* = .{
402402 .doc_comments = null,
403403 .visib_token = null,
404404 .thread_local_token = null,
......@@ -433,22 +433,22 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
433433 node.* = .{ .token = var_tok };
434434 type_expr = &node.base;
435435 } else {
436 type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
437 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
436 type_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
437 .ExpectedTypeExpr = .{ .token = it.index },
438438 });
439439 align_expr = try parseByteAlign(arena, it, tree);
440440 }
441441 }
442442
443443 const value_expr = if (eatToken(it, .Equal)) |_|
444 try expectNode(arena, it, tree, parseExpr, AstError{
445 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
444 try expectNode(arena, it, tree, parseExpr, .{
445 .ExpectedExpr = .{ .token = it.index },
446446 })
447447 else
448448 null;
449449
450450 const node = try arena.create(Node.ContainerField);
451 node.* = Node.ContainerField{
451 node.* = .{
452452 .doc_comments = null,
453453 .comptime_token = comptime_token,
454454 .name_token = name_token,
......@@ -465,7 +465,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
465465/// / KEYWORD_noasync BlockExprStatement
466466/// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
467467/// / KEYWORD_defer BlockExprStatement
468/// / KEYWORD_errdefer BlockExprStatement
468/// / KEYWORD_errdefer Payload? BlockExprStatement
469469/// / IfStatement
470470/// / LabeledStatement
471471/// / SwitchExpr
......@@ -481,12 +481,12 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
481481 }
482482
483483 if (comptime_token) |token| {
484 const block_expr = try expectNode(arena, it, tree, parseBlockExprStatement, AstError{
485 .ExpectedBlockOrAssignment = AstError.ExpectedBlockOrAssignment{ .token = it.index },
484 const block_expr = try expectNode(arena, it, tree, parseBlockExprStatement, .{
485 .ExpectedBlockOrAssignment = .{ .token = it.index },
486486 });
487487
488488 const node = try arena.create(Node.Comptime);
489 node.* = Node.Comptime{
489 node.* = .{
490490 .doc_comments = null,
491491 .comptime_token = token,
492492 .expr = block_expr,
......@@ -511,13 +511,13 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
511511 const semicolon = eatToken(it, .Semicolon);
512512
513513 const body_node = if (semicolon == null) blk: {
514 break :blk try expectNode(arena, it, tree, parseBlockExprStatement, AstError{
515 .ExpectedBlockOrExpression = AstError.ExpectedBlockOrExpression{ .token = it.index },
514 break :blk try expectNode(arena, it, tree, parseBlockExprStatement, .{
515 .ExpectedBlockOrExpression = .{ .token = it.index },
516516 });
517517 } else null;
518518
519519 const node = try arena.create(Node.Suspend);
520 node.* = Node.Suspend{
520 node.* = .{
521521 .suspend_token = suspend_token,
522522 .body = body_node,
523523 };
......@@ -526,13 +526,18 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
526526
527527 const defer_token = eatToken(it, .Keyword_defer) orelse eatToken(it, .Keyword_errdefer);
528528 if (defer_token) |token| {
529 const expr_node = try expectNode(arena, it, tree, parseBlockExprStatement, AstError{
530 .ExpectedBlockOrExpression = AstError.ExpectedBlockOrExpression{ .token = it.index },
529 const payload = if (tree.tokens.at(token).id == .Keyword_errdefer)
530 try parsePayload(arena, it, tree)
531 else
532 null;
533 const expr_node = try expectNode(arena, it, tree, parseBlockExprStatement, .{
534 .ExpectedBlockOrExpression = .{ .token = it.index },
531535 });
532536 const node = try arena.create(Node.Defer);
533 node.* = Node.Defer{
537 node.* = .{
534538 .defer_token = token,
535539 .expr = expr_node,
540 .payload = payload,
536541 };
537542 return &node.base;
538543 }
......@@ -561,8 +566,8 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
561566 } else null;
562567
563568 if (block_expr == null and assign_expr == null) {
564 try tree.errors.push(AstError{
565 .ExpectedBlockOrAssignment = AstError.ExpectedBlockOrAssignment{ .token = it.index },
569 try tree.errors.push(.{
570 .ExpectedBlockOrAssignment = .{ .token = it.index },
566571 });
567572 return error.ParseError;
568573 }
......@@ -572,12 +577,12 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
572577 const else_node = if (semicolon == null) blk: {
573578 const else_token = eatToken(it, .Keyword_else) orelse break :blk null;
574579 const payload = try parsePayload(arena, it, tree);
575 const else_body = try expectNode(arena, it, tree, parseStatement, AstError{
576 .InvalidToken = AstError.InvalidToken{ .token = it.index },
580 const else_body = try expectNode(arena, it, tree, parseStatement, .{
581 .InvalidToken = .{ .token = it.index },
577582 });
578583
579584 const node = try arena.create(Node.Else);
580 node.* = Node.Else{
585 node.* = .{
581586 .else_token = else_token,
582587 .payload = payload,
583588 .body = else_body,
......@@ -599,8 +604,8 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
599604 if_prefix.@"else" = else_node;
600605 return if_node;
601606 }
602 try tree.errors.push(AstError{
603 .ExpectedSemiOrElse = AstError.ExpectedSemiOrElse{ .token = it.index },
607 try tree.errors.push(.{
608 .ExpectedSemiOrElse = .{ .token = it.index },
604609 });
605610 return error.ParseError;
606611 }
......@@ -628,8 +633,8 @@ fn parseLabeledStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*
628633 }
629634
630635 if (label_token != null) {
631 try tree.errors.push(AstError{
632 .ExpectedLabelable = AstError.ExpectedLabelable{ .token = it.index },
636 try tree.errors.push(.{
637 .ExpectedLabelable = .{ .token = it.index },
633638 });
634639 return error.ParseError;
635640 }
......@@ -665,12 +670,12 @@ fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
665670 for_prefix.body = block_expr_node;
666671
667672 if (eatToken(it, .Keyword_else)) |else_token| {
668 const statement_node = try expectNode(arena, it, tree, parseStatement, AstError{
669 .InvalidToken = AstError.InvalidToken{ .token = it.index },
673 const statement_node = try expectNode(arena, it, tree, parseStatement, .{
674 .InvalidToken = .{ .token = it.index },
670675 });
671676
672677 const else_node = try arena.create(Node.Else);
673 else_node.* = Node.Else{
678 else_node.* = .{
674679 .else_token = else_token,
675680 .payload = null,
676681 .body = statement_node,
......@@ -689,12 +694,12 @@ fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
689694 if (eatToken(it, .Semicolon) != null) return node;
690695
691696 if (eatToken(it, .Keyword_else)) |else_token| {
692 const statement_node = try expectNode(arena, it, tree, parseStatement, AstError{
693 .ExpectedStatement = AstError.ExpectedStatement{ .token = it.index },
697 const statement_node = try expectNode(arena, it, tree, parseStatement, .{
698 .ExpectedStatement = .{ .token = it.index },
694699 });
695700
696701 const else_node = try arena.create(Node.Else);
697 else_node.* = Node.Else{
702 else_node.* = .{
698703 .else_token = else_token,
699704 .payload = null,
700705 .body = statement_node,
......@@ -703,8 +708,8 @@ fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
703708 return node;
704709 }
705710
706 try tree.errors.push(AstError{
707 .ExpectedSemiOrElse = AstError.ExpectedSemiOrElse{ .token = it.index },
711 try tree.errors.push(.{
712 .ExpectedSemiOrElse = .{ .token = it.index },
708713 });
709714 return null;
710715 }
......@@ -725,12 +730,12 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
725730 if (eatToken(it, .Keyword_else)) |else_token| {
726731 const payload = try parsePayload(arena, it, tree);
727732
728 const statement_node = try expectNode(arena, it, tree, parseStatement, AstError{
729 .InvalidToken = AstError.InvalidToken{ .token = it.index },
733 const statement_node = try expectNode(arena, it, tree, parseStatement, .{
734 .InvalidToken = .{ .token = it.index },
730735 });
731736
732737 const else_node = try arena.create(Node.Else);
733 else_node.* = Node.Else{
738 else_node.* = .{
734739 .else_token = else_token,
735740 .payload = payload,
736741 .body = statement_node,
......@@ -751,12 +756,12 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
751756 if (eatToken(it, .Keyword_else)) |else_token| {
752757 const payload = try parsePayload(arena, it, tree);
753758
754 const statement_node = try expectNode(arena, it, tree, parseStatement, AstError{
755 .ExpectedStatement = AstError.ExpectedStatement{ .token = it.index },
759 const statement_node = try expectNode(arena, it, tree, parseStatement, .{
760 .ExpectedStatement = .{ .token = it.index },
756761 });
757762
758763 const else_node = try arena.create(Node.Else);
759 else_node.* = Node.Else{
764 else_node.* = .{
760765 .else_token = else_token,
761766 .payload = payload,
762767 .body = statement_node,
......@@ -765,8 +770,8 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
765770 return node;
766771 }
767772
768 try tree.errors.push(AstError{
769 .ExpectedSemiOrElse = AstError.ExpectedSemiOrElse{ .token = it.index },
773 try tree.errors.push(.{
774 .ExpectedSemiOrElse = .{ .token = it.index },
770775 });
771776 return null;
772777 }
......@@ -894,8 +899,8 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
894899 }
895900
896901 if (eatToken(it, .Keyword_comptime)) |token| {
897 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
898 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
902 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
903 .ExpectedExpr = .{ .token = it.index },
899904 });
900905 const node = try arena.create(Node.Comptime);
901906 node.* = .{
......@@ -907,8 +912,8 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
907912 }
908913
909914 if (eatToken(it, .Keyword_noasync)) |token| {
910 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
911 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
915 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
916 .ExpectedExpr = .{ .token = it.index },
912917 });
913918 const node = try arena.create(Node.Noasync);
914919 node.* = .{
......@@ -930,13 +935,13 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
930935 }
931936
932937 if (eatToken(it, .Keyword_resume)) |token| {
933 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
934 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
938 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
939 .ExpectedExpr = .{ .token = it.index },
935940 });
936941 const node = try arena.create(Node.PrefixOp);
937942 node.* = .{
938943 .op_token = token,
939 .op = Node.PrefixOp.Op.Resume,
944 .op = .Resume,
940945 .rhs = expr_node,
941946 };
942947 return &node.base;
......@@ -992,7 +997,7 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
992997 const rbrace = try expectToken(it, tree, .RBrace);
993998
994999 const block_node = try arena.create(Node.Block);
995 block_node.* = Node.Block{
1000 block_node.* = .{
9961001 .label = null,
9971002 .lbrace = lbrace,
9981003 .statements = statements,
......@@ -1019,8 +1024,8 @@ fn parseLoopExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
10191024 if (inline_token == null) return null;
10201025
10211026 // If we've seen "inline", there should have been a "for" or "while"
1022 try tree.errors.push(AstError{
1023 .ExpectedInlinable = AstError.ExpectedInlinable{ .token = it.index },
1027 try tree.errors.push(.{
1028 .ExpectedInlinable = .{ .token = it.index },
10241029 });
10251030 return error.ParseError;
10261031}
......@@ -1030,18 +1035,18 @@ fn parseForExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
10301035 const node = (try parseForPrefix(arena, it, tree)) orelse return null;
10311036 const for_prefix = node.cast(Node.For).?;
10321037
1033 const body_node = try expectNode(arena, it, tree, parseExpr, AstError{
1034 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1038 const body_node = try expectNode(arena, it, tree, parseExpr, .{
1039 .ExpectedExpr = .{ .token = it.index },
10351040 });
10361041 for_prefix.body = body_node;
10371042
10381043 if (eatToken(it, .Keyword_else)) |else_token| {
1039 const body = try expectNode(arena, it, tree, parseExpr, AstError{
1040 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1044 const body = try expectNode(arena, it, tree, parseExpr, .{
1045 .ExpectedExpr = .{ .token = it.index },
10411046 });
10421047
10431048 const else_node = try arena.create(Node.Else);
1044 else_node.* = Node.Else{
1049 else_node.* = .{
10451050 .else_token = else_token,
10461051 .payload = null,
10471052 .body = body,
......@@ -1058,19 +1063,19 @@ fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
10581063 const node = (try parseWhilePrefix(arena, it, tree)) orelse return null;
10591064 const while_prefix = node.cast(Node.While).?;
10601065
1061 const body_node = try expectNode(arena, it, tree, parseExpr, AstError{
1062 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1066 const body_node = try expectNode(arena, it, tree, parseExpr, .{
1067 .ExpectedExpr = .{ .token = it.index },
10631068 });
10641069 while_prefix.body = body_node;
10651070
10661071 if (eatToken(it, .Keyword_else)) |else_token| {
10671072 const payload = try parsePayload(arena, it, tree);
1068 const body = try expectNode(arena, it, tree, parseExpr, AstError{
1069 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1073 const body = try expectNode(arena, it, tree, parseExpr, .{
1074 .ExpectedExpr = .{ .token = it.index },
10701075 });
10711076
10721077 const else_node = try arena.create(Node.Else);
1073 else_node.* = Node.Else{
1078 else_node.* = .{
10741079 .else_token = else_token,
10751080 .payload = payload,
10761081 .body = body,
......@@ -1098,14 +1103,14 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf
10981103 const lbrace = eatToken(it, .LBrace) orelse return null;
10991104 var init_list = Node.SuffixOp.Op.InitList.init(arena);
11001105
1101 const op = blk: {
1106 const op: Node.SuffixOp.Op = blk: {
11021107 if (try parseFieldInit(arena, it, tree)) |field_init| {
11031108 try init_list.push(field_init);
11041109 while (eatToken(it, .Comma)) |_| {
11051110 const next = (try parseFieldInit(arena, it, tree)) orelse break;
11061111 try init_list.push(next);
11071112 }
1108 break :blk Node.SuffixOp.Op{ .StructInitializer = init_list };
1113 break :blk .{ .StructInitializer = init_list };
11091114 }
11101115
11111116 if (try parseExpr(arena, it, tree)) |expr| {
......@@ -1114,14 +1119,14 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf
11141119 const next = (try parseExpr(arena, it, tree)) orelse break;
11151120 try init_list.push(next);
11161121 }
1117 break :blk Node.SuffixOp.Op{ .ArrayInitializer = init_list };
1122 break :blk .{ .ArrayInitializer = init_list };
11181123 }
11191124
1120 break :blk Node.SuffixOp.Op{ .StructInitializer = init_list };
1125 break :blk .{ .StructInitializer = init_list };
11211126 };
11221127
11231128 const node = try arena.create(Node.SuffixOp);
1124 node.* = Node.SuffixOp{
1129 node.* = .{
11251130 .lhs = .{ .node = undefined }, // set by caller
11261131 .op = op,
11271132 .rtoken = try expectToken(it, tree, .RBrace),
......@@ -1140,8 +1145,8 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
11401145
11411146 if (try SimpleBinOpParseFn(.Bang, Node.InfixOp.Op.ErrorUnion)(arena, it, tree)) |node| {
11421147 const error_union = node.cast(Node.InfixOp).?;
1143 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
1144 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
1148 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
1149 .ExpectedTypeExpr = .{ .token = it.index },
11451150 });
11461151 error_union.lhs = suffix_expr;
11471152 error_union.rhs = type_expr;
......@@ -1168,8 +1173,8 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11681173 return parsePrimaryTypeExpr(arena, it, tree);
11691174 }
11701175 // TODO: Implement hack for parsing `async fn ...` in ast_parse_suffix_expr
1171 var res = try expectNode(arena, it, tree, parsePrimaryTypeExpr, AstError{
1172 .ExpectedPrimaryTypeExpr = AstError.ExpectedPrimaryTypeExpr{ .token = it.index },
1176 var res = try expectNode(arena, it, tree, parsePrimaryTypeExpr, .{
1177 .ExpectedPrimaryTypeExpr = .{ .token = it.index },
11731178 });
11741179
11751180 while (try parseSuffixOp(arena, it, tree)) |node| {
......@@ -1182,16 +1187,16 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11821187 }
11831188
11841189 const params = (try parseFnCallArguments(arena, it, tree)) orelse {
1185 try tree.errors.push(AstError{
1186 .ExpectedParamList = AstError.ExpectedParamList{ .token = it.index },
1190 try tree.errors.push(.{
1191 .ExpectedParamList = .{ .token = it.index },
11871192 });
11881193 return null;
11891194 };
11901195 const node = try arena.create(Node.SuffixOp);
1191 node.* = Node.SuffixOp{
1196 node.* = .{
11921197 .lhs = .{ .node = res },
1193 .op = Node.SuffixOp.Op{
1194 .Call = Node.SuffixOp.Op.Call{
1198 .op = .{
1199 .Call = .{
11951200 .params = params.list,
11961201 .async_token = async_token,
11971202 },
......@@ -1215,10 +1220,10 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
12151220 }
12161221 if (try parseFnCallArguments(arena, it, tree)) |params| {
12171222 const call = try arena.create(Node.SuffixOp);
1218 call.* = Node.SuffixOp{
1223 call.* = .{
12191224 .lhs = .{ .node = res },
1220 .op = Node.SuffixOp.Op{
1221 .Call = Node.SuffixOp.Op.Call{
1225 .op = .{
1226 .Call = .{
12221227 .params = params.list,
12231228 .async_token = null,
12241229 },
......@@ -1264,7 +1269,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
12641269 if (try parseBuiltinCall(arena, it, tree)) |node| return node;
12651270 if (eatToken(it, .CharLiteral)) |token| {
12661271 const node = try arena.create(Node.CharLiteral);
1267 node.* = Node.CharLiteral{
1272 node.* = .{
12681273 .token = token,
12691274 };
12701275 return &node.base;
......@@ -1300,15 +1305,15 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
13001305 }
13011306 if (eatToken(it, .Keyword_error)) |token| {
13021307 const period = try expectToken(it, tree, .Period);
1303 const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{
1304 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },
1308 const identifier = try expectNode(arena, it, tree, parseIdentifier, .{
1309 .ExpectedIdentifier = .{ .token = it.index },
13051310 });
13061311 const global_error_set = try createLiteral(arena, Node.ErrorType, token);
13071312 const node = try arena.create(Node.InfixOp);
13081313 node.* = .{
13091314 .op_token = period,
13101315 .lhs = global_error_set,
1311 .op = Node.InfixOp.Op.Period,
1316 .op = .Period,
13121317 .rhs = identifier,
13131318 };
13141319 return &node.base;
......@@ -1358,7 +1363,7 @@ fn parseErrorSetDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
13581363 const rbrace = try expectToken(it, tree, .RBrace);
13591364
13601365 const node = try arena.create(Node.ErrorSetDecl);
1361 node.* = Node.ErrorSetDecl{
1366 node.* = .{
13621367 .error_token = error_token,
13631368 .decls = decls,
13641369 .rbrace_token = rbrace,
......@@ -1369,13 +1374,13 @@ fn parseErrorSetDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
13691374/// GroupedExpr <- LPAREN Expr RPAREN
13701375fn parseGroupedExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
13711376 const lparen = eatToken(it, .LParen) orelse return null;
1372 const expr = try expectNode(arena, it, tree, parseExpr, AstError{
1373 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1377 const expr = try expectNode(arena, it, tree, parseExpr, .{
1378 .ExpectedExpr = .{ .token = it.index },
13741379 });
13751380 const rparen = try expectToken(it, tree, .RParen);
13761381
13771382 const node = try arena.create(Node.GroupedExpression);
1378 node.* = Node.GroupedExpression{
1383 node.* = .{
13791384 .lparen = lparen,
13801385 .expr = expr,
13811386 .rparen = rparen,
......@@ -1435,8 +1440,8 @@ fn parseLoopTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
14351440 if (inline_token == null) return null;
14361441
14371442 // If we've seen "inline", there should have been a "for" or "while"
1438 try tree.errors.push(AstError{
1439 .ExpectedInlinable = AstError.ExpectedInlinable{ .token = it.index },
1443 try tree.errors.push(.{
1444 .ExpectedInlinable = .{ .token = it.index },
14401445 });
14411446 return error.ParseError;
14421447}
......@@ -1446,18 +1451,18 @@ fn parseForTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
14461451 const node = (try parseForPrefix(arena, it, tree)) orelse return null;
14471452 const for_prefix = node.cast(Node.For).?;
14481453
1449 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
1450 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
1454 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
1455 .ExpectedTypeExpr = .{ .token = it.index },
14511456 });
14521457 for_prefix.body = type_expr;
14531458
14541459 if (eatToken(it, .Keyword_else)) |else_token| {
1455 const else_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
1456 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
1460 const else_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
1461 .ExpectedTypeExpr = .{ .token = it.index },
14571462 });
14581463
14591464 const else_node = try arena.create(Node.Else);
1460 else_node.* = Node.Else{
1465 else_node.* = .{
14611466 .else_token = else_token,
14621467 .payload = null,
14631468 .body = else_expr,
......@@ -1474,20 +1479,20 @@ fn parseWhileTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod
14741479 const node = (try parseWhilePrefix(arena, it, tree)) orelse return null;
14751480 const while_prefix = node.cast(Node.While).?;
14761481
1477 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
1478 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
1482 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
1483 .ExpectedTypeExpr = .{ .token = it.index },
14791484 });
14801485 while_prefix.body = type_expr;
14811486
14821487 if (eatToken(it, .Keyword_else)) |else_token| {
14831488 const payload = try parsePayload(arena, it, tree);
14841489
1485 const else_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
1486 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
1490 const else_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
1491 .ExpectedTypeExpr = .{ .token = it.index },
14871492 });
14881493
14891494 const else_node = try arena.create(Node.Else);
1490 else_node.* = Node.Else{
1495 else_node.* = .{
14911496 .else_token = else_token,
14921497 .payload = null,
14931498 .body = else_expr,
......@@ -1503,8 +1508,8 @@ fn parseWhileTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod
15031508fn parseSwitchExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
15041509 const switch_token = eatToken(it, .Keyword_switch) orelse return null;
15051510 _ = try expectToken(it, tree, .LParen);
1506 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
1507 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1511 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
1512 .ExpectedExpr = .{ .token = it.index },
15081513 });
15091514 _ = try expectToken(it, tree, .RParen);
15101515 _ = try expectToken(it, tree, .LBrace);
......@@ -1512,7 +1517,7 @@ fn parseSwitchExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
15121517 const rbrace = try expectToken(it, tree, .RBrace);
15131518
15141519 const node = try arena.create(Node.Switch);
1515 node.* = Node.Switch{
1520 node.* = .{
15161521 .switch_token = switch_token,
15171522 .expr = expr_node,
15181523 .cases = cases,
......@@ -1526,12 +1531,12 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
15261531 const asm_token = eatToken(it, .Keyword_asm) orelse return null;
15271532 const volatile_token = eatToken(it, .Keyword_volatile);
15281533 _ = try expectToken(it, tree, .LParen);
1529 const template = try expectNode(arena, it, tree, parseExpr, AstError{
1530 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1534 const template = try expectNode(arena, it, tree, parseExpr, .{
1535 .ExpectedExpr = .{ .token = it.index },
15311536 });
15321537
15331538 const node = try arena.create(Node.Asm);
1534 node.* = Node.Asm{
1539 node.* = .{
15351540 .asm_token = asm_token,
15361541 .volatile_token = volatile_token,
15371542 .template = template,
......@@ -1553,7 +1558,7 @@ fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
15531558 // anon enum literal
15541559 if (eatToken(it, .Identifier)) |name| {
15551560 const node = try arena.create(Node.EnumLiteral);
1556 node.* = Node.EnumLiteral{
1561 node.* = .{
15571562 .dot = dot,
15581563 .name = name,
15591564 };
......@@ -1580,32 +1585,32 @@ fn parseAsmOutput(arena: *Allocator, it: *TokenIterator, tree: *Tree, asm_node:
15801585/// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
15811586fn parseAsmOutputItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.AsmOutput {
15821587 const lbracket = eatToken(it, .LBracket) orelse return null;
1583 const name = try expectNode(arena, it, tree, parseIdentifier, AstError{
1584 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },
1588 const name = try expectNode(arena, it, tree, parseIdentifier, .{
1589 .ExpectedIdentifier = .{ .token = it.index },
15851590 });
15861591 _ = try expectToken(it, tree, .RBracket);
15871592
1588 const constraint = try expectNode(arena, it, tree, parseStringLiteral, AstError{
1589 .ExpectedStringLiteral = AstError.ExpectedStringLiteral{ .token = it.index },
1593 const constraint = try expectNode(arena, it, tree, parseStringLiteral, .{
1594 .ExpectedStringLiteral = .{ .token = it.index },
15901595 });
15911596
15921597 _ = try expectToken(it, tree, .LParen);
1593 const kind = blk: {
1598 const kind: Node.AsmOutput.Kind = blk: {
15941599 if (eatToken(it, .Arrow) != null) {
1595 const return_ident = try expectNode(arena, it, tree, parseTypeExpr, AstError{
1596 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
1600 const return_ident = try expectNode(arena, it, tree, parseTypeExpr, .{
1601 .ExpectedTypeExpr = .{ .token = it.index },
15971602 });
1598 break :blk Node.AsmOutput.Kind{ .Return = return_ident };
1603 break :blk .{ .Return = return_ident };
15991604 }
1600 const variable = try expectNode(arena, it, tree, parseIdentifier, AstError{
1601 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },
1605 const variable = try expectNode(arena, it, tree, parseIdentifier, .{
1606 .ExpectedIdentifier = .{ .token = it.index },
16021607 });
1603 break :blk Node.AsmOutput.Kind{ .Variable = variable.cast(Node.Identifier).? };
1608 break :blk .{ .Variable = variable.cast(Node.Identifier).? };
16041609 };
16051610 const rparen = try expectToken(it, tree, .RParen);
16061611
16071612 const node = try arena.create(Node.AsmOutput);
1608 node.* = Node.AsmOutput{
1613 node.* = .{
16091614 .lbracket = lbracket,
16101615 .symbolic_name = name,
16111616 .constraint = constraint,
......@@ -1625,23 +1630,23 @@ fn parseAsmInput(arena: *Allocator, it: *TokenIterator, tree: *Tree, asm_node: *
16251630/// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
16261631fn parseAsmInputItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.AsmInput {
16271632 const lbracket = eatToken(it, .LBracket) orelse return null;
1628 const name = try expectNode(arena, it, tree, parseIdentifier, AstError{
1629 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },
1633 const name = try expectNode(arena, it, tree, parseIdentifier, .{
1634 .ExpectedIdentifier = .{ .token = it.index },
16301635 });
16311636 _ = try expectToken(it, tree, .RBracket);
16321637
1633 const constraint = try expectNode(arena, it, tree, parseStringLiteral, AstError{
1634 .ExpectedStringLiteral = AstError.ExpectedStringLiteral{ .token = it.index },
1638 const constraint = try expectNode(arena, it, tree, parseStringLiteral, .{
1639 .ExpectedStringLiteral = .{ .token = it.index },
16351640 });
16361641
16371642 _ = try expectToken(it, tree, .LParen);
1638 const expr = try expectNode(arena, it, tree, parseExpr, AstError{
1639 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1643 const expr = try expectNode(arena, it, tree, parseExpr, .{
1644 .ExpectedExpr = .{ .token = it.index },
16401645 });
16411646 const rparen = try expectToken(it, tree, .RParen);
16421647
16431648 const node = try arena.create(Node.AsmInput);
1644 node.* = Node.AsmInput{
1649 node.* = .{
16451650 .lbracket = lbracket,
16461651 .symbolic_name = name,
16471652 .constraint = constraint,
......@@ -1664,8 +1669,8 @@ fn parseAsmClobbers(arena: *Allocator, it: *TokenIterator, tree: *Tree, asm_node
16641669/// BreakLabel <- COLON IDENTIFIER
16651670fn parseBreakLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
16661671 _ = eatToken(it, .Colon) orelse return null;
1667 return try expectNode(arena, it, tree, parseIdentifier, AstError{
1668 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },
1672 return try expectNode(arena, it, tree, parseIdentifier, .{
1673 .ExpectedIdentifier = .{ .token = it.index },
16691674 });
16701675}
16711676
......@@ -1694,12 +1699,12 @@ fn parseFieldInit(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
16941699 putBackToken(it, period_token);
16951700 return null;
16961701 };
1697 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
1698 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1702 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
1703 .ExpectedExpr = .{ .token = it.index },
16991704 });
17001705
17011706 const node = try arena.create(Node.FieldInitializer);
1702 node.* = Node.FieldInitializer{
1707 node.* = .{
17031708 .period_token = period_token,
17041709 .name_token = name_token,
17051710 .expr = expr_node,
......@@ -1711,8 +1716,8 @@ fn parseFieldInit(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
17111716fn parseWhileContinueExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
17121717 _ = eatToken(it, .Colon) orelse return null;
17131718 _ = try expectToken(it, tree, .LParen);
1714 const node = try expectNode(arena, it, tree, parseAssignExpr, AstError{
1715 .ExpectedExprOrAssignment = AstError.ExpectedExprOrAssignment{ .token = it.index },
1719 const node = try expectNode(arena, it, tree, parseAssignExpr, .{
1720 .ExpectedExprOrAssignment = .{ .token = it.index },
17161721 });
17171722 _ = try expectToken(it, tree, .RParen);
17181723 return node;
......@@ -1722,8 +1727,8 @@ fn parseWhileContinueExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
17221727fn parseLinkSection(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
17231728 _ = eatToken(it, .Keyword_linksection) orelse return null;
17241729 _ = try expectToken(it, tree, .LParen);
1725 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
1726 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1730 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
1731 .ExpectedExpr = .{ .token = it.index },
17271732 });
17281733 _ = try expectToken(it, tree, .RParen);
17291734 return expr_node;
......@@ -1733,8 +1738,8 @@ fn parseLinkSection(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
17331738fn parseCallconv(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
17341739 _ = eatToken(it, .Keyword_callconv) orelse return null;
17351740 _ = try expectToken(it, tree, .LParen);
1736 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
1737 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1741 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
1742 .ExpectedExpr = .{ .token = it.index },
17381743 });
17391744 _ = try expectToken(it, tree, .RParen);
17401745 return expr_node;
......@@ -1775,14 +1780,14 @@ fn parseParamDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
17751780 comptime_token == null and
17761781 name_token == null and
17771782 doc_comments == null) return null;
1778 try tree.errors.push(AstError{
1779 .ExpectedParamType = AstError.ExpectedParamType{ .token = it.index },
1783 try tree.errors.push(.{
1784 .ExpectedParamType = .{ .token = it.index },
17801785 });
17811786 return error.ParseError;
17821787 };
17831788
17841789 const param_decl = try arena.create(Node.ParamDecl);
1785 param_decl.* = Node.ParamDecl{
1790 param_decl.* = .{
17861791 .doc_comments = doc_comments,
17871792 .comptime_token = comptime_token,
17881793 .noalias_token = noalias_token,
......@@ -1821,14 +1826,14 @@ const ParamType = union(enum) {
18211826fn parseIfPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
18221827 const if_token = eatToken(it, .Keyword_if) orelse return null;
18231828 _ = try expectToken(it, tree, .LParen);
1824 const condition = try expectNode(arena, it, tree, parseExpr, AstError{
1825 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1829 const condition = try expectNode(arena, it, tree, parseExpr, .{
1830 .ExpectedExpr = .{ .token = it.index },
18261831 });
18271832 _ = try expectToken(it, tree, .RParen);
18281833 const payload = try parsePtrPayload(arena, it, tree);
18291834
18301835 const node = try arena.create(Node.If);
1831 node.* = Node.If{
1836 node.* = .{
18321837 .if_token = if_token,
18331838 .condition = condition,
18341839 .payload = payload,
......@@ -1843,8 +1848,8 @@ fn parseWhilePrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
18431848 const while_token = eatToken(it, .Keyword_while) orelse return null;
18441849
18451850 _ = try expectToken(it, tree, .LParen);
1846 const condition = try expectNode(arena, it, tree, parseExpr, AstError{
1847 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1851 const condition = try expectNode(arena, it, tree, parseExpr, .{
1852 .ExpectedExpr = .{ .token = it.index },
18481853 });
18491854 _ = try expectToken(it, tree, .RParen);
18501855
......@@ -1852,7 +1857,7 @@ fn parseWhilePrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
18521857 const continue_expr = try parseWhileContinueExpr(arena, it, tree);
18531858
18541859 const node = try arena.create(Node.While);
1855 node.* = Node.While{
1860 node.* = .{
18561861 .label = null,
18571862 .inline_token = null,
18581863 .while_token = while_token,
......@@ -1870,17 +1875,17 @@ fn parseForPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
18701875 const for_token = eatToken(it, .Keyword_for) orelse return null;
18711876
18721877 _ = try expectToken(it, tree, .LParen);
1873 const array_expr = try expectNode(arena, it, tree, parseExpr, AstError{
1874 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
1878 const array_expr = try expectNode(arena, it, tree, parseExpr, .{
1879 .ExpectedExpr = .{ .token = it.index },
18751880 });
18761881 _ = try expectToken(it, tree, .RParen);
18771882
1878 const payload = try expectNode(arena, it, tree, parsePtrIndexPayload, AstError{
1879 .ExpectedPayload = AstError.ExpectedPayload{ .token = it.index },
1883 const payload = try expectNode(arena, it, tree, parsePtrIndexPayload, .{
1884 .ExpectedPayload = .{ .token = it.index },
18801885 });
18811886
18821887 const node = try arena.create(Node.For);
1883 node.* = Node.For{
1888 node.* = .{
18841889 .label = null,
18851890 .inline_token = null,
18861891 .for_token = for_token,
......@@ -1895,13 +1900,13 @@ fn parseForPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
18951900/// Payload <- PIPE IDENTIFIER PIPE
18961901fn parsePayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
18971902 const lpipe = eatToken(it, .Pipe) orelse return null;
1898 const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{
1899 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },
1903 const identifier = try expectNode(arena, it, tree, parseIdentifier, .{
1904 .ExpectedIdentifier = .{ .token = it.index },
19001905 });
19011906 const rpipe = try expectToken(it, tree, .Pipe);
19021907
19031908 const node = try arena.create(Node.Payload);
1904 node.* = Node.Payload{
1909 node.* = .{
19051910 .lpipe = lpipe,
19061911 .error_symbol = identifier,
19071912 .rpipe = rpipe,
......@@ -1913,13 +1918,13 @@ fn parsePayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
19131918fn parsePtrPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
19141919 const lpipe = eatToken(it, .Pipe) orelse return null;
19151920 const asterisk = eatToken(it, .Asterisk);
1916 const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{
1917 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },
1921 const identifier = try expectNode(arena, it, tree, parseIdentifier, .{
1922 .ExpectedIdentifier = .{ .token = it.index },
19181923 });
19191924 const rpipe = try expectToken(it, tree, .Pipe);
19201925
19211926 const node = try arena.create(Node.PointerPayload);
1922 node.* = Node.PointerPayload{
1927 node.* = .{
19231928 .lpipe = lpipe,
19241929 .ptr_token = asterisk,
19251930 .value_symbol = identifier,
......@@ -1932,21 +1937,21 @@ fn parsePtrPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
19321937fn parsePtrIndexPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
19331938 const lpipe = eatToken(it, .Pipe) orelse return null;
19341939 const asterisk = eatToken(it, .Asterisk);
1935 const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{
1936 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },
1940 const identifier = try expectNode(arena, it, tree, parseIdentifier, .{
1941 .ExpectedIdentifier = .{ .token = it.index },
19371942 });
19381943
19391944 const index = if (eatToken(it, .Comma) == null)
19401945 null
19411946 else
1942 try expectNode(arena, it, tree, parseIdentifier, AstError{
1943 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },
1947 try expectNode(arena, it, tree, parseIdentifier, .{
1948 .ExpectedIdentifier = .{ .token = it.index },
19441949 });
19451950
19461951 const rpipe = try expectToken(it, tree, .Pipe);
19471952
19481953 const node = try arena.create(Node.PointerIndexPayload);
1949 node.* = Node.PointerIndexPayload{
1954 node.* = .{
19501955 .lpipe = lpipe,
19511956 .ptr_token = asterisk,
19521957 .value_symbol = identifier,
......@@ -1961,8 +1966,8 @@ fn parseSwitchProng(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
19611966 const node = (try parseSwitchCase(arena, it, tree)) orelse return null;
19621967 const arrow = try expectToken(it, tree, .EqualAngleBracketRight);
19631968 const payload = try parsePtrPayload(arena, it, tree);
1964 const expr = try expectNode(arena, it, tree, parseAssignExpr, AstError{
1965 .ExpectedExprOrAssignment = AstError.ExpectedExprOrAssignment{ .token = it.index },
1969 const expr = try expectNode(arena, it, tree, parseAssignExpr, .{
1970 .ExpectedExprOrAssignment = .{ .token = it.index },
19661971 });
19671972
19681973 const switch_case = node.cast(Node.SwitchCase).?;
......@@ -1987,14 +1992,14 @@ fn parseSwitchCase(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
19871992 }
19881993 } else if (eatToken(it, .Keyword_else)) |else_token| {
19891994 const else_node = try arena.create(Node.SwitchElse);
1990 else_node.* = Node.SwitchElse{
1995 else_node.* = .{
19911996 .token = else_token,
19921997 };
19931998 try list.push(&else_node.base);
19941999 } else return null;
19952000
19962001 const node = try arena.create(Node.SwitchCase);
1997 node.* = Node.SwitchCase{
2002 node.* = .{
19982003 .items = list,
19992004 .arrow_token = undefined, // set by caller
20002005 .payload = null,
......@@ -2007,15 +2012,15 @@ fn parseSwitchCase(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
20072012fn parseSwitchItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
20082013 const expr = (try parseExpr(arena, it, tree)) orelse return null;
20092014 if (eatToken(it, .Ellipsis3)) |token| {
2010 const range_end = try expectNode(arena, it, tree, parseExpr, AstError{
2011 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
2015 const range_end = try expectNode(arena, it, tree, parseExpr, .{
2016 .ExpectedExpr = .{ .token = it.index },
20122017 });
20132018
20142019 const node = try arena.create(Node.InfixOp);
2015 node.* = Node.InfixOp{
2020 node.* = .{
20162021 .op_token = token,
20172022 .lhs = expr,
2018 .op = Node.InfixOp.Op{ .Range = {} },
2023 .op = .Range,
20192024 .rhs = range_end,
20202025 };
20212026 return &node.base;
......@@ -2039,24 +2044,22 @@ fn parseSwitchItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
20392044/// / MINUSPERCENTEQUAL
20402045/// / EQUAL
20412046fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2042 const Op = Node.InfixOp.Op;
2043
20442047 const token = nextToken(it);
2045 const op = switch (token.ptr.id) {
2046 .AsteriskEqual => Op{ .AssignMul = {} },
2047 .SlashEqual => Op{ .AssignDiv = {} },
2048 .PercentEqual => Op{ .AssignMod = {} },
2049 .PlusEqual => Op{ .AssignAdd = {} },
2050 .MinusEqual => Op{ .AssignSub = {} },
2051 .AngleBracketAngleBracketLeftEqual => Op{ .AssignBitShiftLeft = {} },
2052 .AngleBracketAngleBracketRightEqual => Op{ .AssignBitShiftRight = {} },
2053 .AmpersandEqual => Op{ .AssignBitAnd = {} },
2054 .CaretEqual => Op{ .AssignBitXor = {} },
2055 .PipeEqual => Op{ .AssignBitOr = {} },
2056 .AsteriskPercentEqual => Op{ .AssignMulWrap = {} },
2057 .PlusPercentEqual => Op{ .AssignAddWrap = {} },
2058 .MinusPercentEqual => Op{ .AssignSubWrap = {} },
2059 .Equal => Op{ .Assign = {} },
2048 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2049 .AsteriskEqual => .AssignMul,
2050 .SlashEqual => .AssignDiv,
2051 .PercentEqual => .AssignMod,
2052 .PlusEqual => .AssignAdd,
2053 .MinusEqual => .AssignSub,
2054 .AngleBracketAngleBracketLeftEqual => .AssignBitShiftLeft,
2055 .AngleBracketAngleBracketRightEqual => .AssignBitShiftRight,
2056 .AmpersandEqual => .AssignBitAnd,
2057 .CaretEqual => .AssignBitXor,
2058 .PipeEqual => .AssignBitOr,
2059 .AsteriskPercentEqual => .AssignMulWrap,
2060 .PlusPercentEqual => .AssignAddWrap,
2061 .MinusPercentEqual => .AssignSubWrap,
2062 .Equal => .Assign,
20602063 else => {
20612064 putBackToken(it, token.index);
20622065 return null;
......@@ -2064,7 +2067,7 @@ fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
20642067 };
20652068
20662069 const node = try arena.create(Node.InfixOp);
2067 node.* = Node.InfixOp{
2070 node.* = .{
20682071 .op_token = token.index,
20692072 .lhs = undefined, // set by caller
20702073 .op = op,
......@@ -2081,16 +2084,14 @@ fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
20812084/// / LARROWEQUAL
20822085/// / RARROWEQUAL
20832086fn parseCompareOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2084 const ops = Node.InfixOp.Op;
2085
20862087 const token = nextToken(it);
2087 const op = switch (token.ptr.id) {
2088 .EqualEqual => ops{ .EqualEqual = {} },
2089 .BangEqual => ops{ .BangEqual = {} },
2090 .AngleBracketLeft => ops{ .LessThan = {} },
2091 .AngleBracketRight => ops{ .GreaterThan = {} },
2092 .AngleBracketLeftEqual => ops{ .LessOrEqual = {} },
2093 .AngleBracketRightEqual => ops{ .GreaterOrEqual = {} },
2088 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2089 .EqualEqual => .EqualEqual,
2090 .BangEqual => .BangEqual,
2091 .AngleBracketLeft => .LessThan,
2092 .AngleBracketRight => .GreaterThan,
2093 .AngleBracketLeftEqual => .LessOrEqual,
2094 .AngleBracketRightEqual => .GreaterOrEqual,
20942095 else => {
20952096 putBackToken(it, token.index);
20962097 return null;
......@@ -2107,15 +2108,13 @@ fn parseCompareOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
21072108/// / KEYWORD_orelse
21082109/// / KEYWORD_catch Payload?
21092110fn parseBitwiseOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2110 const ops = Node.InfixOp.Op;
2111
21122111 const token = nextToken(it);
2113 const op = switch (token.ptr.id) {
2114 .Ampersand => ops{ .BitAnd = {} },
2115 .Caret => ops{ .BitXor = {} },
2116 .Pipe => ops{ .BitOr = {} },
2117 .Keyword_orelse => ops{ .UnwrapOptional = {} },
2118 .Keyword_catch => ops{ .Catch = try parsePayload(arena, it, tree) },
2112 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2113 .Ampersand => .BitAnd,
2114 .Caret => .BitXor,
2115 .Pipe => .BitOr,
2116 .Keyword_orelse => .UnwrapOptional,
2117 .Keyword_catch => .{ .Catch = try parsePayload(arena, it, tree) },
21192118 else => {
21202119 putBackToken(it, token.index);
21212120 return null;
......@@ -2129,12 +2128,10 @@ fn parseBitwiseOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
21292128/// <- LARROW2
21302129/// / RARROW2
21312130fn parseBitShiftOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2132 const ops = Node.InfixOp.Op;
2133
21342131 const token = nextToken(it);
2135 const op = switch (token.ptr.id) {
2136 .AngleBracketAngleBracketLeft => ops{ .BitShiftLeft = {} },
2137 .AngleBracketAngleBracketRight => ops{ .BitShiftRight = {} },
2132 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2133 .AngleBracketAngleBracketLeft => .BitShiftLeft,
2134 .AngleBracketAngleBracketRight => .BitShiftRight,
21382135 else => {
21392136 putBackToken(it, token.index);
21402137 return null;
......@@ -2151,15 +2148,13 @@ fn parseBitShiftOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
21512148/// / PLUSPERCENT
21522149/// / MINUSPERCENT
21532150fn parseAdditionOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2154 const ops = Node.InfixOp.Op;
2155
21562151 const token = nextToken(it);
2157 const op = switch (token.ptr.id) {
2158 .Plus => ops{ .Add = {} },
2159 .Minus => ops{ .Sub = {} },
2160 .PlusPlus => ops{ .ArrayCat = {} },
2161 .PlusPercent => ops{ .AddWrap = {} },
2162 .MinusPercent => ops{ .SubWrap = {} },
2152 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2153 .Plus => .Add,
2154 .Minus => .Sub,
2155 .PlusPlus => .ArrayCat,
2156 .PlusPercent => .AddWrap,
2157 .MinusPercent => .SubWrap,
21632158 else => {
21642159 putBackToken(it, token.index);
21652160 return null;
......@@ -2177,16 +2172,14 @@ fn parseAdditionOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
21772172/// / ASTERISK2
21782173/// / ASTERISKPERCENT
21792174fn parseMultiplyOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2180 const ops = Node.InfixOp.Op;
2181
21822175 const token = nextToken(it);
2183 const op = switch (token.ptr.id) {
2184 .PipePipe => ops{ .BoolOr = {} },
2185 .Asterisk => ops{ .Mul = {} },
2186 .Slash => ops{ .Div = {} },
2187 .Percent => ops{ .Mod = {} },
2188 .AsteriskAsterisk => ops{ .ArrayMult = {} },
2189 .AsteriskPercent => ops{ .MulWrap = {} },
2176 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2177 .PipePipe => .MergeErrorSets,
2178 .Asterisk => .Mul,
2179 .Slash => .Div,
2180 .Percent => .Mod,
2181 .AsteriskAsterisk => .ArrayMult,
2182 .AsteriskPercent => .MulWrap,
21902183 else => {
21912184 putBackToken(it, token.index);
21922185 return null;
......@@ -2205,17 +2198,15 @@ fn parseMultiplyOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
22052198/// / KEYWORD_try
22062199/// / KEYWORD_await
22072200fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2208 const ops = Node.PrefixOp.Op;
2209
22102201 const token = nextToken(it);
2211 const op = switch (token.ptr.id) {
2212 .Bang => ops{ .BoolNot = {} },
2213 .Minus => ops{ .Negation = {} },
2214 .Tilde => ops{ .BitNot = {} },
2215 .MinusPercent => ops{ .NegationWrap = {} },
2216 .Ampersand => ops{ .AddressOf = {} },
2217 .Keyword_try => ops{ .Try = {} },
2218 .Keyword_await => ops{ .Await = .{} },
2202 const op: Node.PrefixOp.Op = switch (token.ptr.id) {
2203 .Bang => .BoolNot,
2204 .Minus => .Negation,
2205 .Tilde => .BitNot,
2206 .MinusPercent => .NegationWrap,
2207 .Ampersand => .AddressOf,
2208 .Keyword_try => .Try,
2209 .Keyword_await => .Await,
22192210 else => {
22202211 putBackToken(it, token.index);
22212212 return null;
......@@ -2223,7 +2214,7 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
22232214 };
22242215
22252216 const node = try arena.create(Node.PrefixOp);
2226 node.* = Node.PrefixOp{
2217 node.* = .{
22272218 .op_token = token.index,
22282219 .op = op,
22292220 .rhs = undefined, // set by caller
......@@ -2246,9 +2237,9 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
22462237fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
22472238 if (eatToken(it, .QuestionMark)) |token| {
22482239 const node = try arena.create(Node.PrefixOp);
2249 node.* = Node.PrefixOp{
2240 node.* = .{
22502241 .op_token = token,
2251 .op = Node.PrefixOp.Op.OptionalType,
2242 .op = .OptionalType,
22522243 .rhs = undefined, // set by caller
22532244 };
22542245 return &node.base;
......@@ -2264,7 +2255,7 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
22642255 return null;
22652256 };
22662257 const node = try arena.create(Node.AnyFrameType);
2267 node.* = Node.AnyFrameType{
2258 node.* = .{
22682259 .anyframe_token = token,
22692260 .result = Node.AnyFrameType.Result{
22702261 .arrow_token = arrow,
......@@ -2286,18 +2277,18 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
22862277 while (true) {
22872278 if (eatToken(it, .Keyword_align)) |align_token| {
22882279 const lparen = try expectToken(it, tree, .LParen);
2289 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
2290 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
2280 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
2281 .ExpectedExpr = .{ .token = it.index },
22912282 });
22922283
22932284 // Optional bit range
22942285 const bit_range = if (eatToken(it, .Colon)) |_| bit_range_value: {
2295 const range_start = try expectNode(arena, it, tree, parseIntegerLiteral, AstError{
2296 .ExpectedIntegerLiteral = AstError.ExpectedIntegerLiteral{ .token = it.index },
2286 const range_start = try expectNode(arena, it, tree, parseIntegerLiteral, .{
2287 .ExpectedIntegerLiteral = .{ .token = it.index },
22972288 });
22982289 _ = try expectToken(it, tree, .Colon);
2299 const range_end = try expectNode(arena, it, tree, parseIntegerLiteral, AstError{
2300 .ExpectedIntegerLiteral = AstError.ExpectedIntegerLiteral{ .token = it.index },
2290 const range_end = try expectNode(arena, it, tree, parseIntegerLiteral, .{
2291 .ExpectedIntegerLiteral = .{ .token = it.index },
23012292 });
23022293
23032294 break :bit_range_value Node.PrefixOp.PtrInfo.Align.BitRange{
......@@ -2340,8 +2331,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
23402331 while (true) {
23412332 if (try parseByteAlign(arena, it, tree)) |align_expr| {
23422333 if (slice_type.align_info != null) {
2343 try tree.errors.push(AstError{
2344 .ExtraAlignQualifier = AstError.ExtraAlignQualifier{ .token = it.index },
2334 try tree.errors.push(.{
2335 .ExtraAlignQualifier = .{ .token = it.index },
23452336 });
23462337 return error.ParseError;
23472338 }
......@@ -2353,8 +2344,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
23532344 }
23542345 if (eatToken(it, .Keyword_const)) |const_token| {
23552346 if (slice_type.const_token != null) {
2356 try tree.errors.push(AstError{
2357 .ExtraConstQualifier = AstError.ExtraConstQualifier{ .token = it.index },
2347 try tree.errors.push(.{
2348 .ExtraConstQualifier = .{ .token = it.index },
23582349 });
23592350 return error.ParseError;
23602351 }
......@@ -2363,8 +2354,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
23632354 }
23642355 if (eatToken(it, .Keyword_volatile)) |volatile_token| {
23652356 if (slice_type.volatile_token != null) {
2366 try tree.errors.push(AstError{
2367 .ExtraVolatileQualifier = AstError.ExtraVolatileQualifier{ .token = it.index },
2357 try tree.errors.push(.{
2358 .ExtraVolatileQualifier = .{ .token = it.index },
23682359 });
23692360 return error.ParseError;
23702361 }
......@@ -2373,8 +2364,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
23732364 }
23742365 if (eatToken(it, .Keyword_allowzero)) |allowzero_token| {
23752366 if (slice_type.allowzero_token != null) {
2376 try tree.errors.push(AstError{
2377 .ExtraAllowZeroQualifier = AstError.ExtraAllowZeroQualifier{ .token = it.index },
2367 try tree.errors.push(.{
2368 .ExtraAllowZeroQualifier = .{ .token = it.index },
23782369 });
23792370 return error.ParseError;
23802371 }
......@@ -2398,15 +2389,14 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
23982389/// / DOTASTERISK
23992390/// / DOTQUESTIONMARK
24002391fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2401 const Op = Node.SuffixOp.Op;
24022392 const OpAndToken = struct {
24032393 op: Node.SuffixOp.Op,
24042394 token: TokenIndex,
24052395 };
2406 const op_and_token = blk: {
2396 const op_and_token: OpAndToken = blk: {
24072397 if (eatToken(it, .LBracket)) |_| {
2408 const index_expr = try expectNode(arena, it, tree, parseExpr, AstError{
2409 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
2398 const index_expr = try expectNode(arena, it, tree, parseExpr, .{
2399 .ExpectedExpr = .{ .token = it.index },
24102400 });
24112401
24122402 if (eatToken(it, .Ellipsis2) != null) {
......@@ -2415,9 +2405,9 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
24152405 try parseExpr(arena, it, tree)
24162406 else
24172407 null;
2418 break :blk OpAndToken{
2419 .op = Op{
2420 .Slice = Op.Slice{
2408 break :blk .{
2409 .op = .{
2410 .Slice = .{
24212411 .start = index_expr,
24222412 .end = end_expr,
24232413 .sentinel = sentinel,
......@@ -2427,14 +2417,14 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
24272417 };
24282418 }
24292419
2430 break :blk OpAndToken{
2431 .op = Op{ .ArrayAccess = index_expr },
2420 break :blk .{
2421 .op = .{ .ArrayAccess = index_expr },
24322422 .token = try expectToken(it, tree, .RBracket),
24332423 };
24342424 }
24352425
24362426 if (eatToken(it, .PeriodAsterisk)) |period_asterisk| {
2437 break :blk OpAndToken{ .op = Op{ .Deref = {} }, .token = period_asterisk };
2427 break :blk .{ .op = .Deref, .token = period_asterisk };
24382428 }
24392429
24402430 if (eatToken(it, .Period)) |period| {
......@@ -2443,19 +2433,19 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
24432433 // Should there be an ast.Node.SuffixOp.FieldAccess variant? Or should
24442434 // this grammar rule be altered?
24452435 const node = try arena.create(Node.InfixOp);
2446 node.* = Node.InfixOp{
2436 node.* = .{
24472437 .op_token = period,
24482438 .lhs = undefined, // set by caller
2449 .op = Node.InfixOp.Op.Period,
2439 .op = .Period,
24502440 .rhs = identifier,
24512441 };
24522442 return &node.base;
24532443 }
24542444 if (eatToken(it, .QuestionMark)) |question_mark| {
2455 break :blk OpAndToken{ .op = Op{ .UnwrapOptional = {} }, .token = question_mark };
2445 break :blk .{ .op = .UnwrapOptional, .token = question_mark };
24562446 }
2457 try tree.errors.push(AstError{
2458 .ExpectedSuffixOp = AstError.ExpectedSuffixOp{ .token = it.index },
2447 try tree.errors.push(.{
2448 .ExpectedSuffixOp = .{ .token = it.index },
24592449 });
24602450 return null;
24612451 }
......@@ -2464,7 +2454,7 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
24642454 };
24652455
24662456 const node = try arena.create(Node.SuffixOp);
2467 node.* = Node.SuffixOp{
2457 node.* = .{
24682458 .lhs = undefined, // set by caller
24692459 .op = op_and_token.op,
24702460 .rtoken = op_and_token.token,
......@@ -2491,22 +2481,22 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
24912481 const lbracket = eatToken(it, .LBracket) orelse return null;
24922482 const expr = try parseExpr(arena, it, tree);
24932483 const sentinel = if (eatToken(it, .Colon)) |_|
2494 try expectNode(arena, it, tree, parseExpr, AstError{
2484 try expectNode(arena, it, tree, parseExpr, .{
24952485 .ExpectedExpr = .{ .token = it.index },
24962486 })
24972487 else
24982488 null;
24992489 const rbracket = try expectToken(it, tree, .RBracket);
25002490
2501 const op = if (expr) |len_expr|
2502 Node.PrefixOp.Op{
2491 const op: Node.PrefixOp.Op = if (expr) |len_expr|
2492 .{
25032493 .ArrayType = .{
25042494 .len_expr = len_expr,
25052495 .sentinel = sentinel,
25062496 },
25072497 }
25082498 else
2509 Node.PrefixOp.Op{
2499 .{
25102500 .SliceType = Node.PrefixOp.PtrInfo{
25112501 .allowzero_token = null,
25122502 .align_info = null,
......@@ -2517,7 +2507,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
25172507 };
25182508
25192509 const node = try arena.create(Node.PrefixOp);
2520 node.* = Node.PrefixOp{
2510 node.* = .{
25212511 .op_token = lbracket,
25222512 .op = op,
25232513 .rhs = undefined, // set by caller
......@@ -2533,7 +2523,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
25332523fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
25342524 if (eatToken(it, .Asterisk)) |asterisk| {
25352525 const sentinel = if (eatToken(it, .Colon)) |_|
2536 try expectNode(arena, it, tree, parseExpr, AstError{
2526 try expectNode(arena, it, tree, parseExpr, .{
25372527 .ExpectedExpr = .{ .token = it.index },
25382528 })
25392529 else
......@@ -2549,17 +2539,17 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
25492539
25502540 if (eatToken(it, .AsteriskAsterisk)) |double_asterisk| {
25512541 const node = try arena.create(Node.PrefixOp);
2552 node.* = Node.PrefixOp{
2542 node.* = .{
25532543 .op_token = double_asterisk,
2554 .op = Node.PrefixOp.Op{ .PtrType = .{} },
2544 .op = .{ .PtrType = .{} },
25552545 .rhs = undefined, // set by caller
25562546 };
25572547
25582548 // Special case for **, which is its own token
25592549 const child = try arena.create(Node.PrefixOp);
2560 child.* = Node.PrefixOp{
2550 child.* = .{
25612551 .op_token = double_asterisk,
2562 .op = Node.PrefixOp.Op{ .PtrType = .{} },
2552 .op = .{ .PtrType = .{} },
25632553 .rhs = undefined, // set by caller
25642554 };
25652555 node.rhs = &child.base;
......@@ -2586,7 +2576,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
25862576 }
25872577 }
25882578 const sentinel = if (eatToken(it, .Colon)) |_|
2589 try expectNode(arena, it, tree, parseExpr, AstError{
2579 try expectNode(arena, it, tree, parseExpr, .{
25902580 .ExpectedExpr = .{ .token = it.index },
25912581 })
25922582 else
......@@ -2629,8 +2619,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
26292619 .Keyword_struct => Node.ContainerDecl.InitArg{ .None = {} },
26302620 .Keyword_enum => blk: {
26312621 if (eatToken(it, .LParen) != null) {
2632 const expr = try expectNode(arena, it, tree, parseExpr, AstError{
2633 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
2622 const expr = try expectNode(arena, it, tree, parseExpr, .{
2623 .ExpectedExpr = .{ .token = it.index },
26342624 });
26352625 _ = try expectToken(it, tree, .RParen);
26362626 break :blk Node.ContainerDecl.InitArg{ .Type = expr };
......@@ -2641,8 +2631,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
26412631 if (eatToken(it, .LParen) != null) {
26422632 if (eatToken(it, .Keyword_enum) != null) {
26432633 if (eatToken(it, .LParen) != null) {
2644 const expr = try expectNode(arena, it, tree, parseExpr, AstError{
2645 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
2634 const expr = try expectNode(arena, it, tree, parseExpr, .{
2635 .ExpectedExpr = .{ .token = it.index },
26462636 });
26472637 _ = try expectToken(it, tree, .RParen);
26482638 _ = try expectToken(it, tree, .RParen);
......@@ -2651,8 +2641,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
26512641 _ = try expectToken(it, tree, .RParen);
26522642 break :blk Node.ContainerDecl.InitArg{ .Enum = null };
26532643 }
2654 const expr = try expectNode(arena, it, tree, parseExpr, AstError{
2655 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
2644 const expr = try expectNode(arena, it, tree, parseExpr, .{
2645 .ExpectedExpr = .{ .token = it.index },
26562646 });
26572647 _ = try expectToken(it, tree, .RParen);
26582648 break :blk Node.ContainerDecl.InitArg{ .Type = expr };
......@@ -2666,7 +2656,7 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
26662656 };
26672657
26682658 const node = try arena.create(Node.ContainerDecl);
2669 node.* = Node.ContainerDecl{
2659 node.* = .{
26702660 .layout_token = null,
26712661 .kind_token = kind_token.index,
26722662 .init_arg_expr = init_arg_expr,
......@@ -2681,8 +2671,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
26812671fn parseByteAlign(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
26822672 _ = eatToken(it, .Keyword_align) orelse return null;
26832673 _ = try expectToken(it, tree, .LParen);
2684 const expr = try expectNode(arena, it, tree, parseExpr, AstError{
2685 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
2674 const expr = try expectNode(arena, it, tree, parseExpr, .{
2675 .ExpectedExpr = .{ .token = it.index },
26862676 });
26872677 _ = try expectToken(it, tree, .RParen);
26882678 return expr;
......@@ -2738,7 +2728,7 @@ fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.InfixOp.Op) No
27382728 pub fn parse(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*Node {
27392729 const op_token = eatToken(it, token) orelse return null;
27402730 const node = try arena.create(Node.InfixOp);
2741 node.* = Node.InfixOp{
2731 node.* = .{
27422732 .op_token = op_token,
27432733 .lhs = undefined, // set by caller
27442734 .op = op,
......@@ -2754,13 +2744,13 @@ fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.InfixOp.Op) No
27542744fn parseBuiltinCall(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
27552745 const token = eatToken(it, .Builtin) orelse return null;
27562746 const params = (try parseFnCallArguments(arena, it, tree)) orelse {
2757 try tree.errors.push(AstError{
2758 .ExpectedParamList = AstError.ExpectedParamList{ .token = it.index },
2747 try tree.errors.push(.{
2748 .ExpectedParamList = .{ .token = it.index },
27592749 });
27602750 return error.ParseError;
27612751 };
27622752 const node = try arena.create(Node.BuiltinCall);
2763 node.* = Node.BuiltinCall{
2753 node.* = .{
27642754 .builtin_token = token,
27652755 .params = params.list,
27662756 .rparen_token = params.rparen,
......@@ -2773,7 +2763,7 @@ fn parseErrorTag(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
27732763 const token = eatToken(it, .Identifier) orelse return null;
27742764
27752765 const node = try arena.create(Node.ErrorTag);
2776 node.* = Node.ErrorTag{
2766 node.* = .{
27772767 .doc_comments = doc_comments,
27782768 .name_token = token,
27792769 };
......@@ -2783,7 +2773,7 @@ fn parseErrorTag(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
27832773fn parseIdentifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
27842774 const token = eatToken(it, .Identifier) orelse return null;
27852775 const node = try arena.create(Node.Identifier);
2786 node.* = Node.Identifier{
2776 node.* = .{
27872777 .token = token,
27882778 };
27892779 return &node.base;
......@@ -2792,7 +2782,7 @@ fn parseIdentifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
27922782fn parseVarType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
27932783 const token = eatToken(it, .Keyword_var) orelse return null;
27942784 const node = try arena.create(Node.VarType);
2795 node.* = Node.VarType{
2785 node.* = .{
27962786 .token = token,
27972787 };
27982788 return &node.base;
......@@ -2810,7 +2800,7 @@ fn createLiteral(arena: *Allocator, comptime T: type, token: TokenIndex) !*Node
28102800fn parseStringLiteralSingle(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
28112801 if (eatToken(it, .StringLiteral)) |token| {
28122802 const node = try arena.create(Node.StringLiteral);
2813 node.* = Node.StringLiteral{
2803 node.* = .{
28142804 .token = token,
28152805 };
28162806 return &node.base;
......@@ -2824,7 +2814,7 @@ fn parseStringLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod
28242814
28252815 if (eatToken(it, .MultilineStringLiteralLine)) |first_line| {
28262816 const node = try arena.create(Node.MultilineStringLiteral);
2827 node.* = Node.MultilineStringLiteral{
2817 node.* = .{
28282818 .lines = Node.MultilineStringLiteral.LineList.init(arena),
28292819 };
28302820 try node.lines.push(first_line);
......@@ -2840,7 +2830,7 @@ fn parseStringLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod
28402830fn parseIntegerLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
28412831 const token = eatToken(it, .IntegerLiteral) orelse return null;
28422832 const node = try arena.create(Node.IntegerLiteral);
2843 node.* = Node.IntegerLiteral{
2833 node.* = .{
28442834 .token = token,
28452835 };
28462836 return &node.base;
......@@ -2849,7 +2839,7 @@ fn parseIntegerLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
28492839fn parseFloatLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
28502840 const token = eatToken(it, .FloatLiteral) orelse return null;
28512841 const node = try arena.create(Node.FloatLiteral);
2852 node.* = Node.FloatLiteral{
2842 node.* = .{
28532843 .token = token,
28542844 };
28552845 return &node.base;
......@@ -2858,9 +2848,9 @@ fn parseFloatLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
28582848fn parseTry(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
28592849 const token = eatToken(it, .Keyword_try) orelse return null;
28602850 const node = try arena.create(Node.PrefixOp);
2861 node.* = Node.PrefixOp{
2851 node.* = .{
28622852 .op_token = token,
2863 .op = Node.PrefixOp.Op.Try,
2853 .op = .Try,
28642854 .rhs = undefined, // set by caller
28652855 };
28662856 return &node.base;
......@@ -2869,7 +2859,7 @@ fn parseTry(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
28692859fn parseUse(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
28702860 const token = eatToken(it, .Keyword_usingnamespace) orelse return null;
28712861 const node = try arena.create(Node.Use);
2872 node.* = Node.Use{
2862 node.* = .{
28732863 .doc_comments = null,
28742864 .visib_token = null,
28752865 .use_token = token,
......@@ -2884,17 +2874,17 @@ fn parseIf(arena: *Allocator, it: *TokenIterator, tree: *Tree, bodyParseFn: Node
28842874 const node = (try parseIfPrefix(arena, it, tree)) orelse return null;
28852875 const if_prefix = node.cast(Node.If).?;
28862876
2887 if_prefix.body = try expectNode(arena, it, tree, bodyParseFn, AstError{
2888 .InvalidToken = AstError.InvalidToken{ .token = it.index },
2877 if_prefix.body = try expectNode(arena, it, tree, bodyParseFn, .{
2878 .InvalidToken = .{ .token = it.index },
28892879 });
28902880
28912881 const else_token = eatToken(it, .Keyword_else) orelse return node;
28922882 const payload = try parsePayload(arena, it, tree);
2893 const else_expr = try expectNode(arena, it, tree, bodyParseFn, AstError{
2894 .InvalidToken = AstError.InvalidToken{ .token = it.index },
2883 const else_expr = try expectNode(arena, it, tree, bodyParseFn, .{
2884 .InvalidToken = .{ .token = it.index },
28952885 });
28962886 const else_node = try arena.create(Node.Else);
2897 else_node.* = Node.Else{
2887 else_node.* = .{
28982888 .else_token = else_token,
28992889 .payload = payload,
29002890 .body = else_expr,
......@@ -2914,7 +2904,7 @@ fn parseDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.D
29142904 if (lines.len == 0) return null;
29152905
29162906 const node = try arena.create(Node.DocComment);
2917 node.* = Node.DocComment{
2907 node.* = .{
29182908 .lines = lines,
29192909 };
29202910 return node;
......@@ -2925,7 +2915,7 @@ fn parseAppendedDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree, a
29252915 const comment_token = eatToken(it, .DocComment) orelse return null;
29262916 if (tree.tokensOnSameLine(after_token, comment_token)) {
29272917 const node = try arena.create(Node.DocComment);
2928 node.* = Node.DocComment{
2918 node.* = .{
29292919 .lines = Node.DocComment.LineList.init(arena),
29302920 };
29312921 try node.lines.push(comment_token);
......@@ -2974,14 +2964,14 @@ fn parsePrefixOpExpr(
29742964 switch (rightmost_op.id) {
29752965 .PrefixOp => {
29762966 const prefix_op = rightmost_op.cast(Node.PrefixOp).?;
2977 prefix_op.rhs = try expectNode(arena, it, tree, childParseFn, AstError{
2978 .InvalidToken = AstError.InvalidToken{ .token = it.index },
2967 prefix_op.rhs = try expectNode(arena, it, tree, childParseFn, .{
2968 .InvalidToken = .{ .token = it.index },
29792969 });
29802970 },
29812971 .AnyFrameType => {
29822972 const prom = rightmost_op.cast(Node.AnyFrameType).?;
2983 prom.result.?.return_type = try expectNode(arena, it, tree, childParseFn, AstError{
2984 .InvalidToken = AstError.InvalidToken{ .token = it.index },
2973 prom.result.?.return_type = try expectNode(arena, it, tree, childParseFn, .{
2974 .InvalidToken = .{ .token = it.index },
29852975 });
29862976 },
29872977 else => unreachable,
......@@ -3010,8 +3000,8 @@ fn parseBinOpExpr(
30103000 var res = (try childParseFn(arena, it, tree)) orelse return null;
30113001
30123002 while (try opParseFn(arena, it, tree)) |node| {
3013 const right = try expectNode(arena, it, tree, childParseFn, AstError{
3014 .InvalidToken = AstError.InvalidToken{ .token = it.index },
3003 const right = try expectNode(arena, it, tree, childParseFn, .{
3004 .InvalidToken = .{ .token = it.index },
30153005 });
30163006 const left = res;
30173007 res = node;
......@@ -3031,7 +3021,7 @@ fn parseBinOpExpr(
30313021
30323022fn createInfixOp(arena: *Allocator, index: TokenIndex, op: Node.InfixOp.Op) !*Node {
30333023 const node = try arena.create(Node.InfixOp);
3034 node.* = Node.InfixOp{
3024 node.* = .{
30353025 .op_token = index,
30363026 .lhs = undefined, // set by caller
30373027 .op = op,
......@@ -3051,8 +3041,8 @@ fn eatAnnotatedToken(it: *TokenIterator, id: Token.Id) ?AnnotatedToken {
30513041fn expectToken(it: *TokenIterator, tree: *Tree, id: Token.Id) Error!TokenIndex {
30523042 const token = nextToken(it);
30533043 if (token.ptr.id != id) {
3054 try tree.errors.push(AstError{
3055 .ExpectedToken = AstError.ExpectedToken{ .token = token.index, .expected_id = id },
3044 try tree.errors.push(.{
3045 .ExpectedToken = .{ .token = token.index, .expected_id = id },
30563046 });
30573047 return error.ParseError;
30583048 }
lib/std/zig/parser_test.zig+84
......@@ -1,3 +1,16 @@
1test "zig fmt: errdefer with payload" {
2 try testCanonical(
3 \\pub fn main() anyerror!void {
4 \\ errdefer |a| x += 1;
5 \\ errdefer |a| {}
6 \\ errdefer |a| {
7 \\ x += 1;
8 \\ }
9 \\}
10 \\
11 );
12}
13
114test "zig fmt: noasync block" {
215 try testCanonical(
316 \\pub fn main() anyerror!void {
......@@ -1509,6 +1522,8 @@ test "zig fmt: error set declaration" {
15091522 \\const Error = error{OutOfMemory};
15101523 \\const Error = error{};
15111524 \\
1525 \\const Error = error{ OutOfMemory, OutOfTime };
1526 \\
15121527 );
15131528}
15141529
......@@ -2800,6 +2815,75 @@ test "zig fmt: extern without container keyword returns error" {
28002815 );
28012816}
28022817
2818test "zig fmt: integer literals with underscore separators" {
2819 try testTransform(
2820 \\const
2821 \\ x =
2822 \\ 1_234_567
2823 \\ +(0b0_1-0o7_0+0xff_FF ) + 0_0;
2824 ,
2825 \\const x = 1_234_567 + (0b0_1 - 0o7_0 + 0xff_FF) + 0_0;
2826 \\
2827 );
2828}
2829
2830test "zig fmt: hex literals with underscore separators" {
2831 try testTransform(
2832 \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {
2833 \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;
2834 \\ for (c [ 0_0 .. ]) |_, i| {
2835 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
2836 \\ }
2837 \\ return c;
2838 \\}
2839 \\
2840 \\
2841 ,
2842 \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
2843 \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;
2844 \\ for (c[0_0..]) |_, i| {
2845 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
2846 \\ }
2847 \\ return c;
2848 \\}
2849 \\
2850 );
2851}
2852
2853test "zig fmt: decimal float literals with underscore separators" {
2854 try testTransform(
2855 \\pub fn main() void {
2856 \\ const a:f64=(10.0e-0+(10.e+0))+10_00.00_00e-2+00_00.00_10e+4;
2857 \\ const b:f64=010.0--0_10.+0_1_0.0_0+1e2;
2858 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
2859 \\}
2860 ,
2861 \\pub fn main() void {
2862 \\ const a: f64 = (10.0e-0 + (10.e+0)) + 10_00.00_00e-2 + 00_00.00_10e+4;
2863 \\ const b: f64 = 010.0 - -0_10. + 0_1_0.0_0 + 1e2;
2864 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
2865 \\}
2866 \\
2867 );
2868}
2869
2870test "zig fmt: hexadeciaml float literals with underscore separators" {
2871 try testTransform(
2872 \\pub fn main() void {
2873 \\ const a: f64 = (0x10.0p-0+(0x10.p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;
2874 \\ const b: f64 = 0x0010.0--0x00_10.+0x10.00+0x1p4;
2875 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
2876 \\}
2877 ,
2878 \\pub fn main() void {
2879 \\ const a: f64 = (0x10.0p-0 + (0x10.p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;
2880 \\ const b: f64 = 0x0010.0 - -0x00_10. + 0x10.00 + 0x1p4;
2881 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
2882 \\}
2883 \\
2884 );
2885}
2886
28032887const std = @import("std");
28042888const mem = std.mem;
28052889const warn = std.debug.warn;
lib/std/zig/render.zig+44-18
......@@ -376,6 +376,9 @@ fn renderExpression(
376376 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
377377
378378 try renderToken(tree, stream, defer_node.defer_token, indent, start_col, Space.Space);
379 if (defer_node.payload) |payload| {
380 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
381 }
379382 return renderExpression(allocator, stream, tree, indent, start_col, defer_node.expr, space);
380383 },
381384 .Comptime => {
......@@ -583,7 +586,6 @@ fn renderExpression(
583586 },
584587
585588 .Try,
586 .Cancel,
587589 .Resume,
588590 => {
589591 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);
......@@ -1269,25 +1271,51 @@ fn renderExpression(
12691271 }
12701272
12711273 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error
1272 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // {
1273 const new_indent = indent + indent_delta;
12741274
1275 var it = err_set_decl.decls.iterator(0);
1276 while (it.next()) |node| {
1277 try stream.writeByteNTimes(' ', new_indent);
1275 const src_has_trailing_comma = blk: {
1276 const maybe_comma = tree.prevToken(err_set_decl.rbrace_token);
1277 break :blk tree.tokens.at(maybe_comma).id == .Comma;
1278 };
12781279
1279 if (it.peek()) |next_node| {
1280 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None);
1281 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, start_col, Space.Newline); // ,
1280 if (src_has_trailing_comma) {
1281 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // {
1282 const new_indent = indent + indent_delta;
12821283
1283 try renderExtraNewline(tree, stream, start_col, next_node.*);
1284 } else {
1285 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma);
1284 var it = err_set_decl.decls.iterator(0);
1285 while (it.next()) |node| {
1286 try stream.writeByteNTimes(' ', new_indent);
1287
1288 if (it.peek()) |next_node| {
1289 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None);
1290 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, start_col, Space.Newline); // ,
1291
1292 try renderExtraNewline(tree, stream, start_col, next_node.*);
1293 } else {
1294 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma);
1295 }
12861296 }
1287 }
12881297
1289 try stream.writeByteNTimes(' ', indent);
1290 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
1298 try stream.writeByteNTimes(' ', indent);
1299 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
1300 } else {
1301 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); // {
1302
1303 var it = err_set_decl.decls.iterator(0);
1304 while (it.next()) |node| {
1305 if (it.peek()) |next_node| {
1306 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None);
1307
1308 const comma_token = tree.nextToken(node.*.lastToken());
1309 assert(tree.tokens.at(comma_token).id == .Comma);
1310 try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // ,
1311 try renderExtraNewline(tree, stream, start_col, next_node.*);
1312 } else {
1313 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Space);
1314 }
1315 }
1316
1317 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
1318 }
12911319 },
12921320
12931321 .ErrorTag => {
......@@ -1590,8 +1618,7 @@ fn renderExpression(
15901618 }
15911619 } else {
15921620 var it = switch_case.items.iterator(0);
1593 while (true) {
1594 const node = it.next().?;
1621 while (it.next()) |node| {
15951622 if (it.peek()) |next_node| {
15961623 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None);
15971624
......@@ -1602,7 +1629,6 @@ fn renderExpression(
16021629 } else {
16031630 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Comma);
16041631 try stream.writeByteNTimes(' ', indent);
1605 break;
16061632 }
16071633 }
16081634 }
lib/std/zig/system.zig+4-1
......@@ -468,6 +468,9 @@ pub const NativeTargetInfo = struct {
468468 error.InvalidUtf8 => unreachable,
469469 error.BadPathName => unreachable,
470470 error.PipeBusy => unreachable,
471 error.PermissionDenied => unreachable,
472 error.FileBusy => unreachable,
473 error.Locked => unreachable,
471474
472475 error.IsDir,
473476 error.NotDir,
......@@ -754,7 +757,7 @@ pub const NativeTargetInfo = struct {
754757 const rpath_list = mem.toSliceConst(u8, @ptrCast([*:0]u8, strtab[rpoff..].ptr));
755758 var it = mem.tokenize(rpath_list, ":");
756759 while (it.next()) |rpath| {
757 var dir = fs.cwd().openDirList(rpath) catch |err| switch (err) {
760 var dir = fs.cwd().openDir(rpath, .{}) catch |err| switch (err) {
758761 error.NameTooLong => unreachable,
759762 error.InvalidUtf8 => unreachable,
760763 error.BadPathName => unreachable,
lib/std/zig/tokenizer.zig+438-57
......@@ -387,17 +387,23 @@ pub const Tokenizer = struct {
387387 DocComment,
388388 ContainerDocComment,
389389 Zero,
390 IntegerLiteral,
391 IntegerLiteralWithRadix,
392 IntegerLiteralWithRadixHex,
393 NumberDot,
390 IntegerLiteralDec,
391 IntegerLiteralDecNoUnderscore,
392 IntegerLiteralBin,
393 IntegerLiteralBinNoUnderscore,
394 IntegerLiteralOct,
395 IntegerLiteralOctNoUnderscore,
396 IntegerLiteralHex,
397 IntegerLiteralHexNoUnderscore,
398 NumberDotDec,
394399 NumberDotHex,
395 FloatFraction,
400 FloatFractionDec,
401 FloatFractionDecNoUnderscore,
396402 FloatFractionHex,
403 FloatFractionHexNoUnderscore,
397404 FloatExponentUnsigned,
398 FloatExponentUnsignedHex,
399405 FloatExponentNumber,
400 FloatExponentNumberHex,
406 FloatExponentNumberNoUnderscore,
401407 Ampersand,
402408 Caret,
403409 Percent,
......@@ -412,6 +418,10 @@ pub const Tokenizer = struct {
412418 SawAtSign,
413419 };
414420
421 fn isIdentifierChar(char: u8) bool {
422 return std.ascii.isAlNum(char) or char == '_';
423 }
424
415425 pub fn next(self: *Tokenizer) Token {
416426 if (self.pending_invalid_token) |token| {
417427 self.pending_invalid_token = null;
......@@ -550,7 +560,7 @@ pub const Tokenizer = struct {
550560 result.id = Token.Id.IntegerLiteral;
551561 },
552562 '1'...'9' => {
553 state = State.IntegerLiteral;
563 state = State.IntegerLiteralDec;
554564 result.id = Token.Id.IntegerLiteral;
555565 },
556566 else => {
......@@ -1048,55 +1058,145 @@ pub const Tokenizer = struct {
10481058 else => self.checkLiteralCharacter(),
10491059 },
10501060 State.Zero => switch (c) {
1051 'b', 'o' => {
1052 state = State.IntegerLiteralWithRadix;
1061 'b' => {
1062 state = State.IntegerLiteralBinNoUnderscore;
1063 },
1064 'o' => {
1065 state = State.IntegerLiteralOctNoUnderscore;
10531066 },
10541067 'x' => {
1055 state = State.IntegerLiteralWithRadixHex;
1068 state = State.IntegerLiteralHexNoUnderscore;
10561069 },
1057 else => {
1058 // reinterpret as a normal number
1070 '0'...'9', '_', '.', 'e', 'E' => {
1071 // reinterpret as a decimal number
10591072 self.index -= 1;
1060 state = State.IntegerLiteral;
1073 state = State.IntegerLiteralDec;
1074 },
1075 else => {
1076 if (isIdentifierChar(c)) {
1077 result.id = Token.Id.Invalid;
1078 }
1079 break;
1080 },
1081 },
1082 State.IntegerLiteralBinNoUnderscore => switch (c) {
1083 '0'...'1' => {
1084 state = State.IntegerLiteralBin;
1085 },
1086 else => {
1087 result.id = Token.Id.Invalid;
1088 break;
1089 },
1090 },
1091 State.IntegerLiteralBin => switch (c) {
1092 '_' => {
1093 state = State.IntegerLiteralBinNoUnderscore;
1094 },
1095 '0'...'1' => {},
1096 else => {
1097 if (isIdentifierChar(c)) {
1098 result.id = Token.Id.Invalid;
1099 }
1100 break;
1101 },
1102 },
1103 State.IntegerLiteralOctNoUnderscore => switch (c) {
1104 '0'...'7' => {
1105 state = State.IntegerLiteralOct;
1106 },
1107 else => {
1108 result.id = Token.Id.Invalid;
1109 break;
1110 },
1111 },
1112 State.IntegerLiteralOct => switch (c) {
1113 '_' => {
1114 state = State.IntegerLiteralOctNoUnderscore;
1115 },
1116 '0'...'7' => {},
1117 else => {
1118 if (isIdentifierChar(c)) {
1119 result.id = Token.Id.Invalid;
1120 }
1121 break;
1122 },
1123 },
1124 State.IntegerLiteralDecNoUnderscore => switch (c) {
1125 '0'...'9' => {
1126 state = State.IntegerLiteralDec;
1127 },
1128 else => {
1129 result.id = Token.Id.Invalid;
1130 break;
10611131 },
10621132 },
1063 State.IntegerLiteral => switch (c) {
1133 State.IntegerLiteralDec => switch (c) {
1134 '_' => {
1135 state = State.IntegerLiteralDecNoUnderscore;
1136 },
10641137 '.' => {
1065 state = State.NumberDot;
1138 state = State.NumberDotDec;
1139 result.id = Token.Id.FloatLiteral;
10661140 },
1067 'p', 'P', 'e', 'E' => {
1141 'e', 'E' => {
10681142 state = State.FloatExponentUnsigned;
1143 result.id = Token.Id.FloatLiteral;
10691144 },
10701145 '0'...'9' => {},
1071 else => break,
1146 else => {
1147 if (isIdentifierChar(c)) {
1148 result.id = Token.Id.Invalid;
1149 }
1150 break;
1151 },
10721152 },
1073 State.IntegerLiteralWithRadix => switch (c) {
1074 '.' => {
1075 state = State.NumberDot;
1153 State.IntegerLiteralHexNoUnderscore => switch (c) {
1154 '0'...'9', 'a'...'f', 'A'...'F' => {
1155 state = State.IntegerLiteralHex;
1156 },
1157 else => {
1158 result.id = Token.Id.Invalid;
1159 break;
10761160 },
1077 '0'...'9' => {},
1078 else => break,
10791161 },
1080 State.IntegerLiteralWithRadixHex => switch (c) {
1162 State.IntegerLiteralHex => switch (c) {
1163 '_' => {
1164 state = State.IntegerLiteralHexNoUnderscore;
1165 },
10811166 '.' => {
10821167 state = State.NumberDotHex;
1168 result.id = Token.Id.FloatLiteral;
10831169 },
10841170 'p', 'P' => {
1085 state = State.FloatExponentUnsignedHex;
1171 state = State.FloatExponentUnsigned;
1172 result.id = Token.Id.FloatLiteral;
10861173 },
10871174 '0'...'9', 'a'...'f', 'A'...'F' => {},
1088 else => break,
1175 else => {
1176 if (isIdentifierChar(c)) {
1177 result.id = Token.Id.Invalid;
1178 }
1179 break;
1180 },
10891181 },
1090 State.NumberDot => switch (c) {
1182 State.NumberDotDec => switch (c) {
10911183 '.' => {
10921184 self.index -= 1;
10931185 state = State.Start;
10941186 break;
10951187 },
1096 else => {
1097 self.index -= 1;
1188 'e', 'E' => {
1189 state = State.FloatExponentUnsigned;
1190 },
1191 '0'...'9' => {
10981192 result.id = Token.Id.FloatLiteral;
1099 state = State.FloatFraction;
1193 state = State.FloatFractionDec;
1194 },
1195 else => {
1196 if (isIdentifierChar(c)) {
1197 result.id = Token.Id.Invalid;
1198 }
1199 break;
11001200 },
11011201 },
11021202 State.NumberDotHex => switch (c) {
......@@ -1105,65 +1205,112 @@ pub const Tokenizer = struct {
11051205 state = State.Start;
11061206 break;
11071207 },
1108 else => {
1109 self.index -= 1;
1208 'p', 'P' => {
1209 state = State.FloatExponentUnsigned;
1210 },
1211 '0'...'9', 'a'...'f', 'A'...'F' => {
11101212 result.id = Token.Id.FloatLiteral;
11111213 state = State.FloatFractionHex;
11121214 },
1215 else => {
1216 if (isIdentifierChar(c)) {
1217 result.id = Token.Id.Invalid;
1218 }
1219 break;
1220 },
11131221 },
1114 State.FloatFraction => switch (c) {
1222 State.FloatFractionDecNoUnderscore => switch (c) {
1223 '0'...'9' => {
1224 state = State.FloatFractionDec;
1225 },
1226 else => {
1227 result.id = Token.Id.Invalid;
1228 break;
1229 },
1230 },
1231 State.FloatFractionDec => switch (c) {
1232 '_' => {
1233 state = State.FloatFractionDecNoUnderscore;
1234 },
11151235 'e', 'E' => {
11161236 state = State.FloatExponentUnsigned;
11171237 },
11181238 '0'...'9' => {},
1119 else => break,
1239 else => {
1240 if (isIdentifierChar(c)) {
1241 result.id = Token.Id.Invalid;
1242 }
1243 break;
1244 },
1245 },
1246 State.FloatFractionHexNoUnderscore => switch (c) {
1247 '0'...'9', 'a'...'f', 'A'...'F' => {
1248 state = State.FloatFractionHex;
1249 },
1250 else => {
1251 result.id = Token.Id.Invalid;
1252 break;
1253 },
11201254 },
11211255 State.FloatFractionHex => switch (c) {
1256 '_' => {
1257 state = State.FloatFractionHexNoUnderscore;
1258 },
11221259 'p', 'P' => {
1123 state = State.FloatExponentUnsignedHex;
1260 state = State.FloatExponentUnsigned;
11241261 },
11251262 '0'...'9', 'a'...'f', 'A'...'F' => {},
1126 else => break,
1263 else => {
1264 if (isIdentifierChar(c)) {
1265 result.id = Token.Id.Invalid;
1266 }
1267 break;
1268 },
11271269 },
11281270 State.FloatExponentUnsigned => switch (c) {
11291271 '+', '-' => {
1130 state = State.FloatExponentNumber;
1272 state = State.FloatExponentNumberNoUnderscore;
11311273 },
11321274 else => {
11331275 // reinterpret as a normal exponent number
11341276 self.index -= 1;
1135 state = State.FloatExponentNumber;
1277 state = State.FloatExponentNumberNoUnderscore;
11361278 },
11371279 },
1138 State.FloatExponentUnsignedHex => switch (c) {
1139 '+', '-' => {
1140 state = State.FloatExponentNumberHex;
1280 State.FloatExponentNumberNoUnderscore => switch (c) {
1281 '0'...'9' => {
1282 state = State.FloatExponentNumber;
11411283 },
11421284 else => {
1143 // reinterpret as a normal exponent number
1144 self.index -= 1;
1145 state = State.FloatExponentNumberHex;
1285 result.id = Token.Id.Invalid;
1286 break;
11461287 },
11471288 },
11481289 State.FloatExponentNumber => switch (c) {
1290 '_' => {
1291 state = State.FloatExponentNumberNoUnderscore;
1292 },
11491293 '0'...'9' => {},
1150 else => break,
1151 },
1152 State.FloatExponentNumberHex => switch (c) {
1153 '0'...'9', 'a'...'f', 'A'...'F' => {},
1154 else => break,
1294 else => {
1295 if (isIdentifierChar(c)) {
1296 result.id = Token.Id.Invalid;
1297 }
1298 break;
1299 },
11551300 },
11561301 }
11571302 } else if (self.index == self.buffer.len) {
11581303 switch (state) {
11591304 State.Start,
1160 State.IntegerLiteral,
1161 State.IntegerLiteralWithRadix,
1162 State.IntegerLiteralWithRadixHex,
1163 State.FloatFraction,
1305 State.IntegerLiteralDec,
1306 State.IntegerLiteralBin,
1307 State.IntegerLiteralOct,
1308 State.IntegerLiteralHex,
1309 State.NumberDotDec,
1310 State.NumberDotHex,
1311 State.FloatFractionDec,
11641312 State.FloatFractionHex,
11651313 State.FloatExponentNumber,
1166 State.FloatExponentNumberHex,
11671314 State.StringLiteral, // find this error later
11681315 State.MultilineStringLiteralLine,
11691316 State.Builtin,
......@@ -1184,10 +1331,14 @@ pub const Tokenizer = struct {
11841331 result.id = Token.Id.ContainerDocComment;
11851332 },
11861333
1187 State.NumberDot,
1188 State.NumberDotHex,
1334 State.IntegerLiteralDecNoUnderscore,
1335 State.IntegerLiteralBinNoUnderscore,
1336 State.IntegerLiteralOctNoUnderscore,
1337 State.IntegerLiteralHexNoUnderscore,
1338 State.FloatFractionDecNoUnderscore,
1339 State.FloatFractionHexNoUnderscore,
1340 State.FloatExponentNumberNoUnderscore,
11891341 State.FloatExponentUnsigned,
1190 State.FloatExponentUnsignedHex,
11911342 State.SawAtSign,
11921343 State.Backslash,
11931344 State.CharLiteral,
......@@ -1585,6 +1736,236 @@ test "correctly parse pointer assignment" {
15851736 });
15861737}
15871738
1739test "tokenizer - number literals decimal" {
1740 testTokenize("0", &[_]Token.Id{.IntegerLiteral});
1741 testTokenize("1", &[_]Token.Id{.IntegerLiteral});
1742 testTokenize("2", &[_]Token.Id{.IntegerLiteral});
1743 testTokenize("3", &[_]Token.Id{.IntegerLiteral});
1744 testTokenize("4", &[_]Token.Id{.IntegerLiteral});
1745 testTokenize("5", &[_]Token.Id{.IntegerLiteral});
1746 testTokenize("6", &[_]Token.Id{.IntegerLiteral});
1747 testTokenize("7", &[_]Token.Id{.IntegerLiteral});
1748 testTokenize("8", &[_]Token.Id{.IntegerLiteral});
1749 testTokenize("9", &[_]Token.Id{.IntegerLiteral});
1750 testTokenize("0a", &[_]Token.Id{ .Invalid, .Identifier });
1751 testTokenize("9b", &[_]Token.Id{ .Invalid, .Identifier });
1752 testTokenize("1z", &[_]Token.Id{ .Invalid, .Identifier });
1753 testTokenize("1z_1", &[_]Token.Id{ .Invalid, .Identifier });
1754 testTokenize("9z3", &[_]Token.Id{ .Invalid, .Identifier });
1755
1756 testTokenize("0_0", &[_]Token.Id{.IntegerLiteral});
1757 testTokenize("0001", &[_]Token.Id{.IntegerLiteral});
1758 testTokenize("01234567890", &[_]Token.Id{.IntegerLiteral});
1759 testTokenize("012_345_6789_0", &[_]Token.Id{.IntegerLiteral});
1760 testTokenize("0_1_2_3_4_5_6_7_8_9_0", &[_]Token.Id{.IntegerLiteral});
1761
1762 testTokenize("00_", &[_]Token.Id{.Invalid});
1763 testTokenize("0_0_", &[_]Token.Id{.Invalid});
1764 testTokenize("0__0", &[_]Token.Id{ .Invalid, .Identifier });
1765 testTokenize("0_0f", &[_]Token.Id{ .Invalid, .Identifier });
1766 testTokenize("0_0_f", &[_]Token.Id{ .Invalid, .Identifier });
1767 testTokenize("0_0_f_00", &[_]Token.Id{ .Invalid, .Identifier });
1768 testTokenize("1_,", &[_]Token.Id{ .Invalid, .Comma });
1769
1770 testTokenize("1.", &[_]Token.Id{.FloatLiteral});
1771 testTokenize("0.0", &[_]Token.Id{.FloatLiteral});
1772 testTokenize("1.0", &[_]Token.Id{.FloatLiteral});
1773 testTokenize("10.0", &[_]Token.Id{.FloatLiteral});
1774 testTokenize("0e0", &[_]Token.Id{.FloatLiteral});
1775 testTokenize("1e0", &[_]Token.Id{.FloatLiteral});
1776 testTokenize("1e100", &[_]Token.Id{.FloatLiteral});
1777 testTokenize("1.e100", &[_]Token.Id{.FloatLiteral});
1778 testTokenize("1.0e100", &[_]Token.Id{.FloatLiteral});
1779 testTokenize("1.0e+100", &[_]Token.Id{.FloatLiteral});
1780 testTokenize("1.0e-100", &[_]Token.Id{.FloatLiteral});
1781 testTokenize("1_0_0_0.0_0_0_0_0_1e1_0_0_0", &[_]Token.Id{.FloatLiteral});
1782 testTokenize("1.+", &[_]Token.Id{ .FloatLiteral, .Plus });
1783
1784 testTokenize("1e", &[_]Token.Id{.Invalid});
1785 testTokenize("1.0e1f0", &[_]Token.Id{ .Invalid, .Identifier });
1786 testTokenize("1.0p100", &[_]Token.Id{ .Invalid, .Identifier });
1787 testTokenize("1.0p-100", &[_]Token.Id{ .Invalid, .Identifier, .Minus, .IntegerLiteral });
1788 testTokenize("1.0p1f0", &[_]Token.Id{ .Invalid, .Identifier });
1789 testTokenize("1.0_,", &[_]Token.Id{ .Invalid, .Comma });
1790 testTokenize("1_.0", &[_]Token.Id{ .Invalid, .Period, .IntegerLiteral });
1791 testTokenize("1._", &[_]Token.Id{ .Invalid, .Identifier });
1792 testTokenize("1.a", &[_]Token.Id{ .Invalid, .Identifier });
1793 testTokenize("1.z", &[_]Token.Id{ .Invalid, .Identifier });
1794 testTokenize("1._0", &[_]Token.Id{ .Invalid, .Identifier });
1795 testTokenize("1._+", &[_]Token.Id{ .Invalid, .Identifier, .Plus });
1796 testTokenize("1._e", &[_]Token.Id{ .Invalid, .Identifier });
1797 testTokenize("1.0e", &[_]Token.Id{.Invalid});
1798 testTokenize("1.0e,", &[_]Token.Id{ .Invalid, .Comma });
1799 testTokenize("1.0e_", &[_]Token.Id{ .Invalid, .Identifier });
1800 testTokenize("1.0e+_", &[_]Token.Id{ .Invalid, .Identifier });
1801 testTokenize("1.0e-_", &[_]Token.Id{ .Invalid, .Identifier });
1802 testTokenize("1.0e0_+", &[_]Token.Id{ .Invalid, .Plus });
1803}
1804
1805test "tokenizer - number literals binary" {
1806 testTokenize("0b0", &[_]Token.Id{.IntegerLiteral});
1807 testTokenize("0b1", &[_]Token.Id{.IntegerLiteral});
1808 testTokenize("0b2", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1809 testTokenize("0b3", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1810 testTokenize("0b4", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1811 testTokenize("0b5", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1812 testTokenize("0b6", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1813 testTokenize("0b7", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1814 testTokenize("0b8", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1815 testTokenize("0b9", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1816 testTokenize("0ba", &[_]Token.Id{ .Invalid, .Identifier });
1817 testTokenize("0bb", &[_]Token.Id{ .Invalid, .Identifier });
1818 testTokenize("0bc", &[_]Token.Id{ .Invalid, .Identifier });
1819 testTokenize("0bd", &[_]Token.Id{ .Invalid, .Identifier });
1820 testTokenize("0be", &[_]Token.Id{ .Invalid, .Identifier });
1821 testTokenize("0bf", &[_]Token.Id{ .Invalid, .Identifier });
1822 testTokenize("0bz", &[_]Token.Id{ .Invalid, .Identifier });
1823
1824 testTokenize("0b0000_0000", &[_]Token.Id{.IntegerLiteral});
1825 testTokenize("0b1111_1111", &[_]Token.Id{.IntegerLiteral});
1826 testTokenize("0b10_10_10_10", &[_]Token.Id{.IntegerLiteral});
1827 testTokenize("0b0_1_0_1_0_1_0_1", &[_]Token.Id{.IntegerLiteral});
1828 testTokenize("0b1.", &[_]Token.Id{ .IntegerLiteral, .Period });
1829 testTokenize("0b1.0", &[_]Token.Id{ .IntegerLiteral, .Period, .IntegerLiteral });
1830
1831 testTokenize("0B0", &[_]Token.Id{ .Invalid, .Identifier });
1832 testTokenize("0b_", &[_]Token.Id{ .Invalid, .Identifier });
1833 testTokenize("0b_0", &[_]Token.Id{ .Invalid, .Identifier });
1834 testTokenize("0b1_", &[_]Token.Id{.Invalid});
1835 testTokenize("0b0__1", &[_]Token.Id{ .Invalid, .Identifier });
1836 testTokenize("0b0_1_", &[_]Token.Id{.Invalid});
1837 testTokenize("0b1e", &[_]Token.Id{ .Invalid, .Identifier });
1838 testTokenize("0b1p", &[_]Token.Id{ .Invalid, .Identifier });
1839 testTokenize("0b1e0", &[_]Token.Id{ .Invalid, .Identifier });
1840 testTokenize("0b1p0", &[_]Token.Id{ .Invalid, .Identifier });
1841 testTokenize("0b1_,", &[_]Token.Id{ .Invalid, .Comma });
1842}
1843
1844test "tokenizer - number literals octal" {
1845 testTokenize("0o0", &[_]Token.Id{.IntegerLiteral});
1846 testTokenize("0o1", &[_]Token.Id{.IntegerLiteral});
1847 testTokenize("0o2", &[_]Token.Id{.IntegerLiteral});
1848 testTokenize("0o3", &[_]Token.Id{.IntegerLiteral});
1849 testTokenize("0o4", &[_]Token.Id{.IntegerLiteral});
1850 testTokenize("0o5", &[_]Token.Id{.IntegerLiteral});
1851 testTokenize("0o6", &[_]Token.Id{.IntegerLiteral});
1852 testTokenize("0o7", &[_]Token.Id{.IntegerLiteral});
1853 testTokenize("0o8", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1854 testTokenize("0o9", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1855 testTokenize("0oa", &[_]Token.Id{ .Invalid, .Identifier });
1856 testTokenize("0ob", &[_]Token.Id{ .Invalid, .Identifier });
1857 testTokenize("0oc", &[_]Token.Id{ .Invalid, .Identifier });
1858 testTokenize("0od", &[_]Token.Id{ .Invalid, .Identifier });
1859 testTokenize("0oe", &[_]Token.Id{ .Invalid, .Identifier });
1860 testTokenize("0of", &[_]Token.Id{ .Invalid, .Identifier });
1861 testTokenize("0oz", &[_]Token.Id{ .Invalid, .Identifier });
1862
1863 testTokenize("0o01234567", &[_]Token.Id{.IntegerLiteral});
1864 testTokenize("0o0123_4567", &[_]Token.Id{.IntegerLiteral});
1865 testTokenize("0o01_23_45_67", &[_]Token.Id{.IntegerLiteral});
1866 testTokenize("0o0_1_2_3_4_5_6_7", &[_]Token.Id{.IntegerLiteral});
1867 testTokenize("0o7.", &[_]Token.Id{ .IntegerLiteral, .Period });
1868 testTokenize("0o7.0", &[_]Token.Id{ .IntegerLiteral, .Period, .IntegerLiteral });
1869
1870 testTokenize("0O0", &[_]Token.Id{ .Invalid, .Identifier });
1871 testTokenize("0o_", &[_]Token.Id{ .Invalid, .Identifier });
1872 testTokenize("0o_0", &[_]Token.Id{ .Invalid, .Identifier });
1873 testTokenize("0o1_", &[_]Token.Id{.Invalid});
1874 testTokenize("0o0__1", &[_]Token.Id{ .Invalid, .Identifier });
1875 testTokenize("0o0_1_", &[_]Token.Id{.Invalid});
1876 testTokenize("0o1e", &[_]Token.Id{ .Invalid, .Identifier });
1877 testTokenize("0o1p", &[_]Token.Id{ .Invalid, .Identifier });
1878 testTokenize("0o1e0", &[_]Token.Id{ .Invalid, .Identifier });
1879 testTokenize("0o1p0", &[_]Token.Id{ .Invalid, .Identifier });
1880 testTokenize("0o_,", &[_]Token.Id{ .Invalid, .Identifier, .Comma });
1881}
1882
1883test "tokenizer - number literals hexadeciaml" {
1884 testTokenize("0x0", &[_]Token.Id{.IntegerLiteral});
1885 testTokenize("0x1", &[_]Token.Id{.IntegerLiteral});
1886 testTokenize("0x2", &[_]Token.Id{.IntegerLiteral});
1887 testTokenize("0x3", &[_]Token.Id{.IntegerLiteral});
1888 testTokenize("0x4", &[_]Token.Id{.IntegerLiteral});
1889 testTokenize("0x5", &[_]Token.Id{.IntegerLiteral});
1890 testTokenize("0x6", &[_]Token.Id{.IntegerLiteral});
1891 testTokenize("0x7", &[_]Token.Id{.IntegerLiteral});
1892 testTokenize("0x8", &[_]Token.Id{.IntegerLiteral});
1893 testTokenize("0x9", &[_]Token.Id{.IntegerLiteral});
1894 testTokenize("0xa", &[_]Token.Id{.IntegerLiteral});
1895 testTokenize("0xb", &[_]Token.Id{.IntegerLiteral});
1896 testTokenize("0xc", &[_]Token.Id{.IntegerLiteral});
1897 testTokenize("0xd", &[_]Token.Id{.IntegerLiteral});
1898 testTokenize("0xe", &[_]Token.Id{.IntegerLiteral});
1899 testTokenize("0xf", &[_]Token.Id{.IntegerLiteral});
1900 testTokenize("0xA", &[_]Token.Id{.IntegerLiteral});
1901 testTokenize("0xB", &[_]Token.Id{.IntegerLiteral});
1902 testTokenize("0xC", &[_]Token.Id{.IntegerLiteral});
1903 testTokenize("0xD", &[_]Token.Id{.IntegerLiteral});
1904 testTokenize("0xE", &[_]Token.Id{.IntegerLiteral});
1905 testTokenize("0xF", &[_]Token.Id{.IntegerLiteral});
1906 testTokenize("0x0z", &[_]Token.Id{ .Invalid, .Identifier });
1907 testTokenize("0xz", &[_]Token.Id{ .Invalid, .Identifier });
1908
1909 testTokenize("0x0123456789ABCDEF", &[_]Token.Id{.IntegerLiteral});
1910 testTokenize("0x0123_4567_89AB_CDEF", &[_]Token.Id{.IntegerLiteral});
1911 testTokenize("0x01_23_45_67_89AB_CDE_F", &[_]Token.Id{.IntegerLiteral});
1912 testTokenize("0x0_1_2_3_4_5_6_7_8_9_A_B_C_D_E_F", &[_]Token.Id{.IntegerLiteral});
1913
1914 testTokenize("0X0", &[_]Token.Id{ .Invalid, .Identifier });
1915 testTokenize("0x_", &[_]Token.Id{ .Invalid, .Identifier });
1916 testTokenize("0x_1", &[_]Token.Id{ .Invalid, .Identifier });
1917 testTokenize("0x1_", &[_]Token.Id{.Invalid});
1918 testTokenize("0x0__1", &[_]Token.Id{ .Invalid, .Identifier });
1919 testTokenize("0x0_1_", &[_]Token.Id{.Invalid});
1920 testTokenize("0x_,", &[_]Token.Id{ .Invalid, .Identifier, .Comma });
1921
1922 testTokenize("0x1.", &[_]Token.Id{.FloatLiteral});
1923 testTokenize("0x1.0", &[_]Token.Id{.FloatLiteral});
1924 testTokenize("0xF.", &[_]Token.Id{.FloatLiteral});
1925 testTokenize("0xF.0", &[_]Token.Id{.FloatLiteral});
1926 testTokenize("0xF.F", &[_]Token.Id{.FloatLiteral});
1927 testTokenize("0xF.Fp0", &[_]Token.Id{.FloatLiteral});
1928 testTokenize("0xF.FP0", &[_]Token.Id{.FloatLiteral});
1929 testTokenize("0x1p0", &[_]Token.Id{.FloatLiteral});
1930 testTokenize("0xfp0", &[_]Token.Id{.FloatLiteral});
1931 testTokenize("0x1.+0xF.", &[_]Token.Id{ .FloatLiteral, .Plus, .FloatLiteral });
1932
1933 testTokenize("0x0123456.789ABCDEF", &[_]Token.Id{.FloatLiteral});
1934 testTokenize("0x0_123_456.789_ABC_DEF", &[_]Token.Id{.FloatLiteral});
1935 testTokenize("0x0_1_2_3_4_5_6.7_8_9_A_B_C_D_E_F", &[_]Token.Id{.FloatLiteral});
1936 testTokenize("0x0p0", &[_]Token.Id{.FloatLiteral});
1937 testTokenize("0x0.0p0", &[_]Token.Id{.FloatLiteral});
1938 testTokenize("0xff.ffp10", &[_]Token.Id{.FloatLiteral});
1939 testTokenize("0xff.ffP10", &[_]Token.Id{.FloatLiteral});
1940 testTokenize("0xff.p10", &[_]Token.Id{.FloatLiteral});
1941 testTokenize("0xffp10", &[_]Token.Id{.FloatLiteral});
1942 testTokenize("0xff_ff.ff_ffp1_0_0_0", &[_]Token.Id{.FloatLiteral});
1943 testTokenize("0xf_f_f_f.f_f_f_fp+1_000", &[_]Token.Id{.FloatLiteral});
1944 testTokenize("0xf_f_f_f.f_f_f_fp-1_00_0", &[_]Token.Id{.FloatLiteral});
1945
1946 testTokenize("0x1e", &[_]Token.Id{.IntegerLiteral});
1947 testTokenize("0x1e0", &[_]Token.Id{.IntegerLiteral});
1948 testTokenize("0x1p", &[_]Token.Id{.Invalid});
1949 testTokenize("0xfp0z1", &[_]Token.Id{ .Invalid, .Identifier });
1950 testTokenize("0xff.ffpff", &[_]Token.Id{ .Invalid, .Identifier });
1951 testTokenize("0x0.p", &[_]Token.Id{.Invalid});
1952 testTokenize("0x0.z", &[_]Token.Id{ .Invalid, .Identifier });
1953 testTokenize("0x0._", &[_]Token.Id{ .Invalid, .Identifier });
1954 testTokenize("0x0_.0", &[_]Token.Id{ .Invalid, .Period, .IntegerLiteral });
1955 testTokenize("0x0_.0.0", &[_]Token.Id{ .Invalid, .Period, .FloatLiteral });
1956 testTokenize("0x0._0", &[_]Token.Id{ .Invalid, .Identifier });
1957 testTokenize("0x0.0_", &[_]Token.Id{.Invalid});
1958 testTokenize("0x0_p0", &[_]Token.Id{ .Invalid, .Identifier });
1959 testTokenize("0x0_.p0", &[_]Token.Id{ .Invalid, .Period, .Identifier });
1960 testTokenize("0x0._p0", &[_]Token.Id{ .Invalid, .Identifier });
1961 testTokenize("0x0.0_p0", &[_]Token.Id{ .Invalid, .Identifier });
1962 testTokenize("0x0._0p0", &[_]Token.Id{ .Invalid, .Identifier });
1963 testTokenize("0x0.0p_0", &[_]Token.Id{ .Invalid, .Identifier });
1964 testTokenize("0x0.0p+_0", &[_]Token.Id{ .Invalid, .Identifier });
1965 testTokenize("0x0.0p-_0", &[_]Token.Id{ .Invalid, .Identifier });
1966 testTokenize("0x0.0p0_", &[_]Token.Id{ .Invalid, .Eof });
1967}
1968
15881969fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {
15891970 var tokenizer = Tokenizer.init(source);
15901971 for (expected_tokens) |expected_token_id| {
src-self-hosted/c_int.zig+4-4
......@@ -69,9 +69,9 @@ pub const CInt = struct {
6969 };
7070
7171 pub fn sizeInBits(cint: CInt, self: Target) u32 {
72 const arch = self.getArch();
72 const arch = self.cpu.arch;
7373 switch (self.os.tag) {
74 .freestanding, .other => switch (self.getArch()) {
74 .freestanding, .other => switch (self.cpu.arch) {
7575 .msp430 => switch (cint.id) {
7676 .Short,
7777 .UShort,
......@@ -94,7 +94,7 @@ pub const CInt = struct {
9494 => return 32,
9595 .Long,
9696 .ULong,
97 => return self.getArchPtrBitWidth(),
97 => return self.cpu.arch.ptrBitWidth(),
9898 .LongLong,
9999 .ULongLong,
100100 => return 64,
......@@ -114,7 +114,7 @@ pub const CInt = struct {
114114 => return 32,
115115 .Long,
116116 .ULong,
117 => return self.getArchPtrBitWidth(),
117 => return self.cpu.arch.ptrBitWidth(),
118118 .LongLong,
119119 .ULongLong,
120120 => return 64,
src-self-hosted/clang_options.zig created+126
......@@ -0,0 +1,126 @@
1const std = @import("std");
2const mem = std.mem;
3
4pub const list = @import("clang_options_data.zig").data;
5
6pub const CliArg = struct {
7 name: []const u8,
8 syntax: Syntax,
9
10 /// TODO we're going to want to change this when we start shipping self-hosted because this causes
11 /// all the functions in stage2.zig to get exported.
12 zig_equivalent: @import("stage2.zig").ClangArgIterator.ZigEquivalent,
13
14 /// Prefixed by "-"
15 pd1: bool = false,
16
17 /// Prefixed by "--"
18 pd2: bool = false,
19
20 /// Prefixed by "/"
21 psl: bool = false,
22
23 pub const Syntax = union(enum) {
24 /// A flag with no values.
25 flag,
26
27 /// An option which prefixes its (single) value.
28 joined,
29
30 /// An option which is followed by its value.
31 separate,
32
33 /// An option which is either joined to its (non-empty) value, or followed by its value.
34 joined_or_separate,
35
36 /// An option which is both joined to its (first) value, and followed by its (second) value.
37 joined_and_separate,
38
39 /// An option followed by its values, which are separated by commas.
40 comma_joined,
41
42 /// An option which consumes an optional joined argument and any other remaining arguments.
43 remaining_args_joined,
44
45 /// An option which is which takes multiple (separate) arguments.
46 multi_arg: u8,
47 };
48
49 pub fn matchEql(self: CliArg, arg: []const u8) u2 {
50 if (self.pd1 and arg.len >= self.name.len + 1 and
51 mem.startsWith(u8, arg, "-") and mem.eql(u8, arg[1..], self.name))
52 {
53 return 1;
54 }
55 if (self.pd2 and arg.len >= self.name.len + 2 and
56 mem.startsWith(u8, arg, "--") and mem.eql(u8, arg[2..], self.name))
57 {
58 return 2;
59 }
60 if (self.psl and arg.len >= self.name.len + 1 and
61 mem.startsWith(u8, arg, "/") and mem.eql(u8, arg[1..], self.name))
62 {
63 return 1;
64 }
65 return 0;
66 }
67
68 pub fn matchStartsWith(self: CliArg, arg: []const u8) usize {
69 if (self.pd1 and arg.len >= self.name.len + 1 and
70 mem.startsWith(u8, arg, "-") and mem.startsWith(u8, arg[1..], self.name))
71 {
72 return self.name.len + 1;
73 }
74 if (self.pd2 and arg.len >= self.name.len + 2 and
75 mem.startsWith(u8, arg, "--") and mem.startsWith(u8, arg[2..], self.name))
76 {
77 return self.name.len + 2;
78 }
79 if (self.psl and arg.len >= self.name.len + 1 and
80 mem.startsWith(u8, arg, "/") and mem.startsWith(u8, arg[1..], self.name))
81 {
82 return self.name.len + 1;
83 }
84 return 0;
85 }
86};
87
88/// Shortcut function for initializing a `CliArg`
89pub fn flagpd1(name: []const u8) CliArg {
90 return .{
91 .name = name,
92 .syntax = .flag,
93 .zig_equivalent = .other,
94 .pd1 = true,
95 };
96}
97
98/// Shortcut function for initializing a `CliArg`
99pub fn joinpd1(name: []const u8) CliArg {
100 return .{
101 .name = name,
102 .syntax = .joined,
103 .zig_equivalent = .other,
104 .pd1 = true,
105 };
106}
107
108/// Shortcut function for initializing a `CliArg`
109pub fn jspd1(name: []const u8) CliArg {
110 return .{
111 .name = name,
112 .syntax = .joined_or_separate,
113 .zig_equivalent = .other,
114 .pd1 = true,
115 };
116}
117
118/// Shortcut function for initializing a `CliArg`
119pub fn sepd1(name: []const u8) CliArg {
120 return .{
121 .name = name,
122 .syntax = .separate,
123 .zig_equivalent = .other,
124 .pd1 = true,
125 };
126}
src-self-hosted/clang_options_data.zig created+5702
......@@ -0,0 +1,5702 @@
1// This file is generated by tools/update_clang_options.zig.
2// zig fmt: off
3usingnamespace @import("clang_options.zig");
4pub const data = blk: { @setEvalBranchQuota(6000); break :blk &[_]CliArg{
5flagpd1("C"),
6flagpd1("CC"),
7.{
8 .name = "E",
9 .syntax = .flag,
10 .zig_equivalent = .preprocess,
11 .pd1 = true,
12 .pd2 = false,
13 .psl = false,
14},
15flagpd1("EB"),
16flagpd1("EL"),
17flagpd1("Eonly"),
18flagpd1("H"),
19.{
20 .name = "<input>",
21 .syntax = .flag,
22 .zig_equivalent = .other,
23 .pd1 = false,
24 .pd2 = false,
25 .psl = false,
26},
27flagpd1("I-"),
28flagpd1("M"),
29flagpd1("MD"),
30flagpd1("MG"),
31flagpd1("MM"),
32flagpd1("MMD"),
33flagpd1("MP"),
34flagpd1("MV"),
35flagpd1("Mach"),
36flagpd1("O0"),
37flagpd1("O4"),
38.{
39 .name = "O",
40 .syntax = .flag,
41 .zig_equivalent = .optimize,
42 .pd1 = true,
43 .pd2 = false,
44 .psl = false,
45},
46flagpd1("ObjC"),
47flagpd1("ObjC++"),
48flagpd1("P"),
49flagpd1("Q"),
50flagpd1("Qn"),
51flagpd1("Qunused-arguments"),
52flagpd1("Qy"),
53.{
54 .name = "S",
55 .syntax = .flag,
56 .zig_equivalent = .driver_punt,
57 .pd1 = true,
58 .pd2 = false,
59 .psl = false,
60},
61.{
62 .name = "<unknown>",
63 .syntax = .flag,
64 .zig_equivalent = .other,
65 .pd1 = false,
66 .pd2 = false,
67 .psl = false,
68},
69flagpd1("WCL4"),
70flagpd1("Wall"),
71flagpd1("Wdeprecated"),
72flagpd1("Wlarge-by-value-copy"),
73flagpd1("Wno-deprecated"),
74flagpd1("Wno-rewrite-macros"),
75flagpd1("Wno-write-strings"),
76flagpd1("Wwrite-strings"),
77flagpd1("X"),
78sepd1("Xanalyzer"),
79sepd1("Xassembler"),
80sepd1("Xclang"),
81sepd1("Xcuda-fatbinary"),
82sepd1("Xcuda-ptxas"),
83sepd1("Xlinker"),
84sepd1("Xopenmp-target"),
85sepd1("Xpreprocessor"),
86flagpd1("Z"),
87flagpd1("Z-Xlinker-no-demangle"),
88flagpd1("Z-reserved-lib-cckext"),
89flagpd1("Z-reserved-lib-stdc++"),
90sepd1("Zlinker-input"),
91.{
92 .name = "CLASSPATH",
93 .syntax = .separate,
94 .zig_equivalent = .other,
95 .pd1 = false,
96 .pd2 = true,
97 .psl = false,
98},
99flagpd1("###"),
100.{
101 .name = "Brepro",
102 .syntax = .flag,
103 .zig_equivalent = .other,
104 .pd1 = true,
105 .pd2 = false,
106 .psl = true,
107},
108.{
109 .name = "Brepro-",
110 .syntax = .flag,
111 .zig_equivalent = .other,
112 .pd1 = true,
113 .pd2 = false,
114 .psl = true,
115},
116.{
117 .name = "Bt",
118 .syntax = .flag,
119 .zig_equivalent = .other,
120 .pd1 = true,
121 .pd2 = false,
122 .psl = true,
123},
124.{
125 .name = "Bt+",
126 .syntax = .flag,
127 .zig_equivalent = .other,
128 .pd1 = true,
129 .pd2 = false,
130 .psl = true,
131},
132.{
133 .name = "C",
134 .syntax = .flag,
135 .zig_equivalent = .other,
136 .pd1 = true,
137 .pd2 = false,
138 .psl = true,
139},
140.{
141 .name = "E",
142 .syntax = .flag,
143 .zig_equivalent = .preprocess,
144 .pd1 = true,
145 .pd2 = false,
146 .psl = true,
147},
148.{
149 .name = "EP",
150 .syntax = .flag,
151 .zig_equivalent = .other,
152 .pd1 = true,
153 .pd2 = false,
154 .psl = true,
155},
156.{
157 .name = "FA",
158 .syntax = .flag,
159 .zig_equivalent = .other,
160 .pd1 = true,
161 .pd2 = false,
162 .psl = true,
163},
164.{
165 .name = "FC",
166 .syntax = .flag,
167 .zig_equivalent = .other,
168 .pd1 = true,
169 .pd2 = false,
170 .psl = true,
171},
172.{
173 .name = "FS",
174 .syntax = .flag,
175 .zig_equivalent = .other,
176 .pd1 = true,
177 .pd2 = false,
178 .psl = true,
179},
180.{
181 .name = "Fx",
182 .syntax = .flag,
183 .zig_equivalent = .other,
184 .pd1 = true,
185 .pd2 = false,
186 .psl = true,
187},
188.{
189 .name = "G1",
190 .syntax = .flag,
191 .zig_equivalent = .other,
192 .pd1 = true,
193 .pd2 = false,
194 .psl = true,
195},
196.{
197 .name = "G2",
198 .syntax = .flag,
199 .zig_equivalent = .other,
200 .pd1 = true,
201 .pd2 = false,
202 .psl = true,
203},
204.{
205 .name = "GA",
206 .syntax = .flag,
207 .zig_equivalent = .other,
208 .pd1 = true,
209 .pd2 = false,
210 .psl = true,
211},
212.{
213 .name = "GF",
214 .syntax = .flag,
215 .zig_equivalent = .other,
216 .pd1 = true,
217 .pd2 = false,
218 .psl = true,
219},
220.{
221 .name = "GF-",
222 .syntax = .flag,
223 .zig_equivalent = .other,
224 .pd1 = true,
225 .pd2 = false,
226 .psl = true,
227},
228.{
229 .name = "GH",
230 .syntax = .flag,
231 .zig_equivalent = .other,
232 .pd1 = true,
233 .pd2 = false,
234 .psl = true,
235},
236.{
237 .name = "GL",
238 .syntax = .flag,
239 .zig_equivalent = .other,
240 .pd1 = true,
241 .pd2 = false,
242 .psl = true,
243},
244.{
245 .name = "GL-",
246 .syntax = .flag,
247 .zig_equivalent = .other,
248 .pd1 = true,
249 .pd2 = false,
250 .psl = true,
251},
252.{
253 .name = "GR",
254 .syntax = .flag,
255 .zig_equivalent = .other,
256 .pd1 = true,
257 .pd2 = false,
258 .psl = true,
259},
260.{
261 .name = "GR-",
262 .syntax = .flag,
263 .zig_equivalent = .other,
264 .pd1 = true,
265 .pd2 = false,
266 .psl = true,
267},
268.{
269 .name = "GS",
270 .syntax = .flag,
271 .zig_equivalent = .other,
272 .pd1 = true,
273 .pd2 = false,
274 .psl = true,
275},
276.{
277 .name = "GS-",
278 .syntax = .flag,
279 .zig_equivalent = .other,
280 .pd1 = true,
281 .pd2 = false,
282 .psl = true,
283},
284.{
285 .name = "GT",
286 .syntax = .flag,
287 .zig_equivalent = .other,
288 .pd1 = true,
289 .pd2 = false,
290 .psl = true,
291},
292.{
293 .name = "GX",
294 .syntax = .flag,
295 .zig_equivalent = .other,
296 .pd1 = true,
297 .pd2 = false,
298 .psl = true,
299},
300.{
301 .name = "GX-",
302 .syntax = .flag,
303 .zig_equivalent = .other,
304 .pd1 = true,
305 .pd2 = false,
306 .psl = true,
307},
308.{
309 .name = "GZ",
310 .syntax = .flag,
311 .zig_equivalent = .other,
312 .pd1 = true,
313 .pd2 = false,
314 .psl = true,
315},
316.{
317 .name = "Gd",
318 .syntax = .flag,
319 .zig_equivalent = .other,
320 .pd1 = true,
321 .pd2 = false,
322 .psl = true,
323},
324.{
325 .name = "Ge",
326 .syntax = .flag,
327 .zig_equivalent = .other,
328 .pd1 = true,
329 .pd2 = false,
330 .psl = true,
331},
332.{
333 .name = "Gh",
334 .syntax = .flag,
335 .zig_equivalent = .other,
336 .pd1 = true,
337 .pd2 = false,
338 .psl = true,
339},
340.{
341 .name = "Gm",
342 .syntax = .flag,
343 .zig_equivalent = .other,
344 .pd1 = true,
345 .pd2 = false,
346 .psl = true,
347},
348.{
349 .name = "Gm-",
350 .syntax = .flag,
351 .zig_equivalent = .other,
352 .pd1 = true,
353 .pd2 = false,
354 .psl = true,
355},
356.{
357 .name = "Gr",
358 .syntax = .flag,
359 .zig_equivalent = .other,
360 .pd1 = true,
361 .pd2 = false,
362 .psl = true,
363},
364.{
365 .name = "Gregcall",
366 .syntax = .flag,
367 .zig_equivalent = .other,
368 .pd1 = true,
369 .pd2 = false,
370 .psl = true,
371},
372.{
373 .name = "Gv",
374 .syntax = .flag,
375 .zig_equivalent = .other,
376 .pd1 = true,
377 .pd2 = false,
378 .psl = true,
379},
380.{
381 .name = "Gw",
382 .syntax = .flag,
383 .zig_equivalent = .other,
384 .pd1 = true,
385 .pd2 = false,
386 .psl = true,
387},
388.{
389 .name = "Gw-",
390 .syntax = .flag,
391 .zig_equivalent = .other,
392 .pd1 = true,
393 .pd2 = false,
394 .psl = true,
395},
396.{
397 .name = "Gy",
398 .syntax = .flag,
399 .zig_equivalent = .other,
400 .pd1 = true,
401 .pd2 = false,
402 .psl = true,
403},
404.{
405 .name = "Gy-",
406 .syntax = .flag,
407 .zig_equivalent = .other,
408 .pd1 = true,
409 .pd2 = false,
410 .psl = true,
411},
412.{
413 .name = "Gz",
414 .syntax = .flag,
415 .zig_equivalent = .other,
416 .pd1 = true,
417 .pd2 = false,
418 .psl = true,
419},
420.{
421 .name = "H",
422 .syntax = .flag,
423 .zig_equivalent = .other,
424 .pd1 = true,
425 .pd2 = false,
426 .psl = true,
427},
428.{
429 .name = "HELP",
430 .syntax = .flag,
431 .zig_equivalent = .other,
432 .pd1 = true,
433 .pd2 = false,
434 .psl = true,
435},
436.{
437 .name = "J",
438 .syntax = .flag,
439 .zig_equivalent = .other,
440 .pd1 = true,
441 .pd2 = false,
442 .psl = true,
443},
444.{
445 .name = "JMC",
446 .syntax = .flag,
447 .zig_equivalent = .other,
448 .pd1 = true,
449 .pd2 = false,
450 .psl = true,
451},
452.{
453 .name = "LD",
454 .syntax = .flag,
455 .zig_equivalent = .other,
456 .pd1 = true,
457 .pd2 = false,
458 .psl = true,
459},
460.{
461 .name = "LDd",
462 .syntax = .flag,
463 .zig_equivalent = .other,
464 .pd1 = true,
465 .pd2 = false,
466 .psl = true,
467},
468.{
469 .name = "LN",
470 .syntax = .flag,
471 .zig_equivalent = .other,
472 .pd1 = true,
473 .pd2 = false,
474 .psl = true,
475},
476.{
477 .name = "MD",
478 .syntax = .flag,
479 .zig_equivalent = .other,
480 .pd1 = true,
481 .pd2 = false,
482 .psl = true,
483},
484.{
485 .name = "MDd",
486 .syntax = .flag,
487 .zig_equivalent = .other,
488 .pd1 = true,
489 .pd2 = false,
490 .psl = true,
491},
492.{
493 .name = "MT",
494 .syntax = .flag,
495 .zig_equivalent = .other,
496 .pd1 = true,
497 .pd2 = false,
498 .psl = true,
499},
500.{
501 .name = "MTd",
502 .syntax = .flag,
503 .zig_equivalent = .other,
504 .pd1 = true,
505 .pd2 = false,
506 .psl = true,
507},
508.{
509 .name = "P",
510 .syntax = .flag,
511 .zig_equivalent = .other,
512 .pd1 = true,
513 .pd2 = false,
514 .psl = true,
515},
516.{
517 .name = "QIfist",
518 .syntax = .flag,
519 .zig_equivalent = .other,
520 .pd1 = true,
521 .pd2 = false,
522 .psl = true,
523},
524.{
525 .name = "?",
526 .syntax = .flag,
527 .zig_equivalent = .other,
528 .pd1 = true,
529 .pd2 = false,
530 .psl = true,
531},
532.{
533 .name = "Qfast_transcendentals",
534 .syntax = .flag,
535 .zig_equivalent = .other,
536 .pd1 = true,
537 .pd2 = false,
538 .psl = true,
539},
540.{
541 .name = "Qimprecise_fwaits",
542 .syntax = .flag,
543 .zig_equivalent = .other,
544 .pd1 = true,
545 .pd2 = false,
546 .psl = true,
547},
548.{
549 .name = "Qpar",
550 .syntax = .flag,
551 .zig_equivalent = .other,
552 .pd1 = true,
553 .pd2 = false,
554 .psl = true,
555},
556.{
557 .name = "Qsafe_fp_loads",
558 .syntax = .flag,
559 .zig_equivalent = .other,
560 .pd1 = true,
561 .pd2 = false,
562 .psl = true,
563},
564.{
565 .name = "Qspectre",
566 .syntax = .flag,
567 .zig_equivalent = .other,
568 .pd1 = true,
569 .pd2 = false,
570 .psl = true,
571},
572.{
573 .name = "Qvec",
574 .syntax = .flag,
575 .zig_equivalent = .other,
576 .pd1 = true,
577 .pd2 = false,
578 .psl = true,
579},
580.{
581 .name = "Qvec-",
582 .syntax = .flag,
583 .zig_equivalent = .other,
584 .pd1 = true,
585 .pd2 = false,
586 .psl = true,
587},
588.{
589 .name = "TC",
590 .syntax = .flag,
591 .zig_equivalent = .other,
592 .pd1 = true,
593 .pd2 = false,
594 .psl = true,
595},
596.{
597 .name = "TP",
598 .syntax = .flag,
599 .zig_equivalent = .other,
600 .pd1 = true,
601 .pd2 = false,
602 .psl = true,
603},
604.{
605 .name = "V",
606 .syntax = .flag,
607 .zig_equivalent = .other,
608 .pd1 = true,
609 .pd2 = false,
610 .psl = true,
611},
612.{
613 .name = "W0",
614 .syntax = .flag,
615 .zig_equivalent = .other,
616 .pd1 = true,
617 .pd2 = false,
618 .psl = true,
619},
620.{
621 .name = "W1",
622 .syntax = .flag,
623 .zig_equivalent = .other,
624 .pd1 = true,
625 .pd2 = false,
626 .psl = true,
627},
628.{
629 .name = "W2",
630 .syntax = .flag,
631 .zig_equivalent = .other,
632 .pd1 = true,
633 .pd2 = false,
634 .psl = true,
635},
636.{
637 .name = "W3",
638 .syntax = .flag,
639 .zig_equivalent = .other,
640 .pd1 = true,
641 .pd2 = false,
642 .psl = true,
643},
644.{
645 .name = "W4",
646 .syntax = .flag,
647 .zig_equivalent = .other,
648 .pd1 = true,
649 .pd2 = false,
650 .psl = true,
651},
652.{
653 .name = "WL",
654 .syntax = .flag,
655 .zig_equivalent = .other,
656 .pd1 = true,
657 .pd2 = false,
658 .psl = true,
659},
660.{
661 .name = "WX",
662 .syntax = .flag,
663 .zig_equivalent = .other,
664 .pd1 = true,
665 .pd2 = false,
666 .psl = true,
667},
668.{
669 .name = "WX-",
670 .syntax = .flag,
671 .zig_equivalent = .other,
672 .pd1 = true,
673 .pd2 = false,
674 .psl = true,
675},
676.{
677 .name = "Wall",
678 .syntax = .flag,
679 .zig_equivalent = .other,
680 .pd1 = true,
681 .pd2 = false,
682 .psl = true,
683},
684.{
685 .name = "Wp64",
686 .syntax = .flag,
687 .zig_equivalent = .other,
688 .pd1 = true,
689 .pd2 = false,
690 .psl = true,
691},
692.{
693 .name = "X",
694 .syntax = .flag,
695 .zig_equivalent = .other,
696 .pd1 = true,
697 .pd2 = false,
698 .psl = true,
699},
700.{
701 .name = "Y-",
702 .syntax = .flag,
703 .zig_equivalent = .other,
704 .pd1 = true,
705 .pd2 = false,
706 .psl = true,
707},
708.{
709 .name = "Yd",
710 .syntax = .flag,
711 .zig_equivalent = .other,
712 .pd1 = true,
713 .pd2 = false,
714 .psl = true,
715},
716.{
717 .name = "Z7",
718 .syntax = .flag,
719 .zig_equivalent = .other,
720 .pd1 = true,
721 .pd2 = false,
722 .psl = true,
723},
724.{
725 .name = "ZH:MD5",
726 .syntax = .flag,
727 .zig_equivalent = .other,
728 .pd1 = true,
729 .pd2 = false,
730 .psl = true,
731},
732.{
733 .name = "ZH:SHA1",
734 .syntax = .flag,
735 .zig_equivalent = .other,
736 .pd1 = true,
737 .pd2 = false,
738 .psl = true,
739},
740.{
741 .name = "ZH:SHA_256",
742 .syntax = .flag,
743 .zig_equivalent = .other,
744 .pd1 = true,
745 .pd2 = false,
746 .psl = true,
747},
748.{
749 .name = "ZI",
750 .syntax = .flag,
751 .zig_equivalent = .other,
752 .pd1 = true,
753 .pd2 = false,
754 .psl = true,
755},
756.{
757 .name = "Za",
758 .syntax = .flag,
759 .zig_equivalent = .other,
760 .pd1 = true,
761 .pd2 = false,
762 .psl = true,
763},
764.{
765 .name = "Zc:__cplusplus",
766 .syntax = .flag,
767 .zig_equivalent = .other,
768 .pd1 = true,
769 .pd2 = false,
770 .psl = true,
771},
772.{
773 .name = "Zc:alignedNew",
774 .syntax = .flag,
775 .zig_equivalent = .other,
776 .pd1 = true,
777 .pd2 = false,
778 .psl = true,
779},
780.{
781 .name = "Zc:alignedNew-",
782 .syntax = .flag,
783 .zig_equivalent = .other,
784 .pd1 = true,
785 .pd2 = false,
786 .psl = true,
787},
788.{
789 .name = "Zc:auto",
790 .syntax = .flag,
791 .zig_equivalent = .other,
792 .pd1 = true,
793 .pd2 = false,
794 .psl = true,
795},
796.{
797 .name = "Zc:char8_t",
798 .syntax = .flag,
799 .zig_equivalent = .other,
800 .pd1 = true,
801 .pd2 = false,
802 .psl = true,
803},
804.{
805 .name = "Zc:char8_t-",
806 .syntax = .flag,
807 .zig_equivalent = .other,
808 .pd1 = true,
809 .pd2 = false,
810 .psl = true,
811},
812.{
813 .name = "Zc:dllexportInlines",
814 .syntax = .flag,
815 .zig_equivalent = .other,
816 .pd1 = true,
817 .pd2 = false,
818 .psl = true,
819},
820.{
821 .name = "Zc:dllexportInlines-",
822 .syntax = .flag,
823 .zig_equivalent = .other,
824 .pd1 = true,
825 .pd2 = false,
826 .psl = true,
827},
828.{
829 .name = "Zc:forScope",
830 .syntax = .flag,
831 .zig_equivalent = .other,
832 .pd1 = true,
833 .pd2 = false,
834 .psl = true,
835},
836.{
837 .name = "Zc:inline",
838 .syntax = .flag,
839 .zig_equivalent = .other,
840 .pd1 = true,
841 .pd2 = false,
842 .psl = true,
843},
844.{
845 .name = "Zc:rvalueCast",
846 .syntax = .flag,
847 .zig_equivalent = .other,
848 .pd1 = true,
849 .pd2 = false,
850 .psl = true,
851},
852.{
853 .name = "Zc:sizedDealloc",
854 .syntax = .flag,
855 .zig_equivalent = .other,
856 .pd1 = true,
857 .pd2 = false,
858 .psl = true,
859},
860.{
861 .name = "Zc:sizedDealloc-",
862 .syntax = .flag,
863 .zig_equivalent = .other,
864 .pd1 = true,
865 .pd2 = false,
866 .psl = true,
867},
868.{
869 .name = "Zc:strictStrings",
870 .syntax = .flag,
871 .zig_equivalent = .other,
872 .pd1 = true,
873 .pd2 = false,
874 .psl = true,
875},
876.{
877 .name = "Zc:ternary",
878 .syntax = .flag,
879 .zig_equivalent = .other,
880 .pd1 = true,
881 .pd2 = false,
882 .psl = true,
883},
884.{
885 .name = "Zc:threadSafeInit",
886 .syntax = .flag,
887 .zig_equivalent = .other,
888 .pd1 = true,
889 .pd2 = false,
890 .psl = true,
891},
892.{
893 .name = "Zc:threadSafeInit-",
894 .syntax = .flag,
895 .zig_equivalent = .other,
896 .pd1 = true,
897 .pd2 = false,
898 .psl = true,
899},
900.{
901 .name = "Zc:trigraphs",
902 .syntax = .flag,
903 .zig_equivalent = .other,
904 .pd1 = true,
905 .pd2 = false,
906 .psl = true,
907},
908.{
909 .name = "Zc:trigraphs-",
910 .syntax = .flag,
911 .zig_equivalent = .other,
912 .pd1 = true,
913 .pd2 = false,
914 .psl = true,
915},
916.{
917 .name = "Zc:twoPhase",
918 .syntax = .flag,
919 .zig_equivalent = .other,
920 .pd1 = true,
921 .pd2 = false,
922 .psl = true,
923},
924.{
925 .name = "Zc:twoPhase-",
926 .syntax = .flag,
927 .zig_equivalent = .other,
928 .pd1 = true,
929 .pd2 = false,
930 .psl = true,
931},
932.{
933 .name = "Zc:wchar_t",
934 .syntax = .flag,
935 .zig_equivalent = .other,
936 .pd1 = true,
937 .pd2 = false,
938 .psl = true,
939},
940.{
941 .name = "Zd",
942 .syntax = .flag,
943 .zig_equivalent = .other,
944 .pd1 = true,
945 .pd2 = false,
946 .psl = true,
947},
948.{
949 .name = "Ze",
950 .syntax = .flag,
951 .zig_equivalent = .other,
952 .pd1 = true,
953 .pd2 = false,
954 .psl = true,
955},
956.{
957 .name = "Zg",
958 .syntax = .flag,
959 .zig_equivalent = .other,
960 .pd1 = true,
961 .pd2 = false,
962 .psl = true,
963},
964.{
965 .name = "Zi",
966 .syntax = .flag,
967 .zig_equivalent = .other,
968 .pd1 = true,
969 .pd2 = false,
970 .psl = true,
971},
972.{
973 .name = "Zl",
974 .syntax = .flag,
975 .zig_equivalent = .other,
976 .pd1 = true,
977 .pd2 = false,
978 .psl = true,
979},
980.{
981 .name = "Zo",
982 .syntax = .flag,
983 .zig_equivalent = .other,
984 .pd1 = true,
985 .pd2 = false,
986 .psl = true,
987},
988.{
989 .name = "Zo-",
990 .syntax = .flag,
991 .zig_equivalent = .other,
992 .pd1 = true,
993 .pd2 = false,
994 .psl = true,
995},
996.{
997 .name = "Zp",
998 .syntax = .flag,
999 .zig_equivalent = .other,
1000 .pd1 = true,
1001 .pd2 = false,
1002 .psl = true,
1003},
1004.{
1005 .name = "Zs",
1006 .syntax = .flag,
1007 .zig_equivalent = .other,
1008 .pd1 = true,
1009 .pd2 = false,
1010 .psl = true,
1011},
1012.{
1013 .name = "analyze-",
1014 .syntax = .flag,
1015 .zig_equivalent = .other,
1016 .pd1 = true,
1017 .pd2 = false,
1018 .psl = true,
1019},
1020.{
1021 .name = "await",
1022 .syntax = .flag,
1023 .zig_equivalent = .other,
1024 .pd1 = true,
1025 .pd2 = false,
1026 .psl = true,
1027},
1028.{
1029 .name = "bigobj",
1030 .syntax = .flag,
1031 .zig_equivalent = .other,
1032 .pd1 = true,
1033 .pd2 = false,
1034 .psl = true,
1035},
1036.{
1037 .name = "c",
1038 .syntax = .flag,
1039 .zig_equivalent = .c,
1040 .pd1 = true,
1041 .pd2 = false,
1042 .psl = true,
1043},
1044.{
1045 .name = "d1PP",
1046 .syntax = .flag,
1047 .zig_equivalent = .other,
1048 .pd1 = true,
1049 .pd2 = false,
1050 .psl = true,
1051},
1052.{
1053 .name = "d1reportAllClassLayout",
1054 .syntax = .flag,
1055 .zig_equivalent = .other,
1056 .pd1 = true,
1057 .pd2 = false,
1058 .psl = true,
1059},
1060.{
1061 .name = "d2FastFail",
1062 .syntax = .flag,
1063 .zig_equivalent = .other,
1064 .pd1 = true,
1065 .pd2 = false,
1066 .psl = true,
1067},
1068.{
1069 .name = "d2Zi+",
1070 .syntax = .flag,
1071 .zig_equivalent = .other,
1072 .pd1 = true,
1073 .pd2 = false,
1074 .psl = true,
1075},
1076.{
1077 .name = "diagnostics:caret",
1078 .syntax = .flag,
1079 .zig_equivalent = .other,
1080 .pd1 = true,
1081 .pd2 = false,
1082 .psl = true,
1083},
1084.{
1085 .name = "diagnostics:classic",
1086 .syntax = .flag,
1087 .zig_equivalent = .other,
1088 .pd1 = true,
1089 .pd2 = false,
1090 .psl = true,
1091},
1092.{
1093 .name = "diagnostics:column",
1094 .syntax = .flag,
1095 .zig_equivalent = .other,
1096 .pd1 = true,
1097 .pd2 = false,
1098 .psl = true,
1099},
1100.{
1101 .name = "fallback",
1102 .syntax = .flag,
1103 .zig_equivalent = .other,
1104 .pd1 = true,
1105 .pd2 = false,
1106 .psl = true,
1107},
1108.{
1109 .name = "fp:except",
1110 .syntax = .flag,
1111 .zig_equivalent = .other,
1112 .pd1 = true,
1113 .pd2 = false,
1114 .psl = true,
1115},
1116.{
1117 .name = "fp:except-",
1118 .syntax = .flag,
1119 .zig_equivalent = .other,
1120 .pd1 = true,
1121 .pd2 = false,
1122 .psl = true,
1123},
1124.{
1125 .name = "fp:fast",
1126 .syntax = .flag,
1127 .zig_equivalent = .other,
1128 .pd1 = true,
1129 .pd2 = false,
1130 .psl = true,
1131},
1132.{
1133 .name = "fp:precise",
1134 .syntax = .flag,
1135 .zig_equivalent = .other,
1136 .pd1 = true,
1137 .pd2 = false,
1138 .psl = true,
1139},
1140.{
1141 .name = "fp:strict",
1142 .syntax = .flag,
1143 .zig_equivalent = .other,
1144 .pd1 = true,
1145 .pd2 = false,
1146 .psl = true,
1147},
1148.{
1149 .name = "help",
1150 .syntax = .flag,
1151 .zig_equivalent = .driver_punt,
1152 .pd1 = true,
1153 .pd2 = false,
1154 .psl = true,
1155},
1156.{
1157 .name = "homeparams",
1158 .syntax = .flag,
1159 .zig_equivalent = .other,
1160 .pd1 = true,
1161 .pd2 = false,
1162 .psl = true,
1163},
1164.{
1165 .name = "hotpatch",
1166 .syntax = .flag,
1167 .zig_equivalent = .other,
1168 .pd1 = true,
1169 .pd2 = false,
1170 .psl = true,
1171},
1172.{
1173 .name = "kernel",
1174 .syntax = .flag,
1175 .zig_equivalent = .other,
1176 .pd1 = true,
1177 .pd2 = false,
1178 .psl = true,
1179},
1180.{
1181 .name = "kernel-",
1182 .syntax = .flag,
1183 .zig_equivalent = .other,
1184 .pd1 = true,
1185 .pd2 = false,
1186 .psl = true,
1187},
1188.{
1189 .name = "nologo",
1190 .syntax = .flag,
1191 .zig_equivalent = .other,
1192 .pd1 = true,
1193 .pd2 = false,
1194 .psl = true,
1195},
1196.{
1197 .name = "openmp",
1198 .syntax = .flag,
1199 .zig_equivalent = .other,
1200 .pd1 = true,
1201 .pd2 = false,
1202 .psl = true,
1203},
1204.{
1205 .name = "openmp-",
1206 .syntax = .flag,
1207 .zig_equivalent = .other,
1208 .pd1 = true,
1209 .pd2 = false,
1210 .psl = true,
1211},
1212.{
1213 .name = "openmp:experimental",
1214 .syntax = .flag,
1215 .zig_equivalent = .other,
1216 .pd1 = true,
1217 .pd2 = false,
1218 .psl = true,
1219},
1220.{
1221 .name = "permissive-",
1222 .syntax = .flag,
1223 .zig_equivalent = .other,
1224 .pd1 = true,
1225 .pd2 = false,
1226 .psl = true,
1227},
1228.{
1229 .name = "sdl",
1230 .syntax = .flag,
1231 .zig_equivalent = .other,
1232 .pd1 = true,
1233 .pd2 = false,
1234 .psl = true,
1235},
1236.{
1237 .name = "sdl-",
1238 .syntax = .flag,
1239 .zig_equivalent = .other,
1240 .pd1 = true,
1241 .pd2 = false,
1242 .psl = true,
1243},
1244.{
1245 .name = "showFilenames",
1246 .syntax = .flag,
1247 .zig_equivalent = .other,
1248 .pd1 = true,
1249 .pd2 = false,
1250 .psl = true,
1251},
1252.{
1253 .name = "showFilenames-",
1254 .syntax = .flag,
1255 .zig_equivalent = .other,
1256 .pd1 = true,
1257 .pd2 = false,
1258 .psl = true,
1259},
1260.{
1261 .name = "showIncludes",
1262 .syntax = .flag,
1263 .zig_equivalent = .other,
1264 .pd1 = true,
1265 .pd2 = false,
1266 .psl = true,
1267},
1268.{
1269 .name = "u",
1270 .syntax = .flag,
1271 .zig_equivalent = .other,
1272 .pd1 = true,
1273 .pd2 = false,
1274 .psl = true,
1275},
1276.{
1277 .name = "utf-8",
1278 .syntax = .flag,
1279 .zig_equivalent = .other,
1280 .pd1 = true,
1281 .pd2 = false,
1282 .psl = true,
1283},
1284.{
1285 .name = "validate-charset",
1286 .syntax = .flag,
1287 .zig_equivalent = .other,
1288 .pd1 = true,
1289 .pd2 = false,
1290 .psl = true,
1291},
1292.{
1293 .name = "validate-charset-",
1294 .syntax = .flag,
1295 .zig_equivalent = .other,
1296 .pd1 = true,
1297 .pd2 = false,
1298 .psl = true,
1299},
1300.{
1301 .name = "vmb",
1302 .syntax = .flag,
1303 .zig_equivalent = .other,
1304 .pd1 = true,
1305 .pd2 = false,
1306 .psl = true,
1307},
1308.{
1309 .name = "vmg",
1310 .syntax = .flag,
1311 .zig_equivalent = .other,
1312 .pd1 = true,
1313 .pd2 = false,
1314 .psl = true,
1315},
1316.{
1317 .name = "vmm",
1318 .syntax = .flag,
1319 .zig_equivalent = .other,
1320 .pd1 = true,
1321 .pd2 = false,
1322 .psl = true,
1323},
1324.{
1325 .name = "vms",
1326 .syntax = .flag,
1327 .zig_equivalent = .other,
1328 .pd1 = true,
1329 .pd2 = false,
1330 .psl = true,
1331},
1332.{
1333 .name = "vmv",
1334 .syntax = .flag,
1335 .zig_equivalent = .other,
1336 .pd1 = true,
1337 .pd2 = false,
1338 .psl = true,
1339},
1340.{
1341 .name = "volatile:iso",
1342 .syntax = .flag,
1343 .zig_equivalent = .other,
1344 .pd1 = true,
1345 .pd2 = false,
1346 .psl = true,
1347},
1348.{
1349 .name = "volatile:ms",
1350 .syntax = .flag,
1351 .zig_equivalent = .other,
1352 .pd1 = true,
1353 .pd2 = false,
1354 .psl = true,
1355},
1356.{
1357 .name = "w",
1358 .syntax = .flag,
1359 .zig_equivalent = .other,
1360 .pd1 = true,
1361 .pd2 = false,
1362 .psl = true,
1363},
1364.{
1365 .name = "wd4005",
1366 .syntax = .flag,
1367 .zig_equivalent = .other,
1368 .pd1 = true,
1369 .pd2 = false,
1370 .psl = true,
1371},
1372.{
1373 .name = "wd4018",
1374 .syntax = .flag,
1375 .zig_equivalent = .other,
1376 .pd1 = true,
1377 .pd2 = false,
1378 .psl = true,
1379},
1380.{
1381 .name = "wd4100",
1382 .syntax = .flag,
1383 .zig_equivalent = .other,
1384 .pd1 = true,
1385 .pd2 = false,
1386 .psl = true,
1387},
1388.{
1389 .name = "wd4910",
1390 .syntax = .flag,
1391 .zig_equivalent = .other,
1392 .pd1 = true,
1393 .pd2 = false,
1394 .psl = true,
1395},
1396.{
1397 .name = "wd4996",
1398 .syntax = .flag,
1399 .zig_equivalent = .other,
1400 .pd1 = true,
1401 .pd2 = false,
1402 .psl = true,
1403},
1404.{
1405 .name = "all-warnings",
1406 .syntax = .flag,
1407 .zig_equivalent = .other,
1408 .pd1 = false,
1409 .pd2 = true,
1410 .psl = false,
1411},
1412.{
1413 .name = "analyze",
1414 .syntax = .flag,
1415 .zig_equivalent = .other,
1416 .pd1 = false,
1417 .pd2 = true,
1418 .psl = false,
1419},
1420.{
1421 .name = "analyzer-no-default-checks",
1422 .syntax = .flag,
1423 .zig_equivalent = .other,
1424 .pd1 = false,
1425 .pd2 = true,
1426 .psl = false,
1427},
1428.{
1429 .name = "assemble",
1430 .syntax = .flag,
1431 .zig_equivalent = .driver_punt,
1432 .pd1 = false,
1433 .pd2 = true,
1434 .psl = false,
1435},
1436.{
1437 .name = "assert",
1438 .syntax = .separate,
1439 .zig_equivalent = .other,
1440 .pd1 = false,
1441 .pd2 = true,
1442 .psl = false,
1443},
1444.{
1445 .name = "bootclasspath",
1446 .syntax = .separate,
1447 .zig_equivalent = .other,
1448 .pd1 = false,
1449 .pd2 = true,
1450 .psl = false,
1451},
1452.{
1453 .name = "classpath",
1454 .syntax = .separate,
1455 .zig_equivalent = .other,
1456 .pd1 = false,
1457 .pd2 = true,
1458 .psl = false,
1459},
1460.{
1461 .name = "comments",
1462 .syntax = .flag,
1463 .zig_equivalent = .other,
1464 .pd1 = false,
1465 .pd2 = true,
1466 .psl = false,
1467},
1468.{
1469 .name = "comments-in-macros",
1470 .syntax = .flag,
1471 .zig_equivalent = .other,
1472 .pd1 = false,
1473 .pd2 = true,
1474 .psl = false,
1475},
1476.{
1477 .name = "compile",
1478 .syntax = .flag,
1479 .zig_equivalent = .other,
1480 .pd1 = false,
1481 .pd2 = true,
1482 .psl = false,
1483},
1484.{
1485 .name = "constant-cfstrings",
1486 .syntax = .flag,
1487 .zig_equivalent = .other,
1488 .pd1 = false,
1489 .pd2 = true,
1490 .psl = false,
1491},
1492.{
1493 .name = "debug",
1494 .syntax = .flag,
1495 .zig_equivalent = .debug,
1496 .pd1 = false,
1497 .pd2 = true,
1498 .psl = false,
1499},
1500.{
1501 .name = "define-macro",
1502 .syntax = .separate,
1503 .zig_equivalent = .other,
1504 .pd1 = false,
1505 .pd2 = true,
1506 .psl = false,
1507},
1508.{
1509 .name = "dependencies",
1510 .syntax = .flag,
1511 .zig_equivalent = .other,
1512 .pd1 = false,
1513 .pd2 = true,
1514 .psl = false,
1515},
1516.{
1517 .name = "dyld-prefix",
1518 .syntax = .separate,
1519 .zig_equivalent = .other,
1520 .pd1 = false,
1521 .pd2 = true,
1522 .psl = false,
1523},
1524.{
1525 .name = "encoding",
1526 .syntax = .separate,
1527 .zig_equivalent = .other,
1528 .pd1 = false,
1529 .pd2 = true,
1530 .psl = false,
1531},
1532.{
1533 .name = "entry",
1534 .syntax = .flag,
1535 .zig_equivalent = .other,
1536 .pd1 = false,
1537 .pd2 = true,
1538 .psl = false,
1539},
1540.{
1541 .name = "extdirs",
1542 .syntax = .separate,
1543 .zig_equivalent = .other,
1544 .pd1 = false,
1545 .pd2 = true,
1546 .psl = false,
1547},
1548.{
1549 .name = "extra-warnings",
1550 .syntax = .flag,
1551 .zig_equivalent = .other,
1552 .pd1 = false,
1553 .pd2 = true,
1554 .psl = false,
1555},
1556.{
1557 .name = "for-linker",
1558 .syntax = .separate,
1559 .zig_equivalent = .other,
1560 .pd1 = false,
1561 .pd2 = true,
1562 .psl = false,
1563},
1564.{
1565 .name = "force-link",
1566 .syntax = .separate,
1567 .zig_equivalent = .other,
1568 .pd1 = false,
1569 .pd2 = true,
1570 .psl = false,
1571},
1572.{
1573 .name = "help-hidden",
1574 .syntax = .flag,
1575 .zig_equivalent = .other,
1576 .pd1 = false,
1577 .pd2 = true,
1578 .psl = false,
1579},
1580.{
1581 .name = "include-barrier",
1582 .syntax = .flag,
1583 .zig_equivalent = .other,
1584 .pd1 = false,
1585 .pd2 = true,
1586 .psl = false,
1587},
1588.{
1589 .name = "include-directory",
1590 .syntax = .separate,
1591 .zig_equivalent = .other,
1592 .pd1 = false,
1593 .pd2 = true,
1594 .psl = false,
1595},
1596.{
1597 .name = "include-directory-after",
1598 .syntax = .separate,
1599 .zig_equivalent = .other,
1600 .pd1 = false,
1601 .pd2 = true,
1602 .psl = false,
1603},
1604.{
1605 .name = "include-prefix",
1606 .syntax = .separate,
1607 .zig_equivalent = .other,
1608 .pd1 = false,
1609 .pd2 = true,
1610 .psl = false,
1611},
1612.{
1613 .name = "include-with-prefix",
1614 .syntax = .separate,
1615 .zig_equivalent = .other,
1616 .pd1 = false,
1617 .pd2 = true,
1618 .psl = false,
1619},
1620.{
1621 .name = "include-with-prefix-after",
1622 .syntax = .separate,
1623 .zig_equivalent = .other,
1624 .pd1 = false,
1625 .pd2 = true,
1626 .psl = false,
1627},
1628.{
1629 .name = "include-with-prefix-before",
1630 .syntax = .separate,
1631 .zig_equivalent = .other,
1632 .pd1 = false,
1633 .pd2 = true,
1634 .psl = false,
1635},
1636.{
1637 .name = "language",
1638 .syntax = .separate,
1639 .zig_equivalent = .other,
1640 .pd1 = false,
1641 .pd2 = true,
1642 .psl = false,
1643},
1644.{
1645 .name = "library-directory",
1646 .syntax = .separate,
1647 .zig_equivalent = .other,
1648 .pd1 = false,
1649 .pd2 = true,
1650 .psl = false,
1651},
1652.{
1653 .name = "mhwdiv",
1654 .syntax = .separate,
1655 .zig_equivalent = .other,
1656 .pd1 = false,
1657 .pd2 = true,
1658 .psl = false,
1659},
1660.{
1661 .name = "migrate",
1662 .syntax = .flag,
1663 .zig_equivalent = .other,
1664 .pd1 = false,
1665 .pd2 = true,
1666 .psl = false,
1667},
1668.{
1669 .name = "no-line-commands",
1670 .syntax = .flag,
1671 .zig_equivalent = .other,
1672 .pd1 = false,
1673 .pd2 = true,
1674 .psl = false,
1675},
1676.{
1677 .name = "no-standard-includes",
1678 .syntax = .flag,
1679 .zig_equivalent = .other,
1680 .pd1 = false,
1681 .pd2 = true,
1682 .psl = false,
1683},
1684.{
1685 .name = "no-standard-libraries",
1686 .syntax = .flag,
1687 .zig_equivalent = .nostdlib,
1688 .pd1 = false,
1689 .pd2 = true,
1690 .psl = false,
1691},
1692.{
1693 .name = "no-undefined",
1694 .syntax = .flag,
1695 .zig_equivalent = .other,
1696 .pd1 = false,
1697 .pd2 = true,
1698 .psl = false,
1699},
1700.{
1701 .name = "no-warnings",
1702 .syntax = .flag,
1703 .zig_equivalent = .other,
1704 .pd1 = false,
1705 .pd2 = true,
1706 .psl = false,
1707},
1708.{
1709 .name = "optimize",
1710 .syntax = .flag,
1711 .zig_equivalent = .optimize,
1712 .pd1 = false,
1713 .pd2 = true,
1714 .psl = false,
1715},
1716.{
1717 .name = "output",
1718 .syntax = .separate,
1719 .zig_equivalent = .other,
1720 .pd1 = false,
1721 .pd2 = true,
1722 .psl = false,
1723},
1724.{
1725 .name = "output-class-directory",
1726 .syntax = .separate,
1727 .zig_equivalent = .other,
1728 .pd1 = false,
1729 .pd2 = true,
1730 .psl = false,
1731},
1732.{
1733 .name = "param",
1734 .syntax = .separate,
1735 .zig_equivalent = .other,
1736 .pd1 = false,
1737 .pd2 = true,
1738 .psl = false,
1739},
1740.{
1741 .name = "precompile",
1742 .syntax = .flag,
1743 .zig_equivalent = .other,
1744 .pd1 = false,
1745 .pd2 = true,
1746 .psl = false,
1747},
1748.{
1749 .name = "prefix",
1750 .syntax = .separate,
1751 .zig_equivalent = .other,
1752 .pd1 = false,
1753 .pd2 = true,
1754 .psl = false,
1755},
1756.{
1757 .name = "preprocess",
1758 .syntax = .flag,
1759 .zig_equivalent = .preprocess,
1760 .pd1 = false,
1761 .pd2 = true,
1762 .psl = false,
1763},
1764.{
1765 .name = "print-diagnostic-categories",
1766 .syntax = .flag,
1767 .zig_equivalent = .other,
1768 .pd1 = false,
1769 .pd2 = true,
1770 .psl = false,
1771},
1772.{
1773 .name = "print-file-name",
1774 .syntax = .separate,
1775 .zig_equivalent = .other,
1776 .pd1 = false,
1777 .pd2 = true,
1778 .psl = false,
1779},
1780.{
1781 .name = "print-missing-file-dependencies",
1782 .syntax = .flag,
1783 .zig_equivalent = .other,
1784 .pd1 = false,
1785 .pd2 = true,
1786 .psl = false,
1787},
1788.{
1789 .name = "print-prog-name",
1790 .syntax = .separate,
1791 .zig_equivalent = .other,
1792 .pd1 = false,
1793 .pd2 = true,
1794 .psl = false,
1795},
1796.{
1797 .name = "profile",
1798 .syntax = .flag,
1799 .zig_equivalent = .other,
1800 .pd1 = false,
1801 .pd2 = true,
1802 .psl = false,
1803},
1804.{
1805 .name = "profile-blocks",
1806 .syntax = .flag,
1807 .zig_equivalent = .other,
1808 .pd1 = false,
1809 .pd2 = true,
1810 .psl = false,
1811},
1812.{
1813 .name = "resource",
1814 .syntax = .separate,
1815 .zig_equivalent = .other,
1816 .pd1 = false,
1817 .pd2 = true,
1818 .psl = false,
1819},
1820.{
1821 .name = "rtlib",
1822 .syntax = .separate,
1823 .zig_equivalent = .other,
1824 .pd1 = false,
1825 .pd2 = true,
1826 .psl = false,
1827},
1828.{
1829 .name = "serialize-diagnostics",
1830 .syntax = .separate,
1831 .zig_equivalent = .other,
1832 .pd1 = true,
1833 .pd2 = true,
1834 .psl = false,
1835},
1836.{
1837 .name = "signed-char",
1838 .syntax = .flag,
1839 .zig_equivalent = .other,
1840 .pd1 = false,
1841 .pd2 = true,
1842 .psl = false,
1843},
1844.{
1845 .name = "std",
1846 .syntax = .separate,
1847 .zig_equivalent = .other,
1848 .pd1 = false,
1849 .pd2 = true,
1850 .psl = false,
1851},
1852.{
1853 .name = "stdlib",
1854 .syntax = .separate,
1855 .zig_equivalent = .other,
1856 .pd1 = false,
1857 .pd2 = true,
1858 .psl = false,
1859},
1860.{
1861 .name = "sysroot",
1862 .syntax = .separate,
1863 .zig_equivalent = .other,
1864 .pd1 = false,
1865 .pd2 = true,
1866 .psl = false,
1867},
1868.{
1869 .name = "target-help",
1870 .syntax = .flag,
1871 .zig_equivalent = .other,
1872 .pd1 = false,
1873 .pd2 = true,
1874 .psl = false,
1875},
1876.{
1877 .name = "trace-includes",
1878 .syntax = .flag,
1879 .zig_equivalent = .other,
1880 .pd1 = false,
1881 .pd2 = true,
1882 .psl = false,
1883},
1884.{
1885 .name = "undefine-macro",
1886 .syntax = .separate,
1887 .zig_equivalent = .other,
1888 .pd1 = false,
1889 .pd2 = true,
1890 .psl = false,
1891},
1892.{
1893 .name = "unsigned-char",
1894 .syntax = .flag,
1895 .zig_equivalent = .other,
1896 .pd1 = false,
1897 .pd2 = true,
1898 .psl = false,
1899},
1900.{
1901 .name = "user-dependencies",
1902 .syntax = .flag,
1903 .zig_equivalent = .other,
1904 .pd1 = false,
1905 .pd2 = true,
1906 .psl = false,
1907},
1908.{
1909 .name = "verbose",
1910 .syntax = .flag,
1911 .zig_equivalent = .other,
1912 .pd1 = false,
1913 .pd2 = true,
1914 .psl = false,
1915},
1916.{
1917 .name = "version",
1918 .syntax = .flag,
1919 .zig_equivalent = .other,
1920 .pd1 = false,
1921 .pd2 = true,
1922 .psl = false,
1923},
1924.{
1925 .name = "write-dependencies",
1926 .syntax = .flag,
1927 .zig_equivalent = .other,
1928 .pd1 = false,
1929 .pd2 = true,
1930 .psl = false,
1931},
1932.{
1933 .name = "write-user-dependencies",
1934 .syntax = .flag,
1935 .zig_equivalent = .other,
1936 .pd1 = false,
1937 .pd2 = true,
1938 .psl = false,
1939},
1940sepd1("add-plugin"),
1941flagpd1("faggressive-function-elimination"),
1942flagpd1("fno-aggressive-function-elimination"),
1943flagpd1("falign-commons"),
1944flagpd1("fno-align-commons"),
1945flagpd1("falign-jumps"),
1946flagpd1("fno-align-jumps"),
1947flagpd1("falign-labels"),
1948flagpd1("fno-align-labels"),
1949flagpd1("falign-loops"),
1950flagpd1("fno-align-loops"),
1951flagpd1("faligned-alloc-unavailable"),
1952flagpd1("all_load"),
1953flagpd1("fall-intrinsics"),
1954flagpd1("fno-all-intrinsics"),
1955sepd1("allowable_client"),
1956flagpd1("cfg-add-implicit-dtors"),
1957flagpd1("unoptimized-cfg"),
1958flagpd1("analyze"),
1959sepd1("analyze-function"),
1960sepd1("analyzer-checker"),
1961flagpd1("analyzer-checker-help"),
1962flagpd1("analyzer-checker-help-alpha"),
1963flagpd1("analyzer-checker-help-developer"),
1964flagpd1("analyzer-checker-option-help"),
1965flagpd1("analyzer-checker-option-help-alpha"),
1966flagpd1("analyzer-checker-option-help-developer"),
1967sepd1("analyzer-config"),
1968sepd1("analyzer-config-compatibility-mode"),
1969flagpd1("analyzer-config-help"),
1970sepd1("analyzer-constraints"),
1971flagpd1("analyzer-disable-all-checks"),
1972sepd1("analyzer-disable-checker"),
1973flagpd1("analyzer-disable-retry-exhausted"),
1974flagpd1("analyzer-display-progress"),
1975sepd1("analyzer-dump-egraph"),
1976sepd1("analyzer-inline-max-stack-depth"),
1977sepd1("analyzer-inlining-mode"),
1978flagpd1("analyzer-list-enabled-checkers"),
1979sepd1("analyzer-max-loop"),
1980flagpd1("analyzer-opt-analyze-headers"),
1981flagpd1("analyzer-opt-analyze-nested-blocks"),
1982sepd1("analyzer-output"),
1983sepd1("analyzer-purge"),
1984flagpd1("analyzer-stats"),
1985sepd1("analyzer-store"),
1986flagpd1("analyzer-viz-egraph-graphviz"),
1987flagpd1("analyzer-werror"),
1988flagpd1("fslp-vectorize-aggressive"),
1989flagpd1("fno-slp-vectorize-aggressive"),
1990flagpd1("fexpensive-optimizations"),
1991flagpd1("fno-expensive-optimizations"),
1992flagpd1("fdefer-pop"),
1993flagpd1("fno-defer-pop"),
1994flagpd1("fextended-identifiers"),
1995flagpd1("fno-extended-identifiers"),
1996flagpd1("fhonor-infinites"),
1997flagpd1("fno-honor-infinites"),
1998flagpd1("findirect-virtual-calls"),
1999sepd1("fnew-alignment"),
2000flagpd1("faligned-new"),
2001flagpd1("fno-aligned-new"),
2002flagpd1("fsched-interblock"),
2003flagpd1("ftree-vectorize"),
2004flagpd1("fno-tree-vectorize"),
2005flagpd1("ftree-slp-vectorize"),
2006flagpd1("fno-tree-slp-vectorize"),
2007flagpd1("fterminated-vtables"),
2008flagpd1("grecord-gcc-switches"),
2009flagpd1("gno-record-gcc-switches"),
2010flagpd1("fident"),
2011flagpd1("nocudalib"),
2012.{
2013 .name = "system-header-prefix",
2014 .syntax = .separate,
2015 .zig_equivalent = .other,
2016 .pd1 = false,
2017 .pd2 = true,
2018 .psl = false,
2019},
2020.{
2021 .name = "no-system-header-prefix",
2022 .syntax = .separate,
2023 .zig_equivalent = .other,
2024 .pd1 = false,
2025 .pd2 = true,
2026 .psl = false,
2027},
2028flagpd1("integrated-as"),
2029flagpd1("no-integrated-as"),
2030flagpd1("fkeep-inline-functions"),
2031flagpd1("fno-keep-inline-functions"),
2032flagpd1("fno-semantic-interposition"),
2033.{
2034 .name = "Gs",
2035 .syntax = .flag,
2036 .zig_equivalent = .other,
2037 .pd1 = true,
2038 .pd2 = false,
2039 .psl = true,
2040},
2041.{
2042 .name = "O1",
2043 .syntax = .flag,
2044 .zig_equivalent = .optimize,
2045 .pd1 = true,
2046 .pd2 = false,
2047 .psl = true,
2048},
2049.{
2050 .name = "O2",
2051 .syntax = .flag,
2052 .zig_equivalent = .optimize,
2053 .pd1 = true,
2054 .pd2 = false,
2055 .psl = true,
2056},
2057flagpd1("fno-ident"),
2058.{
2059 .name = "Ob0",
2060 .syntax = .flag,
2061 .zig_equivalent = .other,
2062 .pd1 = true,
2063 .pd2 = false,
2064 .psl = true,
2065},
2066.{
2067 .name = "Ob1",
2068 .syntax = .flag,
2069 .zig_equivalent = .other,
2070 .pd1 = true,
2071 .pd2 = false,
2072 .psl = true,
2073},
2074.{
2075 .name = "Ob2",
2076 .syntax = .flag,
2077 .zig_equivalent = .other,
2078 .pd1 = true,
2079 .pd2 = false,
2080 .psl = true,
2081},
2082.{
2083 .name = "Od",
2084 .syntax = .flag,
2085 .zig_equivalent = .other,
2086 .pd1 = true,
2087 .pd2 = false,
2088 .psl = true,
2089},
2090.{
2091 .name = "Og",
2092 .syntax = .flag,
2093 .zig_equivalent = .optimize,
2094 .pd1 = true,
2095 .pd2 = false,
2096 .psl = true,
2097},
2098.{
2099 .name = "Oi",
2100 .syntax = .flag,
2101 .zig_equivalent = .other,
2102 .pd1 = true,
2103 .pd2 = false,
2104 .psl = true,
2105},
2106.{
2107 .name = "Oi-",
2108 .syntax = .flag,
2109 .zig_equivalent = .other,
2110 .pd1 = true,
2111 .pd2 = false,
2112 .psl = true,
2113},
2114.{
2115 .name = "Os",
2116 .syntax = .flag,
2117 .zig_equivalent = .other,
2118 .pd1 = true,
2119 .pd2 = false,
2120 .psl = true,
2121},
2122.{
2123 .name = "Ot",
2124 .syntax = .flag,
2125 .zig_equivalent = .other,
2126 .pd1 = true,
2127 .pd2 = false,
2128 .psl = true,
2129},
2130.{
2131 .name = "Ox",
2132 .syntax = .flag,
2133 .zig_equivalent = .other,
2134 .pd1 = true,
2135 .pd2 = false,
2136 .psl = true,
2137},
2138flagpd1("fcuda-rdc"),
2139.{
2140 .name = "Oy",
2141 .syntax = .flag,
2142 .zig_equivalent = .other,
2143 .pd1 = true,
2144 .pd2 = false,
2145 .psl = true,
2146},
2147.{
2148 .name = "Oy-",
2149 .syntax = .flag,
2150 .zig_equivalent = .other,
2151 .pd1 = true,
2152 .pd2 = false,
2153 .psl = true,
2154},
2155flagpd1("fno-cuda-rdc"),
2156flagpd1("shared-libasan"),
2157flagpd1("frecord-gcc-switches"),
2158flagpd1("fno-record-gcc-switches"),
2159.{
2160 .name = "ansi",
2161 .syntax = .flag,
2162 .zig_equivalent = .other,
2163 .pd1 = true,
2164 .pd2 = true,
2165 .psl = false,
2166},
2167sepd1("arch"),
2168flagpd1("arch_errors_fatal"),
2169sepd1("arch_only"),
2170flagpd1("arcmt-check"),
2171flagpd1("arcmt-migrate"),
2172flagpd1("arcmt-migrate-emit-errors"),
2173sepd1("arcmt-migrate-report-output"),
2174flagpd1("arcmt-modify"),
2175flagpd1("ast-dump"),
2176flagpd1("ast-dump-all"),
2177sepd1("ast-dump-filter"),
2178flagpd1("ast-dump-lookups"),
2179flagpd1("ast-list"),
2180sepd1("ast-merge"),
2181flagpd1("ast-print"),
2182flagpd1("ast-view"),
2183flagpd1("fautomatic"),
2184flagpd1("fno-automatic"),
2185sepd1("aux-triple"),
2186flagpd1("fbackslash"),
2187flagpd1("fno-backslash"),
2188flagpd1("fbacktrace"),
2189flagpd1("fno-backtrace"),
2190flagpd1("bind_at_load"),
2191flagpd1("fbounds-check"),
2192flagpd1("fno-bounds-check"),
2193flagpd1("fbranch-count-reg"),
2194flagpd1("fno-branch-count-reg"),
2195flagpd1("building-pch-with-obj"),
2196flagpd1("bundle"),
2197sepd1("bundle_loader"),
2198.{
2199 .name = "c",
2200 .syntax = .flag,
2201 .zig_equivalent = .c,
2202 .pd1 = true,
2203 .pd2 = false,
2204 .psl = false,
2205},
2206flagpd1("fcaller-saves"),
2207flagpd1("fno-caller-saves"),
2208flagpd1("cc1"),
2209flagpd1("cc1as"),
2210flagpd1("ccc-arcmt-check"),
2211sepd1("ccc-arcmt-migrate"),
2212flagpd1("ccc-arcmt-modify"),
2213sepd1("ccc-gcc-name"),
2214sepd1("ccc-install-dir"),
2215sepd1("ccc-objcmt-migrate"),
2216flagpd1("ccc-print-bindings"),
2217flagpd1("ccc-print-phases"),
2218flagpd1("cfguard"),
2219flagpd1("cfguard-no-checks"),
2220sepd1("chain-include"),
2221flagpd1("fcheck-array-temporaries"),
2222flagpd1("fno-check-array-temporaries"),
2223flagpd1("cl-denorms-are-zero"),
2224flagpd1("cl-fast-relaxed-math"),
2225flagpd1("cl-finite-math-only"),
2226flagpd1("cl-fp32-correctly-rounded-divide-sqrt"),
2227flagpd1("cl-kernel-arg-info"),
2228flagpd1("cl-mad-enable"),
2229flagpd1("cl-no-signed-zeros"),
2230flagpd1("cl-opt-disable"),
2231flagpd1("cl-single-precision-constant"),
2232flagpd1("cl-strict-aliasing"),
2233flagpd1("cl-uniform-work-group-size"),
2234flagpd1("cl-unsafe-math-optimizations"),
2235sepd1("code-completion-at"),
2236flagpd1("code-completion-brief-comments"),
2237flagpd1("code-completion-macros"),
2238flagpd1("code-completion-patterns"),
2239flagpd1("code-completion-with-fixits"),
2240.{
2241 .name = "combine",
2242 .syntax = .flag,
2243 .zig_equivalent = .other,
2244 .pd1 = true,
2245 .pd2 = true,
2246 .psl = false,
2247},
2248flagpd1("compiler-options-dump"),
2249.{
2250 .name = "compress-debug-sections",
2251 .syntax = .flag,
2252 .zig_equivalent = .other,
2253 .pd1 = true,
2254 .pd2 = true,
2255 .psl = false,
2256},
2257.{
2258 .name = "config",
2259 .syntax = .separate,
2260 .zig_equivalent = .other,
2261 .pd1 = false,
2262 .pd2 = true,
2263 .psl = false,
2264},
2265.{
2266 .name = "coverage",
2267 .syntax = .flag,
2268 .zig_equivalent = .other,
2269 .pd1 = true,
2270 .pd2 = true,
2271 .psl = false,
2272},
2273flagpd1("coverage-cfg-checksum"),
2274sepd1("coverage-data-file"),
2275flagpd1("coverage-exit-block-before-body"),
2276flagpd1("coverage-no-function-names-in-data"),
2277sepd1("coverage-notes-file"),
2278flagpd1("cpp"),
2279flagpd1("cpp-precomp"),
2280flagpd1("fcray-pointer"),
2281flagpd1("fno-cray-pointer"),
2282.{
2283 .name = "cuda-compile-host-device",
2284 .syntax = .flag,
2285 .zig_equivalent = .other,
2286 .pd1 = false,
2287 .pd2 = true,
2288 .psl = false,
2289},
2290.{
2291 .name = "cuda-device-only",
2292 .syntax = .flag,
2293 .zig_equivalent = .other,
2294 .pd1 = false,
2295 .pd2 = true,
2296 .psl = false,
2297},
2298.{
2299 .name = "cuda-host-only",
2300 .syntax = .flag,
2301 .zig_equivalent = .other,
2302 .pd1 = false,
2303 .pd2 = true,
2304 .psl = false,
2305},
2306.{
2307 .name = "cuda-noopt-device-debug",
2308 .syntax = .flag,
2309 .zig_equivalent = .other,
2310 .pd1 = false,
2311 .pd2 = true,
2312 .psl = false,
2313},
2314.{
2315 .name = "cuda-path-ignore-env",
2316 .syntax = .flag,
2317 .zig_equivalent = .other,
2318 .pd1 = false,
2319 .pd2 = true,
2320 .psl = false,
2321},
2322flagpd1("dA"),
2323flagpd1("dD"),
2324flagpd1("dI"),
2325flagpd1("dM"),
2326flagpd1("d"),
2327flagpd1("fd-lines-as-code"),
2328flagpd1("fno-d-lines-as-code"),
2329flagpd1("fd-lines-as-comments"),
2330flagpd1("fno-d-lines-as-comments"),
2331flagpd1("dead_strip"),
2332flagpd1("debug-forward-template-params"),
2333flagpd1("debug-info-macro"),
2334flagpd1("fdefault-double-8"),
2335flagpd1("fno-default-double-8"),
2336sepd1("default-function-attr"),
2337flagpd1("fdefault-inline"),
2338flagpd1("fno-default-inline"),
2339flagpd1("fdefault-integer-8"),
2340flagpd1("fno-default-integer-8"),
2341flagpd1("fdefault-real-8"),
2342flagpd1("fno-default-real-8"),
2343sepd1("defsym"),
2344sepd1("dependency-dot"),
2345sepd1("dependency-file"),
2346flagpd1("detailed-preprocessing-record"),
2347flagpd1("fdevirtualize"),
2348flagpd1("fno-devirtualize"),
2349flagpd1("fdevirtualize-speculatively"),
2350flagpd1("fno-devirtualize-speculatively"),
2351sepd1("diagnostic-log-file"),
2352sepd1("serialize-diagnostic-file"),
2353flagpd1("disable-O0-optnone"),
2354flagpd1("disable-free"),
2355flagpd1("disable-lifetime-markers"),
2356flagpd1("disable-llvm-optzns"),
2357flagpd1("disable-llvm-passes"),
2358flagpd1("disable-llvm-verifier"),
2359flagpd1("disable-objc-default-synthesize-properties"),
2360flagpd1("disable-pragma-debug-crash"),
2361flagpd1("disable-red-zone"),
2362flagpd1("discard-value-names"),
2363flagpd1("fdollar-ok"),
2364flagpd1("fno-dollar-ok"),
2365flagpd1("dump-coverage-mapping"),
2366flagpd1("dump-deserialized-decls"),
2367flagpd1("fdump-fortran-optimized"),
2368flagpd1("fno-dump-fortran-optimized"),
2369flagpd1("fdump-fortran-original"),
2370flagpd1("fno-dump-fortran-original"),
2371flagpd1("fdump-parse-tree"),
2372flagpd1("fno-dump-parse-tree"),
2373flagpd1("dump-raw-tokens"),
2374flagpd1("dump-tokens"),
2375flagpd1("dumpmachine"),
2376flagpd1("dumpspecs"),
2377flagpd1("dumpversion"),
2378flagpd1("dwarf-column-info"),
2379sepd1("dwarf-debug-flags"),
2380sepd1("dwarf-debug-producer"),
2381flagpd1("dwarf-explicit-import"),
2382flagpd1("dwarf-ext-refs"),
2383sepd1("dylib_file"),
2384flagpd1("dylinker"),
2385flagpd1("dynamic"),
2386flagpd1("dynamiclib"),
2387flagpd1("feliminate-unused-debug-types"),
2388flagpd1("fno-eliminate-unused-debug-types"),
2389flagpd1("emit-ast"),
2390flagpd1("emit-codegen-only"),
2391flagpd1("emit-header-module"),
2392flagpd1("emit-html"),
2393flagpd1("emit-interface-stubs"),
2394flagpd1("emit-llvm"),
2395flagpd1("emit-llvm-bc"),
2396flagpd1("emit-llvm-only"),
2397flagpd1("emit-llvm-uselists"),
2398flagpd1("emit-merged-ifs"),
2399flagpd1("emit-module"),
2400flagpd1("emit-module-interface"),
2401flagpd1("emit-obj"),
2402flagpd1("emit-pch"),
2403flagpd1("enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang"),
2404sepd1("error-on-deserialized-decl"),
2405sepd1("exported_symbols_list"),
2406flagpd1("fexternal-blas"),
2407flagpd1("fno-external-blas"),
2408flagpd1("ff2c"),
2409flagpd1("fno-f2c"),
2410.{
2411 .name = "fPIC",
2412 .syntax = .flag,
2413 .zig_equivalent = .pic,
2414 .pd1 = true,
2415 .pd2 = false,
2416 .psl = false,
2417},
2418flagpd1("fPIE"),
2419flagpd1("faccess-control"),
2420flagpd1("faddrsig"),
2421flagpd1("falign-functions"),
2422flagpd1("faligned-allocation"),
2423flagpd1("fallow-editor-placeholders"),
2424flagpd1("fallow-half-arguments-and-returns"),
2425flagpd1("fallow-pch-with-compiler-errors"),
2426flagpd1("fallow-unsupported"),
2427flagpd1("faltivec"),
2428flagpd1("fansi-escape-codes"),
2429flagpd1("fapple-kext"),
2430flagpd1("fapple-link-rtlib"),
2431flagpd1("fapple-pragma-pack"),
2432flagpd1("fapplication-extension"),
2433flagpd1("fapply-global-visibility-to-externs"),
2434flagpd1("fasm"),
2435flagpd1("fasm-blocks"),
2436flagpd1("fassociative-math"),
2437flagpd1("fassume-sane-operator-new"),
2438flagpd1("fast"),
2439flagpd1("fastcp"),
2440flagpd1("fastf"),
2441flagpd1("fasynchronous-unwind-tables"),
2442flagpd1("ffat-lto-objects"),
2443flagpd1("fno-fat-lto-objects"),
2444flagpd1("fauto-profile"),
2445flagpd1("fauto-profile-accurate"),
2446flagpd1("fautolink"),
2447flagpd1("fblocks"),
2448flagpd1("fblocks-runtime-optional"),
2449flagpd1("fborland-extensions"),
2450sepd1("fbracket-depth"),
2451flagpd1("fbuiltin"),
2452flagpd1("fbuiltin-module-map"),
2453flagpd1("fcall-saved-x10"),
2454flagpd1("fcall-saved-x11"),
2455flagpd1("fcall-saved-x12"),
2456flagpd1("fcall-saved-x13"),
2457flagpd1("fcall-saved-x14"),
2458flagpd1("fcall-saved-x15"),
2459flagpd1("fcall-saved-x18"),
2460flagpd1("fcall-saved-x8"),
2461flagpd1("fcall-saved-x9"),
2462flagpd1("fcaret-diagnostics"),
2463sepd1("fcaret-diagnostics-max-lines"),
2464flagpd1("fcf-protection"),
2465flagpd1("fchar8_t"),
2466flagpd1("fcheck-new"),
2467flagpd1("fno-check-new"),
2468flagpd1("fcolor-diagnostics"),
2469flagpd1("fcommon"),
2470flagpd1("fcomplete-member-pointers"),
2471flagpd1("fconcepts-ts"),
2472flagpd1("fconst-strings"),
2473flagpd1("fconstant-cfstrings"),
2474sepd1("fconstant-string-class"),
2475sepd1("fconstexpr-backtrace-limit"),
2476sepd1("fconstexpr-depth"),
2477sepd1("fconstexpr-steps"),
2478flagpd1("fconvergent-functions"),
2479flagpd1("fcoroutines-ts"),
2480flagpd1("fcoverage-mapping"),
2481flagpd1("fcreate-profile"),
2482flagpd1("fcs-profile-generate"),
2483flagpd1("fcuda-allow-variadic-functions"),
2484flagpd1("fcuda-approx-transcendentals"),
2485flagpd1("fcuda-flush-denormals-to-zero"),
2486sepd1("fcuda-include-gpubinary"),
2487flagpd1("fcuda-is-device"),
2488flagpd1("fcuda-short-ptr"),
2489flagpd1("fcxx-exceptions"),
2490flagpd1("fcxx-modules"),
2491flagpd1("fc++-static-destructors"),
2492flagpd1("fdata-sections"),
2493sepd1("fdebug-compilation-dir"),
2494flagpd1("fdebug-info-for-profiling"),
2495flagpd1("fdebug-macro"),
2496flagpd1("fdebug-pass-arguments"),
2497flagpd1("fdebug-pass-manager"),
2498flagpd1("fdebug-pass-structure"),
2499flagpd1("fdebug-ranges-base-address"),
2500flagpd1("fdebug-types-section"),
2501flagpd1("fdebugger-cast-result-to-id"),
2502flagpd1("fdebugger-objc-literal"),
2503flagpd1("fdebugger-support"),
2504flagpd1("fdeclare-opencl-builtins"),
2505flagpd1("fdeclspec"),
2506flagpd1("fdelayed-template-parsing"),
2507flagpd1("fdelete-null-pointer-checks"),
2508flagpd1("fdeprecated-macro"),
2509flagpd1("fdiagnostics-absolute-paths"),
2510flagpd1("fdiagnostics-color"),
2511flagpd1("fdiagnostics-fixit-info"),
2512sepd1("fdiagnostics-format"),
2513flagpd1("fdiagnostics-parseable-fixits"),
2514flagpd1("fdiagnostics-print-source-range-info"),
2515sepd1("fdiagnostics-show-category"),
2516flagpd1("fdiagnostics-show-hotness"),
2517flagpd1("fdiagnostics-show-note-include-stack"),
2518flagpd1("fdiagnostics-show-option"),
2519flagpd1("fdiagnostics-show-template-tree"),
2520flagpd1("fdigraphs"),
2521flagpd1("fdisable-module-hash"),
2522flagpd1("fdiscard-value-names"),
2523flagpd1("fdollars-in-identifiers"),
2524flagpd1("fdouble-square-bracket-attributes"),
2525flagpd1("fdump-record-layouts"),
2526flagpd1("fdump-record-layouts-simple"),
2527flagpd1("fdump-vtable-layouts"),
2528flagpd1("fdwarf2-cfi-asm"),
2529flagpd1("fdwarf-directory-asm"),
2530flagpd1("fdwarf-exceptions"),
2531flagpd1("felide-constructors"),
2532flagpd1("feliminate-unused-debug-symbols"),
2533flagpd1("fembed-bitcode"),
2534flagpd1("fembed-bitcode-marker"),
2535flagpd1("femit-all-decls"),
2536flagpd1("femit-coverage-data"),
2537flagpd1("femit-coverage-notes"),
2538flagpd1("femit-debug-entry-values"),
2539flagpd1("femulated-tls"),
2540flagpd1("fencode-extended-block-signature"),
2541sepd1("ferror-limit"),
2542flagpd1("fescaping-block-tail-calls"),
2543flagpd1("fexceptions"),
2544flagpd1("fexperimental-isel"),
2545flagpd1("fexperimental-new-constant-interpreter"),
2546flagpd1("fexperimental-new-pass-manager"),
2547flagpd1("fexternc-nounwind"),
2548flagpd1("ffake-address-space-map"),
2549flagpd1("ffast-math"),
2550flagpd1("ffine-grained-bitfield-accesses"),
2551flagpd1("ffinite-math-only"),
2552flagpd1("ffixed-point"),
2553flagpd1("ffixed-r19"),
2554flagpd1("ffixed-r9"),
2555flagpd1("ffixed-x1"),
2556flagpd1("ffixed-x10"),
2557flagpd1("ffixed-x11"),
2558flagpd1("ffixed-x12"),
2559flagpd1("ffixed-x13"),
2560flagpd1("ffixed-x14"),
2561flagpd1("ffixed-x15"),
2562flagpd1("ffixed-x16"),
2563flagpd1("ffixed-x17"),
2564flagpd1("ffixed-x18"),
2565flagpd1("ffixed-x19"),
2566flagpd1("ffixed-x2"),
2567flagpd1("ffixed-x20"),
2568flagpd1("ffixed-x21"),
2569flagpd1("ffixed-x22"),
2570flagpd1("ffixed-x23"),
2571flagpd1("ffixed-x24"),
2572flagpd1("ffixed-x25"),
2573flagpd1("ffixed-x26"),
2574flagpd1("ffixed-x27"),
2575flagpd1("ffixed-x28"),
2576flagpd1("ffixed-x29"),
2577flagpd1("ffixed-x3"),
2578flagpd1("ffixed-x30"),
2579flagpd1("ffixed-x31"),
2580flagpd1("ffixed-x4"),
2581flagpd1("ffixed-x5"),
2582flagpd1("ffixed-x6"),
2583flagpd1("ffixed-x7"),
2584flagpd1("ffixed-x8"),
2585flagpd1("ffixed-x9"),
2586flagpd1("ffor-scope"),
2587flagpd1("fforbid-guard-variables"),
2588flagpd1("fforce-dwarf-frame"),
2589flagpd1("fforce-emit-vtables"),
2590flagpd1("fforce-enable-int128"),
2591flagpd1("ffreestanding"),
2592flagpd1("ffunction-sections"),
2593flagpd1("fgnu89-inline"),
2594flagpd1("fgnu-inline-asm"),
2595flagpd1("fgnu-keywords"),
2596flagpd1("fgnu-runtime"),
2597flagpd1("fgpu-allow-device-init"),
2598flagpd1("fgpu-rdc"),
2599flagpd1("fheinous-gnu-extensions"),
2600flagpd1("fhip-dump-offload-linker-script"),
2601flagpd1("fhip-new-launch-api"),
2602flagpd1("fhonor-infinities"),
2603flagpd1("fhonor-nans"),
2604flagpd1("fhosted"),
2605sepd1("filelist"),
2606sepd1("filetype"),
2607flagpd1("fimplicit-module-maps"),
2608flagpd1("fimplicit-modules"),
2609flagpd1("finclude-default-header"),
2610flagpd1("finline"),
2611flagpd1("finline-functions"),
2612flagpd1("finline-hint-functions"),
2613flagpd1("finline-limit"),
2614flagpd1("fno-inline-limit"),
2615flagpd1("finstrument-function-entry-bare"),
2616flagpd1("finstrument-functions"),
2617flagpd1("finstrument-functions-after-inlining"),
2618flagpd1("fintegrated-as"),
2619flagpd1("fintegrated-cc1"),
2620flagpd1("fix-only-warnings"),
2621flagpd1("fix-what-you-can"),
2622flagpd1("ffixed-form"),
2623flagpd1("fno-fixed-form"),
2624flagpd1("fixit"),
2625flagpd1("fixit-recompile"),
2626flagpd1("fixit-to-temporary"),
2627flagpd1("fjump-tables"),
2628flagpd1("fkeep-static-consts"),
2629flagpd1("flat_namespace"),
2630flagpd1("flax-vector-conversions"),
2631flagpd1("flimit-debug-info"),
2632flagpd1("ffloat-store"),
2633flagpd1("fno-float-store"),
2634flagpd1("flto"),
2635flagpd1("flto-unit"),
2636flagpd1("flto-visibility-public-std"),
2637sepd1("fmacro-backtrace-limit"),
2638flagpd1("fmath-errno"),
2639flagpd1("fmerge-all-constants"),
2640flagpd1("fmerge-functions"),
2641sepd1("fmessage-length"),
2642sepd1("fmodule-feature"),
2643flagpd1("fmodule-file-deps"),
2644sepd1("fmodule-implementation-of"),
2645flagpd1("fmodule-map-file-home-is-cwd"),
2646flagpd1("fmodule-maps"),
2647sepd1("fmodule-name"),
2648flagpd1("fmodules"),
2649flagpd1("fmodules-codegen"),
2650flagpd1("fmodules-debuginfo"),
2651flagpd1("fmodules-decluse"),
2652flagpd1("fmodules-disable-diagnostic-validation"),
2653flagpd1("fmodules-hash-content"),
2654flagpd1("fmodules-local-submodule-visibility"),
2655flagpd1("fmodules-search-all"),
2656flagpd1("fmodules-strict-context-hash"),
2657flagpd1("fmodules-strict-decluse"),
2658flagpd1("fmodules-ts"),
2659sepd1("fmodules-user-build-path"),
2660flagpd1("fmodules-validate-input-files-content"),
2661flagpd1("fmodules-validate-once-per-build-session"),
2662flagpd1("fmodules-validate-system-headers"),
2663flagpd1("fms-compatibility"),
2664flagpd1("fms-extensions"),
2665flagpd1("fms-volatile"),
2666flagpd1("fmudflap"),
2667flagpd1("fmudflapth"),
2668flagpd1("fnative-half-arguments-and-returns"),
2669flagpd1("fnative-half-type"),
2670flagpd1("fnested-functions"),
2671flagpd1("fnext-runtime"),
2672.{
2673 .name = "fno-PIC",
2674 .syntax = .flag,
2675 .zig_equivalent = .no_pic,
2676 .pd1 = true,
2677 .pd2 = false,
2678 .psl = false,
2679},
2680flagpd1("fno-PIE"),
2681flagpd1("fno-access-control"),
2682flagpd1("fno-addrsig"),
2683flagpd1("fno-align-functions"),
2684flagpd1("fno-aligned-allocation"),
2685flagpd1("fno-allow-editor-placeholders"),
2686flagpd1("fno-altivec"),
2687flagpd1("fno-apple-pragma-pack"),
2688flagpd1("fno-application-extension"),
2689flagpd1("fno-asm"),
2690flagpd1("fno-asm-blocks"),
2691flagpd1("fno-associative-math"),
2692flagpd1("fno-assume-sane-operator-new"),
2693flagpd1("fno-asynchronous-unwind-tables"),
2694flagpd1("fno-auto-profile"),
2695flagpd1("fno-auto-profile-accurate"),
2696flagpd1("fno-autolink"),
2697flagpd1("fno-bitfield-type-align"),
2698flagpd1("fno-blocks"),
2699flagpd1("fno-borland-extensions"),
2700flagpd1("fno-builtin"),
2701flagpd1("fno-caret-diagnostics"),
2702flagpd1("fno-char8_t"),
2703flagpd1("fno-color-diagnostics"),
2704flagpd1("fno-common"),
2705flagpd1("fno-complete-member-pointers"),
2706flagpd1("fno-concept-satisfaction-caching"),
2707flagpd1("fno-const-strings"),
2708flagpd1("fno-constant-cfstrings"),
2709flagpd1("fno-coroutines-ts"),
2710flagpd1("fno-coverage-mapping"),
2711flagpd1("fno-crash-diagnostics"),
2712flagpd1("fno-cuda-approx-transcendentals"),
2713flagpd1("fno-cuda-flush-denormals-to-zero"),
2714flagpd1("fno-cuda-host-device-constexpr"),
2715flagpd1("fno-cuda-short-ptr"),
2716flagpd1("fno-cxx-exceptions"),
2717flagpd1("fno-cxx-modules"),
2718flagpd1("fno-c++-static-destructors"),
2719flagpd1("fno-data-sections"),
2720flagpd1("fno-debug-info-for-profiling"),
2721flagpd1("fno-debug-macro"),
2722flagpd1("fno-debug-pass-manager"),
2723flagpd1("fno-debug-ranges-base-address"),
2724flagpd1("fno-debug-types-section"),
2725flagpd1("fno-declspec"),
2726flagpd1("fno-delayed-template-parsing"),
2727flagpd1("fno-delete-null-pointer-checks"),
2728flagpd1("fno-deprecated-macro"),
2729flagpd1("fno-diagnostics-color"),
2730flagpd1("fno-diagnostics-fixit-info"),
2731flagpd1("fno-diagnostics-show-hotness"),
2732flagpd1("fno-diagnostics-show-note-include-stack"),
2733flagpd1("fno-diagnostics-show-option"),
2734flagpd1("fno-diagnostics-use-presumed-location"),
2735flagpd1("fno-digraphs"),
2736flagpd1("fno-discard-value-names"),
2737flagpd1("fno-dllexport-inlines"),
2738flagpd1("fno-dollars-in-identifiers"),
2739flagpd1("fno-double-square-bracket-attributes"),
2740flagpd1("fno-dwarf2-cfi-asm"),
2741flagpd1("fno-dwarf-directory-asm"),
2742flagpd1("fno-elide-constructors"),
2743flagpd1("fno-elide-type"),
2744flagpd1("fno-eliminate-unused-debug-symbols"),
2745flagpd1("fno-emulated-tls"),
2746flagpd1("fno-escaping-block-tail-calls"),
2747flagpd1("fno-exceptions"),
2748flagpd1("fno-experimental-isel"),
2749flagpd1("fno-experimental-new-pass-manager"),
2750flagpd1("fno-fast-math"),
2751flagpd1("fno-fine-grained-bitfield-accesses"),
2752flagpd1("fno-finite-math-only"),
2753flagpd1("fno-fixed-point"),
2754flagpd1("fno-for-scope"),
2755flagpd1("fno-force-dwarf-frame"),
2756flagpd1("fno-force-emit-vtables"),
2757flagpd1("fno-force-enable-int128"),
2758flagpd1("fno-function-sections"),
2759flagpd1("fno-gnu89-inline"),
2760flagpd1("fno-gnu-inline-asm"),
2761flagpd1("fno-gnu-keywords"),
2762flagpd1("fno-gpu-allow-device-init"),
2763flagpd1("fno-gpu-rdc"),
2764flagpd1("fno-hip-new-launch-api"),
2765flagpd1("fno-honor-infinities"),
2766flagpd1("fno-honor-nans"),
2767flagpd1("fno-implicit-module-maps"),
2768flagpd1("fno-implicit-modules"),
2769flagpd1("fno-inline"),
2770flagpd1("fno-inline-functions"),
2771flagpd1("fno-integrated-as"),
2772flagpd1("fno-integrated-cc1"),
2773flagpd1("fno-jump-tables"),
2774flagpd1("fno-lax-vector-conversions"),
2775flagpd1("fno-limit-debug-info"),
2776flagpd1("fno-lto"),
2777flagpd1("fno-lto-unit"),
2778flagpd1("fno-math-builtin"),
2779flagpd1("fno-math-errno"),
2780flagpd1("fno-max-type-align"),
2781flagpd1("fno-merge-all-constants"),
2782flagpd1("fno-module-file-deps"),
2783flagpd1("fno-module-maps"),
2784flagpd1("fno-modules"),
2785flagpd1("fno-modules-decluse"),
2786flagpd1("fno-modules-error-recovery"),
2787flagpd1("fno-modules-global-index"),
2788flagpd1("fno-modules-search-all"),
2789flagpd1("fno-strict-modules-decluse"),
2790flagpd1("fno_modules-validate-input-files-content"),
2791flagpd1("fno-modules-validate-system-headers"),
2792flagpd1("fno-ms-compatibility"),
2793flagpd1("fno-ms-extensions"),
2794flagpd1("fno-objc-arc"),
2795flagpd1("fno-objc-arc-exceptions"),
2796flagpd1("fno-objc-convert-messages-to-runtime-calls"),
2797flagpd1("fno-objc-exceptions"),
2798flagpd1("fno-objc-infer-related-result-type"),
2799flagpd1("fno-objc-legacy-dispatch"),
2800flagpd1("fno-objc-nonfragile-abi"),
2801flagpd1("fno-objc-weak"),
2802flagpd1("fno-omit-frame-pointer"),
2803flagpd1("fno-openmp"),
2804flagpd1("fno-openmp-cuda-force-full-runtime"),
2805flagpd1("fno-openmp-cuda-mode"),
2806flagpd1("fno-openmp-optimistic-collapse"),
2807flagpd1("fno-openmp-simd"),
2808flagpd1("fno-operator-names"),
2809flagpd1("fno-optimize-sibling-calls"),
2810flagpd1("fno-pack-struct"),
2811flagpd1("fno-padding-on-unsigned-fixed-point"),
2812flagpd1("fno-pascal-strings"),
2813flagpd1("fno-pch-timestamp"),
2814flagpd1("fno_pch-validate-input-files-content"),
2815flagpd1("fno-pic"),
2816flagpd1("fno-pie"),
2817flagpd1("fno-plt"),
2818flagpd1("fno-preserve-as-comments"),
2819flagpd1("fno-profile-arcs"),
2820flagpd1("fno-profile-generate"),
2821flagpd1("fno-profile-instr-generate"),
2822flagpd1("fno-profile-instr-use"),
2823flagpd1("fno-profile-sample-accurate"),
2824flagpd1("fno-profile-sample-use"),
2825flagpd1("fno-profile-use"),
2826flagpd1("fno-reciprocal-math"),
2827flagpd1("fno-record-command-line"),
2828flagpd1("fno-register-global-dtors-with-atexit"),
2829flagpd1("fno-relaxed-template-template-args"),
2830flagpd1("fno-reroll-loops"),
2831flagpd1("fno-rewrite-imports"),
2832flagpd1("fno-rewrite-includes"),
2833flagpd1("fno-ropi"),
2834flagpd1("fno-rounding-math"),
2835flagpd1("fno-rtlib-add-rpath"),
2836flagpd1("fno-rtti"),
2837flagpd1("fno-rtti-data"),
2838flagpd1("fno-rwpi"),
2839flagpd1("fno-sanitize-address-poison-custom-array-cookie"),
2840flagpd1("fno-sanitize-address-use-after-scope"),
2841flagpd1("fno-sanitize-address-use-odr-indicator"),
2842flagpd1("fno-sanitize-blacklist"),
2843flagpd1("fno-sanitize-cfi-canonical-jump-tables"),
2844flagpd1("fno-sanitize-cfi-cross-dso"),
2845flagpd1("fno-sanitize-link-c++-runtime"),
2846flagpd1("fno-sanitize-link-runtime"),
2847flagpd1("fno-sanitize-memory-track-origins"),
2848flagpd1("fno-sanitize-memory-use-after-dtor"),
2849flagpd1("fno-sanitize-minimal-runtime"),
2850flagpd1("fno-sanitize-recover"),
2851flagpd1("fno-sanitize-stats"),
2852flagpd1("fno-sanitize-thread-atomics"),
2853flagpd1("fno-sanitize-thread-func-entry-exit"),
2854flagpd1("fno-sanitize-thread-memory-access"),
2855flagpd1("fno-sanitize-undefined-trap-on-error"),
2856flagpd1("fno-save-optimization-record"),
2857flagpd1("fno-short-enums"),
2858flagpd1("fno-short-wchar"),
2859flagpd1("fno-show-column"),
2860flagpd1("fno-show-source-location"),
2861flagpd1("fno-signaling-math"),
2862flagpd1("fno-signed-char"),
2863flagpd1("fno-signed-wchar"),
2864flagpd1("fno-signed-zeros"),
2865flagpd1("fno-sized-deallocation"),
2866flagpd1("fno-slp-vectorize"),
2867flagpd1("fno-spell-checking"),
2868flagpd1("fno-split-dwarf-inlining"),
2869flagpd1("fno-split-lto-unit"),
2870flagpd1("fno-stack-protector"),
2871flagpd1("fno-stack-size-section"),
2872flagpd1("fno-standalone-debug"),
2873flagpd1("fno-strict-aliasing"),
2874flagpd1("fno-strict-enums"),
2875flagpd1("fno-strict-float-cast-overflow"),
2876flagpd1("fno-strict-overflow"),
2877flagpd1("fno-strict-return"),
2878flagpd1("fno-strict-vtable-pointers"),
2879flagpd1("fno-struct-path-tbaa"),
2880flagpd1("fno-temp-file"),
2881flagpd1("fno-threadsafe-statics"),
2882flagpd1("fno-trapping-math"),
2883flagpd1("fno-trigraphs"),
2884flagpd1("fno-unique-section-names"),
2885flagpd1("fno-unit-at-a-time"),
2886flagpd1("fno-unroll-loops"),
2887flagpd1("fno-unsafe-math-optimizations"),
2888flagpd1("fno-unsigned-char"),
2889flagpd1("fno-unwind-tables"),
2890flagpd1("fno-use-cxa-atexit"),
2891flagpd1("fno-use-init-array"),
2892flagpd1("fno-use-line-directives"),
2893flagpd1("fno-validate-pch"),
2894flagpd1("fno-var-tracking"),
2895flagpd1("fno-vectorize"),
2896flagpd1("fno-verbose-asm"),
2897flagpd1("fno-virtual-function_elimination"),
2898flagpd1("fno-wchar"),
2899flagpd1("fno-whole-program-vtables"),
2900flagpd1("fno-working-directory"),
2901flagpd1("fno-wrapv"),
2902flagpd1("fno-zero-initialized-in-bss"),
2903flagpd1("fno-zvector"),
2904flagpd1("fnoopenmp-relocatable-target"),
2905flagpd1("fnoopenmp-use-tls"),
2906flagpd1("fno-xray-always-emit-customevents"),
2907flagpd1("fno-xray-always-emit-typedevents"),
2908flagpd1("fno-xray-instrument"),
2909flagpd1("fnoxray-link-deps"),
2910flagpd1("fobjc-arc"),
2911flagpd1("fobjc-arc-exceptions"),
2912flagpd1("fobjc-atdefs"),
2913flagpd1("fobjc-call-cxx-cdtors"),
2914flagpd1("fobjc-convert-messages-to-runtime-calls"),
2915flagpd1("fobjc-exceptions"),
2916flagpd1("fobjc-gc"),
2917flagpd1("fobjc-gc-only"),
2918flagpd1("fobjc-infer-related-result-type"),
2919flagpd1("fobjc-legacy-dispatch"),
2920flagpd1("fobjc-link-runtime"),
2921flagpd1("fobjc-new-property"),
2922flagpd1("fobjc-nonfragile-abi"),
2923flagpd1("fobjc-runtime-has-weak"),
2924flagpd1("fobjc-sender-dependent-dispatch"),
2925flagpd1("fobjc-subscripting-legacy-runtime"),
2926flagpd1("fobjc-weak"),
2927flagpd1("fomit-frame-pointer"),
2928flagpd1("fopenmp"),
2929flagpd1("fopenmp-cuda-force-full-runtime"),
2930flagpd1("fopenmp-cuda-mode"),
2931flagpd1("fopenmp-enable-irbuilder"),
2932sepd1("fopenmp-host-ir-file-path"),
2933flagpd1("fopenmp-is-device"),
2934flagpd1("fopenmp-optimistic-collapse"),
2935flagpd1("fopenmp-relocatable-target"),
2936flagpd1("fopenmp-simd"),
2937flagpd1("fopenmp-use-tls"),
2938sepd1("foperator-arrow-depth"),
2939flagpd1("foptimize-sibling-calls"),
2940flagpd1("force_cpusubtype_ALL"),
2941flagpd1("force_flat_namespace"),
2942sepd1("force_load"),
2943flagpd1("forder-file-instrumentation"),
2944flagpd1("fpack-struct"),
2945flagpd1("fpadding-on-unsigned-fixed-point"),
2946flagpd1("fparse-all-comments"),
2947flagpd1("fpascal-strings"),
2948flagpd1("fpcc-struct-return"),
2949flagpd1("fpch-preprocess"),
2950flagpd1("fpch-validate-input-files-content"),
2951flagpd1("fpic"),
2952flagpd1("fpie"),
2953flagpd1("fplt"),
2954flagpd1("fpreserve-as-comments"),
2955flagpd1("fpreserve-vec3-type"),
2956flagpd1("fprofile-arcs"),
2957flagpd1("fprofile-generate"),
2958flagpd1("fprofile-instr-generate"),
2959flagpd1("fprofile-instr-use"),
2960sepd1("fprofile-remapping-file"),
2961flagpd1("fprofile-sample-accurate"),
2962flagpd1("fprofile-sample-use"),
2963flagpd1("fprofile-use"),
2964sepd1("framework"),
2965flagpd1("freciprocal-math"),
2966flagpd1("frecord-command-line"),
2967flagpd1("ffree-form"),
2968flagpd1("fno-free-form"),
2969flagpd1("freg-struct-return"),
2970flagpd1("fregister-global-dtors-with-atexit"),
2971flagpd1("frelaxed-template-template-args"),
2972flagpd1("freroll-loops"),
2973flagpd1("fretain-comments-from-system-headers"),
2974flagpd1("frewrite-imports"),
2975flagpd1("frewrite-includes"),
2976sepd1("frewrite-map-file"),
2977flagpd1("ffriend-injection"),
2978flagpd1("fno-friend-injection"),
2979flagpd1("ffrontend-optimize"),
2980flagpd1("fno-frontend-optimize"),
2981flagpd1("fropi"),
2982flagpd1("frounding-math"),
2983flagpd1("frtlib-add-rpath"),
2984flagpd1("frtti"),
2985flagpd1("frwpi"),
2986flagpd1("fsanitize-address-globals-dead-stripping"),
2987flagpd1("fsanitize-address-poison-custom-array-cookie"),
2988flagpd1("fsanitize-address-use-after-scope"),
2989flagpd1("fsanitize-address-use-odr-indicator"),
2990flagpd1("fsanitize-cfi-canonical-jump-tables"),
2991flagpd1("fsanitize-cfi-cross-dso"),
2992flagpd1("fsanitize-cfi-icall-generalize-pointers"),
2993flagpd1("fsanitize-coverage-8bit-counters"),
2994flagpd1("fsanitize-coverage-indirect-calls"),
2995flagpd1("fsanitize-coverage-inline-8bit-counters"),
2996flagpd1("fsanitize-coverage-no-prune"),
2997flagpd1("fsanitize-coverage-pc-table"),
2998flagpd1("fsanitize-coverage-stack-depth"),
2999flagpd1("fsanitize-coverage-trace-bb"),
3000flagpd1("fsanitize-coverage-trace-cmp"),
3001flagpd1("fsanitize-coverage-trace-div"),
3002flagpd1("fsanitize-coverage-trace-gep"),
3003flagpd1("fsanitize-coverage-trace-pc"),
3004flagpd1("fsanitize-coverage-trace-pc-guard"),
3005flagpd1("fsanitize-link-c++-runtime"),
3006flagpd1("fsanitize-link-runtime"),
3007flagpd1("fsanitize-memory-track-origins"),
3008flagpd1("fsanitize-memory-use-after-dtor"),
3009flagpd1("fsanitize-minimal-runtime"),
3010flagpd1("fsanitize-recover"),
3011flagpd1("fsanitize-stats"),
3012flagpd1("fsanitize-thread-atomics"),
3013flagpd1("fsanitize-thread-func-entry-exit"),
3014flagpd1("fsanitize-thread-memory-access"),
3015flagpd1("fsanitize-undefined-trap-on-error"),
3016flagpd1("fsave-optimization-record"),
3017flagpd1("fseh-exceptions"),
3018flagpd1("fshort-enums"),
3019flagpd1("fshort-wchar"),
3020flagpd1("fshow-column"),
3021flagpd1("fshow-source-location"),
3022flagpd1("fsignaling-math"),
3023flagpd1("fsigned-bitfields"),
3024flagpd1("fsigned-char"),
3025flagpd1("fsigned-wchar"),
3026flagpd1("fsigned-zeros"),
3027flagpd1("fsized-deallocation"),
3028flagpd1("fsjlj-exceptions"),
3029flagpd1("fslp-vectorize"),
3030flagpd1("fspell-checking"),
3031sepd1("fspell-checking-limit"),
3032flagpd1("fsplit-dwarf-inlining"),
3033flagpd1("fsplit-lto-unit"),
3034flagpd1("fsplit-stack"),
3035flagpd1("fstack-protector"),
3036flagpd1("fstack-protector-all"),
3037flagpd1("fstack-protector-strong"),
3038flagpd1("fstack-size-section"),
3039flagpd1("fstandalone-debug"),
3040flagpd1("fstrict-aliasing"),
3041flagpd1("fstrict-enums"),
3042flagpd1("fstrict-float-cast-overflow"),
3043flagpd1("fstrict-overflow"),
3044flagpd1("fstrict-return"),
3045flagpd1("fstrict-vtable-pointers"),
3046flagpd1("fstruct-path-tbaa"),
3047flagpd1("fsycl-is-device"),
3048flagpd1("fsyntax-only"),
3049sepd1("ftabstop"),
3050sepd1("ftemplate-backtrace-limit"),
3051sepd1("ftemplate-depth"),
3052flagpd1("ftest-coverage"),
3053flagpd1("fthreadsafe-statics"),
3054flagpd1("ftime-report"),
3055flagpd1("ftime-trace"),
3056flagpd1("ftrapping-math"),
3057flagpd1("ftrapv"),
3058sepd1("ftrapv-handler"),
3059flagpd1("ftrigraphs"),
3060sepd1("ftype-visibility"),
3061sepd1("function-alignment"),
3062flagpd1("ffunction-attribute-list"),
3063flagpd1("fno-function-attribute-list"),
3064flagpd1("funique-section-names"),
3065flagpd1("funit-at-a-time"),
3066flagpd1("funknown-anytype"),
3067flagpd1("funroll-loops"),
3068flagpd1("funsafe-math-optimizations"),
3069flagpd1("funsigned-bitfields"),
3070flagpd1("funsigned-char"),
3071flagpd1("funwind-tables"),
3072flagpd1("fuse-cxa-atexit"),
3073flagpd1("fuse-init-array"),
3074flagpd1("fuse-line-directives"),
3075flagpd1("fuse-register-sized-bitfield-access"),
3076flagpd1("fvalidate-ast-input-files-content"),
3077flagpd1("fvectorize"),
3078flagpd1("fverbose-asm"),
3079flagpd1("fvirtual-function-elimination"),
3080sepd1("fvisibility"),
3081flagpd1("fvisibility-global-new-delete-hidden"),
3082flagpd1("fvisibility-inlines-hidden"),
3083flagpd1("fvisibility-ms-compat"),
3084flagpd1("fwasm-exceptions"),
3085flagpd1("fwhole-program-vtables"),
3086flagpd1("fwrapv"),
3087flagpd1("fwritable-strings"),
3088flagpd1("fxray-always-emit-customevents"),
3089flagpd1("fxray-always-emit-typedevents"),
3090flagpd1("fxray-instrument"),
3091flagpd1("fxray-link-deps"),
3092flagpd1("fzero-initialized-in-bss"),
3093flagpd1("fzvector"),
3094flagpd1("g0"),
3095flagpd1("g1"),
3096flagpd1("g2"),
3097flagpd1("g3"),
3098.{
3099 .name = "g",
3100 .syntax = .flag,
3101 .zig_equivalent = .debug,
3102 .pd1 = true,
3103 .pd2 = false,
3104 .psl = false,
3105},
3106sepd1("gcc-toolchain"),
3107flagpd1("gcodeview"),
3108flagpd1("gcodeview-ghash"),
3109flagpd1("gcolumn-info"),
3110flagpd1("fgcse-after-reload"),
3111flagpd1("fno-gcse-after-reload"),
3112flagpd1("fgcse"),
3113flagpd1("fno-gcse"),
3114flagpd1("fgcse-las"),
3115flagpd1("fno-gcse-las"),
3116flagpd1("fgcse-sm"),
3117flagpd1("fno-gcse-sm"),
3118flagpd1("gdwarf"),
3119flagpd1("gdwarf-2"),
3120flagpd1("gdwarf-3"),
3121flagpd1("gdwarf-4"),
3122flagpd1("gdwarf-5"),
3123flagpd1("gdwarf-aranges"),
3124flagpd1("gembed-source"),
3125sepd1("gen-cdb-fragment-path"),
3126flagpd1("gen-reproducer"),
3127flagpd1("gfull"),
3128flagpd1("ggdb"),
3129flagpd1("ggdb0"),
3130flagpd1("ggdb1"),
3131flagpd1("ggdb2"),
3132flagpd1("ggdb3"),
3133flagpd1("ggnu-pubnames"),
3134flagpd1("ginline-line-tables"),
3135flagpd1("gline-directives-only"),
3136flagpd1("gline-tables-only"),
3137flagpd1("glldb"),
3138flagpd1("gmlt"),
3139flagpd1("gmodules"),
3140flagpd1("gno-codeview-ghash"),
3141flagpd1("gno-column-info"),
3142flagpd1("gno-embed-source"),
3143flagpd1("gno-gnu-pubnames"),
3144flagpd1("gno-inline-line-tables"),
3145flagpd1("gno-pubnames"),
3146flagpd1("gno-record-command-line"),
3147flagpd1("gno-strict-dwarf"),
3148flagpd1("fgnu"),
3149flagpd1("fno-gnu"),
3150flagpd1("gpubnames"),
3151flagpd1("grecord-command-line"),
3152flagpd1("gsce"),
3153flagpd1("gsplit-dwarf"),
3154flagpd1("gstrict-dwarf"),
3155flagpd1("gtoggle"),
3156flagpd1("gused"),
3157flagpd1("gz"),
3158sepd1("header-include-file"),
3159.{
3160 .name = "help",
3161 .syntax = .flag,
3162 .zig_equivalent = .driver_punt,
3163 .pd1 = true,
3164 .pd2 = true,
3165 .psl = false,
3166},
3167.{
3168 .name = "hip-link",
3169 .syntax = .flag,
3170 .zig_equivalent = .other,
3171 .pd1 = false,
3172 .pd2 = true,
3173 .psl = false,
3174},
3175sepd1("image_base"),
3176flagpd1("fimplement-inlines"),
3177flagpd1("fno-implement-inlines"),
3178flagpd1("fimplicit-none"),
3179flagpd1("fno-implicit-none"),
3180flagpd1("fimplicit-templates"),
3181flagpd1("fno-implicit-templates"),
3182sepd1("imultilib"),
3183sepd1("include-pch"),
3184flagpd1("index-header-map"),
3185sepd1("init"),
3186flagpd1("finit-local-zero"),
3187flagpd1("fno-init-local-zero"),
3188flagpd1("init-only"),
3189flagpd1("finline-functions-called-once"),
3190flagpd1("fno-inline-functions-called-once"),
3191flagpd1("finline-small-functions"),
3192flagpd1("fno-inline-small-functions"),
3193sepd1("install_name"),
3194flagpd1("finteger-4-integer-8"),
3195flagpd1("fno-integer-4-integer-8"),
3196flagpd1("fintrinsic-modules-path"),
3197flagpd1("fno-intrinsic-modules-path"),
3198flagpd1("fipa-cp"),
3199flagpd1("fno-ipa-cp"),
3200flagpd1("fivopts"),
3201flagpd1("fno-ivopts"),
3202flagpd1("keep_private_externs"),
3203sepd1("lazy_framework"),
3204sepd1("lazy_library"),
3205sepd1("load"),
3206flagpd1("m16"),
3207flagpd1("m32"),
3208flagpd1("m3dnow"),
3209flagpd1("m3dnowa"),
3210flagpd1("m64"),
3211flagpd1("m80387"),
3212flagpd1("mabi=ieeelongdouble"),
3213flagpd1("mabicalls"),
3214flagpd1("madx"),
3215flagpd1("maes"),
3216sepd1("main-file-name"),
3217flagpd1("malign-double"),
3218flagpd1("maltivec"),
3219flagpd1("marm"),
3220flagpd1("masm-verbose"),
3221flagpd1("massembler-fatal-warnings"),
3222flagpd1("massembler-no-warn"),
3223flagpd1("matomics"),
3224flagpd1("mavx"),
3225flagpd1("mavx2"),
3226flagpd1("mavx512bf16"),
3227flagpd1("mavx512bitalg"),
3228flagpd1("mavx512bw"),
3229flagpd1("mavx512cd"),
3230flagpd1("mavx512dq"),
3231flagpd1("mavx512er"),
3232flagpd1("mavx512f"),
3233flagpd1("mavx512ifma"),
3234flagpd1("mavx512pf"),
3235flagpd1("mavx512vbmi"),
3236flagpd1("mavx512vbmi2"),
3237flagpd1("mavx512vl"),
3238flagpd1("mavx512vnni"),
3239flagpd1("mavx512vp2intersect"),
3240flagpd1("mavx512vpopcntdq"),
3241flagpd1("fmax-identifier-length"),
3242flagpd1("fno-max-identifier-length"),
3243flagpd1("mbackchain"),
3244flagpd1("mbig-endian"),
3245flagpd1("mbmi"),
3246flagpd1("mbmi2"),
3247flagpd1("mbranch-likely"),
3248flagpd1("mbranch-target-enforce"),
3249flagpd1("mbranches-within-32B-boundaries"),
3250flagpd1("mbulk-memory"),
3251flagpd1("mcheck-zero-division"),
3252flagpd1("mcldemote"),
3253flagpd1("mclflushopt"),
3254flagpd1("mclwb"),
3255flagpd1("mclzero"),
3256flagpd1("mcmodel=medany"),
3257flagpd1("mcmodel=medlow"),
3258flagpd1("mcmpb"),
3259flagpd1("mcmse"),
3260sepd1("mcode-model"),
3261flagpd1("mcode-object-v3"),
3262flagpd1("mconstant-cfstrings"),
3263flagpd1("mconstructor-aliases"),
3264flagpd1("mcpu=?"),
3265flagpd1("mcrbits"),
3266flagpd1("mcrc"),
3267flagpd1("mcumode"),
3268flagpd1("mcx16"),
3269sepd1("mdebug-pass"),
3270flagpd1("mdirect-move"),
3271flagpd1("mdisable-tail-calls"),
3272flagpd1("mdouble-float"),
3273flagpd1("mdsp"),
3274flagpd1("mdspr2"),
3275sepd1("meabi"),
3276flagpd1("membedded-data"),
3277flagpd1("menable-no-infs"),
3278flagpd1("menable-no-nans"),
3279flagpd1("menable-unsafe-fp-math"),
3280flagpd1("menqcmd"),
3281flagpd1("fmerge-constants"),
3282flagpd1("fno-merge-constants"),
3283flagpd1("mexception-handling"),
3284flagpd1("mexecute-only"),
3285flagpd1("mextern-sdata"),
3286flagpd1("mf16c"),
3287flagpd1("mfancy-math-387"),
3288flagpd1("mfentry"),
3289flagpd1("mfix-and-continue"),
3290flagpd1("mfix-cortex-a53-835769"),
3291flagpd1("mfloat128"),
3292sepd1("mfloat-abi"),
3293flagpd1("mfma"),
3294flagpd1("mfma4"),
3295flagpd1("mfp32"),
3296flagpd1("mfp64"),
3297sepd1("mfpmath"),
3298flagpd1("mfprnd"),
3299flagpd1("mfpxx"),
3300flagpd1("mfsgsbase"),
3301flagpd1("mfxsr"),
3302flagpd1("mgeneral-regs-only"),
3303flagpd1("mgfni"),
3304flagpd1("mginv"),
3305flagpd1("mglibc"),
3306flagpd1("mglobal-merge"),
3307flagpd1("mgpopt"),
3308flagpd1("mhard-float"),
3309flagpd1("mhvx"),
3310flagpd1("mhtm"),
3311flagpd1("miamcu"),
3312flagpd1("mieee-fp"),
3313flagpd1("mieee-rnd-near"),
3314flagpd1("migrate"),
3315flagpd1("no-finalize-removal"),
3316flagpd1("no-ns-alloc-error"),
3317flagpd1("mimplicit-float"),
3318flagpd1("mincremental-linker-compatible"),
3319flagpd1("minline-all-stringops"),
3320flagpd1("minvariant-function-descriptors"),
3321flagpd1("minvpcid"),
3322flagpd1("mips1"),
3323flagpd1("mips16"),
3324flagpd1("mips2"),
3325flagpd1("mips3"),
3326flagpd1("mips32"),
3327flagpd1("mips32r2"),
3328flagpd1("mips32r3"),
3329flagpd1("mips32r5"),
3330flagpd1("mips32r6"),
3331flagpd1("mips4"),
3332flagpd1("mips5"),
3333flagpd1("mips64"),
3334flagpd1("mips64r2"),
3335flagpd1("mips64r3"),
3336flagpd1("mips64r5"),
3337flagpd1("mips64r6"),
3338flagpd1("misel"),
3339flagpd1("mkernel"),
3340flagpd1("mldc1-sdc1"),
3341sepd1("mlimit-float-precision"),
3342sepd1("mlink-bitcode-file"),
3343sepd1("mlink-builtin-bitcode"),
3344sepd1("mlink-cuda-bitcode"),
3345flagpd1("mlittle-endian"),
3346sepd1("mllvm"),
3347flagpd1("mlocal-sdata"),
3348flagpd1("mlong-calls"),
3349flagpd1("mlong-double-128"),
3350flagpd1("mlong-double-64"),
3351flagpd1("mlong-double-80"),
3352flagpd1("mlongcall"),
3353flagpd1("mlwp"),
3354flagpd1("mlzcnt"),
3355flagpd1("mmadd4"),
3356flagpd1("mmemops"),
3357flagpd1("mmfcrf"),
3358flagpd1("mmfocrf"),
3359flagpd1("mmicromips"),
3360flagpd1("mmmx"),
3361flagpd1("mmovbe"),
3362flagpd1("mmovdir64b"),
3363flagpd1("mmovdiri"),
3364flagpd1("mmpx"),
3365flagpd1("mms-bitfields"),
3366flagpd1("mmsa"),
3367flagpd1("mmt"),
3368flagpd1("mmultivalue"),
3369flagpd1("mmutable-globals"),
3370flagpd1("mmwaitx"),
3371flagpd1("mno-3dnow"),
3372flagpd1("mno-3dnowa"),
3373flagpd1("mno-80387"),
3374flagpd1("mno-abicalls"),
3375flagpd1("mno-adx"),
3376flagpd1("mno-aes"),
3377flagpd1("mno-altivec"),
3378flagpd1("mno-atomics"),
3379flagpd1("mno-avx"),
3380flagpd1("mno-avx2"),
3381flagpd1("mno-avx512bf16"),
3382flagpd1("mno-avx512bitalg"),
3383flagpd1("mno-avx512bw"),
3384flagpd1("mno-avx512cd"),
3385flagpd1("mno-avx512dq"),
3386flagpd1("mno-avx512er"),
3387flagpd1("mno-avx512f"),
3388flagpd1("mno-avx512ifma"),
3389flagpd1("mno-avx512pf"),
3390flagpd1("mno-avx512vbmi"),
3391flagpd1("mno-avx512vbmi2"),
3392flagpd1("mno-avx512vl"),
3393flagpd1("mno-avx512vnni"),
3394flagpd1("mno-avx512vp2intersect"),
3395flagpd1("mno-avx512vpopcntdq"),
3396flagpd1("mno-backchain"),
3397flagpd1("mno-bmi"),
3398flagpd1("mno-bmi2"),
3399flagpd1("mno-branch-likely"),
3400flagpd1("mno-bulk-memory"),
3401flagpd1("mno-check-zero-division"),
3402flagpd1("mno-cldemote"),
3403flagpd1("mno-clflushopt"),
3404flagpd1("mno-clwb"),
3405flagpd1("mno-clzero"),
3406flagpd1("mno-cmpb"),
3407flagpd1("mno-code-object-v3"),
3408flagpd1("mno-constant-cfstrings"),
3409flagpd1("mno-crbits"),
3410flagpd1("mno-crc"),
3411flagpd1("mno-cumode"),
3412flagpd1("mno-cx16"),
3413flagpd1("mno-dsp"),
3414flagpd1("mno-dspr2"),
3415flagpd1("mno-embedded-data"),
3416flagpd1("mno-enqcmd"),
3417flagpd1("mno-exception-handling"),
3418flagpd1("mnoexecstack"),
3419flagpd1("mno-execute-only"),
3420flagpd1("mno-extern-sdata"),
3421flagpd1("mno-f16c"),
3422flagpd1("mno-fix-cortex-a53-835769"),
3423flagpd1("mno-float128"),
3424flagpd1("mno-fma"),
3425flagpd1("mno-fma4"),
3426flagpd1("mno-fprnd"),
3427flagpd1("mno-fsgsbase"),
3428flagpd1("mno-fxsr"),
3429flagpd1("mno-gfni"),
3430flagpd1("mno-ginv"),
3431flagpd1("mno-global-merge"),
3432flagpd1("mno-gpopt"),
3433flagpd1("mno-hvx"),
3434flagpd1("mno-htm"),
3435flagpd1("mno-iamcu"),
3436flagpd1("mno-implicit-float"),
3437flagpd1("mno-incremental-linker-compatible"),
3438flagpd1("mno-inline-all-stringops"),
3439flagpd1("mno-invariant-function-descriptors"),
3440flagpd1("mno-invpcid"),
3441flagpd1("mno-isel"),
3442flagpd1("mno-ldc1-sdc1"),
3443flagpd1("mno-local-sdata"),
3444flagpd1("mno-long-calls"),
3445flagpd1("mno-longcall"),
3446flagpd1("mno-lwp"),
3447flagpd1("mno-lzcnt"),
3448flagpd1("mno-madd4"),
3449flagpd1("mno-memops"),
3450flagpd1("mno-mfcrf"),
3451flagpd1("mno-mfocrf"),
3452flagpd1("mno-micromips"),
3453flagpd1("mno-mips16"),
3454flagpd1("mno-mmx"),
3455flagpd1("mno-movbe"),
3456flagpd1("mno-movdir64b"),
3457flagpd1("mno-movdiri"),
3458flagpd1("mno-movt"),
3459flagpd1("mno-mpx"),
3460flagpd1("mno-ms-bitfields"),
3461flagpd1("mno-msa"),
3462flagpd1("mno-mt"),
3463flagpd1("mno-multivalue"),
3464flagpd1("mno-mutable-globals"),
3465flagpd1("mno-mwaitx"),
3466flagpd1("mno-neg-immediates"),
3467flagpd1("mno-nontrapping-fptoint"),
3468flagpd1("mno-nvj"),
3469flagpd1("mno-nvs"),
3470flagpd1("mno-odd-spreg"),
3471flagpd1("mno-omit-leaf-frame-pointer"),
3472flagpd1("mno-outline"),
3473flagpd1("mno-packed-stack"),
3474flagpd1("mno-packets"),
3475flagpd1("mno-pascal-strings"),
3476flagpd1("mno-pclmul"),
3477flagpd1("mno-pconfig"),
3478flagpd1("mno-pie-copy-relocations"),
3479flagpd1("mno-pku"),
3480flagpd1("mno-popcnt"),
3481flagpd1("mno-popcntd"),
3482flagpd1("mno-power8-vector"),
3483flagpd1("mno-power9-vector"),
3484flagpd1("mno-prefetchwt1"),
3485flagpd1("mno-prfchw"),
3486flagpd1("mno-ptwrite"),
3487flagpd1("mno-pure-code"),
3488flagpd1("mno-qpx"),
3489flagpd1("mno-rdpid"),
3490flagpd1("mno-rdrnd"),
3491flagpd1("mno-rdseed"),
3492flagpd1("mno-red-zone"),
3493flagpd1("mno-reference-types"),
3494flagpd1("mno-relax"),
3495flagpd1("mno-relax-all"),
3496flagpd1("mno-relax-pic-calls"),
3497flagpd1("mno-restrict-it"),
3498flagpd1("mno-retpoline"),
3499flagpd1("mno-retpoline-external-thunk"),
3500flagpd1("mno-rtd"),
3501flagpd1("mno-rtm"),
3502flagpd1("mno-sahf"),
3503flagpd1("mno-save-restore"),
3504flagpd1("mno-sgx"),
3505flagpd1("mno-sha"),
3506flagpd1("mno-shstk"),
3507flagpd1("mno-sign-ext"),
3508flagpd1("mno-simd128"),
3509flagpd1("mno-soft-float"),
3510flagpd1("mno-spe"),
3511flagpd1("mno-speculative-load-hardening"),
3512flagpd1("mno-sram-ecc"),
3513flagpd1("mno-sse"),
3514flagpd1("mno-sse2"),
3515flagpd1("mno-sse3"),
3516flagpd1("mno-sse4"),
3517flagpd1("mno-sse4.1"),
3518flagpd1("mno-sse4.2"),
3519flagpd1("mno-sse4a"),
3520flagpd1("mno-ssse3"),
3521flagpd1("mno-stack-arg-probe"),
3522flagpd1("mno-stackrealign"),
3523flagpd1("mno-tail-call"),
3524flagpd1("mno-tbm"),
3525flagpd1("mno-thumb"),
3526flagpd1("mno-tls-direct-seg-refs"),
3527flagpd1("mno-unaligned-access"),
3528flagpd1("mno-unimplemented-simd128"),
3529flagpd1("mno-vaes"),
3530flagpd1("mno-virt"),
3531flagpd1("mno-vpclmulqdq"),
3532flagpd1("mno-vsx"),
3533flagpd1("mno-vx"),
3534flagpd1("mno-vzeroupper"),
3535flagpd1("mno-waitpkg"),
3536flagpd1("mno-warn-nonportable-cfstrings"),
3537flagpd1("mno-wavefrontsize64"),
3538flagpd1("mno-wbnoinvd"),
3539flagpd1("mno-x87"),
3540flagpd1("mno-xgot"),
3541flagpd1("mno-xnack"),
3542flagpd1("mno-xop"),
3543flagpd1("mno-xsave"),
3544flagpd1("mno-xsavec"),
3545flagpd1("mno-xsaveopt"),
3546flagpd1("mno-xsaves"),
3547flagpd1("mno-zero-initialized-in-bss"),
3548flagpd1("mno-zvector"),
3549flagpd1("mnocrc"),
3550flagpd1("mno-direct-move"),
3551flagpd1("mnontrapping-fptoint"),
3552flagpd1("mnop-mcount"),
3553flagpd1("mno-crypto"),
3554flagpd1("mnvj"),
3555flagpd1("mnvs"),
3556flagpd1("modd-spreg"),
3557sepd1("module-dependency-dir"),
3558flagpd1("module-file-deps"),
3559flagpd1("module-file-info"),
3560flagpd1("fmodule-private"),
3561flagpd1("fno-module-private"),
3562flagpd1("fmodulo-sched-allow-regmoves"),
3563flagpd1("fno-modulo-sched-allow-regmoves"),
3564flagpd1("fmodulo-sched"),
3565flagpd1("fno-modulo-sched"),
3566flagpd1("momit-leaf-frame-pointer"),
3567flagpd1("moutline"),
3568flagpd1("mpacked-stack"),
3569flagpd1("mpackets"),
3570flagpd1("mpascal-strings"),
3571flagpd1("mpclmul"),
3572flagpd1("mpconfig"),
3573flagpd1("mpie-copy-relocations"),
3574flagpd1("mpku"),
3575flagpd1("mpopcnt"),
3576flagpd1("mpopcntd"),
3577flagpd1("mcrypto"),
3578flagpd1("mpower8-vector"),
3579flagpd1("mpower9-vector"),
3580flagpd1("mprefetchwt1"),
3581flagpd1("mprfchw"),
3582flagpd1("mptwrite"),
3583flagpd1("mpure-code"),
3584flagpd1("mqdsp6-compat"),
3585flagpd1("mqpx"),
3586flagpd1("mrdpid"),
3587flagpd1("mrdrnd"),
3588flagpd1("mrdseed"),
3589flagpd1("mreassociate"),
3590flagpd1("mrecip"),
3591flagpd1("mrecord-mcount"),
3592flagpd1("mred-zone"),
3593flagpd1("mreference-types"),
3594sepd1("mregparm"),
3595flagpd1("mrelax"),
3596flagpd1("mrelax-all"),
3597flagpd1("mrelax-pic-calls"),
3598.{
3599 .name = "mrelax-relocations",
3600 .syntax = .flag,
3601 .zig_equivalent = .other,
3602 .pd1 = false,
3603 .pd2 = true,
3604 .psl = false,
3605},
3606sepd1("mrelocation-model"),
3607flagpd1("mrestrict-it"),
3608flagpd1("mretpoline"),
3609flagpd1("mretpoline-external-thunk"),
3610flagpd1("mrtd"),
3611flagpd1("mrtm"),
3612flagpd1("msahf"),
3613flagpd1("msave-restore"),
3614flagpd1("msave-temp-labels"),
3615flagpd1("msecure-plt"),
3616flagpd1("msgx"),
3617flagpd1("msha"),
3618flagpd1("mshstk"),
3619flagpd1("msign-ext"),
3620flagpd1("msimd128"),
3621flagpd1("msingle-float"),
3622flagpd1("msoft-float"),
3623flagpd1("mspe"),
3624flagpd1("mspeculative-load-hardening"),
3625flagpd1("msram-ecc"),
3626flagpd1("msse"),
3627flagpd1("msse2"),
3628flagpd1("msse3"),
3629flagpd1("msse4"),
3630flagpd1("msse4.1"),
3631flagpd1("msse4.2"),
3632flagpd1("msse4a"),
3633flagpd1("mssse3"),
3634flagpd1("mstack-arg-probe"),
3635flagpd1("mstackrealign"),
3636flagpd1("mstrict-align"),
3637sepd1("mt-migrate-directory"),
3638flagpd1("mtail-call"),
3639flagpd1("mtbm"),
3640sepd1("mthread-model"),
3641flagpd1("mthumb"),
3642flagpd1("mtls-direct-seg-refs"),
3643sepd1("mtp"),
3644flagpd1("mtune=?"),
3645flagpd1("muclibc"),
3646flagpd1("multi_module"),
3647sepd1("multiply_defined"),
3648sepd1("multiply_defined_unused"),
3649flagpd1("munaligned-access"),
3650flagpd1("munimplemented-simd128"),
3651flagpd1("munwind-tables"),
3652flagpd1("mv5"),
3653flagpd1("mv55"),
3654flagpd1("mv60"),
3655flagpd1("mv62"),
3656flagpd1("mv65"),
3657flagpd1("mv66"),
3658flagpd1("mvaes"),
3659flagpd1("mvirt"),
3660flagpd1("mvpclmulqdq"),
3661flagpd1("mvsx"),
3662flagpd1("mvx"),
3663flagpd1("mvzeroupper"),
3664flagpd1("mwaitpkg"),
3665flagpd1("mwarn-nonportable-cfstrings"),
3666flagpd1("mwavefrontsize64"),
3667flagpd1("mwbnoinvd"),
3668flagpd1("mx32"),
3669flagpd1("mx87"),
3670flagpd1("mxgot"),
3671flagpd1("mxnack"),
3672flagpd1("mxop"),
3673flagpd1("mxsave"),
3674flagpd1("mxsavec"),
3675flagpd1("mxsaveopt"),
3676flagpd1("mxsaves"),
3677flagpd1("mzvector"),
3678flagpd1("n"),
3679flagpd1("new-struct-path-tbaa"),
3680flagpd1("no_dead_strip_inits_and_terms"),
3681flagpd1("no-canonical-prefixes"),
3682flagpd1("no-code-completion-globals"),
3683flagpd1("no-code-completion-ns-level-decls"),
3684flagpd1("no-cpp-precomp"),
3685.{
3686 .name = "no-cuda-noopt-device-debug",
3687 .syntax = .flag,
3688 .zig_equivalent = .other,
3689 .pd1 = false,
3690 .pd2 = true,
3691 .psl = false,
3692},
3693.{
3694 .name = "no-cuda-version-check",
3695 .syntax = .flag,
3696 .zig_equivalent = .other,
3697 .pd1 = false,
3698 .pd2 = true,
3699 .psl = false,
3700},
3701flagpd1("no-emit-llvm-uselists"),
3702flagpd1("no-implicit-float"),
3703.{
3704 .name = "no-integrated-cpp",
3705 .syntax = .flag,
3706 .zig_equivalent = .other,
3707 .pd1 = true,
3708 .pd2 = true,
3709 .psl = false,
3710},
3711.{
3712 .name = "no-pedantic",
3713 .syntax = .flag,
3714 .zig_equivalent = .other,
3715 .pd1 = true,
3716 .pd2 = true,
3717 .psl = false,
3718},
3719flagpd1("no-pie"),
3720flagpd1("no-pthread"),
3721flagpd1("no-struct-path-tbaa"),
3722flagpd1("nobuiltininc"),
3723flagpd1("nocpp"),
3724flagpd1("nocudainc"),
3725flagpd1("nodefaultlibs"),
3726flagpd1("nofixprebinding"),
3727flagpd1("nogpulib"),
3728flagpd1("nolibc"),
3729flagpd1("nomultidefs"),
3730flagpd1("fnon-call-exceptions"),
3731flagpd1("fno-non-call-exceptions"),
3732flagpd1("nopie"),
3733flagpd1("noprebind"),
3734flagpd1("noprofilelib"),
3735flagpd1("noseglinkedit"),
3736flagpd1("nostartfiles"),
3737flagpd1("nostdinc"),
3738flagpd1("nostdinc++"),
3739.{
3740 .name = "nostdlib",
3741 .syntax = .flag,
3742 .zig_equivalent = .nostdlib,
3743 .pd1 = true,
3744 .pd2 = false,
3745 .psl = false,
3746},
3747flagpd1("nostdlibinc"),
3748flagpd1("nostdlib++"),
3749flagpd1("nostdsysteminc"),
3750flagpd1("objcmt-atomic-property"),
3751flagpd1("objcmt-migrate-all"),
3752flagpd1("objcmt-migrate-annotation"),
3753flagpd1("objcmt-migrate-designated-init"),
3754flagpd1("objcmt-migrate-instancetype"),
3755flagpd1("objcmt-migrate-literals"),
3756flagpd1("objcmt-migrate-ns-macros"),
3757flagpd1("objcmt-migrate-property"),
3758flagpd1("objcmt-migrate-property-dot-syntax"),
3759flagpd1("objcmt-migrate-protocol-conformance"),
3760flagpd1("objcmt-migrate-readonly-property"),
3761flagpd1("objcmt-migrate-readwrite-property"),
3762flagpd1("objcmt-migrate-subscripting"),
3763flagpd1("objcmt-ns-nonatomic-iosonly"),
3764flagpd1("objcmt-returns-innerpointer-property"),
3765flagpd1("object"),
3766sepd1("opt-record-file"),
3767sepd1("opt-record-format"),
3768sepd1("opt-record-passes"),
3769sepd1("output-asm-variant"),
3770flagpd1("p"),
3771flagpd1("fpack-derived"),
3772flagpd1("fno-pack-derived"),
3773.{
3774 .name = "pass-exit-codes",
3775 .syntax = .flag,
3776 .zig_equivalent = .other,
3777 .pd1 = true,
3778 .pd2 = true,
3779 .psl = false,
3780},
3781flagpd1("pch-through-hdrstop-create"),
3782flagpd1("pch-through-hdrstop-use"),
3783.{
3784 .name = "pedantic",
3785 .syntax = .flag,
3786 .zig_equivalent = .other,
3787 .pd1 = true,
3788 .pd2 = true,
3789 .psl = false,
3790},
3791.{
3792 .name = "pedantic-errors",
3793 .syntax = .flag,
3794 .zig_equivalent = .other,
3795 .pd1 = true,
3796 .pd2 = true,
3797 .psl = false,
3798},
3799flagpd1("fpeel-loops"),
3800flagpd1("fno-peel-loops"),
3801flagpd1("fpermissive"),
3802flagpd1("fno-permissive"),
3803flagpd1("pg"),
3804flagpd1("pic-is-pie"),
3805sepd1("pic-level"),
3806flagpd1("pie"),
3807.{
3808 .name = "pipe",
3809 .syntax = .flag,
3810 .zig_equivalent = .ignore,
3811 .pd1 = true,
3812 .pd2 = true,
3813 .psl = false,
3814},
3815sepd1("plugin"),
3816flagpd1("prebind"),
3817flagpd1("prebind_all_twolevel_modules"),
3818flagpd1("fprefetch-loop-arrays"),
3819flagpd1("fno-prefetch-loop-arrays"),
3820flagpd1("preload"),
3821flagpd1("print-dependency-directives-minimized-source"),
3822.{
3823 .name = "print-effective-triple",
3824 .syntax = .flag,
3825 .zig_equivalent = .other,
3826 .pd1 = true,
3827 .pd2 = true,
3828 .psl = false,
3829},
3830flagpd1("print-ivar-layout"),
3831.{
3832 .name = "print-libgcc-file-name",
3833 .syntax = .flag,
3834 .zig_equivalent = .other,
3835 .pd1 = true,
3836 .pd2 = true,
3837 .psl = false,
3838},
3839.{
3840 .name = "print-multi-directory",
3841 .syntax = .flag,
3842 .zig_equivalent = .other,
3843 .pd1 = true,
3844 .pd2 = true,
3845 .psl = false,
3846},
3847.{
3848 .name = "print-multi-lib",
3849 .syntax = .flag,
3850 .zig_equivalent = .other,
3851 .pd1 = true,
3852 .pd2 = true,
3853 .psl = false,
3854},
3855.{
3856 .name = "print-multi-os-directory",
3857 .syntax = .flag,
3858 .zig_equivalent = .other,
3859 .pd1 = true,
3860 .pd2 = true,
3861 .psl = false,
3862},
3863flagpd1("print-preamble"),
3864.{
3865 .name = "print-resource-dir",
3866 .syntax = .flag,
3867 .zig_equivalent = .other,
3868 .pd1 = true,
3869 .pd2 = true,
3870 .psl = false,
3871},
3872.{
3873 .name = "print-search-dirs",
3874 .syntax = .flag,
3875 .zig_equivalent = .other,
3876 .pd1 = true,
3877 .pd2 = true,
3878 .psl = false,
3879},
3880flagpd1("print-stats"),
3881.{
3882 .name = "print-supported-cpus",
3883 .syntax = .flag,
3884 .zig_equivalent = .other,
3885 .pd1 = true,
3886 .pd2 = true,
3887 .psl = false,
3888},
3889.{
3890 .name = "print-target-triple",
3891 .syntax = .flag,
3892 .zig_equivalent = .other,
3893 .pd1 = true,
3894 .pd2 = true,
3895 .psl = false,
3896},
3897flagpd1("fprintf"),
3898flagpd1("fno-printf"),
3899flagpd1("private_bundle"),
3900flagpd1("fprofile-correction"),
3901flagpd1("fno-profile-correction"),
3902flagpd1("fprofile"),
3903flagpd1("fno-profile"),
3904flagpd1("fprofile-generate-sampling"),
3905flagpd1("fno-profile-generate-sampling"),
3906flagpd1("fprofile-reusedist"),
3907flagpd1("fno-profile-reusedist"),
3908flagpd1("fprofile-values"),
3909flagpd1("fno-profile-values"),
3910flagpd1("fprotect-parens"),
3911flagpd1("fno-protect-parens"),
3912flagpd1("pthread"),
3913flagpd1("pthreads"),
3914flagpd1("r"),
3915flagpd1("frange-check"),
3916flagpd1("fno-range-check"),
3917.{
3918 .name = "rdynamic",
3919 .syntax = .flag,
3920 .zig_equivalent = .rdynamic,
3921 .pd1 = true,
3922 .pd2 = false,
3923 .psl = false,
3924},
3925sepd1("read_only_relocs"),
3926flagpd1("freal-4-real-10"),
3927flagpd1("fno-real-4-real-10"),
3928flagpd1("freal-4-real-16"),
3929flagpd1("fno-real-4-real-16"),
3930flagpd1("freal-4-real-8"),
3931flagpd1("fno-real-4-real-8"),
3932flagpd1("freal-8-real-10"),
3933flagpd1("fno-real-8-real-10"),
3934flagpd1("freal-8-real-16"),
3935flagpd1("fno-real-8-real-16"),
3936flagpd1("freal-8-real-4"),
3937flagpd1("fno-real-8-real-4"),
3938flagpd1("frealloc-lhs"),
3939flagpd1("fno-realloc-lhs"),
3940sepd1("record-command-line"),
3941flagpd1("frecursive"),
3942flagpd1("fno-recursive"),
3943flagpd1("fregs-graph"),
3944flagpd1("fno-regs-graph"),
3945flagpd1("relaxed-aliasing"),
3946.{
3947 .name = "relocatable-pch",
3948 .syntax = .flag,
3949 .zig_equivalent = .other,
3950 .pd1 = true,
3951 .pd2 = true,
3952 .psl = false,
3953},
3954flagpd1("remap"),
3955sepd1("remap-file"),
3956flagpd1("frename-registers"),
3957flagpd1("fno-rename-registers"),
3958flagpd1("freorder-blocks"),
3959flagpd1("fno-reorder-blocks"),
3960flagpd1("frepack-arrays"),
3961flagpd1("fno-repack-arrays"),
3962sepd1("resource-dir"),
3963flagpd1("rewrite-legacy-objc"),
3964flagpd1("rewrite-macros"),
3965flagpd1("rewrite-objc"),
3966flagpd1("rewrite-test"),
3967flagpd1("fripa"),
3968flagpd1("fno-ripa"),
3969sepd1("rpath"),
3970flagpd1("s"),
3971.{
3972 .name = "save-stats",
3973 .syntax = .flag,
3974 .zig_equivalent = .other,
3975 .pd1 = true,
3976 .pd2 = true,
3977 .psl = false,
3978},
3979.{
3980 .name = "save-temps",
3981 .syntax = .flag,
3982 .zig_equivalent = .other,
3983 .pd1 = true,
3984 .pd2 = true,
3985 .psl = false,
3986},
3987flagpd1("fschedule-insns2"),
3988flagpd1("fno-schedule-insns2"),
3989flagpd1("fschedule-insns"),
3990flagpd1("fno-schedule-insns"),
3991flagpd1("fsecond-underscore"),
3992flagpd1("fno-second-underscore"),
3993.{
3994 .name = "sectalign",
3995 .syntax = .{.multi_arg=3},
3996 .zig_equivalent = .other,
3997 .pd1 = true,
3998 .pd2 = false,
3999 .psl = false,
4000},
4001.{
4002 .name = "sectcreate",
4003 .syntax = .{.multi_arg=3},
4004 .zig_equivalent = .other,
4005 .pd1 = true,
4006 .pd2 = false,
4007 .psl = false,
4008},
4009.{
4010 .name = "sectobjectsymbols",
4011 .syntax = .{.multi_arg=2},
4012 .zig_equivalent = .other,
4013 .pd1 = true,
4014 .pd2 = false,
4015 .psl = false,
4016},
4017.{
4018 .name = "sectorder",
4019 .syntax = .{.multi_arg=3},
4020 .zig_equivalent = .other,
4021 .pd1 = true,
4022 .pd2 = false,
4023 .psl = false,
4024},
4025flagpd1("fsee"),
4026flagpd1("fno-see"),
4027sepd1("seg_addr_table"),
4028sepd1("seg_addr_table_filename"),
4029.{
4030 .name = "segaddr",
4031 .syntax = .{.multi_arg=2},
4032 .zig_equivalent = .other,
4033 .pd1 = true,
4034 .pd2 = false,
4035 .psl = false,
4036},
4037.{
4038 .name = "segcreate",
4039 .syntax = .{.multi_arg=3},
4040 .zig_equivalent = .other,
4041 .pd1 = true,
4042 .pd2 = false,
4043 .psl = false,
4044},
4045flagpd1("seglinkedit"),
4046.{
4047 .name = "segprot",
4048 .syntax = .{.multi_arg=3},
4049 .zig_equivalent = .other,
4050 .pd1 = true,
4051 .pd2 = false,
4052 .psl = false,
4053},
4054sepd1("segs_read_only_addr"),
4055sepd1("segs_read_write_addr"),
4056flagpd1("setup-static-analyzer"),
4057.{
4058 .name = "shared",
4059 .syntax = .flag,
4060 .zig_equivalent = .shared,
4061 .pd1 = true,
4062 .pd2 = true,
4063 .psl = false,
4064},
4065flagpd1("shared-libgcc"),
4066flagpd1("shared-libsan"),
4067flagpd1("show-encoding"),
4068.{
4069 .name = "show-includes",
4070 .syntax = .flag,
4071 .zig_equivalent = .other,
4072 .pd1 = false,
4073 .pd2 = true,
4074 .psl = false,
4075},
4076flagpd1("show-inst"),
4077flagpd1("fsign-zero"),
4078flagpd1("fno-sign-zero"),
4079flagpd1("fsignaling-nans"),
4080flagpd1("fno-signaling-nans"),
4081flagpd1("single_module"),
4082flagpd1("fsingle-precision-constant"),
4083flagpd1("fno-single-precision-constant"),
4084flagpd1("fspec-constr-count"),
4085flagpd1("fno-spec-constr-count"),
4086.{
4087 .name = "specs",
4088 .syntax = .separate,
4089 .zig_equivalent = .other,
4090 .pd1 = true,
4091 .pd2 = true,
4092 .psl = false,
4093},
4094sepd1("split-dwarf-file"),
4095sepd1("split-dwarf-output"),
4096flagpd1("split-stacks"),
4097flagpd1("fstack-arrays"),
4098flagpd1("fno-stack-arrays"),
4099flagpd1("fstack-check"),
4100flagpd1("fno-stack-check"),
4101sepd1("stack-protector"),
4102sepd1("stack-protector-buffer-size"),
4103.{
4104 .name = "static",
4105 .syntax = .flag,
4106 .zig_equivalent = .other,
4107 .pd1 = true,
4108 .pd2 = true,
4109 .psl = false,
4110},
4111flagpd1("static-define"),
4112flagpd1("static-libgcc"),
4113flagpd1("static-libgfortran"),
4114flagpd1("static-libsan"),
4115flagpd1("static-libstdc++"),
4116flagpd1("static-openmp"),
4117flagpd1("static-pie"),
4118flagpd1("fstrength-reduce"),
4119flagpd1("fno-strength-reduce"),
4120flagpd1("sys-header-deps"),
4121flagpd1("t"),
4122sepd1("target-abi"),
4123sepd1("target-cpu"),
4124sepd1("target-feature"),
4125.{
4126 .name = "target",
4127 .syntax = .separate,
4128 .zig_equivalent = .target,
4129 .pd1 = true,
4130 .pd2 = false,
4131 .psl = false,
4132},
4133sepd1("target-linker-version"),
4134flagpd1("templight-dump"),
4135flagpd1("test-coverage"),
4136flagpd1("time"),
4137flagpd1("ftls-model"),
4138flagpd1("fno-tls-model"),
4139flagpd1("ftracer"),
4140flagpd1("fno-tracer"),
4141.{
4142 .name = "traditional",
4143 .syntax = .flag,
4144 .zig_equivalent = .other,
4145 .pd1 = true,
4146 .pd2 = true,
4147 .psl = false,
4148},
4149.{
4150 .name = "traditional-cpp",
4151 .syntax = .flag,
4152 .zig_equivalent = .other,
4153 .pd1 = true,
4154 .pd2 = true,
4155 .psl = false,
4156},
4157flagpd1("ftree-dce"),
4158flagpd1("fno-tree-dce"),
4159flagpd1("ftree_loop_im"),
4160flagpd1("fno-tree_loop_im"),
4161flagpd1("ftree_loop_ivcanon"),
4162flagpd1("fno-tree_loop_ivcanon"),
4163flagpd1("ftree_loop_linear"),
4164flagpd1("fno-tree_loop_linear"),
4165flagpd1("ftree-salias"),
4166flagpd1("fno-tree-salias"),
4167flagpd1("ftree-ter"),
4168flagpd1("fno-tree-ter"),
4169flagpd1("ftree-vectorizer-verbose"),
4170flagpd1("fno-tree-vectorizer-verbose"),
4171flagpd1("ftree-vrp"),
4172flagpd1("fno-tree-vrp"),
4173.{
4174 .name = "trigraphs",
4175 .syntax = .flag,
4176 .zig_equivalent = .other,
4177 .pd1 = true,
4178 .pd2 = true,
4179 .psl = false,
4180},
4181flagpd1("trim-egraph"),
4182sepd1("triple"),
4183flagpd1("twolevel_namespace"),
4184flagpd1("twolevel_namespace_hints"),
4185sepd1("umbrella"),
4186flagpd1("undef"),
4187flagpd1("funderscoring"),
4188flagpd1("fno-underscoring"),
4189sepd1("unexported_symbols_list"),
4190flagpd1("funroll-all-loops"),
4191flagpd1("fno-unroll-all-loops"),
4192flagpd1("funsafe-loop-optimizations"),
4193flagpd1("fno-unsafe-loop-optimizations"),
4194flagpd1("funswitch-loops"),
4195flagpd1("fno-unswitch-loops"),
4196flagpd1("fuse-linker-plugin"),
4197flagpd1("fno-use-linker-plugin"),
4198flagpd1("v"),
4199flagpd1("fvariable-expansion-in-unroller"),
4200flagpd1("fno-variable-expansion-in-unroller"),
4201flagpd1("fvect-cost-model"),
4202flagpd1("fno-vect-cost-model"),
4203flagpd1("vectorize-loops"),
4204flagpd1("vectorize-slp"),
4205flagpd1("verify"),
4206.{
4207 .name = "verify-debug-info",
4208 .syntax = .flag,
4209 .zig_equivalent = .other,
4210 .pd1 = false,
4211 .pd2 = true,
4212 .psl = false,
4213},
4214flagpd1("verify-ignore-unexpected"),
4215flagpd1("verify-pch"),
4216flagpd1("version"),
4217.{
4218 .name = "via-file-asm",
4219 .syntax = .flag,
4220 .zig_equivalent = .other,
4221 .pd1 = true,
4222 .pd2 = true,
4223 .psl = false,
4224},
4225flagpd1("w"),
4226sepd1("weak_framework"),
4227sepd1("weak_library"),
4228sepd1("weak_reference_mismatches"),
4229flagpd1("fweb"),
4230flagpd1("fno-web"),
4231flagpd1("whatsloaded"),
4232flagpd1("fwhole-file"),
4233flagpd1("fno-whole-file"),
4234flagpd1("fwhole-program"),
4235flagpd1("fno-whole-program"),
4236flagpd1("whyload"),
4237sepd1("z"),
4238joinpd1("fsanitize-undefined-strip-path-components="),
4239joinpd1("fopenmp-cuda-teams-reduction-recs-num="),
4240joinpd1("analyzer-config-compatibility-mode="),
4241joinpd1("fpatchable-function-entry-offset="),
4242joinpd1("analyzer-inline-max-stack-depth="),
4243joinpd1("fsanitize-address-field-padding="),
4244joinpd1("fdiagnostics-hotness-threshold="),
4245joinpd1("fsanitize-memory-track-origins="),
4246joinpd1("mwatchos-simulator-version-min="),
4247joinpd1("mappletvsimulator-version-min="),
4248joinpd1("fobjc-nonfragile-abi-version="),
4249joinpd1("fprofile-instrument-use-path="),
4250jspd1("fxray-instrumentation-bundle="),
4251joinpd1("miphonesimulator-version-min="),
4252joinpd1("faddress-space-map-mangling="),
4253joinpd1("foptimization-record-passes="),
4254joinpd1("ftest-module-file-extension="),
4255jspd1("fxray-instruction-threshold="),
4256joinpd1("mno-default-build-attributes"),
4257joinpd1("mtvos-simulator-version-min="),
4258joinpd1("mwatchsimulator-version-min="),
4259.{
4260 .name = "include-with-prefix-before=",
4261 .syntax = .joined,
4262 .zig_equivalent = .other,
4263 .pd1 = false,
4264 .pd2 = true,
4265 .psl = false,
4266},
4267joinpd1("objcmt-white-list-dir-path="),
4268joinpd1("error-on-deserialized-decl="),
4269joinpd1("fconstexpr-backtrace-limit="),
4270joinpd1("fdiagnostics-show-category="),
4271joinpd1("fdiagnostics-show-location="),
4272joinpd1("fopenmp-cuda-blocks-per-sm="),
4273joinpd1("fsanitize-system-blacklist="),
4274jspd1("fxray-instruction-threshold"),
4275joinpd1("headerpad_max_install_names"),
4276joinpd1("mios-simulator-version-min="),
4277.{
4278 .name = "include-with-prefix-after=",
4279 .syntax = .joined,
4280 .zig_equivalent = .other,
4281 .pd1 = false,
4282 .pd2 = true,
4283 .psl = false,
4284},
4285joinpd1("fms-compatibility-version="),
4286joinpd1("fopenmp-cuda-number-of-sm="),
4287joinpd1("foptimization-record-file="),
4288joinpd1("fpatchable-function-entry="),
4289joinpd1("fsave-optimization-record="),
4290joinpd1("ftemplate-backtrace-limit="),
4291.{
4292 .name = "gpu-max-threads-per-block=",
4293 .syntax = .joined,
4294 .zig_equivalent = .other,
4295 .pd1 = false,
4296 .pd2 = true,
4297 .psl = false,
4298},
4299joinpd1("malign-branch-prefix-size="),
4300joinpd1("objcmt-whitelist-dir-path="),
4301joinpd1("Wno-nonportable-cfstrings"),
4302joinpd1("analyzer-disable-checker="),
4303joinpd1("fbuild-session-timestamp="),
4304joinpd1("fprofile-instrument-path="),
4305joinpd1("mdefault-build-attributes"),
4306joinpd1("msign-return-address-key="),
4307.{
4308 .name = "verify-ignore-unexpected=",
4309 .syntax = .comma_joined,
4310 .zig_equivalent = .other,
4311 .pd1 = true,
4312 .pd2 = false,
4313 .psl = false,
4314},
4315.{
4316 .name = "include-directory-after=",
4317 .syntax = .joined,
4318 .zig_equivalent = .other,
4319 .pd1 = false,
4320 .pd2 = true,
4321 .psl = false,
4322},
4323.{
4324 .name = "compress-debug-sections=",
4325 .syntax = .joined,
4326 .zig_equivalent = .other,
4327 .pd1 = true,
4328 .pd2 = true,
4329 .psl = false,
4330},
4331.{
4332 .name = "fcomment-block-commands=",
4333 .syntax = .comma_joined,
4334 .zig_equivalent = .other,
4335 .pd1 = true,
4336 .pd2 = false,
4337 .psl = false,
4338},
4339joinpd1("flax-vector-conversions="),
4340joinpd1("fmodules-embed-all-files"),
4341joinpd1("fmodules-prune-interval="),
4342joinpd1("foverride-record-layout="),
4343joinpd1("fprofile-instr-generate="),
4344joinpd1("fprofile-remapping-file="),
4345joinpd1("fsanitize-coverage-type="),
4346joinpd1("fsanitize-hwaddress-abi="),
4347joinpd1("ftime-trace-granularity="),
4348jspd1("fxray-always-instrument="),
4349jspd1("internal-externc-isystem"),
4350.{
4351 .name = "libomptarget-nvptx-path=",
4352 .syntax = .joined,
4353 .zig_equivalent = .other,
4354 .pd1 = false,
4355 .pd2 = true,
4356 .psl = false,
4357},
4358.{
4359 .name = "no-system-header-prefix=",
4360 .syntax = .joined,
4361 .zig_equivalent = .other,
4362 .pd1 = false,
4363 .pd2 = true,
4364 .psl = false,
4365},
4366.{
4367 .name = "output-class-directory=",
4368 .syntax = .joined,
4369 .zig_equivalent = .other,
4370 .pd1 = false,
4371 .pd2 = true,
4372 .psl = false,
4373},
4374joinpd1("analyzer-inlining-mode="),
4375joinpd1("fconstant-string-class="),
4376joinpd1("fcrash-diagnostics-dir="),
4377joinpd1("fdebug-compilation-dir="),
4378joinpd1("fdebug-default-version="),
4379joinpd1("ffp-exception-behavior="),
4380joinpd1("fmacro-backtrace-limit="),
4381joinpd1("fmax-array-constructor="),
4382joinpd1("fprofile-exclude-files="),
4383joinpd1("ftrivial-auto-var-init="),
4384jspd1("fxray-never-instrument="),
4385jspd1("interface-stub-version="),
4386joinpd1("malign-branch-boundary="),
4387joinpd1("mappletvos-version-min="),
4388joinpd1("Wnonportable-cfstrings"),
4389joinpd1("fdefault-calling-conv="),
4390joinpd1("fmax-subrecord-length="),
4391joinpd1("fmodules-ignore-macro="),
4392.{
4393 .name = "fno-sanitize-coverage=",
4394 .syntax = .comma_joined,
4395 .zig_equivalent = .other,
4396 .pd1 = true,
4397 .pd2 = false,
4398 .psl = false,
4399},
4400joinpd1("fobjc-dispatch-method="),
4401joinpd1("foperator-arrow-depth="),
4402joinpd1("fprebuilt-module-path="),
4403joinpd1("fprofile-filter-files="),
4404joinpd1("fspell-checking-limit="),
4405joinpd1("miphoneos-version-min="),
4406joinpd1("msmall-data-threshold="),
4407joinpd1("Wlarge-by-value-copy="),
4408joinpd1("analyzer-constraints="),
4409joinpd1("analyzer-dump-egraph="),
4410jspd1("compatibility_version"),
4411jspd1("dylinker_install_name"),
4412joinpd1("fcs-profile-generate="),
4413joinpd1("fmodules-prune-after="),
4414.{
4415 .name = "fno-sanitize-recover=",
4416 .syntax = .comma_joined,
4417 .zig_equivalent = .other,
4418 .pd1 = true,
4419 .pd2 = false,
4420 .psl = false,
4421},
4422jspd1("iframeworkwithsysroot"),
4423joinpd1("mamdgpu-debugger-abi="),
4424joinpd1("mprefer-vector-width="),
4425joinpd1("msign-return-address="),
4426joinpd1("mwatchos-version-min="),
4427.{
4428 .name = "system-header-prefix=",
4429 .syntax = .joined,
4430 .zig_equivalent = .other,
4431 .pd1 = false,
4432 .pd2 = true,
4433 .psl = false,
4434},
4435.{
4436 .name = "include-with-prefix=",
4437 .syntax = .joined,
4438 .zig_equivalent = .other,
4439 .pd1 = false,
4440 .pd2 = true,
4441 .psl = false,
4442},
4443joinpd1("coverage-notes-file="),
4444joinpd1("fbuild-session-file="),
4445joinpd1("fdiagnostics-format="),
4446joinpd1("fmax-stack-var-size="),
4447joinpd1("fmodules-cache-path="),
4448joinpd1("fmodules-embed-file="),
4449joinpd1("fprofile-instrument="),
4450joinpd1("fprofile-sample-use="),
4451joinpd1("fsanitize-blacklist="),
4452.{
4453 .name = "hip-device-lib-path=",
4454 .syntax = .joined,
4455 .zig_equivalent = .other,
4456 .pd1 = false,
4457 .pd2 = true,
4458 .psl = false,
4459},
4460joinpd1("mmacosx-version-min="),
4461.{
4462 .name = "no-cuda-include-ptx=",
4463 .syntax = .joined,
4464 .zig_equivalent = .other,
4465 .pd1 = false,
4466 .pd2 = true,
4467 .psl = false,
4468},
4469joinpd1("Wframe-larger-than="),
4470joinpd1("code-completion-at="),
4471joinpd1("coverage-data-file="),
4472joinpd1("fblas-matmul-limit="),
4473joinpd1("fdiagnostics-color="),
4474joinpd1("ffixed-line-length-"),
4475joinpd1("flimited-precision="),
4476joinpd1("fprofile-instr-use="),
4477.{
4478 .name = "fsanitize-coverage=",
4479 .syntax = .comma_joined,
4480 .zig_equivalent = .other,
4481 .pd1 = true,
4482 .pd2 = false,
4483 .psl = false,
4484},
4485joinpd1("fthin-link-bitcode="),
4486joinpd1("mbranch-protection="),
4487joinpd1("mmacos-version-min="),
4488joinpd1("pch-through-header="),
4489joinpd1("target-sdk-version="),
4490.{
4491 .name = "execution-charset:",
4492 .syntax = .joined,
4493 .zig_equivalent = .other,
4494 .pd1 = true,
4495 .pd2 = false,
4496 .psl = true,
4497},
4498.{
4499 .name = "include-directory=",
4500 .syntax = .joined,
4501 .zig_equivalent = .other,
4502 .pd1 = false,
4503 .pd2 = true,
4504 .psl = false,
4505},
4506.{
4507 .name = "library-directory=",
4508 .syntax = .joined,
4509 .zig_equivalent = .other,
4510 .pd1 = false,
4511 .pd2 = true,
4512 .psl = false,
4513},
4514.{
4515 .name = "config-system-dir=",
4516 .syntax = .joined,
4517 .zig_equivalent = .other,
4518 .pd1 = false,
4519 .pd2 = true,
4520 .psl = false,
4521},
4522joinpd1("fclang-abi-compat="),
4523joinpd1("fcompile-resource="),
4524joinpd1("fdebug-prefix-map="),
4525joinpd1("fdenormal-fp-math="),
4526joinpd1("fexcess-precision="),
4527joinpd1("ffree-line-length-"),
4528joinpd1("fmacro-prefix-map="),
4529.{
4530 .name = "fno-sanitize-trap=",
4531 .syntax = .comma_joined,
4532 .zig_equivalent = .other,
4533 .pd1 = true,
4534 .pd2 = false,
4535 .psl = false,
4536},
4537joinpd1("fobjc-abi-version="),
4538joinpd1("foutput-class-dir="),
4539joinpd1("fprofile-generate="),
4540joinpd1("frewrite-map-file="),
4541.{
4542 .name = "fsanitize-recover=",
4543 .syntax = .comma_joined,
4544 .zig_equivalent = .other,
4545 .pd1 = true,
4546 .pd2 = false,
4547 .psl = false,
4548},
4549joinpd1("fsymbol-partition="),
4550joinpd1("mcompact-branches="),
4551joinpd1("mstack-probe-size="),
4552joinpd1("mtvos-version-min="),
4553joinpd1("working-directory="),
4554joinpd1("analyze-function="),
4555joinpd1("analyzer-checker="),
4556joinpd1("coverage-version="),
4557.{
4558 .name = "cuda-include-ptx=",
4559 .syntax = .joined,
4560 .zig_equivalent = .other,
4561 .pd1 = false,
4562 .pd2 = true,
4563 .psl = false,
4564},
4565joinpd1("falign-functions="),
4566joinpd1("fconstexpr-depth="),
4567joinpd1("fconstexpr-steps="),
4568joinpd1("ffile-prefix-map="),
4569joinpd1("fmodule-map-file="),
4570joinpd1("fobjc-arc-cxxlib="),
4571jspd1("iwithprefixbefore"),
4572joinpd1("malign-functions="),
4573joinpd1("mios-version-min="),
4574joinpd1("mstack-alignment="),
4575.{
4576 .name = "no-cuda-gpu-arch=",
4577 .syntax = .joined,
4578 .zig_equivalent = .other,
4579 .pd1 = false,
4580 .pd2 = true,
4581 .psl = false,
4582},
4583jspd1("working-directory"),
4584joinpd1("analyzer-output="),
4585.{
4586 .name = "config-user-dir=",
4587 .syntax = .joined,
4588 .zig_equivalent = .other,
4589 .pd1 = false,
4590 .pd2 = true,
4591 .psl = false,
4592},
4593joinpd1("debug-info-kind="),
4594joinpd1("debugger-tuning="),
4595joinpd1("fcf-runtime-abi="),
4596joinpd1("finit-character="),
4597joinpd1("fmax-type-align="),
4598joinpd1("fmessage-length="),
4599.{
4600 .name = "fopenmp-targets=",
4601 .syntax = .comma_joined,
4602 .zig_equivalent = .other,
4603 .pd1 = true,
4604 .pd2 = false,
4605 .psl = false,
4606},
4607joinpd1("fopenmp-version="),
4608joinpd1("fshow-overloads="),
4609joinpd1("ftemplate-depth-"),
4610joinpd1("ftemplate-depth="),
4611jspd1("fxray-attr-list="),
4612jspd1("internal-isystem"),
4613joinpd1("mlinker-version="),
4614.{
4615 .name = "print-file-name=",
4616 .syntax = .joined,
4617 .zig_equivalent = .other,
4618 .pd1 = true,
4619 .pd2 = true,
4620 .psl = false,
4621},
4622.{
4623 .name = "print-prog-name=",
4624 .syntax = .joined,
4625 .zig_equivalent = .other,
4626 .pd1 = true,
4627 .pd2 = true,
4628 .psl = false,
4629},
4630jspd1("stdlib++-isystem"),
4631joinpd1("Rpass-analysis="),
4632.{
4633 .name = "Xopenmp-target=",
4634 .syntax = .joined_and_separate,
4635 .zig_equivalent = .other,
4636 .pd1 = true,
4637 .pd2 = false,
4638 .psl = false,
4639},
4640.{
4641 .name = "source-charset:",
4642 .syntax = .joined,
4643 .zig_equivalent = .other,
4644 .pd1 = true,
4645 .pd2 = false,
4646 .psl = true,
4647},
4648.{
4649 .name = "analyzer-output",
4650 .syntax = .joined_or_separate,
4651 .zig_equivalent = .other,
4652 .pd1 = false,
4653 .pd2 = true,
4654 .psl = false,
4655},
4656.{
4657 .name = "include-prefix=",
4658 .syntax = .joined,
4659 .zig_equivalent = .other,
4660 .pd1 = false,
4661 .pd2 = true,
4662 .psl = false,
4663},
4664.{
4665 .name = "undefine-macro=",
4666 .syntax = .joined,
4667 .zig_equivalent = .other,
4668 .pd1 = false,
4669 .pd2 = true,
4670 .psl = false,
4671},
4672joinpd1("analyzer-purge="),
4673joinpd1("analyzer-store="),
4674jspd1("current_version"),
4675joinpd1("fbootclasspath="),
4676joinpd1("fbracket-depth="),
4677joinpd1("fcf-protection="),
4678joinpd1("fdepfile-entry="),
4679joinpd1("fembed-bitcode="),
4680joinpd1("finput-charset="),
4681joinpd1("fmodule-format="),
4682joinpd1("fms-memptr-rep="),
4683joinpd1("fnew-alignment="),
4684joinpd1("frecord-marker="),
4685.{
4686 .name = "fsanitize-trap=",
4687 .syntax = .comma_joined,
4688 .zig_equivalent = .other,
4689 .pd1 = true,
4690 .pd2 = false,
4691 .psl = false,
4692},
4693joinpd1("fthinlto-index="),
4694joinpd1("ftrap-function="),
4695joinpd1("ftrapv-handler="),
4696.{
4697 .name = "hip-device-lib=",
4698 .syntax = .joined,
4699 .zig_equivalent = .other,
4700 .pd1 = false,
4701 .pd2 = true,
4702 .psl = false,
4703},
4704joinpd1("mdynamic-no-pic"),
4705joinpd1("mframe-pointer="),
4706joinpd1("mindirect-jump="),
4707joinpd1("preamble-bytes="),
4708.{
4709 .name = "bootclasspath=",
4710 .syntax = .joined,
4711 .zig_equivalent = .other,
4712 .pd1 = false,
4713 .pd2 = true,
4714 .psl = false,
4715},
4716.{
4717 .name = "cuda-gpu-arch=",
4718 .syntax = .joined,
4719 .zig_equivalent = .other,
4720 .pd1 = false,
4721 .pd2 = true,
4722 .psl = false,
4723},
4724.{
4725 .name = "dependent-lib=",
4726 .syntax = .joined,
4727 .zig_equivalent = .other,
4728 .pd1 = false,
4729 .pd2 = true,
4730 .psl = false,
4731},
4732joinpd1("dwarf-version="),
4733joinpd1("falign-labels="),
4734joinpd1("fauto-profile="),
4735joinpd1("fexec-charset="),
4736joinpd1("fgnuc-version="),
4737joinpd1("finit-integer="),
4738joinpd1("finit-logical="),
4739joinpd1("finline-limit="),
4740joinpd1("fobjc-runtime="),
4741.{
4742 .name = "gcc-toolchain=",
4743 .syntax = .joined,
4744 .zig_equivalent = .other,
4745 .pd1 = false,
4746 .pd2 = true,
4747 .psl = false,
4748},
4749.{
4750 .name = "linker-option=",
4751 .syntax = .joined,
4752 .zig_equivalent = .other,
4753 .pd1 = false,
4754 .pd2 = true,
4755 .psl = false,
4756},
4757.{
4758 .name = "malign-branch=",
4759 .syntax = .comma_joined,
4760 .zig_equivalent = .other,
4761 .pd1 = true,
4762 .pd2 = false,
4763 .psl = false,
4764},
4765jspd1("objcxx-isystem"),
4766joinpd1("vtordisp-mode="),
4767joinpd1("Rpass-missed="),
4768joinpd1("Wlarger-than-"),
4769joinpd1("Wlarger-than="),
4770.{
4771 .name = "define-macro=",
4772 .syntax = .joined,
4773 .zig_equivalent = .other,
4774 .pd1 = false,
4775 .pd2 = true,
4776 .psl = false,
4777},
4778joinpd1("ast-dump-all="),
4779.{
4780 .name = "autocomplete=",
4781 .syntax = .joined,
4782 .zig_equivalent = .other,
4783 .pd1 = false,
4784 .pd2 = true,
4785 .psl = false,
4786},
4787joinpd1("falign-jumps="),
4788joinpd1("falign-loops="),
4789joinpd1("faligned-new="),
4790joinpd1("ferror-limit="),
4791joinpd1("ffp-contract="),
4792joinpd1("fmodule-file="),
4793joinpd1("fmodule-name="),
4794joinpd1("fmsc-version="),
4795.{
4796 .name = "fno-sanitize=",
4797 .syntax = .comma_joined,
4798 .zig_equivalent = .other,
4799 .pd1 = true,
4800 .pd2 = false,
4801 .psl = false,
4802},
4803joinpd1("fpack-struct="),
4804joinpd1("fpass-plugin="),
4805joinpd1("fprofile-dir="),
4806joinpd1("fprofile-use="),
4807joinpd1("frandom-seed="),
4808joinpd1("gsplit-dwarf="),
4809jspd1("isystem-after"),
4810joinpd1("malign-jumps="),
4811joinpd1("malign-loops="),
4812joinpd1("mimplicit-it="),
4813jspd1("pagezero_size"),
4814joinpd1("resource-dir="),
4815.{
4816 .name = "dyld-prefix=",
4817 .syntax = .joined,
4818 .zig_equivalent = .other,
4819 .pd1 = false,
4820 .pd2 = true,
4821 .psl = false,
4822},
4823.{
4824 .name = "driver-mode=",
4825 .syntax = .joined,
4826 .zig_equivalent = .other,
4827 .pd1 = false,
4828 .pd2 = true,
4829 .psl = false,
4830},
4831joinpd1("fmax-errors="),
4832joinpd1("fno-builtin-"),
4833joinpd1("fvisibility="),
4834joinpd1("fwchar-type="),
4835jspd1("fxray-modes="),
4836jspd1("iwithsysroot"),
4837joinpd1("mhvx-length="),
4838jspd1("objc-isystem"),
4839.{
4840 .name = "rsp-quoting=",
4841 .syntax = .joined,
4842 .zig_equivalent = .other,
4843 .pd1 = false,
4844 .pd2 = true,
4845 .psl = false,
4846},
4847joinpd1("std-default="),
4848jspd1("sub_umbrella"),
4849.{
4850 .name = "Qpar-report",
4851 .syntax = .joined,
4852 .zig_equivalent = .other,
4853 .pd1 = true,
4854 .pd2 = false,
4855 .psl = true,
4856},
4857.{
4858 .name = "Qvec-report",
4859 .syntax = .joined,
4860 .zig_equivalent = .other,
4861 .pd1 = true,
4862 .pd2 = false,
4863 .psl = true,
4864},
4865.{
4866 .name = "errorReport",
4867 .syntax = .joined,
4868 .zig_equivalent = .other,
4869 .pd1 = true,
4870 .pd2 = false,
4871 .psl = true,
4872},
4873.{
4874 .name = "for-linker=",
4875 .syntax = .joined,
4876 .zig_equivalent = .other,
4877 .pd1 = false,
4878 .pd2 = true,
4879 .psl = false,
4880},
4881.{
4882 .name = "force-link=",
4883 .syntax = .joined,
4884 .zig_equivalent = .other,
4885 .pd1 = false,
4886 .pd2 = true,
4887 .psl = false,
4888},
4889jspd1("client_name"),
4890jspd1("cxx-isystem"),
4891joinpd1("fclasspath="),
4892joinpd1("finit-real="),
4893joinpd1("fforce-addr"),
4894joinpd1("ftls-model="),
4895jspd1("ivfsoverlay"),
4896jspd1("iwithprefix"),
4897joinpd1("mfloat-abi="),
4898.{
4899 .name = "plugin-arg-",
4900 .syntax = .joined_and_separate,
4901 .zig_equivalent = .other,
4902 .pd1 = true,
4903 .pd2 = false,
4904 .psl = false,
4905},
4906.{
4907 .name = "ptxas-path=",
4908 .syntax = .joined,
4909 .zig_equivalent = .other,
4910 .pd1 = false,
4911 .pd2 = true,
4912 .psl = false,
4913},
4914.{
4915 .name = "save-stats=",
4916 .syntax = .joined,
4917 .zig_equivalent = .other,
4918 .pd1 = true,
4919 .pd2 = true,
4920 .psl = false,
4921},
4922.{
4923 .name = "save-temps=",
4924 .syntax = .joined,
4925 .zig_equivalent = .other,
4926 .pd1 = true,
4927 .pd2 = true,
4928 .psl = false,
4929},
4930joinpd1("stats-file="),
4931jspd1("sub_library"),
4932.{
4933 .name = "CLASSPATH=",
4934 .syntax = .joined,
4935 .zig_equivalent = .other,
4936 .pd1 = false,
4937 .pd2 = true,
4938 .psl = false,
4939},
4940.{
4941 .name = "constexpr:",
4942 .syntax = .joined,
4943 .zig_equivalent = .other,
4944 .pd1 = true,
4945 .pd2 = false,
4946 .psl = true,
4947},
4948.{
4949 .name = "classpath=",
4950 .syntax = .joined,
4951 .zig_equivalent = .other,
4952 .pd1 = false,
4953 .pd2 = true,
4954 .psl = false,
4955},
4956.{
4957 .name = "cuda-path=",
4958 .syntax = .joined,
4959 .zig_equivalent = .other,
4960 .pd1 = false,
4961 .pd2 = true,
4962 .psl = false,
4963},
4964joinpd1("fencoding="),
4965joinpd1("ffp-model="),
4966joinpd1("ffpe-trap="),
4967joinpd1("flto-jobs="),
4968.{
4969 .name = "fsanitize=",
4970 .syntax = .comma_joined,
4971 .zig_equivalent = .sanitize,
4972 .pd1 = true,
4973 .pd2 = false,
4974 .psl = false,
4975},
4976jspd1("iframework"),
4977joinpd1("mtls-size="),
4978joinpd1("segs_read_"),
4979.{
4980 .name = "unwindlib=",
4981 .syntax = .joined,
4982 .zig_equivalent = .other,
4983 .pd1 = true,
4984 .pd2 = true,
4985 .psl = false,
4986},
4987.{
4988 .name = "cgthreads",
4989 .syntax = .joined,
4990 .zig_equivalent = .other,
4991 .pd1 = true,
4992 .pd2 = false,
4993 .psl = true,
4994},
4995.{
4996 .name = "encoding=",
4997 .syntax = .joined,
4998 .zig_equivalent = .other,
4999 .pd1 = false,
5000 .pd2 = true,
5001 .psl = false,
5002},
5003.{
5004 .name = "language=",
5005 .syntax = .joined,
5006 .zig_equivalent = .other,
5007 .pd1 = false,
5008 .pd2 = true,
5009 .psl = false,
5010},
5011.{
5012 .name = "optimize=",
5013 .syntax = .joined,
5014 .zig_equivalent = .optimize,
5015 .pd1 = false,
5016 .pd2 = true,
5017 .psl = false,
5018},
5019.{
5020 .name = "resource=",
5021 .syntax = .joined,
5022 .zig_equivalent = .other,
5023 .pd1 = false,
5024 .pd2 = true,
5025 .psl = false,
5026},
5027joinpd1("ast-dump="),
5028jspd1("c-isystem"),
5029joinpd1("fcoarray="),
5030joinpd1("fconvert="),
5031joinpd1("fextdirs="),
5032joinpd1("ftabstop="),
5033jspd1("idirafter"),
5034joinpd1("mregparm="),
5035jspd1("undefined"),
5036.{
5037 .name = "extdirs=",
5038 .syntax = .joined,
5039 .zig_equivalent = .other,
5040 .pd1 = false,
5041 .pd2 = true,
5042 .psl = false,
5043},
5044.{
5045 .name = "imacros=",
5046 .syntax = .joined,
5047 .zig_equivalent = .other,
5048 .pd1 = false,
5049 .pd2 = true,
5050 .psl = false,
5051},
5052.{
5053 .name = "include=",
5054 .syntax = .joined,
5055 .zig_equivalent = .other,
5056 .pd1 = false,
5057 .pd2 = true,
5058 .psl = false,
5059},
5060.{
5061 .name = "sysroot=",
5062 .syntax = .joined,
5063 .zig_equivalent = .other,
5064 .pd1 = false,
5065 .pd2 = true,
5066 .psl = false,
5067},
5068joinpd1("fopenmp="),
5069joinpd1("fplugin="),
5070joinpd1("fuse-ld="),
5071joinpd1("fveclib="),
5072jspd1("isysroot"),
5073joinpd1("mcmodel="),
5074joinpd1("mconsole"),
5075joinpd1("mfpmath="),
5076joinpd1("mhwmult="),
5077joinpd1("mthreads"),
5078joinpd1("municode"),
5079joinpd1("mwindows"),
5080jspd1("seg1addr"),
5081.{
5082 .name = "assert=",
5083 .syntax = .joined,
5084 .zig_equivalent = .other,
5085 .pd1 = false,
5086 .pd2 = true,
5087 .psl = false,
5088},
5089.{
5090 .name = "mhwdiv=",
5091 .syntax = .joined,
5092 .zig_equivalent = .other,
5093 .pd1 = false,
5094 .pd2 = true,
5095 .psl = false,
5096},
5097.{
5098 .name = "output=",
5099 .syntax = .joined,
5100 .zig_equivalent = .other,
5101 .pd1 = false,
5102 .pd2 = true,
5103 .psl = false,
5104},
5105.{
5106 .name = "prefix=",
5107 .syntax = .joined,
5108 .zig_equivalent = .other,
5109 .pd1 = false,
5110 .pd2 = true,
5111 .psl = false,
5112},
5113.{
5114 .name = "cl-ext=",
5115 .syntax = .comma_joined,
5116 .zig_equivalent = .other,
5117 .pd1 = true,
5118 .pd2 = false,
5119 .psl = false,
5120},
5121joinpd1("cl-std="),
5122joinpd1("fcheck="),
5123.{
5124 .name = "imacros",
5125 .syntax = .joined_or_separate,
5126 .zig_equivalent = .other,
5127 .pd1 = true,
5128 .pd2 = true,
5129 .psl = false,
5130},
5131.{
5132 .name = "include",
5133 .syntax = .joined_or_separate,
5134 .zig_equivalent = .other,
5135 .pd1 = true,
5136 .pd2 = true,
5137 .psl = false,
5138},
5139jspd1("iprefix"),
5140jspd1("isystem"),
5141joinpd1("mhwdiv="),
5142joinpd1("moslib="),
5143.{
5144 .name = "mrecip=",
5145 .syntax = .comma_joined,
5146 .zig_equivalent = .other,
5147 .pd1 = true,
5148 .pd2 = false,
5149 .psl = false,
5150},
5151.{
5152 .name = "stdlib=",
5153 .syntax = .joined,
5154 .zig_equivalent = .other,
5155 .pd1 = true,
5156 .pd2 = true,
5157 .psl = false,
5158},
5159.{
5160 .name = "target=",
5161 .syntax = .joined,
5162 .zig_equivalent = .target,
5163 .pd1 = false,
5164 .pd2 = true,
5165 .psl = false,
5166},
5167joinpd1("triple="),
5168.{
5169 .name = "verify=",
5170 .syntax = .comma_joined,
5171 .zig_equivalent = .other,
5172 .pd1 = true,
5173 .pd2 = false,
5174 .psl = false,
5175},
5176joinpd1("Rpass="),
5177.{
5178 .name = "Xarch_",
5179 .syntax = .joined_and_separate,
5180 .zig_equivalent = .other,
5181 .pd1 = true,
5182 .pd2 = false,
5183 .psl = false,
5184},
5185.{
5186 .name = "clang:",
5187 .syntax = .joined,
5188 .zig_equivalent = .other,
5189 .pd1 = true,
5190 .pd2 = false,
5191 .psl = true,
5192},
5193.{
5194 .name = "guard:",
5195 .syntax = .joined,
5196 .zig_equivalent = .other,
5197 .pd1 = true,
5198 .pd2 = false,
5199 .psl = true,
5200},
5201.{
5202 .name = "debug=",
5203 .syntax = .joined,
5204 .zig_equivalent = .debug,
5205 .pd1 = false,
5206 .pd2 = true,
5207 .psl = false,
5208},
5209.{
5210 .name = "param=",
5211 .syntax = .joined,
5212 .zig_equivalent = .other,
5213 .pd1 = false,
5214 .pd2 = true,
5215 .psl = false,
5216},
5217.{
5218 .name = "warn-=",
5219 .syntax = .joined,
5220 .zig_equivalent = .other,
5221 .pd1 = false,
5222 .pd2 = true,
5223 .psl = false,
5224},
5225joinpd1("fixit="),
5226joinpd1("gstabs"),
5227joinpd1("gxcoff"),
5228jspd1("iquote"),
5229joinpd1("march="),
5230joinpd1("mtune="),
5231.{
5232 .name = "rtlib=",
5233 .syntax = .joined,
5234 .zig_equivalent = .other,
5235 .pd1 = true,
5236 .pd2 = true,
5237 .psl = false,
5238},
5239.{
5240 .name = "specs=",
5241 .syntax = .joined,
5242 .zig_equivalent = .other,
5243 .pd1 = true,
5244 .pd2 = true,
5245 .psl = false,
5246},
5247joinpd1("weak-l"),
5248.{
5249 .name = "Ofast",
5250 .syntax = .joined,
5251 .zig_equivalent = .optimize,
5252 .pd1 = true,
5253 .pd2 = false,
5254 .psl = false,
5255},
5256jspd1("Tdata"),
5257jspd1("Ttext"),
5258.{
5259 .name = "arch:",
5260 .syntax = .joined,
5261 .zig_equivalent = .other,
5262 .pd1 = true,
5263 .pd2 = false,
5264 .psl = true,
5265},
5266.{
5267 .name = "favor",
5268 .syntax = .joined,
5269 .zig_equivalent = .other,
5270 .pd1 = true,
5271 .pd2 = false,
5272 .psl = true,
5273},
5274.{
5275 .name = "imsvc",
5276 .syntax = .joined_or_separate,
5277 .zig_equivalent = .other,
5278 .pd1 = true,
5279 .pd2 = false,
5280 .psl = true,
5281},
5282.{
5283 .name = "warn-",
5284 .syntax = .joined,
5285 .zig_equivalent = .other,
5286 .pd1 = false,
5287 .pd2 = true,
5288 .psl = false,
5289},
5290joinpd1("flto="),
5291joinpd1("gcoff"),
5292joinpd1("mabi="),
5293joinpd1("mabs="),
5294joinpd1("masm="),
5295joinpd1("mcpu="),
5296joinpd1("mfpu="),
5297joinpd1("mhvx="),
5298joinpd1("mmcu="),
5299joinpd1("mnan="),
5300jspd1("Tbss"),
5301.{
5302 .name = "link",
5303 .syntax = .remaining_args_joined,
5304 .zig_equivalent = .other,
5305 .pd1 = true,
5306 .pd2 = false,
5307 .psl = true,
5308},
5309.{
5310 .name = "std:",
5311 .syntax = .joined,
5312 .zig_equivalent = .other,
5313 .pd1 = true,
5314 .pd2 = false,
5315 .psl = true,
5316},
5317joinpd1("ccc-"),
5318joinpd1("gvms"),
5319joinpd1("mdll"),
5320joinpd1("mtp="),
5321.{
5322 .name = "std=",
5323 .syntax = .joined,
5324 .zig_equivalent = .other,
5325 .pd1 = true,
5326 .pd2 = true,
5327 .psl = false,
5328},
5329.{
5330 .name = "Wa,",
5331 .syntax = .comma_joined,
5332 .zig_equivalent = .other,
5333 .pd1 = true,
5334 .pd2 = false,
5335 .psl = false,
5336},
5337.{
5338 .name = "Wl,",
5339 .syntax = .comma_joined,
5340 .zig_equivalent = .wl,
5341 .pd1 = true,
5342 .pd2 = false,
5343 .psl = false,
5344},
5345.{
5346 .name = "Wp,",
5347 .syntax = .comma_joined,
5348 .zig_equivalent = .other,
5349 .pd1 = true,
5350 .pd2 = false,
5351 .psl = false,
5352},
5353.{
5354 .name = "RTC",
5355 .syntax = .joined,
5356 .zig_equivalent = .other,
5357 .pd1 = true,
5358 .pd2 = false,
5359 .psl = true,
5360},
5361.{
5362 .name = "Zc:",
5363 .syntax = .joined,
5364 .zig_equivalent = .other,
5365 .pd1 = true,
5366 .pd2 = false,
5367 .psl = true,
5368},
5369.{
5370 .name = "clr",
5371 .syntax = .joined,
5372 .zig_equivalent = .other,
5373 .pd1 = true,
5374 .pd2 = false,
5375 .psl = true,
5376},
5377.{
5378 .name = "doc",
5379 .syntax = .joined,
5380 .zig_equivalent = .other,
5381 .pd1 = true,
5382 .pd2 = false,
5383 .psl = true,
5384},
5385joinpd1("gz="),
5386joinpd1("A-"),
5387joinpd1("G="),
5388jspd1("MF"),
5389jspd1("MJ"),
5390jspd1("MQ"),
5391jspd1("MT"),
5392.{
5393 .name = "AI",
5394 .syntax = .joined_or_separate,
5395 .zig_equivalent = .other,
5396 .pd1 = true,
5397 .pd2 = false,
5398 .psl = true,
5399},
5400.{
5401 .name = "EH",
5402 .syntax = .joined,
5403 .zig_equivalent = .other,
5404 .pd1 = true,
5405 .pd2 = false,
5406 .psl = true,
5407},
5408.{
5409 .name = "FA",
5410 .syntax = .joined,
5411 .zig_equivalent = .other,
5412 .pd1 = true,
5413 .pd2 = false,
5414 .psl = true,
5415},
5416.{
5417 .name = "FI",
5418 .syntax = .joined_or_separate,
5419 .zig_equivalent = .other,
5420 .pd1 = true,
5421 .pd2 = false,
5422 .psl = true,
5423},
5424.{
5425 .name = "FR",
5426 .syntax = .joined,
5427 .zig_equivalent = .other,
5428 .pd1 = true,
5429 .pd2 = false,
5430 .psl = true,
5431},
5432.{
5433 .name = "FU",
5434 .syntax = .joined_or_separate,
5435 .zig_equivalent = .other,
5436 .pd1 = true,
5437 .pd2 = false,
5438 .psl = true,
5439},
5440.{
5441 .name = "Fa",
5442 .syntax = .joined,
5443 .zig_equivalent = .other,
5444 .pd1 = true,
5445 .pd2 = false,
5446 .psl = true,
5447},
5448.{
5449 .name = "Fd",
5450 .syntax = .joined,
5451 .zig_equivalent = .other,
5452 .pd1 = true,
5453 .pd2 = false,
5454 .psl = true,
5455},
5456.{
5457 .name = "Fe",
5458 .syntax = .joined,
5459 .zig_equivalent = .other,
5460 .pd1 = true,
5461 .pd2 = false,
5462 .psl = true,
5463},
5464.{
5465 .name = "Fi",
5466 .syntax = .joined,
5467 .zig_equivalent = .other,
5468 .pd1 = true,
5469 .pd2 = false,
5470 .psl = true,
5471},
5472.{
5473 .name = "Fm",
5474 .syntax = .joined,
5475 .zig_equivalent = .other,
5476 .pd1 = true,
5477 .pd2 = false,
5478 .psl = true,
5479},
5480.{
5481 .name = "Fo",
5482 .syntax = .joined,
5483 .zig_equivalent = .other,
5484 .pd1 = true,
5485 .pd2 = false,
5486 .psl = true,
5487},
5488.{
5489 .name = "Fp",
5490 .syntax = .joined,
5491 .zig_equivalent = .other,
5492 .pd1 = true,
5493 .pd2 = false,
5494 .psl = true,
5495},
5496.{
5497 .name = "Fr",
5498 .syntax = .joined,
5499 .zig_equivalent = .other,
5500 .pd1 = true,
5501 .pd2 = false,
5502 .psl = true,
5503},
5504.{
5505 .name = "Gs",
5506 .syntax = .joined,
5507 .zig_equivalent = .other,
5508 .pd1 = true,
5509 .pd2 = false,
5510 .psl = true,
5511},
5512.{
5513 .name = "MP",
5514 .syntax = .joined,
5515 .zig_equivalent = .other,
5516 .pd1 = true,
5517 .pd2 = false,
5518 .psl = true,
5519},
5520.{
5521 .name = "Tc",
5522 .syntax = .joined_or_separate,
5523 .zig_equivalent = .other,
5524 .pd1 = true,
5525 .pd2 = false,
5526 .psl = true,
5527},
5528.{
5529 .name = "Tp",
5530 .syntax = .joined_or_separate,
5531 .zig_equivalent = .other,
5532 .pd1 = true,
5533 .pd2 = false,
5534 .psl = true,
5535},
5536.{
5537 .name = "Yc",
5538 .syntax = .joined,
5539 .zig_equivalent = .other,
5540 .pd1 = true,
5541 .pd2 = false,
5542 .psl = true,
5543},
5544.{
5545 .name = "Yl",
5546 .syntax = .joined,
5547 .zig_equivalent = .other,
5548 .pd1 = true,
5549 .pd2 = false,
5550 .psl = true,
5551},
5552.{
5553 .name = "Yu",
5554 .syntax = .joined,
5555 .zig_equivalent = .other,
5556 .pd1 = true,
5557 .pd2 = false,
5558 .psl = true,
5559},
5560.{
5561 .name = "ZW",
5562 .syntax = .joined,
5563 .zig_equivalent = .other,
5564 .pd1 = true,
5565 .pd2 = false,
5566 .psl = true,
5567},
5568.{
5569 .name = "Zm",
5570 .syntax = .joined,
5571 .zig_equivalent = .other,
5572 .pd1 = true,
5573 .pd2 = false,
5574 .psl = true,
5575},
5576.{
5577 .name = "Zp",
5578 .syntax = .joined,
5579 .zig_equivalent = .other,
5580 .pd1 = true,
5581 .pd2 = false,
5582 .psl = true,
5583},
5584.{
5585 .name = "d2",
5586 .syntax = .joined,
5587 .zig_equivalent = .other,
5588 .pd1 = true,
5589 .pd2 = false,
5590 .psl = true,
5591},
5592.{
5593 .name = "vd",
5594 .syntax = .joined,
5595 .zig_equivalent = .other,
5596 .pd1 = true,
5597 .pd2 = false,
5598 .psl = true,
5599},
5600jspd1("A"),
5601jspd1("B"),
5602jspd1("D"),
5603jspd1("F"),
5604jspd1("G"),
5605jspd1("I"),
5606jspd1("J"),
5607jspd1("L"),
5608.{
5609 .name = "O",
5610 .syntax = .joined,
5611 .zig_equivalent = .optimize,
5612 .pd1 = true,
5613 .pd2 = false,
5614 .psl = false,
5615},
5616joinpd1("R"),
5617jspd1("T"),
5618jspd1("U"),
5619jspd1("V"),
5620joinpd1("W"),
5621joinpd1("X"),
5622joinpd1("Z"),
5623.{
5624 .name = "D",
5625 .syntax = .joined_or_separate,
5626 .zig_equivalent = .other,
5627 .pd1 = true,
5628 .pd2 = false,
5629 .psl = true,
5630},
5631.{
5632 .name = "F",
5633 .syntax = .joined_or_separate,
5634 .zig_equivalent = .other,
5635 .pd1 = true,
5636 .pd2 = false,
5637 .psl = true,
5638},
5639.{
5640 .name = "I",
5641 .syntax = .joined_or_separate,
5642 .zig_equivalent = .other,
5643 .pd1 = true,
5644 .pd2 = false,
5645 .psl = true,
5646},
5647.{
5648 .name = "O",
5649 .syntax = .joined,
5650 .zig_equivalent = .optimize,
5651 .pd1 = true,
5652 .pd2 = false,
5653 .psl = true,
5654},
5655.{
5656 .name = "U",
5657 .syntax = .joined_or_separate,
5658 .zig_equivalent = .other,
5659 .pd1 = true,
5660 .pd2 = false,
5661 .psl = true,
5662},
5663.{
5664 .name = "o",
5665 .syntax = .joined_or_separate,
5666 .zig_equivalent = .o,
5667 .pd1 = true,
5668 .pd2 = false,
5669 .psl = true,
5670},
5671.{
5672 .name = "w",
5673 .syntax = .joined,
5674 .zig_equivalent = .other,
5675 .pd1 = true,
5676 .pd2 = false,
5677 .psl = true,
5678},
5679joinpd1("a"),
5680jspd1("b"),
5681joinpd1("d"),
5682jspd1("e"),
5683.{
5684 .name = "l",
5685 .syntax = .joined_or_separate,
5686 .zig_equivalent = .l,
5687 .pd1 = true,
5688 .pd2 = false,
5689 .psl = false,
5690},
5691.{
5692 .name = "o",
5693 .syntax = .joined_or_separate,
5694 .zig_equivalent = .o,
5695 .pd1 = true,
5696 .pd2 = false,
5697 .psl = false,
5698},
5699jspd1("u"),
5700jspd1("x"),
5701joinpd1("y"),
5702};};
src-self-hosted/compilation.zig+17-16
......@@ -95,7 +95,7 @@ pub const ZigCompiler = struct {
9595
9696 pub fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
9797 if (self.native_libc.start()) |ptr| return ptr;
98 try self.native_libc.data.findNative(self.allocator);
98 self.native_libc.data = try LibCInstallation.findNative(.{ .allocator = self.allocator });
9999 self.native_libc.resolve();
100100 return &self.native_libc.data;
101101 }
......@@ -126,7 +126,7 @@ pub const Compilation = struct {
126126 name: Buffer,
127127 llvm_triple: Buffer,
128128 root_src_path: ?[]const u8,
129 target: Target,
129 target: std.Target,
130130 llvm_target: *llvm.Target,
131131 build_mode: builtin.Mode,
132132 zig_lib_dir: []const u8,
......@@ -338,7 +338,7 @@ pub const Compilation = struct {
338338 zig_compiler: *ZigCompiler,
339339 name: []const u8,
340340 root_src_path: ?[]const u8,
341 target: Target,
341 target: std.zig.CrossTarget,
342342 kind: Kind,
343343 build_mode: builtin.Mode,
344344 is_static: bool,
......@@ -370,13 +370,18 @@ pub const Compilation = struct {
370370 zig_compiler: *ZigCompiler,
371371 name: []const u8,
372372 root_src_path: ?[]const u8,
373 target: Target,
373 cross_target: std.zig.CrossTarget,
374374 kind: Kind,
375375 build_mode: builtin.Mode,
376376 is_static: bool,
377377 zig_lib_dir: []const u8,
378378 ) !void {
379379 const allocator = zig_compiler.allocator;
380
381 // TODO merge this line with stage2.zig crossTargetToTarget
382 const target_info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator, cross_target);
383 const target = target_info.target;
384
380385 var comp = Compilation{
381386 .arena_allocator = std.heap.ArenaAllocator.init(allocator),
382387 .zig_compiler = zig_compiler,
......@@ -419,7 +424,7 @@ pub const Compilation = struct {
419424 .target_machine = undefined,
420425 .target_data_ref = undefined,
421426 .target_layout_str = undefined,
422 .target_ptr_bits = target.getArchPtrBitWidth(),
427 .target_ptr_bits = target.cpu.arch.ptrBitWidth(),
423428
424429 .root_package = undefined,
425430 .std_package = undefined,
......@@ -440,7 +445,7 @@ pub const Compilation = struct {
440445 }
441446
442447 comp.name = try Buffer.init(comp.arena(), name);
443 comp.llvm_triple = try util.getTriple(comp.arena(), target);
448 comp.llvm_triple = try util.getLLVMTriple(comp.arena(), target);
444449 comp.llvm_target = try util.llvmTargetFromTriple(comp.llvm_triple);
445450 comp.zig_std_dir = try fs.path.join(comp.arena(), &[_][]const u8{ zig_lib_dir, "std" });
446451
......@@ -451,17 +456,12 @@ pub const Compilation = struct {
451456
452457 const reloc_mode = if (is_static) llvm.RelocStatic else llvm.RelocPIC;
453458
454 // LLVM creates invalid binaries on Windows sometimes.
455 // See https://github.com/ziglang/zig/issues/508
456 // As a workaround we do not use target native features on Windows.
457459 var target_specific_cpu_args: ?[*:0]u8 = null;
458460 var target_specific_cpu_features: ?[*:0]u8 = null;
459461 defer llvm.DisposeMessage(target_specific_cpu_args);
460462 defer llvm.DisposeMessage(target_specific_cpu_features);
461 if (target == Target.Native and !target.isWindows()) {
462 target_specific_cpu_args = llvm.GetHostCPUName() orelse return error.OutOfMemory;
463 target_specific_cpu_features = llvm.GetNativeFeatures() orelse return error.OutOfMemory;
464 }
463
464 // TODO detect native CPU & features here
465465
466466 comp.target_machine = llvm.CreateTargetMachine(
467467 comp.llvm_target,
......@@ -520,8 +520,7 @@ pub const Compilation = struct {
520520
521521 if (comp.tmp_dir.getOrNull()) |tmp_dir_result|
522522 if (tmp_dir_result.*) |tmp_dir| {
523 // TODO evented I/O?
524 fs.deleteTree(tmp_dir) catch {};
523 fs.cwd().deleteTree(tmp_dir) catch {};
525524 } else |_| {};
526525 }
527526
......@@ -1125,7 +1124,9 @@ pub const Compilation = struct {
11251124 self.libc_link_lib = link_lib;
11261125
11271126 // get a head start on looking for the native libc
1128 if (self.target == Target.Native and self.override_libc == null) {
1127 // TODO this is missing a bunch of logic related to whether the target is native
1128 // and whether we can build libc
1129 if (self.override_libc == null) {
11291130 try self.deinit_group.call(startFindingNativeLibC, .{self});
11301131 }
11311132 }
src-self-hosted/errmsg.zig+4-7
......@@ -164,8 +164,7 @@ pub const Msg = struct {
164164 const realpath_copy = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);
165165 errdefer comp.gpa().free(realpath_copy);
166166
167 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
168 try parse_error.render(&tree_scope.tree.tokens, out_stream);
167 try parse_error.render(&tree_scope.tree.tokens, text_buf.outStream());
169168
170169 const msg = try comp.gpa().create(Msg);
171170 msg.* = Msg{
......@@ -204,8 +203,7 @@ pub const Msg = struct {
204203 const realpath_copy = try mem.dupe(allocator, u8, realpath);
205204 errdefer allocator.free(realpath_copy);
206205
207 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
208 try parse_error.render(&tree.tokens, out_stream);
206 try parse_error.render(&tree.tokens, text_buf.outStream());
209207
210208 const msg = try allocator.create(Msg);
211209 msg.* = Msg{
......@@ -272,7 +270,7 @@ pub const Msg = struct {
272270 });
273271 try stream.writeByteNTimes(' ', start_loc.column);
274272 try stream.writeByteNTimes('~', last_token.end - first_token.start);
275 try stream.write("\n");
273 try stream.writeAll("\n");
276274 }
277275
278276 pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void {
......@@ -281,7 +279,6 @@ pub const Msg = struct {
281279 .On => true,
282280 .Off => false,
283281 };
284 var stream = &file.outStream().stream;
285 return msg.printToStream(stream, color_on);
282 return msg.printToStream(file.outStream(), color_on);
286283 }
287284};
src-self-hosted/ir.zig+10-7
......@@ -1099,7 +1099,6 @@ pub const Builder = struct {
10991099 .Await => return error.Unimplemented,
11001100 .BitNot => return error.Unimplemented,
11011101 .BoolNot => return error.Unimplemented,
1102 .Cancel => return error.Unimplemented,
11031102 .OptionalType => return error.Unimplemented,
11041103 .Negation => return error.Unimplemented,
11051104 .NegationWrap => return error.Unimplemented,
......@@ -1188,6 +1187,7 @@ pub const Builder = struct {
11881187 .ParamDecl => return error.Unimplemented,
11891188 .FieldInitializer => return error.Unimplemented,
11901189 .EnumLiteral => return error.Unimplemented,
1190 .Noasync => return error.Unimplemented,
11911191 }
11921192 }
11931193
......@@ -1311,13 +1311,16 @@ pub const Builder = struct {
13111311 var base: u8 = undefined;
13121312 var rest: []const u8 = undefined;
13131313 if (int_token.len >= 3 and int_token[0] == '0') {
1314 base = switch (int_token[1]) {
1315 'b' => 2,
1316 'o' => 8,
1317 'x' => 16,
1318 else => unreachable,
1319 };
13201314 rest = int_token[2..];
1315 switch (int_token[1]) {
1316 'b' => base = 2,
1317 'o' => base = 8,
1318 'x' => base = 16,
1319 else => {
1320 base = 10;
1321 rest = int_token;
1322 },
1323 }
13211324 } else {
13221325 base = 10;
13231326 rest = int_token;
src-self-hosted/libc_installation.zig+5-5
......@@ -280,7 +280,7 @@ pub const LibCInstallation = struct {
280280 // search in reverse order
281281 const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
282282 const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");
283 var search_dir = fs.cwd().openDirList(search_path) catch |err| switch (err) {
283 var search_dir = fs.cwd().openDir(search_path, .{}) catch |err| switch (err) {
284284 error.FileNotFound,
285285 error.NotDir,
286286 error.NoDevice,
......@@ -335,7 +335,7 @@ pub const LibCInstallation = struct {
335335 const stream = result_buf.outStream();
336336 try stream.print("{}\\Include\\{}\\ucrt", .{ search.path, search.version });
337337
338 var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
338 var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) {
339339 error.FileNotFound,
340340 error.NotDir,
341341 error.NoDevice,
......@@ -382,7 +382,7 @@ pub const LibCInstallation = struct {
382382 const stream = result_buf.outStream();
383383 try stream.print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir });
384384
385 var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
385 var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) {
386386 error.FileNotFound,
387387 error.NotDir,
388388 error.NoDevice,
......@@ -437,7 +437,7 @@ pub const LibCInstallation = struct {
437437 const stream = result_buf.outStream();
438438 try stream.print("{}\\Lib\\{}\\um\\{}", .{ search.path, search.version, arch_sub_dir });
439439
440 var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
440 var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) {
441441 error.FileNotFound,
442442 error.NotDir,
443443 error.NoDevice,
......@@ -475,7 +475,7 @@ pub const LibCInstallation = struct {
475475
476476 try result_buf.append("\\include");
477477
478 var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
478 var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) {
479479 error.FileNotFound,
480480 error.NotDir,
481481 error.NoDevice,
src-self-hosted/link.zig+54-58
......@@ -56,12 +56,13 @@ pub fn link(comp: *Compilation) !void {
5656 if (comp.haveLibC()) {
5757 // TODO https://github.com/ziglang/zig/issues/3190
5858 var libc = ctx.comp.override_libc orelse blk: {
59 switch (comp.target) {
60 Target.Native => {
61 break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound;
62 },
63 else => return error.LibCRequiredButNotProvidedOrFound,
64 }
59 @panic("this code has bitrotted");
60 //switch (comp.target) {
61 // Target.Native => {
62 // break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound;
63 // },
64 // else => return error.LibCRequiredButNotProvidedOrFound,
65 //}
6566 };
6667 ctx.libc = libc;
6768 }
......@@ -155,11 +156,11 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
155156 //bool shared = !g->is_static && is_lib;
156157 //Buf *soname = nullptr;
157158 if (ctx.comp.is_static) {
158 if (util.isArmOrThumb(ctx.comp.target)) {
159 try ctx.args.append("-Bstatic");
160 } else {
161 try ctx.args.append("-static");
162 }
159 //if (util.isArmOrThumb(ctx.comp.target)) {
160 // try ctx.args.append("-Bstatic");
161 //} else {
162 // try ctx.args.append("-static");
163 //}
163164 }
164165 //} else if (shared) {
165166 // lj->args.append("-shared");
......@@ -176,29 +177,24 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
176177
177178 if (ctx.link_in_crt) {
178179 const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o";
179 const crtbegino = if (ctx.comp.is_static) "crtbeginT.o" else "crtbegin.o";
180 try addPathJoin(ctx, ctx.libc.lib_dir.?, crt1o);
181 try addPathJoin(ctx, ctx.libc.lib_dir.?, "crti.o");
182 try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino);
180 try addPathJoin(ctx, ctx.libc.crt_dir.?, crt1o);
181 try addPathJoin(ctx, ctx.libc.crt_dir.?, "crti.o");
183182 }
184183
185184 if (ctx.comp.haveLibC()) {
186185 try ctx.args.append("-L");
187186 // TODO addNullByte should probably return [:0]u8
188 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr));
187 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.crt_dir.?)).ptr));
189188
190 try ctx.args.append("-L");
191 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr));
192
193 if (!ctx.comp.is_static) {
194 const dl = blk: {
195 if (ctx.libc.dynamic_linker_path) |dl| break :blk dl;
196 if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl;
197 return error.LibCMissingDynamicLinker;
198 };
199 try ctx.args.append("-dynamic-linker");
200 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr));
201 }
189 //if (!ctx.comp.is_static) {
190 // const dl = blk: {
191 // //if (ctx.libc.dynamic_linker_path) |dl| break :blk dl;
192 // //if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl;
193 // return error.LibCMissingDynamicLinker;
194 // };
195 // try ctx.args.append("-dynamic-linker");
196 // try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr));
197 //}
202198 }
203199
204200 //if (shared) {
......@@ -265,13 +261,12 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
265261
266262 // crt end
267263 if (ctx.link_in_crt) {
268 try addPathJoin(ctx, ctx.libc.static_lib_dir.?, "crtend.o");
269 try addPathJoin(ctx, ctx.libc.lib_dir.?, "crtn.o");
264 try addPathJoin(ctx, ctx.libc.crt_dir.?, "crtn.o");
270265 }
271266
272 if (ctx.comp.target != Target.Native) {
273 try ctx.args.append("--allow-shlib-undefined");
274 }
267 //if (ctx.comp.target != Target.Native) {
268 // try ctx.args.append("--allow-shlib-undefined");
269 //}
275270}
276271
277272fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
......@@ -287,7 +282,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
287282 try ctx.args.append("-DEBUG");
288283 }
289284
290 switch (ctx.comp.target.getArch()) {
285 switch (ctx.comp.target.cpu.arch) {
291286 .i386 => try ctx.args.append("-MACHINE:X86"),
292287 .x86_64 => try ctx.args.append("-MACHINE:X64"),
293288 .aarch64 => try ctx.args.append("-MACHINE:ARM"),
......@@ -302,7 +297,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
302297 if (ctx.comp.haveLibC()) {
303298 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr));
304299 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr));
305 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr));
300 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.crt_dir.?})).ptr));
306301 }
307302
308303 if (ctx.link_in_crt) {
......@@ -417,7 +412,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
417412 }
418413 },
419414 .IPhoneOS => {
420 if (ctx.comp.target.getArch() == .aarch64) {
415 if (ctx.comp.target.cpu.arch == .aarch64) {
421416 // iOS does not need any crt1 files for arm64
422417 } else if (platform.versionLessThan(3, 1)) {
423418 try ctx.args.append("-lcrt1.o");
......@@ -435,28 +430,29 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
435430 }
436431 try addFnObjects(ctx);
437432
438 if (ctx.comp.target == Target.Native) {
439 for (ctx.comp.link_libs_list.toSliceConst()) |lib| {
440 if (mem.eql(u8, lib.name, "c")) {
441 // on Darwin, libSystem has libc in it, but also you have to use it
442 // to make syscalls because the syscall numbers are not documented
443 // and change between versions.
444 // so we always link against libSystem
445 try ctx.args.append("-lSystem");
446 } else {
447 if (mem.indexOfScalar(u8, lib.name, '/') == null) {
448 const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});
449 try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
450 } else {
451 const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);
452 try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
453 }
454 }
455 }
456 } else {
457 try ctx.args.append("-undefined");
458 try ctx.args.append("dynamic_lookup");
459 }
433 // TODO
434 //if (ctx.comp.target == Target.Native) {
435 // for (ctx.comp.link_libs_list.toSliceConst()) |lib| {
436 // if (mem.eql(u8, lib.name, "c")) {
437 // // on Darwin, libSystem has libc in it, but also you have to use it
438 // // to make syscalls because the syscall numbers are not documented
439 // // and change between versions.
440 // // so we always link against libSystem
441 // try ctx.args.append("-lSystem");
442 // } else {
443 // if (mem.indexOfScalar(u8, lib.name, '/') == null) {
444 // const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});
445 // try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
446 // } else {
447 // const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);
448 // try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
449 // }
450 // }
451 // }
452 //} else {
453 // try ctx.args.append("-undefined");
454 // try ctx.args.append("dynamic_lookup");
455 //}
460456
461457 if (platform.kind == .MacOS) {
462458 if (platform.versionLessThan(10, 5)) {
src-self-hosted/main.zig+56-47
......@@ -18,10 +18,6 @@ const Target = std.Target;
1818const errmsg = @import("errmsg.zig");
1919const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
2020
21var stderr_file: fs.File = undefined;
22var stderr: *io.OutStream(fs.File.WriteError) = undefined;
23var stdout: *io.OutStream(fs.File.WriteError) = undefined;
24
2521pub const io_mode = .evented;
2622
2723pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
......@@ -51,17 +47,14 @@ const Command = struct {
5147pub fn main() !void {
5248 const allocator = std.heap.c_allocator;
5349
54 stdout = &std.io.getStdOut().outStream().stream;
55
56 stderr_file = std.io.getStdErr();
57 stderr = &stderr_file.outStream().stream;
50 const stderr = io.getStdErr().outStream();
5851
5952 const args = try process.argsAlloc(allocator);
6053 defer process.argsFree(allocator, args);
6154
6255 if (args.len <= 1) {
63 try stderr.write("expected command argument\n\n");
64 try stderr.write(usage);
56 try stderr.writeAll("expected command argument\n\n");
57 try stderr.writeAll(usage);
6558 process.exit(1);
6659 }
6760
......@@ -78,8 +71,8 @@ pub fn main() !void {
7871 } else if (mem.eql(u8, cmd, "libc")) {
7972 return cmdLibC(allocator, cmd_args);
8073 } else if (mem.eql(u8, cmd, "targets")) {
81 const info = try std.zig.system.NativeTargetInfo.detect(allocator);
82 defer info.deinit(allocator);
74 const info = try std.zig.system.NativeTargetInfo.detect(allocator, .{});
75 const stdout = io.getStdOut().outStream();
8376 return @import("print_targets.zig").cmdTargets(allocator, cmd_args, stdout, info.target);
8477 } else if (mem.eql(u8, cmd, "version")) {
8578 return cmdVersion(allocator, cmd_args);
......@@ -91,7 +84,7 @@ pub fn main() !void {
9184 return cmdInternal(allocator, cmd_args);
9285 } else {
9386 try stderr.print("unknown command: {}\n\n", .{args[1]});
94 try stderr.write(usage);
87 try stderr.writeAll(usage);
9588 process.exit(1);
9689 }
9790}
......@@ -156,6 +149,8 @@ const usage_build_generic =
156149;
157150
158151fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {
152 const stderr = io.getStdErr().outStream();
153
159154 var color: errmsg.Color = .Auto;
160155 var build_mode: std.builtin.Mode = .Debug;
161156 var emit_bin = true;
......@@ -208,11 +203,11 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
208203 const arg = args[i];
209204 if (mem.startsWith(u8, arg, "-")) {
210205 if (mem.eql(u8, arg, "--help")) {
211 try stdout.write(usage_build_generic);
206 try io.getStdOut().writeAll(usage_build_generic);
212207 process.exit(0);
213208 } else if (mem.eql(u8, arg, "--color")) {
214209 if (i + 1 >= args.len) {
215 try stderr.write("expected [auto|on|off] after --color\n");
210 try stderr.writeAll("expected [auto|on|off] after --color\n");
216211 process.exit(1);
217212 }
218213 i += 1;
......@@ -229,7 +224,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
229224 }
230225 } else if (mem.eql(u8, arg, "--mode")) {
231226 if (i + 1 >= args.len) {
232 try stderr.write("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode\n");
227 try stderr.writeAll("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode\n");
233228 process.exit(1);
234229 }
235230 i += 1;
......@@ -248,49 +243,49 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
248243 }
249244 } else if (mem.eql(u8, arg, "--name")) {
250245 if (i + 1 >= args.len) {
251 try stderr.write("expected parameter after --name\n");
246 try stderr.writeAll("expected parameter after --name\n");
252247 process.exit(1);
253248 }
254249 i += 1;
255250 provided_name = args[i];
256251 } else if (mem.eql(u8, arg, "--ver-major")) {
257252 if (i + 1 >= args.len) {
258 try stderr.write("expected parameter after --ver-major\n");
253 try stderr.writeAll("expected parameter after --ver-major\n");
259254 process.exit(1);
260255 }
261256 i += 1;
262257 version.major = try std.fmt.parseInt(u32, args[i], 10);
263258 } else if (mem.eql(u8, arg, "--ver-minor")) {
264259 if (i + 1 >= args.len) {
265 try stderr.write("expected parameter after --ver-minor\n");
260 try stderr.writeAll("expected parameter after --ver-minor\n");
266261 process.exit(1);
267262 }
268263 i += 1;
269264 version.minor = try std.fmt.parseInt(u32, args[i], 10);
270265 } else if (mem.eql(u8, arg, "--ver-patch")) {
271266 if (i + 1 >= args.len) {
272 try stderr.write("expected parameter after --ver-patch\n");
267 try stderr.writeAll("expected parameter after --ver-patch\n");
273268 process.exit(1);
274269 }
275270 i += 1;
276271 version.patch = try std.fmt.parseInt(u32, args[i], 10);
277272 } else if (mem.eql(u8, arg, "--linker-script")) {
278273 if (i + 1 >= args.len) {
279 try stderr.write("expected parameter after --linker-script\n");
274 try stderr.writeAll("expected parameter after --linker-script\n");
280275 process.exit(1);
281276 }
282277 i += 1;
283278 linker_script = args[i];
284279 } else if (mem.eql(u8, arg, "--libc")) {
285280 if (i + 1 >= args.len) {
286 try stderr.write("expected parameter after --libc\n");
281 try stderr.writeAll("expected parameter after --libc\n");
287282 process.exit(1);
288283 }
289284 i += 1;
290285 libc_arg = args[i];
291286 } else if (mem.eql(u8, arg, "-mllvm")) {
292287 if (i + 1 >= args.len) {
293 try stderr.write("expected parameter after -mllvm\n");
288 try stderr.writeAll("expected parameter after -mllvm\n");
294289 process.exit(1);
295290 }
296291 i += 1;
......@@ -300,14 +295,14 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
300295 try mllvm_flags.append(args[i]);
301296 } else if (mem.eql(u8, arg, "-mmacosx-version-min")) {
302297 if (i + 1 >= args.len) {
303 try stderr.write("expected parameter after -mmacosx-version-min\n");
298 try stderr.writeAll("expected parameter after -mmacosx-version-min\n");
304299 process.exit(1);
305300 }
306301 i += 1;
307302 macosx_version_min = args[i];
308303 } else if (mem.eql(u8, arg, "-mios-version-min")) {
309304 if (i + 1 >= args.len) {
310 try stderr.write("expected parameter after -mios-version-min\n");
305 try stderr.writeAll("expected parameter after -mios-version-min\n");
311306 process.exit(1);
312307 }
313308 i += 1;
......@@ -348,7 +343,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
348343 linker_rdynamic = true;
349344 } else if (mem.eql(u8, arg, "--pkg-begin")) {
350345 if (i + 2 >= args.len) {
351 try stderr.write("expected [name] [path] after --pkg-begin\n");
346 try stderr.writeAll("expected [name] [path] after --pkg-begin\n");
352347 process.exit(1);
353348 }
354349 i += 1;
......@@ -363,7 +358,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
363358 if (cur_pkg.parent) |parent| {
364359 cur_pkg = parent;
365360 } else {
366 try stderr.write("encountered --pkg-end with no matching --pkg-begin\n");
361 try stderr.writeAll("encountered --pkg-end with no matching --pkg-begin\n");
367362 process.exit(1);
368363 }
369364 } else if (mem.startsWith(u8, arg, "-l")) {
......@@ -411,18 +406,18 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
411406 var it = mem.separate(basename, ".");
412407 break :blk it.next() orelse basename;
413408 } else {
414 try stderr.write("--name [name] not provided and unable to infer\n");
409 try stderr.writeAll("--name [name] not provided and unable to infer\n");
415410 process.exit(1);
416411 }
417412 };
418413
419414 if (root_src_file == null and link_objects.len == 0 and assembly_files.len == 0) {
420 try stderr.write("Expected source file argument or at least one --object or --assembly argument\n");
415 try stderr.writeAll("Expected source file argument or at least one --object or --assembly argument\n");
421416 process.exit(1);
422417 }
423418
424419 if (out_type == Compilation.Kind.Obj and link_objects.len != 0) {
425 try stderr.write("When building an object file, --object arguments are invalid\n");
420 try stderr.writeAll("When building an object file, --object arguments are invalid\n");
426421 process.exit(1);
427422 }
428423
......@@ -440,7 +435,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
440435 &zig_compiler,
441436 root_name,
442437 root_src_file,
443 Target.Native,
438 .{},
444439 out_type,
445440 build_mode,
446441 !is_dynamic,
......@@ -478,7 +473,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
478473 comp.linker_rdynamic = linker_rdynamic;
479474
480475 if (macosx_version_min != null and ios_version_min != null) {
481 try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n");
476 try stderr.writeAll("-mmacosx-version-min and -mios-version-min options not allowed together\n");
482477 process.exit(1);
483478 }
484479
......@@ -501,6 +496,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
501496}
502497
503498fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
499 const stderr_file = io.getStdErr();
500 const stderr = stderr_file.outStream();
504501 var count: usize = 0;
505502 while (!comp.cancelled) {
506503 const build_event = comp.events.get();
......@@ -551,7 +548,8 @@ const Fmt = struct {
551548};
552549
553550fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void {
554 libc.parse(allocator, libc_paths_file, stderr) catch |err| {
551 const stderr = io.getStdErr().outStream();
552 libc.* = LibCInstallation.parse(allocator, libc_paths_file, stderr) catch |err| {
555553 stderr.print("Unable to parse libc path file '{}': {}.\n" ++
556554 "Try running `zig libc` to see an example for the native target.\n", .{
557555 libc_paths_file,
......@@ -562,6 +560,7 @@ fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_fil
562560}
563561
564562fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
563 const stderr = io.getStdErr().outStream();
565564 switch (args.len) {
566565 0 => {},
567566 1 => {
......@@ -582,10 +581,12 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
582581 stderr.print("unable to find libc: {}\n", .{@errorName(err)}) catch {};
583582 process.exit(1);
584583 };
585 libc.render(stdout) catch process.exit(1);
584 libc.render(io.getStdOut().outStream()) catch process.exit(1);
586585}
587586
588587fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
588 const stderr_file = io.getStdErr();
589 const stderr = stderr_file.outStream();
589590 var color: errmsg.Color = .Auto;
590591 var stdin_flag: bool = false;
591592 var check_flag: bool = false;
......@@ -597,11 +598,12 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
597598 const arg = args[i];
598599 if (mem.startsWith(u8, arg, "-")) {
599600 if (mem.eql(u8, arg, "--help")) {
600 try stdout.write(usage_fmt);
601 const stdout = io.getStdOut().outStream();
602 try stdout.writeAll(usage_fmt);
601603 process.exit(0);
602604 } else if (mem.eql(u8, arg, "--color")) {
603605 if (i + 1 >= args.len) {
604 try stderr.write("expected [auto|on|off] after --color\n");
606 try stderr.writeAll("expected [auto|on|off] after --color\n");
605607 process.exit(1);
606608 }
607609 i += 1;
......@@ -632,14 +634,13 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
632634
633635 if (stdin_flag) {
634636 if (input_files.len != 0) {
635 try stderr.write("cannot use --stdin with positional arguments\n");
637 try stderr.writeAll("cannot use --stdin with positional arguments\n");
636638 process.exit(1);
637639 }
638640
639 var stdin_file = io.getStdIn();
640 var stdin = stdin_file.inStream();
641 const stdin = io.getStdIn().inStream();
641642
642 const source_code = try stdin.stream.readAllAlloc(allocator, max_src_size);
643 const source_code = try stdin.readAllAlloc(allocator, max_src_size);
643644 defer allocator.free(source_code);
644645
645646 const tree = std.zig.parse(allocator, source_code) catch |err| {
......@@ -653,7 +654,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
653654 const msg = try errmsg.Msg.createFromParseError(allocator, parse_error, tree, "<stdin>");
654655 defer msg.destroy();
655656
656 try msg.printToFile(stderr_file, color);
657 try msg.printToFile(io.getStdErr(), color);
657658 }
658659 if (tree.errors.len != 0) {
659660 process.exit(1);
......@@ -664,12 +665,13 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
664665 process.exit(code);
665666 }
666667
668 const stdout = io.getStdOut().outStream();
667669 _ = try std.zig.render(allocator, stdout, tree);
668670 return;
669671 }
670672
671673 if (input_files.len == 0) {
672 try stderr.write("expected at least one source file argument\n");
674 try stderr.writeAll("expected at least one source file argument\n");
673675 process.exit(1);
674676 }
675677
......@@ -713,6 +715,9 @@ const FmtError = error{
713715} || fs.File.OpenError;
714716
715717async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
718 const stderr_file = io.getStdErr();
719 const stderr = stderr_file.outStream();
720
716721 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
717722 defer fmt.allocator.free(file_path);
718723
......@@ -729,7 +734,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
729734 max_src_size,
730735 ) catch |err| switch (err) {
731736 error.IsDir, error.AccessDenied => {
732 var dir = try fs.cwd().openDirList(file_path);
737 var dir = try fs.cwd().openDir(file_path, .{ .iterate = true });
733738 defer dir.close();
734739
735740 var group = event.Group(FmtError!void).init(fmt.allocator);
......@@ -791,11 +796,13 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
791796}
792797
793798fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
799 const stdout = io.getStdOut().outStream();
794800 try stdout.print("{}\n", .{c.ZIG_VERSION_STRING});
795801}
796802
797803fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
798 try stdout.write(usage);
804 const stdout = io.getStdOut();
805 try stdout.writeAll(usage);
799806}
800807
801808pub const info_zen =
......@@ -816,7 +823,7 @@ pub const info_zen =
816823;
817824
818825fn cmdZen(allocator: *Allocator, args: []const []const u8) !void {
819 try stdout.write(info_zen);
826 try io.getStdOut().writeAll(info_zen);
820827}
821828
822829const usage_internal =
......@@ -829,8 +836,9 @@ const usage_internal =
829836;
830837
831838fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {
839 const stderr = io.getStdErr().outStream();
832840 if (args.len == 0) {
833 try stderr.write(usage_internal);
841 try stderr.writeAll(usage_internal);
834842 process.exit(1);
835843 }
836844
......@@ -849,10 +857,11 @@ fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {
849857 }
850858
851859 try stderr.print("unknown sub command: {}\n\n", .{args[0]});
852 try stderr.write(usage_internal);
860 try stderr.writeAll(usage_internal);
853861}
854862
855863fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {
864 const stdout = io.getStdOut().outStream();
856865 try stdout.print(
857866 \\ZIG_CMAKE_BINARY_DIR {}
858867 \\ZIG_CXX_COMPILER {}
src-self-hosted/print_targets.zig+1-1
......@@ -72,7 +72,7 @@ pub fn cmdTargets(
7272 };
7373 defer allocator.free(zig_lib_dir);
7474
75 var dir = try std.fs.cwd().openDirList(zig_lib_dir);
75 var dir = try std.fs.cwd().openDir(zig_lib_dir, .{});
7676 defer dir.close();
7777
7878 const vers_txt = try dir.readFileAlloc(allocator, "libc/glibc/vers.txt", 10 * 1024);
src-self-hosted/stage2.zig+187-2
......@@ -113,6 +113,10 @@ const Error = extern enum {
113113 TargetHasNoDynamicLinker,
114114 InvalidAbiVersion,
115115 InvalidOperatingSystemVersion,
116 UnknownClangOption,
117 PermissionDenied,
118 FileBusy,
119 Locked,
116120};
117121
118122const FILE = std.c.FILE;
......@@ -128,7 +132,7 @@ export fn stage2_translate_c(
128132 args_end: [*]?[*]const u8,
129133 resources_path: [*:0]const u8,
130134) Error {
131 var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0];
135 var errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{};
132136 out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {
133137 error.SemanticAnalyzeFail => {
134138 out_errors_ptr.* = errors.ptr;
......@@ -319,7 +323,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
319323 const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
320324 error.IsDir, error.AccessDenied => {
321325 // TODO make event based (and dir.next())
322 var dir = try fs.cwd().openDirList(file_path);
326 var dir = try fs.cwd().openDir(file_path, .{ .iterate = true });
323327 defer dir.close();
324328
325329 var dir_it = dir.iterate();
......@@ -843,6 +847,9 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [
843847 error.NoDevice => return .NoDevice,
844848 error.NotDir => return .NotDir,
845849 error.DeviceBusy => return .DeviceBusy,
850 error.PermissionDenied => return .PermissionDenied,
851 error.FileBusy => return .FileBusy,
852 error.Locked => return .Locked,
846853 };
847854 stage1_libc.initFromStage2(libc);
848855 return .None;
......@@ -909,6 +916,7 @@ const Stage2Target = extern struct {
909916 os_builtin_str: ?[*:0]const u8,
910917
911918 dynamic_linker: ?[*:0]const u8,
919 standard_dynamic_linker_path: ?[*:0]const u8,
912920
913921 fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void {
914922 const allocator = std.heap.c_allocator;
......@@ -1119,6 +1127,12 @@ const Stage2Target = extern struct {
11191127 }
11201128 };
11211129
1130 const std_dl = target.standardDynamicLinkerPath();
1131 const std_dl_z = if (std_dl.get()) |dl|
1132 (try mem.dupeZ(std.heap.c_allocator, u8, dl)).ptr
1133 else
1134 null;
1135
11221136 const cache_hash_slice = cache_hash.toOwnedSlice();
11231137 self.* = .{
11241138 .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
......@@ -1134,6 +1148,7 @@ const Stage2Target = extern struct {
11341148 .is_native = cross_target.isNative(),
11351149 .glibc_or_darwin_version = glibc_or_darwin_version,
11361150 .dynamic_linker = dynamic_linker,
1151 .standard_dynamic_linker_path = std_dl_z,
11371152 };
11381153 }
11391154};
......@@ -1207,3 +1222,173 @@ fn convertSlice(slice: [][:0]u8, ptr: *[*][*:0]u8, len: *usize) !void {
12071222 }
12081223 ptr.* = new_slice.ptr;
12091224}
1225
1226const clang_args = @import("clang_options.zig").list;
1227
1228// ABI warning
1229pub const ClangArgIterator = extern struct {
1230 has_next: bool,
1231 zig_equivalent: ZigEquivalent,
1232 only_arg: [*:0]const u8,
1233 second_arg: [*:0]const u8,
1234 other_args_ptr: [*]const [*:0]const u8,
1235 other_args_len: usize,
1236 argv_ptr: [*]const [*:0]const u8,
1237 argv_len: usize,
1238 next_index: usize,
1239
1240 // ABI warning
1241 pub const ZigEquivalent = extern enum {
1242 target,
1243 o,
1244 c,
1245 other,
1246 positional,
1247 l,
1248 ignore,
1249 driver_punt,
1250 pic,
1251 no_pic,
1252 nostdlib,
1253 shared,
1254 rdynamic,
1255 wl,
1256 preprocess,
1257 optimize,
1258 debug,
1259 sanitize,
1260 };
1261
1262 fn init(argv: []const [*:0]const u8) ClangArgIterator {
1263 return .{
1264 .next_index = 2, // `zig cc foo` this points to `foo`
1265 .has_next = argv.len > 2,
1266 .zig_equivalent = undefined,
1267 .only_arg = undefined,
1268 .second_arg = undefined,
1269 .other_args_ptr = undefined,
1270 .other_args_len = undefined,
1271 .argv_ptr = argv.ptr,
1272 .argv_len = argv.len,
1273 };
1274 }
1275
1276 fn next(self: *ClangArgIterator) !void {
1277 assert(self.has_next);
1278 assert(self.next_index < self.argv_len);
1279 // In this state we know that the parameter we are looking at is a root parameter
1280 // rather than an argument to a parameter.
1281 self.other_args_ptr = self.argv_ptr + self.next_index;
1282 self.other_args_len = 1; // We adjust this value below when necessary.
1283 const arg = mem.span(self.argv_ptr[self.next_index]);
1284 self.next_index += 1;
1285 defer {
1286 if (self.next_index >= self.argv_len) self.has_next = false;
1287 }
1288
1289 if (!mem.startsWith(u8, arg, "-")) {
1290 self.zig_equivalent = .positional;
1291 self.only_arg = arg.ptr;
1292 return;
1293 }
1294
1295 find_clang_arg: for (clang_args) |clang_arg| switch (clang_arg.syntax) {
1296 .flag => {
1297 const prefix_len = clang_arg.matchEql(arg);
1298 if (prefix_len > 0) {
1299 self.zig_equivalent = clang_arg.zig_equivalent;
1300 self.only_arg = arg.ptr + prefix_len;
1301
1302 break :find_clang_arg;
1303 }
1304 },
1305 .joined, .comma_joined => {
1306 // joined example: --target=foo
1307 // comma_joined example: -Wl,-soname,libsoundio.so.2
1308 const prefix_len = clang_arg.matchStartsWith(arg);
1309 if (prefix_len != 0) {
1310 self.zig_equivalent = clang_arg.zig_equivalent;
1311 self.only_arg = arg.ptr + prefix_len; // This will skip over the "--target=" part.
1312
1313 break :find_clang_arg;
1314 }
1315 },
1316 .joined_or_separate => {
1317 // Examples: `-lfoo`, `-l foo`
1318 const prefix_len = clang_arg.matchStartsWith(arg);
1319 if (prefix_len == arg.len) {
1320 if (self.next_index >= self.argv_len) {
1321 std.debug.warn("Expected parameter after '{}'\n", .{arg});
1322 process.exit(1);
1323 }
1324 self.only_arg = self.argv_ptr[self.next_index];
1325 self.next_index += 1;
1326 self.other_args_len += 1;
1327 self.zig_equivalent = clang_arg.zig_equivalent;
1328
1329 break :find_clang_arg;
1330 } else if (prefix_len != 0) {
1331 self.zig_equivalent = clang_arg.zig_equivalent;
1332 self.only_arg = arg.ptr + prefix_len;
1333
1334 break :find_clang_arg;
1335 }
1336 },
1337 .joined_and_separate => {
1338 // Example: `-Xopenmp-target=riscv64-linux-unknown foo`
1339 const prefix_len = clang_arg.matchStartsWith(arg);
1340 if (prefix_len != 0) {
1341 self.only_arg = arg.ptr + prefix_len;
1342 if (self.next_index >= self.argv_len) {
1343 std.debug.warn("Expected parameter after '{}'\n", .{arg});
1344 process.exit(1);
1345 }
1346 self.second_arg = self.argv_ptr[self.next_index];
1347 self.next_index += 1;
1348 self.other_args_len += 1;
1349 self.zig_equivalent = clang_arg.zig_equivalent;
1350 break :find_clang_arg;
1351 }
1352 },
1353 .separate => if (clang_arg.matchEql(arg) > 0) {
1354 if (self.next_index >= self.argv_len) {
1355 std.debug.warn("Expected parameter after '{}'\n", .{arg});
1356 process.exit(1);
1357 }
1358 self.only_arg = self.argv_ptr[self.next_index];
1359 self.next_index += 1;
1360 self.other_args_len += 1;
1361 self.zig_equivalent = clang_arg.zig_equivalent;
1362 break :find_clang_arg;
1363 },
1364 .remaining_args_joined => {
1365 const prefix_len = clang_arg.matchStartsWith(arg);
1366 if (prefix_len != 0) {
1367 @panic("TODO");
1368 }
1369 },
1370 .multi_arg => if (clang_arg.matchEql(arg) > 0) {
1371 @panic("TODO");
1372 },
1373 }
1374 else {
1375 std.debug.warn("Unknown Clang option: '{}'\n", .{arg});
1376 process.exit(1);
1377 }
1378 }
1379};
1380
1381export fn stage2_clang_arg_iterator(
1382 result: *ClangArgIterator,
1383 argc: usize,
1384 argv: [*]const [*:0]const u8,
1385) void {
1386 result.* = ClangArgIterator.init(argv[0..argc]);
1387}
1388
1389export fn stage2_clang_arg_next(it: *ClangArgIterator) Error {
1390 it.next() catch |err| switch (err) {
1391 error.UnknownClangOption => return .UnknownClangOption,
1392 };
1393 return .None;
1394}
src-self-hosted/test.zig+2-2
......@@ -57,11 +57,11 @@ pub const TestContext = struct {
5757 errdefer allocator.free(self.zig_lib_dir);
5858
5959 try std.fs.cwd().makePath(tmp_dir_name);
60 errdefer std.fs.deleteTree(tmp_dir_name) catch {};
60 errdefer std.fs.cwd().deleteTree(tmp_dir_name) catch {};
6161 }
6262
6363 fn deinit(self: *TestContext) void {
64 std.fs.deleteTree(tmp_dir_name) catch {};
64 std.fs.cwd().deleteTree(tmp_dir_name) catch {};
6565 allocator.free(self.zig_lib_dir);
6666 self.zig_compiler.deinit();
6767 }
src-self-hosted/translate_c.zig+12-14
......@@ -1744,20 +1744,18 @@ fn writeEscapedString(buf: []u8, s: []const u8) void {
17441744// Returns either a string literal or a slice of `buf`.
17451745fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
17461746 return switch (c) {
1747 '\"' => "\\\""[0..],
1748 '\'' => "\\'"[0..],
1749 '\\' => "\\\\"[0..],
1750 '\n' => "\\n"[0..],
1751 '\r' => "\\r"[0..],
1752 '\t' => "\\t"[0..],
1753 else => {
1754 // Handle the remaining escapes Zig doesn't support by turning them
1755 // into their respective hex representation
1756 if (std.ascii.isCntrl(c))
1757 return std.fmt.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable
1758 else
1759 return std.fmt.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable;
1760 },
1747 '\"' => "\\\"",
1748 '\'' => "\\'",
1749 '\\' => "\\\\",
1750 '\n' => "\\n",
1751 '\r' => "\\r",
1752 '\t' => "\\t",
1753 // Handle the remaining escapes Zig doesn't support by turning them
1754 // into their respective hex representation
1755 else => if (std.ascii.isCntrl(c))
1756 std.fmt.bufPrint(char_buf, "\\x{x:0<2}", .{c}) catch unreachable
1757 else
1758 std.fmt.bufPrint(char_buf, "{c}", .{c}) catch unreachable,
17611759 };
17621760}
17631761
src-self-hosted/util.zig+13-2
......@@ -3,8 +3,7 @@ const Target = std.Target;
33const llvm = @import("llvm.zig");
44
55pub fn getDarwinArchString(self: Target) [:0]const u8 {
6 const arch = self.getArch();
7 switch (arch) {
6 switch (self.cpu.arch) {
87 .aarch64 => return "arm64",
98 .thumb,
109 .arm,
......@@ -34,3 +33,15 @@ pub fn initializeAllTargets() void {
3433 llvm.InitializeAllAsmPrinters();
3534 llvm.InitializeAllAsmParsers();
3635}
36
37pub fn getLLVMTriple(allocator: *std.mem.Allocator, target: std.Target) !std.Buffer {
38 var result = try std.Buffer.initSize(allocator, 0);
39 errdefer result.deinit();
40
41 try result.outStream().print(
42 "{}-unknown-{}-{}",
43 .{ @tagName(target.cpu.arch), @tagName(target.os.tag), @tagName(target.abi) },
44 );
45
46 return result;
47}
src/all_types.hpp+10
......@@ -231,6 +231,7 @@ enum ConstPtrSpecial {
231231 // The pointer is a reference to a single object.
232232 ConstPtrSpecialRef,
233233 // The pointer points to an element in an underlying array.
234 // Not to be confused with ConstPtrSpecialSubArray.
234235 ConstPtrSpecialBaseArray,
235236 // The pointer points to a field in an underlying struct.
236237 ConstPtrSpecialBaseStruct,
......@@ -257,6 +258,10 @@ enum ConstPtrSpecial {
257258 // types to be the same, so all optionals of pointer types use x_ptr
258259 // instead of x_optional.
259260 ConstPtrSpecialNull,
261 // The pointer points to a sub-array (not an individual element).
262 // Not to be confused with ConstPtrSpecialBaseArray. However, it uses the same
263 // union payload struct (base_array).
264 ConstPtrSpecialSubArray,
260265};
261266
262267enum ConstPtrMut {
......@@ -739,6 +744,7 @@ struct AstNodeReturnExpr {
739744
740745struct AstNodeDefer {
741746 ReturnKind kind;
747 AstNode *err_payload;
742748 AstNode *expr;
743749
744750 // temporary data used in IR generation
......@@ -1997,6 +2003,7 @@ enum WantCSanitize {
19972003struct CFile {
19982004 ZigList<const char *> args;
19992005 const char *source_path;
2006 const char *preprocessor_only_basename;
20002007};
20012008
20022009// When adding fields, check if they should be added to the hash computation in build_with_cache
......@@ -2141,6 +2148,7 @@ struct CodeGen {
21412148 // As an input parameter, mutually exclusive with enable_cache. But it gets
21422149 // populated in codegen_build_and_link.
21432150 Buf *output_dir;
2151 Buf *c_artifact_dir;
21442152 const char **libc_include_dir_list;
21452153 size_t libc_include_dir_len;
21462154
......@@ -2262,6 +2270,7 @@ struct CodeGen {
22622270 Buf *zig_lib_dir;
22632271 Buf *zig_std_dir;
22642272 Buf *version_script_path;
2273 Buf *override_soname;
22652274
22662275 const char **llvm_argv;
22672276 size_t llvm_argv_len;
......@@ -3706,6 +3715,7 @@ struct IrInstGenSlice {
37063715 IrInstGen *start;
37073716 IrInstGen *end;
37083717 IrInstGen *result_loc;
3718 ZigValue *sentinel;
37093719 bool safety_check_on;
37103720};
37113721
src/analyze.cpp+36-20
......@@ -780,6 +780,8 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
780780}
781781
782782ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ZigValue *sentinel) {
783 Error err;
784
783785 TypeId type_id = {};
784786 type_id.id = ZigTypeIdArray;
785787 type_id.data.array.codegen = g;
......@@ -791,7 +793,11 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi
791793 return existing_entry->value;
792794 }
793795
794 assert(type_is_resolved(child_type, ResolveStatusSizeKnown));
796 size_t full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0);
797
798 if (full_array_size != 0 && (err = type_resolve(g, child_type, ResolveStatusSizeKnown))) {
799 codegen_report_errors_and_exit(g);
800 }
795801
796802 ZigType *entry = new_type_table_entry(ZigTypeIdArray);
797803
......@@ -803,15 +809,8 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi
803809 }
804810 buf_appendf(&entry->name, "]%s", buf_ptr(&child_type->name));
805811
806 size_t full_array_size;
807 if (array_size == 0) {
808 full_array_size = 0;
809 } else {
810 full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0);
811 }
812
813812 entry->size_in_bits = child_type->size_in_bits * full_array_size;
814 entry->abi_align = child_type->abi_align;
813 entry->abi_align = (full_array_size == 0) ? 0 : child_type->abi_align;
815814 entry->abi_size = child_type->abi_size * full_array_size;
816815
817816 entry->data.array.child_type = child_type;
......@@ -1197,7 +1196,8 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
11971196 LazyValueArrayType *lazy_array_type =
11981197 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
11991198
1200 if (lazy_array_type->length < 1) {
1199 // The sentinel counts as an extra element
1200 if (lazy_array_type->length == 0 && lazy_array_type->sentinel == nullptr) {
12011201 *is_zero_bits = true;
12021202 return ErrorNone;
12031203 }
......@@ -1452,7 +1452,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV
14521452 case LazyValueIdArrayType: {
14531453 LazyValueArrayType *lazy_array_type =
14541454 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
1455 if (lazy_array_type->length < 1)
1455 if (lazy_array_type->length == 0)
14561456 return OnePossibleValueYes;
14571457 return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value);
14581458 }
......@@ -4488,7 +4488,14 @@ static uint32_t get_async_frame_align_bytes(CodeGen *g) {
44884488}
44894489
44904490uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
4491 ZigType *ptr_type = get_src_ptr_type(type);
4491 ZigType *ptr_type;
4492 if (type->id == ZigTypeIdStruct) {
4493 assert(type->data.structure.special == StructSpecialSlice);
4494 TypeStructField *ptr_field = type->data.structure.fields[slice_ptr_index];
4495 ptr_type = resolve_struct_field_type(g, ptr_field);
4496 } else {
4497 ptr_type = get_src_ptr_type(type);
4498 }
44924499 if (ptr_type->id == ZigTypeIdPointer) {
44934500 return (ptr_type->data.pointer.explicit_alignment == 0) ?
44944501 get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment;
......@@ -4505,8 +4512,15 @@ uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
45054512 }
45064513}
45074514
4508bool get_ptr_const(ZigType *type) {
4509 ZigType *ptr_type = get_src_ptr_type(type);
4515bool get_ptr_const(CodeGen *g, ZigType *type) {
4516 ZigType *ptr_type;
4517 if (type->id == ZigTypeIdStruct) {
4518 assert(type->data.structure.special == StructSpecialSlice);
4519 TypeStructField *ptr_field = type->data.structure.fields[slice_ptr_index];
4520 ptr_type = resolve_struct_field_type(g, ptr_field);
4521 } else {
4522 ptr_type = get_src_ptr_type(type);
4523 }
45104524 if (ptr_type->id == ZigTypeIdPointer) {
45114525 return ptr_type->data.pointer.is_const;
45124526 } else if (ptr_type->id == ZigTypeIdFn) {
......@@ -5282,6 +5296,11 @@ static uint32_t hash_const_val_ptr(ZigValue *const_val) {
52825296 hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
52835297 hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);
52845298 return hash_val;
5299 case ConstPtrSpecialSubArray:
5300 hash_val += (uint32_t)2643358777;
5301 hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
5302 hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);
5303 return hash_val;
52855304 case ConstPtrSpecialBaseStruct:
52865305 hash_val += (uint32_t)3518317043;
52875306 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
......@@ -5811,18 +5830,13 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
58115830 // The elements array cannot be left unpopulated
58125831 ZigType *array_type = result->type;
58135832 ZigType *elem_type = array_type->data.array.child_type;
5814 ZigValue *sentinel_value = array_type->data.array.sentinel;
5815 const size_t elem_count = array_type->data.array.len + (sentinel_value != nullptr);
5833 const size_t elem_count = array_type->data.array.len;
58165834
58175835 result->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(elem_count);
58185836 for (size_t i = 0; i < elem_count; i += 1) {
58195837 ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];
58205838 copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));
58215839 }
5822 if (sentinel_value != nullptr) {
5823 ZigValue *last_elem_val = &result->data.x_array.data.s_none.elements[elem_count - 1];
5824 copy_const_val(g, last_elem_val, sentinel_value);
5825 }
58265840 } else if (result->type->id == ZigTypeIdPointer) {
58275841 result->data.x_ptr.special = ConstPtrSpecialRef;
58285842 result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
......@@ -6753,6 +6767,7 @@ bool const_values_equal_ptr(ZigValue *a, ZigValue *b) {
67536767 return false;
67546768 return true;
67556769 case ConstPtrSpecialBaseArray:
6770 case ConstPtrSpecialSubArray:
67566771 if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val) {
67576772 return false;
67586773 }
......@@ -7010,6 +7025,7 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ZigValue *const_val, ZigT
70107025 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
70117026 return;
70127027 case ConstPtrSpecialBaseArray:
7028 case ConstPtrSpecialSubArray:
70137029 buf_appendf(buf, "*");
70147030 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
70157031 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
src/analyze.hpp+1-1
......@@ -76,7 +76,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool all
7676
7777ZigType *get_src_ptr_type(ZigType *type);
7878uint32_t get_ptr_align(CodeGen *g, ZigType *type);
79bool get_ptr_const(ZigType *type);
79bool get_ptr_const(CodeGen *g, ZigType *type);
8080ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
8181ZigType *container_ref_type(ZigType *type_entry);
8282bool type_is_complete(ZigType *type_entry);
src/codegen.cpp+128-55
......@@ -5418,12 +5418,16 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
54185418 ZigType *array_type = array_ptr_type->data.pointer.child_type;
54195419 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
54205420
5421 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5422
54235421 bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
54245422
5425 ZigType *res_slice_ptr_type = instruction->base.value->type->data.structure.fields[slice_ptr_index]->type_entry;
5426 ZigValue *sentinel = res_slice_ptr_type->data.pointer.sentinel;
5423 ZigType *result_type = instruction->base.value->type;
5424 if (!type_has_bits(g, result_type)) {
5425 return nullptr;
5426 }
5427
5428 // This is not whether the result type has a sentinel, but whether there should be a sentinel check,
5429 // e.g. if they used [a..b :s] syntax.
5430 ZigValue *sentinel = instruction->sentinel;
54275431
54285432 if (array_type->id == ZigTypeIdArray ||
54295433 (array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
......@@ -5458,6 +5462,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
54585462 }
54595463 }
54605464 if (!type_has_bits(g, array_type)) {
5465 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5466
54615467 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
54625468
54635469 // TODO if runtime safety is on, store 0xaaaaaaa in ptr field
......@@ -5466,20 +5472,26 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
54665472 return tmp_struct_ptr;
54675473 }
54685474
5469
5470 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, "");
54715475 LLVMValueRef indices[] = {
54725476 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
54735477 start_val,
54745478 };
54755479 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
5476 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
5480 if (result_type->id == ZigTypeIdPointer) {
5481 ir_assert(instruction->result_loc == nullptr, &instruction->base);
5482 LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
5483 return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
5484 } else {
5485 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5486 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, "");
5487 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
54775488
5478 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
5479 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5480 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
5489 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
5490 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5491 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
54815492
5482 return tmp_struct_ptr;
5493 return tmp_struct_ptr;
5494 }
54835495 } else if (array_type->id == ZigTypeIdPointer) {
54845496 assert(array_type->data.pointer.ptr_len != PtrLenSingle);
54855497 LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
......@@ -5493,24 +5505,39 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
54935505 }
54945506 }
54955507
5496 if (type_has_bits(g, array_type)) {
5497 size_t gen_ptr_index = instruction->base.value->type->data.structure.fields[slice_ptr_index]->gen_index;
5498 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, "");
5499 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
5500 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
5508 if (!type_has_bits(g, array_type)) {
5509 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5510 size_t gen_len_index = result_type->data.structure.fields[slice_len_index]->gen_index;
5511 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, "");
5512 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5513 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
5514 return tmp_struct_ptr;
5515 }
5516
5517 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
5518 if (result_type->id == ZigTypeIdPointer) {
5519 ir_assert(instruction->result_loc == nullptr, &instruction->base);
5520 LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
5521 return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
55015522 }
55025523
5503 size_t gen_len_index = instruction->base.value->type->data.structure.fields[slice_len_index]->gen_index;
5524 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5525
5526 size_t gen_ptr_index = result_type->data.structure.fields[slice_ptr_index]->gen_index;
5527 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, "");
5528 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
5529
5530 size_t gen_len_index = result_type->data.structure.fields[slice_len_index]->gen_index;
55045531 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, "");
55055532 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
55065533 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
55075534
55085535 return tmp_struct_ptr;
5536
55095537 } else if (array_type->id == ZigTypeIdStruct) {
55105538 assert(array_type->data.structure.special == StructSpecialSlice);
55115539 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
55125540 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
5513 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
55145541
55155542 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;
55165543 assert(ptr_index != SIZE_MAX);
......@@ -5547,15 +5574,22 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
55475574 }
55485575 }
55495576
5550 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, "");
55515577 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, "");
5552 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
5578 if (result_type->id == ZigTypeIdPointer) {
5579 ir_assert(instruction->result_loc == nullptr, &instruction->base);
5580 LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
5581 return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
5582 } else {
5583 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5584 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, "");
5585 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
55535586
5554 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)len_index, "");
5555 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5556 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
5587 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)len_index, "");
5588 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5589 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
55575590
5558 return tmp_struct_ptr;
5591 return tmp_struct_ptr;
5592 }
55595593 } else {
55605594 zig_unreachable();
55615595 }
......@@ -6640,7 +6674,6 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_co
66406674 };
66416675 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
66426676 } else {
6643 assert(parent->id == ConstParentIdScalar);
66446677 return base_ptr;
66456678 }
66466679}
......@@ -6790,6 +6823,22 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Zig
67906823 used_bits += packed_bits_size;
67916824 }
67926825 }
6826
6827 if (type_entry->data.array.sentinel != nullptr) {
6828 ZigValue *elem_val = type_entry->data.array.sentinel;
6829 LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, elem_val);
6830
6831 if (is_big_endian) {
6832 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false);
6833 val = LLVMConstShl(val, shift_amt);
6834 val = LLVMConstOr(val, child_val);
6835 } else {
6836 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
6837 LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
6838 val = LLVMConstOr(val, child_val_shifted);
6839 used_bits += packed_bits_size;
6840 }
6841 }
67936842 return val;
67946843 }
67956844 case ZigTypeIdVector:
......@@ -6852,24 +6901,16 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
68526901 return const_val->llvm_value;
68536902 }
68546903 case ConstPtrSpecialBaseArray:
6904 case ConstPtrSpecialSubArray:
68556905 {
68566906 ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
68576907 assert(array_const_val->type->id == ZigTypeIdArray);
68586908 if (!type_has_bits(g, array_const_val->type)) {
6859 if (array_const_val->type->data.array.sentinel != nullptr) {
6860 ZigValue *pointee = array_const_val->type->data.array.sentinel;
6861 render_const_val(g, pointee, "");
6862 render_const_val_global(g, pointee, "");
6863 const_val->llvm_value = LLVMConstBitCast(pointee->llvm_global,
6864 get_llvm_type(g, const_val->type));
6865 return const_val->llvm_value;
6866 } else {
6867 // make this a null pointer
6868 ZigType *usize = g->builtin_types.entry_usize;
6869 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
6870 get_llvm_type(g, const_val->type));
6871 return const_val->llvm_value;
6872 }
6909 // make this a null pointer
6910 ZigType *usize = g->builtin_types.entry_usize;
6911 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
6912 get_llvm_type(g, const_val->type));
6913 return const_val->llvm_value;
68736914 }
68746915 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
68756916 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
......@@ -9228,6 +9269,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
92289269 case BuildModeDebug:
92299270 // windows c runtime requires -D_DEBUG if using debug libraries
92309271 args.append("-D_DEBUG");
9272 args.append("-Og");
92319273
92329274 if (g->libc_link_lib != nullptr) {
92339275 args.append("-fstack-protector-strong");
......@@ -9650,6 +9692,21 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
96509692 return ErrorNone;
96519693}
96529694
9695static bool need_llvm_module(CodeGen *g) {
9696 return buf_len(&g->main_pkg->root_src_path) != 0;
9697}
9698
9699// before gen_c_objects
9700static bool main_output_dir_is_just_one_c_object_pre(CodeGen *g) {
9701 return g->enable_cache && g->c_source_files.length == 1 && !need_llvm_module(g) &&
9702 g->out_type == OutTypeObj && g->link_objects.length == 0;
9703}
9704
9705// after gen_c_objects
9706static bool main_output_dir_is_just_one_c_object_post(CodeGen *g) {
9707 return g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g) && g->out_type == OutTypeObj;
9708}
9709
96539710// returns true if it was a cache miss
96549711static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
96559712 Error err;
......@@ -9667,8 +9724,17 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
96679724 buf_len(c_source_basename), 0);
96689725
96699726 Buf *final_o_basename = buf_alloc();
9670 os_path_extname(c_source_basename, final_o_basename, nullptr);
9671 buf_append_str(final_o_basename, target_o_file_ext(g->zig_target));
9727 if (c_file->preprocessor_only_basename == nullptr) {
9728 // We special case when doing build-obj for just one C file
9729 if (main_output_dir_is_just_one_c_object_pre(g)) {
9730 buf_init_from_buf(final_o_basename, g->root_out_name);
9731 } else {
9732 os_path_extname(c_source_basename, final_o_basename, nullptr);
9733 }
9734 buf_append_str(final_o_basename, target_o_file_ext(g->zig_target));
9735 } else {
9736 buf_init_from_str(final_o_basename, c_file->preprocessor_only_basename);
9737 }
96729738
96739739 CacheHash *cache_hash;
96749740 if ((err = create_c_object_cache(g, &cache_hash, true))) {
......@@ -9717,7 +9783,13 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
97179783 Termination term;
97189784 ZigList<const char *> args = {};
97199785 args.append(buf_ptr(self_exe_path));
9720 args.append("cc");
9786 args.append("clang");
9787
9788 if (c_file->preprocessor_only_basename != nullptr) {
9789 args.append("-E");
9790 } else {
9791 args.append("-c");
9792 }
97219793
97229794 Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));
97239795 add_cc_args(g, args, buf_ptr(out_dep_path), false);
......@@ -9725,7 +9797,6 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
97259797 args.append("-o");
97269798 args.append(buf_ptr(out_obj_path));
97279799
9728 args.append("-c");
97299800 args.append(buf_ptr(c_source_file));
97309801
97319802 for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {
......@@ -9780,6 +9851,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
97809851 os_path_join(artifact_dir, final_o_basename, o_final_path);
97819852 }
97829853
9854 g->c_artifact_dir = artifact_dir;
97839855 g->link_objects.append(o_final_path);
97849856 g->caches_to_release.append(cache_hash);
97859857
......@@ -10449,6 +10521,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
1044910521 cache_str(ch, g->libc->kernel32_lib_dir);
1045010522 }
1045110523 cache_buf_opt(ch, g->version_script_path);
10524 cache_buf_opt(ch, g->override_soname);
1045210525
1045310526 // gen_c_objects appends objects to g->link_objects which we want to include in the hash
1045410527 gen_c_objects(g);
......@@ -10467,10 +10540,6 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
1046710540 return ErrorNone;
1046810541}
1046910542
10470static bool need_llvm_module(CodeGen *g) {
10471 return buf_len(&g->main_pkg->root_src_path) != 0;
10472}
10473
1047410543static void resolve_out_paths(CodeGen *g) {
1047510544 assert(g->output_dir != nullptr);
1047610545 assert(g->root_out_name != nullptr);
......@@ -10482,10 +10551,6 @@ static void resolve_out_paths(CodeGen *g) {
1048210551 case OutTypeUnknown:
1048310552 zig_unreachable();
1048410553 case OutTypeObj:
10485 if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) {
10486 buf_init_from_buf(&g->bin_file_output_path, g->link_objects.at(0));
10487 return;
10488 }
1048910554 if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache &&
1049010555 buf_eql_buf(o_basename, out_basename))
1049110556 {
......@@ -10580,6 +10645,16 @@ static void output_type_information(CodeGen *g) {
1058010645 }
1058110646}
1058210647
10648static void init_output_dir(CodeGen *g, Buf *digest) {
10649 if (main_output_dir_is_just_one_c_object_post(g)) {
10650 g->output_dir = buf_alloc();
10651 os_path_dirname(g->link_objects.at(0), g->output_dir);
10652 } else {
10653 g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s",
10654 buf_ptr(g->cache_dir), buf_ptr(digest));
10655 }
10656}
10657
1058310658void codegen_build_and_link(CodeGen *g) {
1058410659 Error err;
1058510660 assert(g->out_type != OutTypeUnknown);
......@@ -10622,8 +10697,7 @@ void codegen_build_and_link(CodeGen *g) {
1062210697 }
1062310698
1062410699 if (g->enable_cache && buf_len(&digest) != 0) {
10625 g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s",
10626 buf_ptr(g->cache_dir), buf_ptr(&digest));
10700 init_output_dir(g, &digest);
1062710701 resolve_out_paths(g);
1062810702 } else {
1062910703 if (need_llvm_module(g)) {
......@@ -10644,8 +10718,7 @@ void codegen_build_and_link(CodeGen *g) {
1064410718 exit(1);
1064510719 }
1064610720 }
10647 g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s",
10648 buf_ptr(g->cache_dir), buf_ptr(&digest));
10721 init_output_dir(g, &digest);
1064910722
1065010723 if ((err = os_make_path(g->output_dir))) {
1065110724 fprintf(stderr, "Unable to create output directory: %s\n", err_str(err));
src/error.cpp+4
......@@ -83,6 +83,10 @@ const char *err_str(Error err) {
8383 case ErrorTargetHasNoDynamicLinker: return "target has no dynamic linker";
8484 case ErrorInvalidAbiVersion: return "invalid C ABI version";
8585 case ErrorInvalidOperatingSystemVersion: return "invalid operating system version";
86 case ErrorUnknownClangOption: return "unknown Clang option";
87 case ErrorPermissionDenied: return "permission is denied";
88 case ErrorFileBusy: return "file is busy";
89 case ErrorLocked: return "file is locked by another process";
8690 }
8791 return "(invalid error)";
8892}
src/glibc.cpp+10
......@@ -16,6 +16,7 @@ static const ZigGLibCLib glibc_libs[] = {
1616 {"pthread", 0},
1717 {"dl", 2},
1818 {"rt", 1},
19 {"ld", 2},
1920};
2021
2122Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbose) {
......@@ -330,6 +331,8 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con
330331 return err;
331332 }
332333
334 bool is_ld = (strcmp(lib->name, "ld") == 0);
335
333336 CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr, lib->name, progress_node);
334337 codegen_set_lib_version(child_gen, lib->sover, 0, 0);
335338 child_gen->is_dynamic = true;
......@@ -337,6 +340,13 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con
337340 child_gen->version_script_path = map_file_path;
338341 child_gen->enable_cache = false;
339342 child_gen->output_dir = dummy_dir;
343 if (is_ld) {
344 assert(g->zig_target->standard_dynamic_linker_path != nullptr);
345 Buf *ld_basename = buf_alloc();
346 os_path_split(buf_create_from_str(g->zig_target->standard_dynamic_linker_path),
347 nullptr, ld_basename);
348 child_gen->override_soname = ld_basename;
349 }
340350 codegen_build_and_link(child_gen);
341351 }
342352
src/ir.cpp+498-130
......@@ -272,6 +272,15 @@ static ResultLoc *no_result_loc(void);
272272static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, IrInstGen *value);
273273static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst *source_instr);
274274static IrInstGen *ir_const_undef(IrAnalyze *ira, IrInst *source_instruction, ZigType *ty);
275static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name,
276 bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime);
277static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var,
278 IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime);
279static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instruction,
280 AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstGen *field_result_loc,
281 IrInstGen *result_loc);
282static IrInstGen *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst* source_instr,
283 IrInstGen *struct_operand, TypeStructField *field);
275284
276285static void destroy_instruction_src(IrInstSrc *inst) {
277286 switch (inst->id) {
......@@ -784,14 +793,32 @@ static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_
784793 break;
785794 case ConstPtrSpecialBaseArray: {
786795 ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
787 if (const_val->data.x_ptr.data.base_array.elem_index == array_val->type->data.array.len) {
796 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
797 if (elem_index == array_val->type->data.array.len) {
788798 result = array_val->type->data.array.sentinel;
789799 } else {
790800 expand_undef_array(g, array_val);
791 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
801 result = &array_val->data.x_array.data.s_none.elements[elem_index];
792802 }
793803 break;
794804 }
805 case ConstPtrSpecialSubArray: {
806 ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
807 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
808
809 // TODO handle sentinel terminated arrays
810 expand_undef_array(g, array_val);
811 result = g->pass1_arena->create<ZigValue>();
812 result->special = array_val->special;
813 result->type = get_array_type(g, array_val->type->data.array.child_type,
814 array_val->type->data.array.len - elem_index, nullptr);
815 result->data.x_array.special = ConstArraySpecialNone;
816 result->data.x_array.data.s_none.elements = &array_val->data.x_array.data.s_none.elements[elem_index];
817 result->parent.id = ConstParentIdArray;
818 result->parent.data.p_array.array_val = array_val;
819 result->parent.data.p_array.elem_index = elem_index;
820 break;
821 }
795822 case ConstPtrSpecialBaseStruct: {
796823 ZigValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;
797824 expand_undef_struct(g, struct_val);
......@@ -849,11 +876,6 @@ static bool is_slice(ZigType *type) {
849876 return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialSlice;
850877}
851878
852static bool slice_is_const(ZigType *type) {
853 assert(is_slice(type));
854 return type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
855}
856
857879// This function returns true when you can change the type of a ZigValue and the
858880// value remains meaningful.
859881static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expected, ZigType *actual) {
......@@ -3719,7 +3741,8 @@ static IrInstSrc *ir_build_slice_src(IrBuilderSrc *irb, Scope *scope, AstNode *s
37193741}
37203742
37213743static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *slice_type,
3722 IrInstGen *ptr, IrInstGen *start, IrInstGen *end, bool safety_check_on, IrInstGen *result_loc)
3744 IrInstGen *ptr, IrInstGen *start, IrInstGen *end, bool safety_check_on, IrInstGen *result_loc,
3745 ZigValue *sentinel)
37233746{
37243747 IrInstGenSlice *instruction = ir_build_inst_gen<IrInstGenSlice>(
37253748 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
......@@ -3729,11 +3752,12 @@ static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction,
37293752 instruction->end = end;
37303753 instruction->safety_check_on = safety_check_on;
37313754 instruction->result_loc = result_loc;
3755 instruction->sentinel = sentinel;
37323756
37333757 ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
37343758 ir_ref_inst_gen(start, ira->new_irb.current_basic_block);
3735 if (end) ir_ref_inst_gen(end, ira->new_irb.current_basic_block);
3736 ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block);
3759 if (end != nullptr) ir_ref_inst_gen(end, ira->new_irb.current_basic_block);
3760 if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block);
37373761
37383762 return &instruction->base;
37393763}
......@@ -4996,39 +5020,73 @@ static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) {
49965020 return instruction;
49975021}
49985022
4999static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) {
5023static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) {
50005024 Scope *scope = inner_scope;
5001 bool is_noreturn = false;
5025 if (is_noreturn != nullptr) *is_noreturn = false;
50025026 while (scope != outer_scope) {
50035027 if (!scope)
5004 return is_noreturn;
5028 return true;
50055029
50065030 switch (scope->id) {
50075031 case ScopeIdDefer: {
50085032 AstNode *defer_node = scope->source_node;
50095033 assert(defer_node->type == NodeTypeDefer);
50105034 ReturnKind defer_kind = defer_node->data.defer.kind;
5011 if (defer_kind == ReturnKindUnconditional ||
5012 (gen_error_defers && defer_kind == ReturnKindError))
5013 {
5014 AstNode *defer_expr_node = defer_node->data.defer.expr;
5015 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
5016 IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
5017 if (defer_expr_value != irb->codegen->invalid_inst_src) {
5018 if (defer_expr_value->is_noreturn) {
5019 is_noreturn = true;
5020 } else {
5021 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,
5022 defer_expr_value));
5023 }
5035 AstNode *defer_expr_node = defer_node->data.defer.expr;
5036 AstNode *defer_var_node = defer_node->data.defer.err_payload;
5037
5038 if (defer_kind == ReturnKindError && err_value == nullptr) {
5039 // This is an `errdefer` but we're generating code for a
5040 // `return` that doesn't return an error, skip it
5041 scope = scope->parent;
5042 continue;
5043 }
5044
5045 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
5046 if (defer_var_node != nullptr) {
5047 assert(defer_kind == ReturnKindError);
5048 assert(defer_var_node->type == NodeTypeSymbol);
5049 Buf *var_name = defer_var_node->data.symbol_expr.symbol;
5050
5051 if (defer_expr_node->type == NodeTypeUnreachable) {
5052 add_node_error(irb->codegen, defer_var_node,
5053 buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
5054 return false;
50245055 }
5056
5057 IrInstSrc *is_comptime;
5058 if (ir_should_inline(irb->exec, defer_expr_scope)) {
5059 is_comptime = ir_build_const_bool(irb, defer_expr_scope,
5060 defer_expr_node, true);
5061 } else {
5062 is_comptime = ir_build_test_comptime(irb, defer_expr_scope,
5063 defer_expr_node, err_value);
5064 }
5065
5066 ZigVar *err_var = ir_create_var(irb, defer_var_node, defer_expr_scope,
5067 var_name, true, true, false, is_comptime);
5068 build_decl_var_and_init(irb, defer_expr_scope, defer_var_node, err_var, err_value,
5069 buf_ptr(var_name), is_comptime);
5070
5071 defer_expr_scope = err_var->child_scope;
5072 }
5073
5074 IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
5075 if (defer_expr_value == irb->codegen->invalid_inst_src)
5076 return irb->codegen->invalid_inst_src;
5077
5078 if (defer_expr_value->is_noreturn) {
5079 if (is_noreturn != nullptr) *is_noreturn = true;
5080 } else {
5081 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,
5082 defer_expr_value));
50255083 }
50265084 scope = scope->parent;
50275085 continue;
50285086 }
50295087 case ScopeIdDecls:
50305088 case ScopeIdFnDef:
5031 return is_noreturn;
5089 return true;
50325090 case ScopeIdBlock:
50335091 case ScopeIdVarDecl:
50345092 case ScopeIdLoop:
......@@ -5045,7 +5103,7 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope
50455103 zig_unreachable();
50465104 }
50475105 }
5048 return is_noreturn;
5106 return true;
50495107}
50505108
50515109static void ir_set_cursor_at_end_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) {
......@@ -5131,7 +5189,8 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,
51315189 bool have_err_defers = defer_counts[ReturnKindError] > 0;
51325190 if (!have_err_defers && !irb->codegen->have_err_ret_tracing) {
51335191 // only generate unconditional defers
5134 ir_gen_defers_for_block(irb, scope, outer_scope, false);
5192 if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr))
5193 return irb->codegen->invalid_inst_src;
51355194 IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr);
51365195 result_loc_ret->base.source_instruction = result;
51375196 return result;
......@@ -5154,14 +5213,16 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,
51545213 IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");
51555214
51565215 ir_set_cursor_at_end_and_append_block(irb, err_block);
5157 ir_gen_defers_for_block(irb, scope, outer_scope, true);
5216 if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, return_value))
5217 return irb->codegen->invalid_inst_src;
51585218 if (irb->codegen->have_err_ret_tracing && !should_inline) {
51595219 ir_build_save_err_ret_addr_src(irb, scope, node);
51605220 }
51615221 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
51625222
51635223 ir_set_cursor_at_end_and_append_block(irb, ok_block);
5164 ir_gen_defers_for_block(irb, scope, outer_scope, false);
5224 if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr))
5225 return irb->codegen->invalid_inst_src;
51655226 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
51665227
51675228 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
......@@ -5198,7 +5259,12 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,
51985259 result_loc_ret->base.id = ResultLocIdReturn;
51995260 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
52005261 ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base);
5201 if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {
5262
5263 bool is_noreturn = false;
5264 if (!ir_gen_defers_for_block(irb, scope, outer_scope, &is_noreturn, err_val)) {
5265 return irb->codegen->invalid_inst_src;
5266 }
5267 if (!is_noreturn) {
52025268 if (irb->codegen->have_err_ret_tracing && !should_inline) {
52035269 ir_build_save_err_ret_addr_src(irb, scope, node);
52045270 }
......@@ -5400,7 +5466,8 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *
54005466
54015467 bool is_return_from_fn = block_node == irb->main_block_node;
54025468 if (!is_return_from_fn) {
5403 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
5469 if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr))
5470 return irb->codegen->invalid_inst_src;
54045471 }
54055472
54065473 IrInstSrc *result;
......@@ -5425,7 +5492,8 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *
54255492 result_loc_ret->base.id = ResultLocIdReturn;
54265493 ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base);
54275494 ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base));
5428 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
5495 if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr))
5496 return irb->codegen->invalid_inst_src;
54295497 return ir_mark_gen(ir_build_return_src(irb, child_scope, result->base.source_node, result));
54305498}
54315499
......@@ -9225,7 +9293,8 @@ static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope
92259293 }
92269294
92279295 IrBasicBlockSrc *dest_block = block_scope->end_block;
9228 ir_gen_defers_for_block(irb, break_scope, dest_block->scope, false);
9296 if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr))
9297 return irb->codegen->invalid_inst_src;
92299298
92309299 block_scope->incoming_blocks->append(irb->current_basic_block);
92319300 block_scope->incoming_values->append(result_value);
......@@ -9299,7 +9368,8 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n
92999368 }
93009369
93019370 IrBasicBlockSrc *dest_block = loop_scope->break_block;
9302 ir_gen_defers_for_block(irb, break_scope, dest_block->scope, false);
9371 if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr))
9372 return irb->codegen->invalid_inst_src;
93039373
93049374 loop_scope->incoming_blocks->append(irb->current_basic_block);
93059375 loop_scope->incoming_values->append(result_value);
......@@ -9358,7 +9428,8 @@ static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstN
93589428 }
93599429
93609430 IrBasicBlockSrc *dest_block = loop_scope->continue_block;
9361 ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false);
9431 if (!ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, nullptr, nullptr))
9432 return irb->codegen->invalid_inst_src;
93629433 return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime));
93639434}
93649435
......@@ -12335,11 +12406,22 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1233512406 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
1233612407 prev_type->data.pointer.ptr_len == PtrLenSingle &&
1233712408 ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) ||
12338 is_slice(cur_type)))
12409 (cur_type->id == ZigTypeIdOptional && is_slice(cur_type->data.maybe.child_type)) ||
12410 is_slice(cur_type)))
1233912411 {
1234012412 ZigType *array_type = prev_type->data.pointer.child_type;
12341 ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ?
12342 cur_type->data.error_union.payload_type : cur_type;
12413 ZigType *slice_type;
12414 switch (cur_type->id) {
12415 case ZigTypeIdErrorUnion:
12416 slice_type = cur_type->data.error_union.payload_type;
12417 break;
12418 case ZigTypeIdOptional:
12419 slice_type = cur_type->data.maybe.child_type;
12420 break;
12421 default:
12422 slice_type = cur_type;
12423 break;
12424 }
1234312425 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
1234412426 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
1234512427 !prev_type->data.pointer.is_const) &&
......@@ -12677,41 +12759,80 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc
1267712759 Error err;
1267812760
1267912761 assert(array_ptr->value->type->id == ZigTypeIdPointer);
12762 assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray);
12763
12764 ZigType *array_type = array_ptr->value->type->data.pointer.child_type;
12765 size_t array_len = array_type->data.array.len;
12766
12767 // A zero-sized array can be casted regardless of the destination alignment, or
12768 // whether the pointer is undefined, and the result is always comptime known.
12769 // TODO However, this is exposing a result location bug that I failed to solve on the first try.
12770 // If you want to try to fix the bug, uncomment this block and get the tests passing.
12771 //if (array_len == 0 && array_type->data.array.sentinel == nullptr) {
12772 // ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>();
12773 // undef_array->special = ConstValSpecialUndef;
12774 // undef_array->type = array_type;
12775
12776 // IrInstGen *result = ir_const(ira, source_instr, wanted_type);
12777 // init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false);
12778 // result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst;
12779 // result->value->type = wanted_type;
12780 // return result;
12781 //}
1268012782
1268112783 if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) {
1268212784 return ira->codegen->invalid_inst_gen;
1268312785 }
1268412786
12685 assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray);
12686
12687 const size_t array_len = array_ptr->value->type->data.pointer.child_type->data.array.len;
12688
12689 // A zero-sized array can always be casted irregardless of the destination
12690 // alignment
1269112787 if (array_len != 0) {
1269212788 wanted_type = adjust_slice_align(ira->codegen, wanted_type,
1269312789 get_ptr_align(ira->codegen, array_ptr->value->type));
1269412790 }
1269512791
1269612792 if (instr_is_comptime(array_ptr)) {
12697 ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
12793 UndefAllowed undef_allowed = (array_len == 0) ? UndefOk : UndefBad;
12794 ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, undef_allowed);
1269812795 if (array_ptr_val == nullptr)
1269912796 return ira->codegen->invalid_inst_gen;
12700 ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node);
12701 if (pointee == nullptr)
12702 return ira->codegen->invalid_inst_gen;
12703 if (pointee->special != ConstValSpecialRuntime) {
12704 assert(array_ptr_val->type->id == ZigTypeIdPointer);
12705 ZigType *array_type = array_ptr_val->type->data.pointer.child_type;
12706 assert(is_slice(wanted_type));
12707 bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
12797 ir_assert(is_slice(wanted_type), source_instr);
12798 if (array_ptr_val->special == ConstValSpecialUndef) {
12799 ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>();
12800 undef_array->special = ConstValSpecialUndef;
12801 undef_array->type = array_type;
1270812802
1270912803 IrInstGen *result = ir_const(ira, source_instr, wanted_type);
12710 init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, is_const);
12711 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
12804 init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false);
12805 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst;
1271212806 result->value->type = wanted_type;
1271312807 return result;
1271412808 }
12809 bool wanted_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
12810 // Optimization to avoid creating unnecessary ZigValue in const_ptr_pointee
12811 if (array_ptr_val->data.x_ptr.special == ConstPtrSpecialSubArray) {
12812 ZigValue *array_val = array_ptr_val->data.x_ptr.data.base_array.array_val;
12813 if (array_val->special != ConstValSpecialRuntime) {
12814 IrInstGen *result = ir_const(ira, source_instr, wanted_type);
12815 init_const_slice(ira->codegen, result->value, array_val,
12816 array_ptr_val->data.x_ptr.data.base_array.elem_index,
12817 array_type->data.array.len, wanted_const);
12818 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
12819 result->value->type = wanted_type;
12820 return result;
12821 }
12822 } else if (array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
12823 ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node);
12824 if (pointee == nullptr)
12825 return ira->codegen->invalid_inst_gen;
12826 if (pointee->special != ConstValSpecialRuntime) {
12827 assert(array_ptr_val->type->id == ZigTypeIdPointer);
12828
12829 IrInstGen *result = ir_const(ira, source_instr, wanted_type);
12830 init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, wanted_const);
12831 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
12832 result->value->type = wanted_type;
12833 return result;
12834 }
12835 }
1271512836 }
1271612837
1271712838 if (result_loc == nullptr) result_loc = no_result_loc();
......@@ -14329,10 +14450,71 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so
1432914450}
1433014451
1433114452static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr,
14332 IrInstGen *value, ZigType *wanted_type)
14453 IrInstGen *value, ZigType *union_type)
1433314454{
14334 ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to union"));
14335 return ira->codegen->invalid_inst_gen;
14455 Error err;
14456 ZigType *struct_type = value->value->type;
14457
14458 assert(struct_type->id == ZigTypeIdStruct);
14459 assert(union_type->id == ZigTypeIdUnion);
14460 assert(struct_type->data.structure.src_field_count == 1);
14461
14462 TypeStructField *only_field = struct_type->data.structure.fields[0];
14463
14464 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusZeroBitsKnown)))
14465 return ira->codegen->invalid_inst_gen;
14466
14467 TypeUnionField *union_field = find_union_type_field(union_type, only_field->name);
14468 if (union_field == nullptr) {
14469 ir_add_error_node(ira, only_field->decl_node,
14470 buf_sprintf("no member named '%s' in union '%s'",
14471 buf_ptr(only_field->name), buf_ptr(&union_type->name)));
14472 return ira->codegen->invalid_inst_gen;
14473 }
14474
14475 ZigType *payload_type = resolve_union_field_type(ira->codegen, union_field);
14476 if (payload_type == nullptr)
14477 return ira->codegen->invalid_inst_gen;
14478
14479 IrInstGen *field_value = ir_analyze_struct_value_field_value(ira, source_instr, value, only_field);
14480 if (type_is_invalid(field_value->value->type))
14481 return ira->codegen->invalid_inst_gen;
14482
14483 IrInstGen *casted_value = ir_implicit_cast(ira, field_value, payload_type);
14484 if (type_is_invalid(casted_value->value->type))
14485 return ira->codegen->invalid_inst_gen;
14486
14487 if (instr_is_comptime(casted_value)) {
14488 ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad);
14489 if (val == nullptr)
14490 return ira->codegen->invalid_inst_gen;
14491
14492 IrInstGen *result = ir_const(ira, source_instr, union_type);
14493 bigint_init_bigint(&result->value->data.x_union.tag, &union_field->enum_field->value);
14494 result->value->data.x_union.payload = val;
14495
14496 val->parent.id = ConstParentIdUnion;
14497 val->parent.data.p_union.union_val = result->value;
14498
14499 return result;
14500 }
14501
14502 IrInstGen *result_loc_inst = ir_resolve_result(ira, source_instr, no_result_loc(),
14503 union_type, nullptr, true, true);
14504 if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
14505 return ira->codegen->invalid_inst_gen;
14506 }
14507
14508 IrInstGen *payload_ptr = ir_analyze_container_field_ptr(ira, only_field->name, source_instr,
14509 result_loc_inst, source_instr, union_type, true);
14510 if (type_is_invalid(payload_ptr->value->type))
14511 return ira->codegen->invalid_inst_gen;
14512
14513 IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, payload_ptr, casted_value, false);
14514 if (type_is_invalid(store_ptr_inst->value->type))
14515 return ira->codegen->invalid_inst_gen;
14516
14517 return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);
1433614518}
1433714519
1433814520// Add a compile error and return ErrorSemanticAnalyzeFail if the pointer alignment does not work,
......@@ -14581,7 +14763,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
1458114763 return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
1458214764 }
1458314765
14584 // *[N]T to ?[]const T
14766 // *[N]T to ?[]T
1458514767 if (wanted_type->id == ZigTypeIdOptional &&
1458614768 is_slice(wanted_type->data.maybe.child_type) &&
1458714769 actual_type->id == ZigTypeIdPointer &&
......@@ -16170,6 +16352,15 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i
1617016352 IrInstGen *union_val = op1->value->type->id == ZigTypeIdUnion ? op1 : op2;
1617116353 IrInstGen *enum_val = op1->value->type->id == ZigTypeIdUnion ? op2 : op1;
1617216354
16355 if (!is_tagged_union(union_val->value->type)) {
16356 ErrorMsg *msg = ir_add_error_node(ira, source_node,
16357 buf_sprintf("comparison of union and enum literal is only valid for tagged union types"));
16358 add_error_note(ira->codegen, msg, union_val->value->type->data.unionation.decl_node,
16359 buf_sprintf("type %s is not a tagged union",
16360 buf_ptr(&union_val->value->type->name)));
16361 return ira->codegen->invalid_inst_gen;
16362 }
16363
1617316364 ZigType *tag_type = union_val->value->type->data.unionation.tag_type;
1617416365 assert(tag_type != nullptr);
1617516366
......@@ -19917,6 +20108,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1991720108 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee);
1991820109 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
1991920110 return err;
20111 buf_deinit(&buf);
1992020112 return ErrorNone;
1992120113 }
1992220114
......@@ -19936,6 +20128,31 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1993620128 dst_size, buf_ptr(&pointee->type->name), src_size));
1993720129 return ErrorSemanticAnalyzeFail;
1993820130 }
20131 case ConstPtrSpecialSubArray: {
20132 ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
20133 assert(array_val->type->id == ZigTypeIdArray);
20134 if (array_val->data.x_array.special != ConstArraySpecialNone)
20135 zig_panic("TODO");
20136 if (dst_size > src_size) {
20137 size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index;
20138 opt_ir_add_error_node(ira, codegen, source_node,
20139 buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from %s at index %" ZIG_PRI_usize " which is %" ZIG_PRI_usize " bytes",
20140 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
20141 return ErrorSemanticAnalyzeFail;
20142 }
20143 size_t elem_size = src_size;
20144 size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
20145 Buf buf = BUF_INIT;
20146 buf_resize(&buf, elem_count * elem_size);
20147 for (size_t i = 0; i < elem_count; i += 1) {
20148 ZigValue *elem_val = &array_val->data.x_array.data.s_none.elements[i];
20149 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
20150 }
20151 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
20152 return err;
20153 buf_deinit(&buf);
20154 return ErrorNone;
20155 }
1993920156 case ConstPtrSpecialBaseArray: {
1994020157 ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
1994120158 assert(array_val->type->id == ZigTypeIdArray);
......@@ -19959,6 +20176,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1995920176 }
1996020177 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
1996120178 return err;
20179 buf_deinit(&buf);
1996220180 return ErrorNone;
1996320181 }
1996420182 case ConstPtrSpecialBaseStruct:
......@@ -20538,6 +20756,44 @@ static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_
2053820756 allow_zero);
2053920757}
2054020758
20759static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align,
20760 uint64_t elem_index, uint32_t *result)
20761{
20762 Error err;
20763
20764 if (base_ptr_align == 0) {
20765 *result = 0;
20766 return ErrorNone;
20767 }
20768
20769 // figure out the largest alignment possible
20770 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
20771 return err;
20772
20773 uint64_t elem_size = type_size(ira->codegen, elem_type);
20774 uint64_t abi_align = get_abi_alignment(ira->codegen, elem_type);
20775 uint64_t ptr_align = base_ptr_align;
20776
20777 uint64_t chosen_align = abi_align;
20778 if (ptr_align >= abi_align) {
20779 while (ptr_align > abi_align) {
20780 if ((elem_index * elem_size) % ptr_align == 0) {
20781 chosen_align = ptr_align;
20782 break;
20783 }
20784 ptr_align >>= 1;
20785 }
20786 } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
20787 chosen_align = ptr_align;
20788 } else {
20789 // can't get here because guaranteed elem_size >= abi_align
20790 zig_unreachable();
20791 }
20792
20793 *result = chosen_align;
20794 return ErrorNone;
20795}
20796
2054120797static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemPtr *elem_ptr_instruction) {
2054220798 Error err;
2054320799 IrInstGen *array_ptr = elem_ptr_instruction->array_ptr->child;
......@@ -20578,11 +20834,6 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
2057820834 }
2057920835
2058020836 if (array_type->id == ZigTypeIdArray) {
20581 if (array_type->data.array.len == 0) {
20582 ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node,
20583 buf_sprintf("index 0 outside array of size 0"));
20584 return ira->codegen->invalid_inst_gen;
20585 }
2058620837 ZigType *child_type = array_type->data.array.child_type;
2058720838 if (ptr_type->data.pointer.host_int_bytes == 0) {
2058820839 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
......@@ -20681,29 +20932,11 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
2068120932 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,
2068220933 nullptr, nullptr);
2068320934 } else if (return_type->data.pointer.explicit_alignment != 0) {
20684 // figure out the largest alignment possible
20685
20686 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))
20935 uint32_t chosen_align;
20936 if ((err = compute_elem_align(ira, return_type->data.pointer.child_type,
20937 return_type->data.pointer.explicit_alignment, index, &chosen_align)))
20938 {
2068720939 return ira->codegen->invalid_inst_gen;
20688
20689 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
20690 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
20691 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
20692
20693 uint64_t chosen_align = abi_align;
20694 if (ptr_align >= abi_align) {
20695 while (ptr_align > abi_align) {
20696 if ((index * elem_size) % ptr_align == 0) {
20697 chosen_align = ptr_align;
20698 break;
20699 }
20700 ptr_align >>= 1;
20701 }
20702 } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
20703 chosen_align = ptr_align;
20704 } else {
20705 // can't get here because guaranteed elem_size >= abi_align
20706 zig_unreachable();
2070720940 }
2070820941 return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align);
2070920942 }
......@@ -20824,6 +21057,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
2082421057 }
2082521058 break;
2082621059 case ConstPtrSpecialBaseArray:
21060 case ConstPtrSpecialSubArray:
2082721061 {
2082821062 size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
2082921063 new_index = offset + index;
......@@ -20894,6 +21128,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
2089421128 out_val->data.x_ptr.special = ConstPtrSpecialRef;
2089521129 out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee;
2089621130 break;
21131 case ConstPtrSpecialSubArray:
2089721132 case ConstPtrSpecialBaseArray:
2089821133 {
2089921134 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
......@@ -22881,7 +23116,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi
2288123116 Error err;
2288223117 assert(union_type->id == ZigTypeIdUnion);
2288323118
22884 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown)))
23119 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusZeroBitsKnown)))
2288523120 return ira->codegen->invalid_inst_gen;
2288623121
2288723122 TypeUnionField *type_field = find_union_type_field(union_type, field_name);
......@@ -25445,11 +25680,22 @@ static IrInstGen *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstSrcE
2544525680static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
2544625681 Error err;
2544725682
25448 ZigType *ptr_type = get_src_ptr_type(ty);
25683 ZigType *ptr_type;
25684 if (is_slice(ty)) {
25685 TypeStructField *ptr_field = ty->data.structure.fields[slice_ptr_index];
25686 ptr_type = resolve_struct_field_type(ira->codegen, ptr_field);
25687 } else {
25688 ptr_type = get_src_ptr_type(ty);
25689 }
2544925690 assert(ptr_type != nullptr);
2545025691 if (ptr_type->id == ZigTypeIdPointer) {
2545125692 if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
2545225693 return err;
25694 } else if (is_slice(ptr_type)) {
25695 TypeStructField *ptr_field = ptr_type->data.structure.fields[slice_ptr_index];
25696 ZigType *slice_ptr_type = resolve_struct_field_type(ira->codegen, ptr_field);
25697 if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
25698 return err;
2545325699 }
2545425700
2545525701 *result_align = get_ptr_align(ira->codegen, ty);
......@@ -25904,6 +26150,7 @@ static IrInstGen *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstSrcMemset
2590426150 start = 0;
2590526151 bound_end = 1;
2590626152 break;
26153 case ConstPtrSpecialSubArray:
2590726154 case ConstPtrSpecialBaseArray:
2590826155 {
2590926156 ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
......@@ -26037,6 +26284,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy
2603726284 dest_start = 0;
2603826285 dest_end = 1;
2603926286 break;
26287 case ConstPtrSpecialSubArray:
2604026288 case ConstPtrSpecialBaseArray:
2604126289 {
2604226290 ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
......@@ -26080,6 +26328,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy
2608026328 src_start = 0;
2608126329 src_end = 1;
2608226330 break;
26331 case ConstPtrSpecialSubArray:
2608326332 case ConstPtrSpecialBaseArray:
2608426333 {
2608526334 ZigValue *array_val = src_ptr_val->data.x_ptr.data.base_array.array_val;
......@@ -26123,7 +26372,19 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy
2612326372 return ir_build_memcpy_gen(ira, &instruction->base.base, casted_dest_ptr, casted_src_ptr, casted_count);
2612426373}
2612526374
26375static ZigType *get_result_loc_type(IrAnalyze *ira, ResultLoc *result_loc) {
26376 if (result_loc == nullptr) return nullptr;
26377
26378 if (result_loc->id == ResultLocIdCast) {
26379 return ir_resolve_type(ira, result_loc->source_instruction->child);
26380 }
26381
26382 return nullptr;
26383}
26384
2612626385static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *instruction) {
26386 Error err;
26387
2612726388 IrInstGen *ptr_ptr = instruction->ptr->child;
2612826389 if (type_is_invalid(ptr_ptr->value->type))
2612926390 return ira->codegen->invalid_inst_gen;
......@@ -26153,6 +26414,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2615326414 end = nullptr;
2615426415 }
2615526416
26417 ZigValue *slice_sentinel_val = nullptr;
2615626418 ZigType *non_sentinel_slice_ptr_type;
2615726419 ZigType *elem_type;
2615826420
......@@ -26203,6 +26465,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2620326465 }
2620426466 } else if (is_slice(array_type)) {
2620526467 ZigType *maybe_sentineled_slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
26468 slice_sentinel_val = maybe_sentineled_slice_ptr_type->data.pointer.sentinel;
2620626469 non_sentinel_slice_ptr_type = adjust_ptr_sentinel(ira->codegen, maybe_sentineled_slice_ptr_type, nullptr);
2620726470 elem_type = non_sentinel_slice_ptr_type->data.pointer.child_type;
2620826471 } else {
......@@ -26211,7 +26474,6 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2621126474 return ira->codegen->invalid_inst_gen;
2621226475 }
2621326476
26214 ZigType *return_type;
2621526477 ZigValue *sentinel_val = nullptr;
2621626478 if (instruction->sentinel) {
2621726479 IrInstGen *uncasted_sentinel = instruction->sentinel->child;
......@@ -26223,11 +26485,76 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2622326485 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
2622426486 if (sentinel_val == nullptr)
2622526487 return ira->codegen->invalid_inst_gen;
26226 ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val);
26488 }
26489
26490 ZigType *child_array_type = (array_type->id == ZigTypeIdPointer &&
26491 array_type->data.pointer.ptr_len == PtrLenSingle) ? array_type->data.pointer.child_type : array_type;
26492
26493 ZigType *return_type;
26494
26495 // If start index and end index are both comptime known, then the result type is a pointer to array
26496 // not a slice. However, if the start or end index is a lazy value, and the result location is a slice,
26497 // then the pointer-to-array would be casted to a slice anyway. So, we preserve the laziness of these
26498 // values by making the return type a slice.
26499 ZigType *res_loc_type = get_result_loc_type(ira, instruction->result_loc);
26500 bool result_loc_is_slice = (res_loc_type != nullptr && is_slice(res_loc_type));
26501 bool end_is_known = !result_loc_is_slice &&
26502 ((end != nullptr && value_is_comptime(end->value)) ||
26503 (end == nullptr && child_array_type->id == ZigTypeIdArray));
26504
26505 ZigValue *array_sentinel = sentinel_val;
26506 if (end_is_known) {
26507 uint64_t end_scalar;
26508 if (end != nullptr) {
26509 ZigValue *end_val = ir_resolve_const(ira, end, UndefBad);
26510 if (!end_val)
26511 return ira->codegen->invalid_inst_gen;
26512 end_scalar = bigint_as_u64(&end_val->data.x_bigint);
26513 } else {
26514 end_scalar = child_array_type->data.array.len;
26515 }
26516 array_sentinel = (child_array_type->id == ZigTypeIdArray && end_scalar == child_array_type->data.array.len)
26517 ? child_array_type->data.array.sentinel : sentinel_val;
26518
26519 if (value_is_comptime(casted_start->value)) {
26520 ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad);
26521 if (!start_val)
26522 return ira->codegen->invalid_inst_gen;
26523
26524 uint64_t start_scalar = bigint_as_u64(&start_val->data.x_bigint);
26525
26526 if (start_scalar > end_scalar) {
26527 ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds slice"));
26528 return ira->codegen->invalid_inst_gen;
26529 }
26530
26531 uint32_t base_ptr_align = non_sentinel_slice_ptr_type->data.pointer.explicit_alignment;
26532 uint32_t ptr_byte_alignment = 0;
26533 if (end_scalar > start_scalar) {
26534 if ((err = compute_elem_align(ira, elem_type, base_ptr_align, start_scalar, &ptr_byte_alignment)))
26535 return ira->codegen->invalid_inst_gen;
26536 }
26537
26538 ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar,
26539 array_sentinel);
26540 return_type = get_pointer_to_type_extra(ira->codegen, return_array_type,
26541 non_sentinel_slice_ptr_type->data.pointer.is_const,
26542 non_sentinel_slice_ptr_type->data.pointer.is_volatile,
26543 PtrLenSingle, ptr_byte_alignment, 0, 0, false);
26544 goto done_with_return_type;
26545 }
26546 } else if (array_sentinel == nullptr && end == nullptr) {
26547 array_sentinel = slice_sentinel_val;
26548 }
26549 if (array_sentinel != nullptr) {
26550 // TODO deal with non-abi-alignment here
26551 ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, array_sentinel);
2622726552 return_type = get_slice_type(ira->codegen, slice_ptr_type);
2622826553 } else {
26554 // TODO deal with non-abi-alignment here
2622926555 return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type);
2623026556 }
26557done_with_return_type:
2623126558
2623226559 if (instr_is_comptime(ptr_ptr) &&
2623326560 value_is_comptime(casted_start->value) &&
......@@ -26238,12 +26565,8 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2623826565 size_t abs_offset;
2623926566 size_t rel_end;
2624026567 bool ptr_is_undef = false;
26241 if (array_type->id == ZigTypeIdArray ||
26242 (array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
26243 {
26568 if (child_array_type->id == ZigTypeIdArray) {
2624426569 if (array_type->id == ZigTypeIdPointer) {
26245 ZigType *child_array_type = array_type->data.pointer.child_type;
26246 assert(child_array_type->id == ZigTypeIdArray);
2624726570 parent_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.base.source_node);
2624826571 if (parent_ptr == nullptr)
2624926572 return ira->codegen->invalid_inst_gen;
......@@ -26254,6 +26577,10 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2625426577 abs_offset = 0;
2625526578 rel_end = SIZE_MAX;
2625626579 ptr_is_undef = true;
26580 } else if (parent_ptr->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
26581 array_val = nullptr;
26582 abs_offset = 0;
26583 rel_end = SIZE_MAX;
2625726584 } else {
2625826585 array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.base.source_node);
2625926586 if (array_val == nullptr)
......@@ -26296,6 +26623,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2629626623 rel_end = 1;
2629726624 }
2629826625 break;
26626 case ConstPtrSpecialSubArray:
2629926627 case ConstPtrSpecialBaseArray:
2630026628 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
2630126629 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
......@@ -26346,6 +26674,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2634626674 abs_offset = SIZE_MAX;
2634726675 rel_end = 1;
2634826676 break;
26677 case ConstPtrSpecialSubArray:
2634926678 case ConstPtrSpecialBaseArray:
2635026679 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
2635126680 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
......@@ -26406,15 +26735,28 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2640626735 }
2640726736
2640826737 IrInstGen *result = ir_const(ira, &instruction->base.base, return_type);
26409 ZigValue *out_val = result->value;
26410 out_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2);
2641126738
26412 ZigValue *ptr_val = out_val->data.x_struct.fields[slice_ptr_index];
26739 ZigValue *ptr_val;
26740 if (return_type->id == ZigTypeIdPointer) {
26741 // pointer to array
26742 ptr_val = result->value;
26743 } else {
26744 // slice
26745 result->value->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2);
26746
26747 ptr_val = result->value->data.x_struct.fields[slice_ptr_index];
2641326748
26749 ZigValue *len_val = result->value->data.x_struct.fields[slice_len_index];
26750 init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);
26751 }
26752
26753 bool return_type_is_const = non_sentinel_slice_ptr_type->data.pointer.is_const;
2641426754 if (array_val) {
2641526755 size_t index = abs_offset + start_scalar;
26416 bool is_const = slice_is_const(return_type);
26417 init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const, PtrLenUnknown);
26756 init_const_ptr_array(ira->codegen, ptr_val, array_val, index, return_type_is_const, PtrLenUnknown);
26757 if (return_type->id == ZigTypeIdPointer) {
26758 ptr_val->data.x_ptr.special = ConstPtrSpecialSubArray;
26759 }
2641826760 if (array_type->id == ZigTypeIdArray) {
2641926761 ptr_val->data.x_ptr.mut = ptr_ptr->value->data.x_ptr.mut;
2642026762 } else if (is_slice(array_type)) {
......@@ -26424,16 +26766,17 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2642426766 }
2642526767 } else if (ptr_is_undef) {
2642626768 ptr_val->type = get_pointer_to_type(ira->codegen, parent_ptr->type->data.pointer.child_type,
26427 slice_is_const(return_type));
26769 return_type_is_const);
2642826770 ptr_val->special = ConstValSpecialUndef;
2642926771 } else switch (parent_ptr->data.x_ptr.special) {
2643026772 case ConstPtrSpecialInvalid:
2643126773 case ConstPtrSpecialDiscard:
2643226774 zig_unreachable();
2643326775 case ConstPtrSpecialRef:
26434 init_const_ptr_ref(ira->codegen, ptr_val,
26435 parent_ptr->data.x_ptr.data.ref.pointee, slice_is_const(return_type));
26776 init_const_ptr_ref(ira->codegen, ptr_val, parent_ptr->data.x_ptr.data.ref.pointee,
26777 return_type_is_const);
2643626778 break;
26779 case ConstPtrSpecialSubArray:
2643726780 case ConstPtrSpecialBaseArray:
2643826781 zig_unreachable();
2643926782 case ConstPtrSpecialBaseStruct:
......@@ -26448,7 +26791,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2644826791 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
2644926792 parent_ptr->type->data.pointer.child_type,
2645026793 parent_ptr->data.x_ptr.data.hard_coded_addr.addr + start_scalar,
26451 slice_is_const(return_type));
26794 return_type_is_const);
2645226795 break;
2645326796 case ConstPtrSpecialFunction:
2645426797 zig_panic("TODO");
......@@ -26456,26 +26799,11 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2645626799 zig_panic("TODO");
2645726800 }
2645826801
26459 ZigValue *len_val = out_val->data.x_struct.fields[slice_len_index];
26460 init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);
26461
26802 // In the case of pointer-to-array, we must restore this because above it overwrites ptr_val->type
26803 result->value->type = return_type;
2646226804 return result;
2646326805 }
2646426806
26465 IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
26466 return_type, nullptr, true, true);
26467 if (result_loc != nullptr) {
26468 if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
26469 return result_loc;
26470 }
26471 IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type);
26472 dummy_value->value->special = ConstValSpecialRuntime;
26473 IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base,
26474 dummy_value, result_loc->value->type->data.pointer.child_type);
26475 if (type_is_invalid(dummy_result->value->type))
26476 return ira->codegen->invalid_inst_gen;
26477 }
26478
2647926807 if (generate_non_null_assert) {
2648026808 IrInstGen *ptr_val = ir_get_deref(ira, &instruction->base.base, ptr_ptr, nullptr);
2648126809
......@@ -26485,8 +26813,26 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2648526813 ir_build_assert_non_null(ira, &instruction->base.base, ptr_val);
2648626814 }
2648726815
26816 IrInstGen *result_loc = nullptr;
26817
26818 if (return_type->id != ZigTypeIdPointer) {
26819 result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
26820 return_type, nullptr, true, true);
26821 if (result_loc != nullptr) {
26822 if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
26823 return result_loc;
26824 }
26825 IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type);
26826 dummy_value->value->special = ConstValSpecialRuntime;
26827 IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base,
26828 dummy_value, result_loc->value->type->data.pointer.child_type);
26829 if (type_is_invalid(dummy_result->value->type))
26830 return ira->codegen->invalid_inst_gen;
26831 }
26832 }
26833
2648826834 return ir_build_slice_gen(ira, &instruction->base.base, return_type, ptr_ptr,
26489 casted_start, end, instruction->safety_check_on, result_loc);
26835 casted_start, end, instruction->safety_check_on, result_loc, sentinel_val);
2649026836}
2649126837
2649226838static IrInstGen *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstSrcHasField *instruction) {
......@@ -27512,10 +27858,18 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
2751227858 // We have a check for zero bits later so we use get_src_ptr_type to
2751327859 // validate src_type and dest_type.
2751427860
27515 ZigType *src_ptr_type = get_src_ptr_type(src_type);
27516 if (src_ptr_type == nullptr) {
27517 ir_add_error(ira, ptr_src, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
27518 return ira->codegen->invalid_inst_gen;
27861 ZigType *if_slice_ptr_type;
27862 if (is_slice(src_type)) {
27863 TypeStructField *ptr_field = src_type->data.structure.fields[slice_ptr_index];
27864 if_slice_ptr_type = resolve_struct_field_type(ira->codegen, ptr_field);
27865 } else {
27866 if_slice_ptr_type = src_type;
27867
27868 ZigType *src_ptr_type = get_src_ptr_type(src_type);
27869 if (src_ptr_type == nullptr) {
27870 ir_add_error(ira, ptr_src, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
27871 return ira->codegen->invalid_inst_gen;
27872 }
2751927873 }
2752027874
2752127875 ZigType *dest_ptr_type = get_src_ptr_type(dest_type);
......@@ -27525,7 +27879,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
2752527879 return ira->codegen->invalid_inst_gen;
2752627880 }
2752727881
27528 if (get_ptr_const(src_type) && !get_ptr_const(dest_type)) {
27882 if (get_ptr_const(ira->codegen, src_type) && !get_ptr_const(ira->codegen, dest_type)) {
2752927883 ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));
2753027884 return ira->codegen->invalid_inst_gen;
2753127885 }
......@@ -27543,7 +27897,10 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
2754327897 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusZeroBitsKnown)))
2754427898 return ira->codegen->invalid_inst_gen;
2754527899
27546 if (type_has_bits(ira->codegen, dest_type) && !type_has_bits(ira->codegen, src_type) && safety_check_on) {
27900 if (safety_check_on &&
27901 type_has_bits(ira->codegen, dest_type) &&
27902 !type_has_bits(ira->codegen, if_slice_ptr_type))
27903 {
2754727904 ErrorMsg *msg = ir_add_error(ira, source_instr,
2754827905 buf_sprintf("'%s' and '%s' do not have the same in-memory representation",
2754927906 buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
......@@ -27554,6 +27911,14 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
2755427911 return ira->codegen->invalid_inst_gen;
2755527912 }
2755627913
27914 // For slices, follow the `ptr` field.
27915 if (is_slice(src_type)) {
27916 TypeStructField *ptr_field = src_type->data.structure.fields[slice_ptr_index];
27917 IrInstGen *ptr_ref = ir_get_ref(ira, source_instr, ptr, true, false);
27918 IrInstGen *ptr_ptr = ir_analyze_struct_field_ptr(ira, source_instr, ptr_field, ptr_ref, src_type, false);
27919 ptr = ir_get_deref(ira, source_instr, ptr_ptr, nullptr);
27920 }
27921
2755727922 if (instr_is_comptime(ptr)) {
2755827923 bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type);
2755927924 UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad;
......@@ -27657,6 +28022,9 @@ static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ZigValue
2765728022 buf_write_value_bytes(codegen, &buf[buf_i], elem);
2765828023 buf_i += type_size(codegen, elem->type);
2765928024 }
28025 if (val->type->id == ZigTypeIdArray && val->type->data.array.sentinel != nullptr) {
28026 buf_write_value_bytes(codegen, &buf[buf_i], val->type->data.array.sentinel);
28027 }
2766028028}
2766128029
2766228030static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val) {
src/link.cpp+6-5
......@@ -566,6 +566,7 @@ static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFil
566566 Stage2ProgressNode *progress_node)
567567{
568568 CodeGen *child_gen = create_child_codegen(parent_gen, nullptr, OutTypeObj, nullptr, name, progress_node);
569 child_gen->root_out_name = buf_create_from_str(name);
569570 ZigList<CFile *> c_source_files = {0};
570571 c_source_files.append(c_file);
571572 child_gen->c_source_files = c_source_files;
......@@ -1650,7 +1651,6 @@ static void construct_linker_job_elf(LinkJob *lj) {
16501651
16511652 bool is_lib = g->out_type == OutTypeLib;
16521653 bool is_dyn_lib = g->is_dynamic && is_lib;
1653 Buf *soname = nullptr;
16541654 if (!g->have_dynamic_link) {
16551655 if (g->zig_target->arch == ZigLLVM_arm || g->zig_target->arch == ZigLLVM_armeb ||
16561656 g->zig_target->arch == ZigLLVM_thumb || g->zig_target->arch == ZigLLVM_thumbeb)
......@@ -1661,15 +1661,13 @@ static void construct_linker_job_elf(LinkJob *lj) {
16611661 }
16621662 } else if (is_dyn_lib) {
16631663 lj->args.append("-shared");
1664
1665 assert(buf_len(&g->bin_file_output_path) != 0);
1666 soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major);
16671664 }
16681665
16691666 if (target_requires_pie(g->zig_target) && g->out_type == OutTypeExe) {
16701667 lj->args.append("-pie");
16711668 }
16721669
1670 assert(buf_len(&g->bin_file_output_path) != 0);
16731671 lj->args.append("-o");
16741672 lj->args.append(buf_ptr(&g->bin_file_output_path));
16751673
......@@ -1739,6 +1737,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
17391737 }
17401738
17411739 if (is_dyn_lib) {
1740 Buf *soname = (g->override_soname == nullptr) ?
1741 buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major) :
1742 g->override_soname;
17421743 lj->args.append("-soname");
17431744 lj->args.append(buf_ptr(soname));
17441745
......@@ -2007,7 +2008,7 @@ static const char *get_def_lib(CodeGen *parent, const char *name, Buf *def_in_fi
20072008
20082009 ZigList<const char *> args = {};
20092010 args.append(buf_ptr(self_exe_path));
2010 args.append("cc");
2011 args.append("clang");
20112012 args.append("-x");
20122013 args.append("c");
20132014 args.append(buf_ptr(def_in_file));
src/main.cpp+303-12
......@@ -36,7 +36,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
3636 " build-lib [source] create library from source or object files\n"
3737 " build-obj [source] create object from source or assembly\n"
3838 " builtin show the source code of @import(\"builtin\")\n"
39 " cc C compiler\n"
39 " cc use Zig as a drop-in C compiler\n"
4040 " fmt parse files and render in canonical zig format\n"
4141 " id print the base64-encoded compiler id\n"
4242 " init-exe initialize a `zig build` application in the cwd\n"
......@@ -54,7 +54,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
5454 " --cache-dir [path] override the local cache directory\n"
5555 " --cache [auto|off|on] build in cache, print output path to stdout\n"
5656 " --color [auto|off|on] enable or disable colored error messages\n"
57 " --disable-gen-h do not generate a C header file (.h)\n"
5857 " --disable-valgrind omit valgrind client requests in debug builds\n"
5958 " --eh-frame-hdr enable C++ exception handling by passing --eh-frame-hdr to linker\n"
6059 " --enable-valgrind include valgrind client requests release builds\n"
......@@ -77,6 +76,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
7776 " -fno-emit-asm (default) do not output .s (assembly code)\n"
7877 " -femit-llvm-ir produce a .ll file with LLVM IR\n"
7978 " -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n"
79 " -femit-h generate a C header file (.h)\n"
80 " -fno-emit-h (default) do not generate a C header file (.h)\n"
8081 " --libc [file] Provide a file which specifies libc paths\n"
8182 " --name [name] override output name\n"
8283 " --output-dir [dir] override output directory (defaults to cwd)\n"
......@@ -270,7 +271,7 @@ static int main0(int argc, char **argv) {
270271 return 0;
271272 }
272273
273 if (argc >= 2 && (strcmp(argv[1], "cc") == 0 ||
274 if (argc >= 2 && (strcmp(argv[1], "clang") == 0 ||
274275 strcmp(argv[1], "-cc1") == 0 || strcmp(argv[1], "-cc1as") == 0))
275276 {
276277 return ZigClang_main(argc, argv);
......@@ -429,8 +430,10 @@ static int main0(int argc, char **argv) {
429430 bool enable_dump_analysis = false;
430431 bool enable_doc_generation = false;
431432 bool emit_bin = true;
433 const char *emit_bin_override_path = nullptr;
432434 bool emit_asm = false;
433435 bool emit_llvm_ir = false;
436 bool emit_h = false;
434437 const char *cache_dir = nullptr;
435438 CliPkg *cur_pkg = heap::c_allocator.create<CliPkg>();
436439 BuildMode build_mode = BuildModeDebug;
......@@ -439,7 +442,6 @@ static int main0(int argc, char **argv) {
439442 bool system_linker_hack = false;
440443 TargetSubsystem subsystem = TargetSubsystemAuto;
441444 bool want_single_threaded = false;
442 bool disable_gen_h = false;
443445 bool bundle_compiler_rt = false;
444446 Buf *override_lib_dir = nullptr;
445447 Buf *main_pkg_path = nullptr;
......@@ -450,6 +452,8 @@ static int main0(int argc, char **argv) {
450452 bool function_sections = false;
451453 const char *mcpu = nullptr;
452454 CodeModel code_model = CodeModelDefault;
455 const char *override_soname = nullptr;
456 bool only_preprocess = false;
453457
454458 ZigList<const char *> llvm_argv = {0};
455459 llvm_argv.append("zig (LLVM option parsing)");
......@@ -574,9 +578,240 @@ static int main0(int argc, char **argv) {
574578 return (term.how == TerminationIdClean) ? term.code : -1;
575579 } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
576580 return stage2_fmt(argc, argv);
577 }
581 } else if (argc >= 2 && strcmp(argv[1], "cc") == 0) {
582 emit_h = false;
583 strip = true;
584
585 bool c_arg = false;
586 Stage2ClangArgIterator it;
587 stage2_clang_arg_iterator(&it, argc, argv);
588 bool nostdlib = false;
589 bool is_shared_lib = false;
590 ZigList<Buf *> linker_args = {};
591 while (it.has_next) {
592 if ((err = stage2_clang_arg_next(&it))) {
593 fprintf(stderr, "unable to parse command line parameters: %s\n", err_str(err));
594 return EXIT_FAILURE;
595 }
596 switch (it.kind) {
597 case Stage2ClangArgTarget: // example: -target riscv64-linux-unknown
598 target_string = it.only_arg;
599 break;
600 case Stage2ClangArgO: // -o
601 emit_bin_override_path = it.only_arg;
602 enable_cache = CacheOptOn;
603 break;
604 case Stage2ClangArgC: // -c
605 c_arg = true;
606 break;
607 case Stage2ClangArgOther:
608 for (size_t i = 0; i < it.other_args_len; i += 1) {
609 clang_argv.append(it.other_args_ptr[i]);
610 }
611 break;
612 case Stage2ClangArgPositional: {
613 Buf *arg_buf = buf_create_from_str(it.only_arg);
614 if (buf_ends_with_str(arg_buf, ".c") ||
615 buf_ends_with_str(arg_buf, ".C") ||
616 buf_ends_with_str(arg_buf, ".cc") ||
617 buf_ends_with_str(arg_buf, ".cpp") ||
618 buf_ends_with_str(arg_buf, ".cxx") ||
619 buf_ends_with_str(arg_buf, ".s") ||
620 buf_ends_with_str(arg_buf, ".S"))
621 {
622 CFile *c_file = heap::c_allocator.create<CFile>();
623 c_file->source_path = it.only_arg;
624 c_source_files.append(c_file);
625 } else {
626 objects.append(it.only_arg);
627 }
628 break;
629 }
630 case Stage2ClangArgL: // -l
631 if (strcmp(it.only_arg, "c") == 0)
632 have_libc = true;
633 link_libs.append(it.only_arg);
634 break;
635 case Stage2ClangArgIgnore:
636 break;
637 case Stage2ClangArgDriverPunt:
638 // Never mind what we're doing, just pass the args directly. For example --help.
639 return ZigClang_main(argc, argv);
640 case Stage2ClangArgPIC:
641 want_pic = WantPICEnabled;
642 break;
643 case Stage2ClangArgNoPIC:
644 want_pic = WantPICDisabled;
645 break;
646 case Stage2ClangArgNoStdLib:
647 nostdlib = true;
648 break;
649 case Stage2ClangArgShared:
650 is_dynamic = true;
651 is_shared_lib = true;
652 break;
653 case Stage2ClangArgRDynamic:
654 rdynamic = true;
655 break;
656 case Stage2ClangArgWL: {
657 const char *arg = it.only_arg;
658 for (;;) {
659 size_t pos = 0;
660 while (arg[pos] != ',' && arg[pos] != 0) pos += 1;
661 linker_args.append(buf_create_from_mem(arg, pos));
662 if (arg[pos] == 0) break;
663 arg += pos + 1;
664 }
665 break;
666 }
667 case Stage2ClangArgPreprocess:
668 only_preprocess = true;
669 break;
670 case Stage2ClangArgOptimize:
671 // alright what release mode do they want?
672 if (strcmp(it.only_arg, "Os") == 0) {
673 build_mode = BuildModeSmallRelease;
674 } else if (strcmp(it.only_arg, "O2") == 0 ||
675 strcmp(it.only_arg, "O3") == 0 ||
676 strcmp(it.only_arg, "O4") == 0)
677 {
678 build_mode = BuildModeFastRelease;
679 } else if (strcmp(it.only_arg, "Og") == 0) {
680 build_mode = BuildModeDebug;
681 } else {
682 for (size_t i = 0; i < it.other_args_len; i += 1) {
683 clang_argv.append(it.other_args_ptr[i]);
684 }
685 }
686 break;
687 case Stage2ClangArgDebug:
688 strip = false;
689 if (strcmp(it.only_arg, "-g") == 0) {
690 // we handled with strip = false above
691 } else {
692 for (size_t i = 0; i < it.other_args_len; i += 1) {
693 clang_argv.append(it.other_args_ptr[i]);
694 }
695 }
696 break;
697 case Stage2ClangArgSanitize:
698 if (strcmp(it.only_arg, "undefined") == 0) {
699 want_sanitize_c = WantCSanitizeEnabled;
700 } else {
701 for (size_t i = 0; i < it.other_args_len; i += 1) {
702 clang_argv.append(it.other_args_ptr[i]);
703 }
704 }
705 break;
706 }
707 }
708 // Parse linker args
709 for (size_t i = 0; i < linker_args.length; i += 1) {
710 Buf *arg = linker_args.at(i);
711 if (buf_eql_str(arg, "-soname")) {
712 i += 1;
713 if (i >= linker_args.length) {
714 fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
715 return EXIT_FAILURE;
716 }
717 Buf *soname_buf = linker_args.at(i);
718 override_soname = buf_ptr(soname_buf);
719 // use it as --name
720 // example: libsoundio.so.2
721 size_t prefix = 0;
722 if (buf_starts_with_str(soname_buf, "lib")) {
723 prefix = 3;
724 }
725 size_t end = buf_len(soname_buf);
726 if (buf_ends_with_str(soname_buf, ".so")) {
727 end -= 3;
728 } else {
729 bool found_digit = false;
730 while (end > 0 && isdigit(buf_ptr(soname_buf)[end - 1])) {
731 found_digit = true;
732 end -= 1;
733 }
734 if (found_digit && end > 0 && buf_ptr(soname_buf)[end - 1] == '.') {
735 end -= 1;
736 } else {
737 end = buf_len(soname_buf);
738 }
739 if (buf_ends_with_str(buf_slice(soname_buf, prefix, end), ".so")) {
740 end -= 3;
741 }
742 }
743 out_name = buf_ptr(buf_slice(soname_buf, prefix, end));
744 } else if (buf_eql_str(arg, "-rpath")) {
745 i += 1;
746 if (i >= linker_args.length) {
747 fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
748 return EXIT_FAILURE;
749 }
750 Buf *rpath = linker_args.at(i);
751 rpath_list.append(buf_ptr(rpath));
752 } else if (buf_eql_str(arg, "-I") ||
753 buf_eql_str(arg, "--dynamic-linker") ||
754 buf_eql_str(arg, "-dynamic-linker"))
755 {
756 i += 1;
757 if (i >= linker_args.length) {
758 fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
759 return EXIT_FAILURE;
760 }
761 dynamic_linker = buf_ptr(linker_args.at(i));
762 } else {
763 fprintf(stderr, "warning: unsupported linker arg: %s\n", buf_ptr(arg));
764 }
765 }
766
767 if (want_sanitize_c == WantCSanitizeEnabled && build_mode == BuildModeFastRelease) {
768 build_mode = BuildModeSafeRelease;
769 }
578770
579 for (int i = 1; i < argc; i += 1) {
771 if (!nostdlib && !have_libc) {
772 have_libc = true;
773 link_libs.append("c");
774 }
775 if (only_preprocess) {
776 cmd = CmdBuild;
777 out_type = OutTypeObj;
778 emit_bin = false;
779 // Transfer "objects" into c_source_files
780 for (size_t i = 0; i < objects.length; i += 1) {
781 CFile *c_file = heap::c_allocator.create<CFile>();
782 c_file->source_path = objects.at(i);
783 c_source_files.append(c_file);
784 }
785 for (size_t i = 0; i < c_source_files.length; i += 1) {
786 Buf *src_path;
787 if (emit_bin_override_path != nullptr) {
788 src_path = buf_create_from_str(emit_bin_override_path);
789 } else {
790 src_path = buf_create_from_str(c_source_files.at(i)->source_path);
791 }
792 Buf basename = BUF_INIT;
793 os_path_split(src_path, nullptr, &basename);
794 c_source_files.at(i)->preprocessor_only_basename = buf_ptr(&basename);
795 }
796 } else if (!c_arg) {
797 cmd = CmdBuild;
798 if (is_shared_lib) {
799 out_type = OutTypeLib;
800 } else {
801 out_type = OutTypeExe;
802 }
803 if (emit_bin_override_path == nullptr) {
804 emit_bin_override_path = "a.out";
805 }
806 } else {
807 cmd = CmdBuild;
808 out_type = OutTypeObj;
809 }
810 if (c_source_files.length == 0 && objects.length == 0) {
811 // For example `zig cc` and no args should print the "no input files" message.
812 return ZigClang_main(argc, argv);
813 }
814 } else for (int i = 1; i < argc; i += 1) {
580815 char *arg = argv[i];
581816
582817 if (arg[0] == '-') {
......@@ -660,9 +895,7 @@ static int main0(int argc, char **argv) {
660895 } else if (strcmp(arg, "--system-linker-hack") == 0) {
661896 system_linker_hack = true;
662897 } else if (strcmp(arg, "--single-threaded") == 0) {
663 want_single_threaded = true;
664 } else if (strcmp(arg, "--disable-gen-h") == 0) {
665 disable_gen_h = true;
898 want_single_threaded = true;;
666899 } else if (strcmp(arg, "--bundle-compiler-rt") == 0) {
667900 bundle_compiler_rt = true;
668901 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
......@@ -719,6 +952,11 @@ static int main0(int argc, char **argv) {
719952 emit_llvm_ir = true;
720953 } else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) {
721954 emit_llvm_ir = false;
955 } else if (strcmp(arg, "-femit-h") == 0) {
956 emit_h = true;
957 } else if (strcmp(arg, "-fno-emit-h") == 0 || strcmp(arg, "--disable-gen-h") == 0) {
958 // the --disable-gen-h is there to support godbolt. once they upgrade to -fno-emit-h then we can remove this
959 emit_h = false;
722960 } else if (str_starts_with(arg, "-mcpu=")) {
723961 mcpu = arg + strlen("-mcpu=");
724962 } else if (i + 1 >= argc) {
......@@ -1134,6 +1372,18 @@ static int main0(int argc, char **argv) {
11341372 buf_out_name = buf_alloc();
11351373 os_path_extname(&basename, buf_out_name, nullptr);
11361374 }
1375 if (need_name && buf_out_name == nullptr && objects.length == 1) {
1376 Buf basename = BUF_INIT;
1377 os_path_split(buf_create_from_str(objects.at(0)), nullptr, &basename);
1378 buf_out_name = buf_alloc();
1379 os_path_extname(&basename, buf_out_name, nullptr);
1380 }
1381 if (need_name && buf_out_name == nullptr && emit_bin_override_path != nullptr) {
1382 Buf basename = BUF_INIT;
1383 os_path_split(buf_create_from_str(emit_bin_override_path), nullptr, &basename);
1384 buf_out_name = buf_alloc();
1385 os_path_extname(&basename, buf_out_name, nullptr);
1386 }
11371387
11381388 if (need_name && buf_out_name == nullptr) {
11391389 fprintf(stderr, "--name [name] not provided and unable to infer\n\n");
......@@ -1202,13 +1452,17 @@ static int main0(int argc, char **argv) {
12021452 g->verbose_cc = verbose_cc;
12031453 g->verbose_llvm_cpu_features = verbose_llvm_cpu_features;
12041454 g->output_dir = output_dir;
1205 g->disable_gen_h = disable_gen_h;
1455 g->disable_gen_h = !emit_h;
12061456 g->bundle_compiler_rt = bundle_compiler_rt;
12071457 codegen_set_errmsg_color(g, color);
12081458 g->system_linker_hack = system_linker_hack;
12091459 g->function_sections = function_sections;
12101460 g->code_model = code_model;
12111461
1462 if (override_soname) {
1463 g->override_soname = buf_create_from_str(override_soname);
1464 }
1465
12121466 for (size_t i = 0; i < lib_dirs.length; i += 1) {
12131467 codegen_add_lib_dir(g, lib_dirs.at(i));
12141468 }
......@@ -1287,9 +1541,46 @@ static int main0(int argc, char **argv) {
12871541 os_spawn_process(args, &term);
12881542 return term.code;
12891543 } else if (cmd == CmdBuild) {
1290 if (g->enable_cache) {
1544 if (emit_bin_override_path != nullptr) {
1545#if defined(ZIG_OS_WINDOWS)
1546 buf_replace(g->output_dir, '/', '\\');
1547#endif
1548 Buf *dest_path = buf_create_from_str(emit_bin_override_path);
1549 Buf *source_path;
1550 if (only_preprocess) {
1551 source_path = buf_alloc();
1552 Buf *pp_only_basename = buf_create_from_str(
1553 c_source_files.at(0)->preprocessor_only_basename);
1554 os_path_join(g->output_dir, pp_only_basename, source_path);
1555
1556 } else {
1557 source_path = &g->bin_file_output_path;
1558 }
1559 if ((err = os_update_file(source_path, dest_path))) {
1560 fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(source_path),
1561 buf_ptr(dest_path), err_str(err));
1562 return main_exit(root_progress_node, EXIT_FAILURE);
1563 }
1564 } else if (only_preprocess) {
1565#if defined(ZIG_OS_WINDOWS)
1566 buf_replace(g->c_artifact_dir, '/', '\\');
1567#endif
1568 // dump the preprocessed output to stdout
1569 for (size_t i = 0; i < c_source_files.length; i += 1) {
1570 Buf *source_path = buf_alloc();
1571 Buf *pp_only_basename = buf_create_from_str(
1572 c_source_files.at(i)->preprocessor_only_basename);
1573 os_path_join(g->c_artifact_dir, pp_only_basename, source_path);
1574 if ((err = os_dump_file(source_path, stdout))) {
1575 fprintf(stderr, "unable to read %s: %s\n", buf_ptr(source_path),
1576 err_str(err));
1577 return main_exit(root_progress_node, EXIT_FAILURE);
1578 }
1579 }
1580 } else if (g->enable_cache) {
12911581#if defined(ZIG_OS_WINDOWS)
12921582 buf_replace(&g->bin_file_output_path, '/', '\\');
1583 buf_replace(g->output_dir, '/', '\\');
12931584#endif
12941585 if (final_output_dir_step != nullptr) {
12951586 Buf *dest_basename = buf_alloc();
......@@ -1303,7 +1594,7 @@ static int main0(int argc, char **argv) {
13031594 return main_exit(root_progress_node, EXIT_FAILURE);
13041595 }
13051596 } else {
1306 if (g->emit_bin && printf("%s\n", buf_ptr(&g->bin_file_output_path)) < 0)
1597 if (printf("%s\n", buf_ptr(g->output_dir)) < 0)
13071598 return main_exit(root_progress_node, EXIT_FAILURE);
13081599 }
13091600 }
src/os.cpp+24
......@@ -1051,6 +1051,30 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) {
10511051 }
10521052}
10531053
1054Error os_dump_file(Buf *src_path, FILE *dest_file) {
1055 Error err;
1056
1057 FILE *src_f = fopen(buf_ptr(src_path), "rb");
1058 if (!src_f) {
1059 int err = errno;
1060 if (err == ENOENT) {
1061 return ErrorFileNotFound;
1062 } else if (err == EACCES || err == EPERM) {
1063 return ErrorAccess;
1064 } else {
1065 return ErrorFileSystem;
1066 }
1067 }
1068 copy_open_files(src_f, dest_file);
1069 if ((err = copy_open_files(src_f, dest_file))) {
1070 fclose(src_f);
1071 return err;
1072 }
1073
1074 fclose(src_f);
1075 return ErrorNone;
1076}
1077
10541078#if defined(ZIG_OS_WINDOWS)
10551079static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) {
10561080 mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
src/os.hpp+1
......@@ -129,6 +129,7 @@ void os_file_close(OsFile *file);
129129Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
130130Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
131131Error ATTRIBUTE_MUST_USE os_update_file(Buf *src_path, Buf *dest_path);
132Error ATTRIBUTE_MUST_USE os_dump_file(Buf *src_path, FILE *dest_file);
132133
133134Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);
134135Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);
src/parse_f128.c+62-17
......@@ -165,22 +165,36 @@ static long long scanexp(struct MuslFILE *f, int pok)
165165 int x;
166166 long long y;
167167 int neg = 0;
168
168
169169 c = shgetc(f);
170170 if (c=='+' || c=='-') {
171171 neg = (c=='-');
172172 c = shgetc(f);
173173 if (c-'0'>=10U && pok) shunget(f);
174174 }
175 if (c-'0'>=10U) {
175 if (c-'0'>=10U && c!='_') {
176176 shunget(f);
177177 return LLONG_MIN;
178178 }
179 for (x=0; c-'0'<10U && x<INT_MAX/10; c = shgetc(f))
180 x = 10*x + c-'0';
181 for (y=x; c-'0'<10U && y<LLONG_MAX/100; c = shgetc(f))
182 y = 10*y + c-'0';
183 for (; c-'0'<10U; c = shgetc(f));
179 for (x=0; ; c = shgetc(f)) {
180 if (c=='_') {
181 continue;
182 } else if (c-'0'<10U && x<INT_MAX/10) {
183 x = 10*x + c-'0';
184 } else {
185 break;
186 }
187 }
188 for (y=x; ; c = shgetc(f)) {
189 if (c=='_') {
190 continue;
191 } else if (c-'0'<10U && y<LLONG_MAX/100) {
192 y = 10*y + c-'0';
193 } else {
194 break;
195 }
196 }
197 for (; c-'0'<10U || c=='_'; c = shgetc(f));
184198 shunget(f);
185199 return neg ? -y : y;
186200}
......@@ -450,16 +464,36 @@ static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int si
450464 j=0;
451465 k=0;
452466
453 /* Don't let leading zeros consume buffer space */
454 for (; c=='0'; c = shgetc(f)) gotdig=1;
467 /* Don't let leading zeros/underscores consume buffer space */
468 for (; ; c = shgetc(f)) {
469 if (c=='_') {
470 continue;
471 } else if (c=='0') {
472 gotdig=1;
473 } else {
474 break;
475 }
476 }
477
455478 if (c=='.') {
456479 gotrad = 1;
457 for (c = shgetc(f); c=='0'; c = shgetc(f)) gotdig=1, lrp--;
480 for (c = shgetc(f); ; c = shgetc(f)) {
481 if (c == '_') {
482 continue;
483 } else if (c=='0') {
484 gotdig=1;
485 lrp--;
486 } else {
487 break;
488 }
489 }
458490 }
459491
460492 x[0] = 0;
461 for (; c-'0'<10U || c=='.'; c = shgetc(f)) {
462 if (c == '.') {
493 for (; c-'0'<10U || c=='.' || c=='_'; c = shgetc(f)) {
494 if (c == '_') {
495 continue;
496 } else if (c == '.') {
463497 if (gotrad) break;
464498 gotrad = 1;
465499 lrp = dc;
......@@ -773,18 +807,29 @@ static float128_t hexfloat(struct MuslFILE *f, int bits, int emin, int sign, int
773807
774808 c = shgetc(f);
775809
776 /* Skip leading zeros */
777 for (; c=='0'; c = shgetc(f)) gotdig = 1;
810 /* Skip leading zeros/underscores */
811 for (; c=='0' || c=='_'; c = shgetc(f)) gotdig = 1;
778812
779813 if (c=='.') {
780814 gotrad = 1;
781815 c = shgetc(f);
782816 /* Count zeros after the radix point before significand */
783 for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1;
817 for (rp=0; ; c = shgetc(f)) {
818 if (c == '_') {
819 continue;
820 } else if (c == '0') {
821 gotdig = 1;
822 rp--;
823 } else {
824 break;
825 }
826 }
784827 }
785828
786 for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) {
787 if (c=='.') {
829 for (; c-'0'<10U || (c|32)-'a'<6U || c=='.' || c=='_'; c = shgetc(f)) {
830 if (c=='_') {
831 continue;
832 } else if (c=='.') {
788833 if (gotrad) break;
789834 rp = dc;
790835 gotrad = 1;
src/parser.cpp+9-2
......@@ -879,7 +879,7 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {
879879// / KEYWORD_noasync BlockExprStatement
880880// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
881881// / KEYWORD_defer BlockExprStatement
882// / KEYWORD_errdefer BlockExprStatement
882// / KEYWORD_errdefer Payload? BlockExprStatement
883883// / IfStatement
884884// / LabeledStatement
885885// / SwitchExpr
......@@ -923,12 +923,18 @@ static AstNode *ast_parse_statement(ParseContext *pc) {
923923 if (defer == nullptr)
924924 defer = eat_token_if(pc, TokenIdKeywordErrdefer);
925925 if (defer != nullptr) {
926 Token *payload = (defer->id == TokenIdKeywordErrdefer) ?
927 ast_parse_payload(pc) : nullptr;
926928 AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
927929 AstNode *res = ast_create_node(pc, NodeTypeDefer, defer);
930
928931 res->data.defer.kind = ReturnKindUnconditional;
929932 res->data.defer.expr = statement;
930 if (defer->id == TokenIdKeywordErrdefer)
933 if (defer->id == TokenIdKeywordErrdefer) {
931934 res->data.defer.kind = ReturnKindError;
935 if (payload != nullptr)
936 res->data.defer.err_payload = token_symbol(pc, payload);
937 }
932938 return res;
933939 }
934940
......@@ -3032,6 +3038,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
30323038 break;
30333039 case NodeTypeDefer:
30343040 visit_field(&node->data.defer.expr, visit, context);
3041 visit_field(&node->data.defer.err_payload, visit, context);
30353042 break;
30363043 case NodeTypeVariableDeclaration:
30373044 visit_field(&node->data.variable_declaration.type, visit, context);
src/stage2.cpp+12
......@@ -304,3 +304,15 @@ enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths) {
304304
305305 return ErrorNone;
306306}
307
308void stage2_clang_arg_iterator(struct Stage2ClangArgIterator *it,
309 size_t argc, char **argv)
310{
311 const char *msg = "stage0 called stage2_clang_arg_iterator";
312 stage2_panic(msg, strlen(msg));
313}
314
315enum Error stage2_clang_arg_next(struct Stage2ClangArgIterator *it) {
316 const char *msg = "stage0 called stage2_clang_arg_next";
317 stage2_panic(msg, strlen(msg));
318}
src/stage2.h+47
......@@ -105,6 +105,10 @@ enum Error {
105105 ErrorTargetHasNoDynamicLinker,
106106 ErrorInvalidAbiVersion,
107107 ErrorInvalidOperatingSystemVersion,
108 ErrorUnknownClangOption,
109 ErrorPermissionDenied,
110 ErrorFileBusy,
111 ErrorLocked,
108112};
109113
110114// ABI warning
......@@ -291,6 +295,7 @@ struct ZigTarget {
291295 size_t cache_hash_len;
292296 const char *os_builtin_str;
293297 const char *dynamic_linker;
298 const char *standard_dynamic_linker_path;
294299};
295300
296301// ABI warning
......@@ -315,4 +320,46 @@ struct Stage2NativePaths {
315320// ABI warning
316321ZIG_EXTERN_C enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths);
317322
323// ABI warning
324enum Stage2ClangArg {
325 Stage2ClangArgTarget,
326 Stage2ClangArgO,
327 Stage2ClangArgC,
328 Stage2ClangArgOther,
329 Stage2ClangArgPositional,
330 Stage2ClangArgL,
331 Stage2ClangArgIgnore,
332 Stage2ClangArgDriverPunt,
333 Stage2ClangArgPIC,
334 Stage2ClangArgNoPIC,
335 Stage2ClangArgNoStdLib,
336 Stage2ClangArgShared,
337 Stage2ClangArgRDynamic,
338 Stage2ClangArgWL,
339 Stage2ClangArgPreprocess,
340 Stage2ClangArgOptimize,
341 Stage2ClangArgDebug,
342 Stage2ClangArgSanitize,
343};
344
345// ABI warning
346struct Stage2ClangArgIterator {
347 bool has_next;
348 enum Stage2ClangArg kind;
349 const char *only_arg;
350 const char *second_arg;
351 const char **other_args_ptr;
352 size_t other_args_len;
353 const char **argv_ptr;
354 size_t argv_len;
355 size_t next_index;
356};
357
358// ABI warning
359ZIG_EXTERN_C void stage2_clang_arg_iterator(struct Stage2ClangArgIterator *it,
360 size_t argc, char **argv);
361
362// ABI warning
363ZIG_EXTERN_C enum Error stage2_clang_arg_next(struct Stage2ClangArgIterator *it);
364
318365#endif
src/tokenizer.cpp+89-56
......@@ -177,10 +177,13 @@ enum TokenizeState {
177177 TokenizeStateSymbol,
178178 TokenizeStateZero, // "0", which might lead to "0x"
179179 TokenizeStateNumber, // "123", "0x123"
180 TokenizeStateNumberNoUnderscore, // "12_", "0x12_" next char must be digit
180181 TokenizeStateNumberDot,
181182 TokenizeStateFloatFraction, // "123.456", "0x123.456"
183 TokenizeStateFloatFractionNoUnderscore, // "123.45_", "0x123.45_"
182184 TokenizeStateFloatExponentUnsigned, // "123.456e", "123e", "0x123p"
183 TokenizeStateFloatExponentNumber, // "123.456e-", "123.456e5", "123.456e5e-5"
185 TokenizeStateFloatExponentNumber, // "123.456e7", "123.456e+7", "123.456e-7"
186 TokenizeStateFloatExponentNumberNoUnderscore, // "123.456e7_", "123.456e+7_", "123.456e-7_"
184187 TokenizeStateString,
185188 TokenizeStateStringEscape,
186189 TokenizeStateStringEscapeUnicodeStart,
......@@ -233,14 +236,10 @@ struct Tokenize {
233236 Token *cur_tok;
234237 Tokenization *out;
235238 uint32_t radix;
236 int32_t exp_add_amt;
237 bool is_exp_negative;
239 bool is_trailing_underscore;
238240 size_t char_code_index;
239241 bool unicode;
240242 uint32_t char_code;
241 int exponent_in_bin_or_dec;
242 BigInt specified_exponent;
243 BigInt significand;
244243 size_t remaining_code_units;
245244};
246245
......@@ -426,20 +425,16 @@ void tokenize(Buf *buf, Tokenization *out) {
426425 case '0':
427426 t.state = TokenizeStateZero;
428427 begin_token(&t, TokenIdIntLiteral);
428 t.is_trailing_underscore = false;
429429 t.radix = 10;
430 t.exp_add_amt = 1;
431 t.exponent_in_bin_or_dec = 0;
432430 bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, 0);
433 bigint_init_unsigned(&t.specified_exponent, 0);
434431 break;
435432 case DIGIT_NON_ZERO:
436433 t.state = TokenizeStateNumber;
437434 begin_token(&t, TokenIdIntLiteral);
435 t.is_trailing_underscore = false;
438436 t.radix = 10;
439 t.exp_add_amt = 1;
440 t.exponent_in_bin_or_dec = 0;
441437 bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, get_digit_value(c));
442 bigint_init_unsigned(&t.specified_exponent, 0);
443438 break;
444439 case '"':
445440 begin_token(&t, TokenIdStringLiteral);
......@@ -1189,17 +1184,15 @@ void tokenize(Buf *buf, Tokenization *out) {
11891184 switch (c) {
11901185 case 'b':
11911186 t.radix = 2;
1192 t.state = TokenizeStateNumber;
1187 t.state = TokenizeStateNumberNoUnderscore;
11931188 break;
11941189 case 'o':
11951190 t.radix = 8;
1196 t.exp_add_amt = 3;
1197 t.state = TokenizeStateNumber;
1191 t.state = TokenizeStateNumberNoUnderscore;
11981192 break;
11991193 case 'x':
12001194 t.radix = 16;
1201 t.exp_add_amt = 4;
1202 t.state = TokenizeStateNumber;
1195 t.state = TokenizeStateNumberNoUnderscore;
12031196 break;
12041197 default:
12051198 // reinterpret as normal number
......@@ -1208,9 +1201,27 @@ void tokenize(Buf *buf, Tokenization *out) {
12081201 continue;
12091202 }
12101203 break;
1204 case TokenizeStateNumberNoUnderscore:
1205 if (c == '_') {
1206 invalid_char_error(&t, c);
1207 break;
1208 } else if (get_digit_value(c) < t.radix) {
1209 t.is_trailing_underscore = false;
1210 t.state = TokenizeStateNumber;
1211 }
1212 // fall through
12111213 case TokenizeStateNumber:
12121214 {
1215 if (c == '_') {
1216 t.is_trailing_underscore = true;
1217 t.state = TokenizeStateNumberNoUnderscore;
1218 break;
1219 }
12131220 if (c == '.') {
1221 if (t.is_trailing_underscore) {
1222 invalid_char_error(&t, c);
1223 break;
1224 }
12141225 if (t.radix != 16 && t.radix != 10) {
12151226 invalid_char_error(&t, c);
12161227 }
......@@ -1218,17 +1229,26 @@ void tokenize(Buf *buf, Tokenization *out) {
12181229 break;
12191230 }
12201231 if (is_exponent_signifier(c, t.radix)) {
1232 if (t.is_trailing_underscore) {
1233 invalid_char_error(&t, c);
1234 break;
1235 }
12211236 if (t.radix != 16 && t.radix != 10) {
12221237 invalid_char_error(&t, c);
12231238 }
12241239 t.state = TokenizeStateFloatExponentUnsigned;
1240 t.radix = 10; // exponent is always base 10
12251241 assert(t.cur_tok->id == TokenIdIntLiteral);
1226 bigint_init_bigint(&t.significand, &t.cur_tok->data.int_lit.bigint);
12271242 set_token_id(&t, t.cur_tok, TokenIdFloatLiteral);
12281243 break;
12291244 }
12301245 uint32_t digit_value = get_digit_value(c);
12311246 if (digit_value >= t.radix) {
1247 if (t.is_trailing_underscore) {
1248 invalid_char_error(&t, c);
1249 break;
1250 }
1251
12321252 if (is_symbol_char(c)) {
12331253 invalid_char_error(&t, c);
12341254 }
......@@ -1259,20 +1279,41 @@ void tokenize(Buf *buf, Tokenization *out) {
12591279 continue;
12601280 }
12611281 t.pos -= 1;
1262 t.state = TokenizeStateFloatFraction;
1282 t.state = TokenizeStateFloatFractionNoUnderscore;
12631283 assert(t.cur_tok->id == TokenIdIntLiteral);
1264 bigint_init_bigint(&t.significand, &t.cur_tok->data.int_lit.bigint);
12651284 set_token_id(&t, t.cur_tok, TokenIdFloatLiteral);
12661285 continue;
12671286 }
1287 case TokenizeStateFloatFractionNoUnderscore:
1288 if (c == '_') {
1289 invalid_char_error(&t, c);
1290 } else if (get_digit_value(c) < t.radix) {
1291 t.is_trailing_underscore = false;
1292 t.state = TokenizeStateFloatFraction;
1293 }
1294 // fall through
12681295 case TokenizeStateFloatFraction:
12691296 {
1297 if (c == '_') {
1298 t.is_trailing_underscore = true;
1299 t.state = TokenizeStateFloatFractionNoUnderscore;
1300 break;
1301 }
12701302 if (is_exponent_signifier(c, t.radix)) {
1303 if (t.is_trailing_underscore) {
1304 invalid_char_error(&t, c);
1305 break;
1306 }
12711307 t.state = TokenizeStateFloatExponentUnsigned;
1308 t.radix = 10; // exponent is always base 10
12721309 break;
12731310 }
12741311 uint32_t digit_value = get_digit_value(c);
12751312 if (digit_value >= t.radix) {
1313 if (t.is_trailing_underscore) {
1314 invalid_char_error(&t, c);
1315 break;
1316 }
12761317 if (is_symbol_char(c)) {
12771318 invalid_char_error(&t, c);
12781319 }
......@@ -1282,46 +1323,47 @@ void tokenize(Buf *buf, Tokenization *out) {
12821323 t.state = TokenizeStateStart;
12831324 continue;
12841325 }
1285 t.exponent_in_bin_or_dec -= t.exp_add_amt;
1286 if (t.radix == 10) {
1287 // For now we use strtod to parse decimal floats, so we just have to get to the
1288 // end of the token.
1289 break;
1290 }
1291 BigInt digit_value_bi;
1292 bigint_init_unsigned(&digit_value_bi, digit_value);
1293
1294 BigInt radix_bi;
1295 bigint_init_unsigned(&radix_bi, t.radix);
1296
1297 BigInt multiplied;
1298 bigint_mul(&multiplied, &t.significand, &radix_bi);
12991326
1300 bigint_add(&t.significand, &multiplied, &digit_value_bi);
1301 break;
1327 // we use parse_f128 to generate the float literal, so just
1328 // need to get to the end of the token
13021329 }
1330 break;
13031331 case TokenizeStateFloatExponentUnsigned:
13041332 switch (c) {
13051333 case '+':
1306 t.is_exp_negative = false;
1307 t.state = TokenizeStateFloatExponentNumber;
1334 t.state = TokenizeStateFloatExponentNumberNoUnderscore;
13081335 break;
13091336 case '-':
1310 t.is_exp_negative = true;
1311 t.state = TokenizeStateFloatExponentNumber;
1337 t.state = TokenizeStateFloatExponentNumberNoUnderscore;
13121338 break;
13131339 default:
13141340 // reinterpret as normal exponent number
13151341 t.pos -= 1;
1316 t.is_exp_negative = false;
1317 t.state = TokenizeStateFloatExponentNumber;
1342 t.state = TokenizeStateFloatExponentNumberNoUnderscore;
13181343 continue;
13191344 }
13201345 break;
1346 case TokenizeStateFloatExponentNumberNoUnderscore:
1347 if (c == '_') {
1348 invalid_char_error(&t, c);
1349 } else if (get_digit_value(c) < t.radix) {
1350 t.is_trailing_underscore = false;
1351 t.state = TokenizeStateFloatExponentNumber;
1352 }
1353 // fall through
13211354 case TokenizeStateFloatExponentNumber:
13221355 {
1356 if (c == '_') {
1357 t.is_trailing_underscore = true;
1358 t.state = TokenizeStateFloatExponentNumberNoUnderscore;
1359 break;
1360 }
13231361 uint32_t digit_value = get_digit_value(c);
13241362 if (digit_value >= t.radix) {
1363 if (t.is_trailing_underscore) {
1364 invalid_char_error(&t, c);
1365 break;
1366 }
13251367 if (is_symbol_char(c)) {
13261368 invalid_char_error(&t, c);
13271369 }
......@@ -1331,21 +1373,9 @@ void tokenize(Buf *buf, Tokenization *out) {
13311373 t.state = TokenizeStateStart;
13321374 continue;
13331375 }
1334 if (t.radix == 10) {
1335 // For now we use strtod to parse decimal floats, so we just have to get to the
1336 // end of the token.
1337 break;
1338 }
1339 BigInt digit_value_bi;
1340 bigint_init_unsigned(&digit_value_bi, digit_value);
1341
1342 BigInt radix_bi;
1343 bigint_init_unsigned(&radix_bi, 10);
1344
1345 BigInt multiplied;
1346 bigint_mul(&multiplied, &t.specified_exponent, &radix_bi);
13471376
1348 bigint_add(&t.specified_exponent, &multiplied, &digit_value_bi);
1377 // we use parse_f128 to generate the float literal, so just
1378 // need to get to the end of the token
13491379 }
13501380 break;
13511381 case TokenizeStateSawDash:
......@@ -1399,6 +1429,9 @@ void tokenize(Buf *buf, Tokenization *out) {
13991429 case TokenizeStateStart:
14001430 case TokenizeStateError:
14011431 break;
1432 case TokenizeStateNumberNoUnderscore:
1433 case TokenizeStateFloatFractionNoUnderscore:
1434 case TokenizeStateFloatExponentNumberNoUnderscore:
14021435 case TokenizeStateNumberDot:
14031436 tokenize_error(&t, "unterminated number literal");
14041437 break;
test/cli.zig+1-1
......@@ -36,7 +36,7 @@ pub fn main() !void {
3636 testMissingOutputPath,
3737 };
3838 for (test_fns) |testFn| {
39 try fs.deleteTree(dir_path);
39 try fs.cwd().deleteTree(dir_path);
4040 try fs.cwd().makeDir(dir_path);
4141 try testFn(zig_exe, dir_path);
4242 }
test/compare_output.zig+1-1
......@@ -292,7 +292,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
292292 \\pub export fn main() c_int {
293293 \\ var array = [_]u32{ 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };
294294 \\
295 \\ c.qsort(@ptrCast(?*c_void, array[0..].ptr), @intCast(c_ulong, array.len), @sizeOf(i32), compare_fn);
295 \\ c.qsort(@ptrCast(?*c_void, &array), @intCast(c_ulong, array.len), @sizeOf(i32), compare_fn);
296296 \\
297297 \\ for (array) |item, i| {
298298 \\ if (item != i) {
test/compile_errors.zig+178-15
......@@ -2,6 +2,29 @@ const tests = @import("tests.zig");
22const std = @import("std");
33
44pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.addTest("unused variable error on errdefer",
6 \\fn foo() !void {
7 \\ errdefer |a| unreachable;
8 \\ return error.A;
9 \\}
10 \\export fn entry() void {
11 \\ foo() catch unreachable;
12 \\}
13 , &[_][]const u8{
14 "tmp.zig:2:15: error: unused variable: 'a'",
15 });
16
17 cases.addTest("comparison of non-tagged union and enum literal",
18 \\export fn entry() void {
19 \\ const U = union { A: u32, B: u64 };
20 \\ var u = U{ .A = 42 };
21 \\ var ok = u == .A;
22 \\}
23 , &[_][]const u8{
24 "tmp.zig:4:16: error: comparison of union and enum literal is only valid for tagged union types",
25 "tmp.zig:2:15: note: type U is not a tagged union",
26 });
27
528 cases.addTest("shift on type with non-power-of-two size",
629 \\export fn entry() void {
730 \\ const S = struct {
......@@ -103,18 +126,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
103126 "tmp.zig:3:23: error: pointer to size 0 type has no address",
104127 });
105128
106 cases.addTest("slice to pointer conversion mismatch",
107 \\pub fn bytesAsSlice(bytes: var) [*]align(1) const u16 {
108 \\ return @ptrCast([*]align(1) const u16, bytes.ptr)[0..1];
109 \\}
110 \\test "bytesAsSlice" {
111 \\ const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };
112 \\ const slice = bytesAsSlice(bytes[0..]);
113 \\}
114 , &[_][]const u8{
115 "tmp.zig:2:54: error: expected type '[*]align(1) const u16', found '[]align(1) const u16'",
116 });
117
118129 cases.addTest("access invalid @typeInfo decl",
119130 \\const A = B;
120131 \\test "Crash" {
......@@ -384,11 +395,163 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
384395 \\ var bad_float :f32 = 0.0;
385396 \\ bad_float = bad_float + .20;
386397 \\ std.debug.assert(bad_float < 1.0);
387 \\})
398 \\}
388399 , &[_][]const u8{
389400 "tmp.zig:5:29: error: invalid token: '.'",
390401 });
391402
403 cases.add("invalid exponent in float literal - 1",
404 \\fn main() void {
405 \\ var bad: f128 = 0x1.0p1ab1;
406 \\}
407 , &[_][]const u8{
408 "tmp.zig:2:28: error: invalid character: 'a'",
409 });
410
411 cases.add("invalid exponent in float literal - 2",
412 \\fn main() void {
413 \\ var bad: f128 = 0x1.0p50F;
414 \\}
415 , &[_][]const u8{
416 "tmp.zig:2:29: error: invalid character: 'F'",
417 });
418
419 cases.add("invalid underscore placement in float literal - 1",
420 \\fn main() void {
421 \\ var bad: f128 = 0._0;
422 \\}
423 , &[_][]const u8{
424 "tmp.zig:2:23: error: invalid character: '_'",
425 });
426
427 cases.add("invalid underscore placement in float literal - 2",
428 \\fn main() void {
429 \\ var bad: f128 = 0_.0;
430 \\}
431 , &[_][]const u8{
432 "tmp.zig:2:23: error: invalid character: '.'",
433 });
434
435 cases.add("invalid underscore placement in float literal - 3",
436 \\fn main() void {
437 \\ var bad: f128 = 0.0_;
438 \\}
439 , &[_][]const u8{
440 "tmp.zig:2:25: error: invalid character: ';'",
441 });
442
443 cases.add("invalid underscore placement in float literal - 4",
444 \\fn main() void {
445 \\ var bad: f128 = 1.0e_1;
446 \\}
447 , &[_][]const u8{
448 "tmp.zig:2:25: error: invalid character: '_'",
449 });
450
451 cases.add("invalid underscore placement in float literal - 5",
452 \\fn main() void {
453 \\ var bad: f128 = 1.0e+_1;
454 \\}
455 , &[_][]const u8{
456 "tmp.zig:2:26: error: invalid character: '_'",
457 });
458
459 cases.add("invalid underscore placement in float literal - 6",
460 \\fn main() void {
461 \\ var bad: f128 = 1.0e-_1;
462 \\}
463 , &[_][]const u8{
464 "tmp.zig:2:26: error: invalid character: '_'",
465 });
466
467 cases.add("invalid underscore placement in float literal - 7",
468 \\fn main() void {
469 \\ var bad: f128 = 1.0e-1_;
470 \\}
471 , &[_][]const u8{
472 "tmp.zig:2:28: error: invalid character: ';'",
473 });
474
475 cases.add("invalid underscore placement in float literal - 9",
476 \\fn main() void {
477 \\ var bad: f128 = 1__0.0e-1;
478 \\}
479 , &[_][]const u8{
480 "tmp.zig:2:23: error: invalid character: '_'",
481 });
482
483 cases.add("invalid underscore placement in float literal - 10",
484 \\fn main() void {
485 \\ var bad: f128 = 1.0__0e-1;
486 \\}
487 , &[_][]const u8{
488 "tmp.zig:2:25: error: invalid character: '_'",
489 });
490
491 cases.add("invalid underscore placement in float literal - 11",
492 \\fn main() void {
493 \\ var bad: f128 = 1.0e-1__0;
494 \\}
495 , &[_][]const u8{
496 "tmp.zig:2:28: error: invalid character: '_'",
497 });
498
499 cases.add("invalid underscore placement in float literal - 12",
500 \\fn main() void {
501 \\ var bad: f128 = 0_x0.0;
502 \\}
503 , &[_][]const u8{
504 "tmp.zig:2:23: error: invalid character: 'x'",
505 });
506
507 cases.add("invalid underscore placement in float literal - 13",
508 \\fn main() void {
509 \\ var bad: f128 = 0x_0.0;
510 \\}
511 , &[_][]const u8{
512 "tmp.zig:2:23: error: invalid character: '_'",
513 });
514
515 cases.add("invalid underscore placement in float literal - 14",
516 \\fn main() void {
517 \\ var bad: f128 = 0x0.0_p1;
518 \\}
519 , &[_][]const u8{
520 "tmp.zig:2:27: error: invalid character: 'p'",
521 });
522
523 cases.add("invalid underscore placement in int literal - 1",
524 \\fn main() void {
525 \\ var bad: u128 = 0010_;
526 \\}
527 , &[_][]const u8{
528 "tmp.zig:2:26: error: invalid character: ';'",
529 });
530
531 cases.add("invalid underscore placement in int literal - 2",
532 \\fn main() void {
533 \\ var bad: u128 = 0b0010_;
534 \\}
535 , &[_][]const u8{
536 "tmp.zig:2:28: error: invalid character: ';'",
537 });
538
539 cases.add("invalid underscore placement in int literal - 3",
540 \\fn main() void {
541 \\ var bad: u128 = 0o0010_;
542 \\}
543 , &[_][]const u8{
544 "tmp.zig:2:28: error: invalid character: ';'",
545 });
546
547 cases.add("invalid underscore placement in int literal - 4",
548 \\fn main() void {
549 \\ var bad: u128 = 0x0010_;
550 \\}
551 , &[_][]const u8{
552 "tmp.zig:2:28: error: invalid character: ';'",
553 });
554
392555 cases.add("var args without c calling conv",
393556 \\fn foo(args: ...) void {}
394557 \\comptime {
......@@ -1918,8 +2081,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
19182081 cases.add("reading past end of pointer casted array",
19192082 \\comptime {
19202083 \\ const array: [4]u8 = "aoeu".*;
1921 \\ const slice = array[1..];
1922 \\ const int_ptr = @ptrCast(*const u24, slice.ptr);
2084 \\ const sub_array = array[1..];
2085 \\ const int_ptr = @ptrCast(*const u24, sub_array);
19232086 \\ const deref = int_ptr.*;
19242087 \\}
19252088 , &[_][]const u8{
test/runtime_safety.zig+1-1
......@@ -69,7 +69,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
6969 \\}
7070 \\pub fn main() void {
7171 \\ var buf: [4]u8 = undefined;
72 \\ const ptr = buf[0..].ptr;
72 \\ const ptr: [*]u8 = &buf;
7373 \\ const slice = ptr[0..3 :0];
7474 \\}
7575 );
test/stage1/behavior/align.zig+22-14
......@@ -5,10 +5,17 @@ const builtin = @import("builtin");
55var foo: u8 align(4) = 100;
66
77test "global variable alignment" {
8 expect(@TypeOf(&foo).alignment == 4);
9 expect(@TypeOf(&foo) == *align(4) u8);
10 const slice = @as(*[1]u8, &foo)[0..];
11 expect(@TypeOf(slice) == []align(4) u8);
8 comptime expect(@TypeOf(&foo).alignment == 4);
9 comptime expect(@TypeOf(&foo) == *align(4) u8);
10 {
11 const slice = @as(*[1]u8, &foo)[0..];
12 comptime expect(@TypeOf(slice) == *align(4) [1]u8);
13 }
14 {
15 var runtime_zero: usize = 0;
16 const slice = @as(*[1]u8, &foo)[runtime_zero..];
17 comptime expect(@TypeOf(slice) == []align(4) u8);
18 }
1219}
1320
1421fn derp() align(@sizeOf(usize) * 2) i32 {
......@@ -171,18 +178,19 @@ test "runtime known array index has best alignment possible" {
171178
172179 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
173180 var smaller align(2) = [_]u32{ 1, 2, 3, 4 };
174 comptime expect(@TypeOf(smaller[0..]) == []align(2) u32);
175 comptime expect(@TypeOf(smaller[0..].ptr) == [*]align(2) u32);
176 testIndex(smaller[0..].ptr, 0, *align(2) u32);
177 testIndex(smaller[0..].ptr, 1, *align(2) u32);
178 testIndex(smaller[0..].ptr, 2, *align(2) u32);
179 testIndex(smaller[0..].ptr, 3, *align(2) u32);
181 var runtime_zero: usize = 0;
182 comptime expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32);
183 comptime expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32);
184 testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32);
185 testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32);
186 testIndex(smaller[runtime_zero..].ptr, 2, *align(2) u32);
187 testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32);
180188
181189 // has to use ABI alignment because index known at runtime only
182 testIndex2(array[0..].ptr, 0, *u8);
183 testIndex2(array[0..].ptr, 1, *u8);
184 testIndex2(array[0..].ptr, 2, *u8);
185 testIndex2(array[0..].ptr, 3, *u8);
190 testIndex2(array[runtime_zero..].ptr, 0, *u8);
191 testIndex2(array[runtime_zero..].ptr, 1, *u8);
192 testIndex2(array[runtime_zero..].ptr, 2, *u8);
193 testIndex2(array[runtime_zero..].ptr, 3, *u8);
186194}
187195fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
188196 comptime expect(@TypeOf(&smaller[index]) == T);
test/stage1/behavior/array.zig+38
......@@ -28,6 +28,24 @@ fn getArrayLen(a: []const u32) usize {
2828 return a.len;
2929}
3030
31test "array with sentinels" {
32 const S = struct {
33 fn doTheTest(is_ct: bool) void {
34 var zero_sized: [0:0xde]u8 = [_:0xde]u8{};
35 expectEqual(@as(u8, 0xde), zero_sized[0]);
36 // Disabled at runtime because of
37 // https://github.com/ziglang/zig/issues/4372
38 if (is_ct) {
39 var reinterpreted = @ptrCast(*[1]u8, &zero_sized);
40 expectEqual(@as(u8, 0xde), reinterpreted[0]);
41 }
42 }
43 };
44
45 S.doTheTest(false);
46 comptime S.doTheTest(true);
47}
48
3149test "void arrays" {
3250 var array: [4]void = undefined;
3351 array[0] = void{};
......@@ -376,3 +394,23 @@ test "type deduction for array subscript expression" {
376394 S.doTheTest();
377395 comptime S.doTheTest();
378396}
397
398test "sentinel element count towards the ABI size calculation" {
399 const S = struct {
400 fn doTheTest() void {
401 const T = packed struct {
402 fill_pre: u8 = 0x55,
403 data: [0:0]u8 = undefined,
404 fill_post: u8 = 0xAA,
405 };
406 var x = T{};
407 var as_slice = mem.asBytes(&x);
408 expectEqual(@as(usize, 3), as_slice.len);
409 expectEqual(@as(u8, 0x55), as_slice[0]);
410 expectEqual(@as(u8, 0xAA), as_slice[2]);
411 }
412 };
413
414 S.doTheTest();
415 comptime S.doTheTest();
416}
test/stage1/behavior/cast.zig+2-1
......@@ -435,7 +435,8 @@ fn incrementVoidPtrValue(value: ?*c_void) void {
435435
436436test "implicit cast from [*]T to ?*c_void" {
437437 var a = [_]u8{ 3, 2, 1 };
438 incrementVoidPtrArray(a[0..].ptr, 3);
438 var runtime_zero: usize = 0;
439 incrementVoidPtrArray(a[runtime_zero..].ptr, 3);
439440 expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 }));
440441}
441442
test/stage1/behavior/defer.zig+20-1
......@@ -1,4 +1,7 @@
1const expect = @import("std").testing.expect;
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const expectError = std.testing.expectError;
25
36var result: [3]u8 = undefined;
47var index: usize = undefined;
......@@ -93,3 +96,19 @@ test "return variable while defer expression in scope to modify it" {
9396 S.doTheTest();
9497 comptime S.doTheTest();
9598}
99
100test "errdefer with payload" {
101 const S = struct {
102 fn foo() !i32 {
103 errdefer |a| {
104 expectEqual(error.One, a);
105 }
106 return error.One;
107 }
108 fn doTheTest() void {
109 expectError(error.One, foo());
110 }
111 };
112 S.doTheTest();
113 comptime S.doTheTest();
114}
test/stage1/behavior/eval.zig+1-1
......@@ -524,7 +524,7 @@ test "comptime slice of slice preserves comptime var" {
524524test "comptime slice of pointer preserves comptime var" {
525525 comptime {
526526 var buff: [10]u8 = undefined;
527 var a = buff[0..].ptr;
527 var a = @ptrCast([*]u8, &buff);
528528 a[0..1][0] = 1;
529529 expect(buff[0..][0..][0] == 1);
530530 }
test/stage1/behavior/math.zig+28
......@@ -411,6 +411,34 @@ test "quad hex float literal parsing accurate" {
411411 comptime S.doTheTest();
412412}
413413
414test "underscore separator parsing" {
415 expect(0_0_0_0 == 0);
416 expect(1_234_567 == 1234567);
417 expect(001_234_567 == 1234567);
418 expect(0_0_1_2_3_4_5_6_7 == 1234567);
419
420 expect(0b0_0_0_0 == 0);
421 expect(0b1010_1010 == 0b10101010);
422 expect(0b0000_1010_1010 == 0b10101010);
423 expect(0b1_0_1_0_1_0_1_0 == 0b10101010);
424
425 expect(0o0_0_0_0 == 0);
426 expect(0o1010_1010 == 0o10101010);
427 expect(0o0000_1010_1010 == 0o10101010);
428 expect(0o1_0_1_0_1_0_1_0 == 0o10101010);
429
430 expect(0x0_0_0_0 == 0);
431 expect(0x1010_1010 == 0x10101010);
432 expect(0x0000_1010_1010 == 0x10101010);
433 expect(0x1_0_1_0_1_0_1_0 == 0x10101010);
434
435 expect(123_456.789_000e1_0 == 123456.789000e10);
436 expect(0_1_2_3_4_5_6.7_8_9_0_0_0e0_0_1_0 == 123456.789000e10);
437
438 expect(0x1234_5678.9ABC_DEF0p-1_0 == 0x12345678.9ABCDEF0p-10);
439 expect(0x1_2_3_4_5_6_7_8.9_A_B_C_D_E_F_0p-0_0_0_1_0 == 0x12345678.9ABCDEF0p-10);
440}
441
414442test "hex float literal within range" {
415443 const a = 0x1.0p16383;
416444 const b = 0x0.1p16387;
test/stage1/behavior/misc.zig+9-5
......@@ -102,8 +102,8 @@ test "memcpy and memset intrinsics" {
102102 var foo: [20]u8 = undefined;
103103 var bar: [20]u8 = undefined;
104104
105 @memset(foo[0..].ptr, 'A', foo.len);
106 @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);
105 @memset(&foo, 'A', foo.len);
106 @memcpy(&bar, &foo, bar.len);
107107
108108 if (bar[11] != 'A') unreachable;
109109}
......@@ -565,12 +565,16 @@ test "volatile load and store" {
565565 expect(ptr.* == 1235);
566566}
567567
568test "slice string literal has type []const u8" {
568test "slice string literal has correct type" {
569569 comptime {
570 expect(@TypeOf("aoeu"[0..]) == []const u8);
570 expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
571571 const array = [_]i32{ 1, 2, 3, 4 };
572 expect(@TypeOf(array[0..]) == []const i32);
572 expect(@TypeOf(array[0..]) == *const [4]i32);
573573 }
574 var runtime_zero: usize = 0;
575 comptime expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
576 const array = [_]i32{ 1, 2, 3, 4 };
577 comptime expect(@TypeOf(array[runtime_zero..]) == []const i32);
574578}
575579
576580test "pointer child field" {
test/stage1/behavior/pointers.zig+5-4
......@@ -159,12 +159,13 @@ test "allowzero pointer and slice" {
159159 var opt_ptr: ?[*]allowzero i32 = ptr;
160160 expect(opt_ptr != null);
161161 expect(@ptrToInt(ptr) == 0);
162 var slice = ptr[0..10];
163 expect(@TypeOf(slice) == []allowzero i32);
162 var runtime_zero: usize = 0;
163 var slice = ptr[runtime_zero..10];
164 comptime expect(@TypeOf(slice) == []allowzero i32);
164165 expect(@ptrToInt(&slice[5]) == 20);
165166
166 expect(@typeInfo(@TypeOf(ptr)).Pointer.is_allowzero);
167 expect(@typeInfo(@TypeOf(slice)).Pointer.is_allowzero);
167 comptime expect(@typeInfo(@TypeOf(ptr)).Pointer.is_allowzero);
168 comptime expect(@typeInfo(@TypeOf(slice)).Pointer.is_allowzero);
168169}
169170
170171test "assign null directly to C pointer and test null equality" {
test/stage1/behavior/ptrcast.zig+1-1
......@@ -13,7 +13,7 @@ fn testReinterpretBytesAsInteger() void {
1313 builtin.Endian.Little => 0xab785634,
1414 builtin.Endian.Big => 0x345678ab,
1515 };
16 expect(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
16 expect(@ptrCast(*align(1) const u32, bytes[1..5]).* == expected);
1717}
1818
1919test "reinterpret bytes of an array into an extern struct" {
test/stage1/behavior/slice.zig+177-4
......@@ -7,10 +7,10 @@ const mem = std.mem;
77const x = @intToPtr([*]i32, 0x1000)[0..0x500];
88const y = x[0x100..];
99test "compile time slice of pointer to hard coded address" {
10 expect(@ptrToInt(x.ptr) == 0x1000);
10 expect(@ptrToInt(x) == 0x1000);
1111 expect(x.len == 0x500);
1212
13 expect(@ptrToInt(y.ptr) == 0x1100);
13 expect(@ptrToInt(y) == 0x1100);
1414 expect(y.len == 0x400);
1515}
1616
......@@ -47,7 +47,9 @@ test "C pointer slice access" {
4747 var buf: [10]u32 = [1]u32{42} ** 10;
4848 const c_ptr = @ptrCast([*c]const u32, &buf);
4949
50 comptime expectEqual([]const u32, @TypeOf(c_ptr[0..1]));
50 var runtime_zero: usize = 0;
51 comptime expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
52 comptime expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
5153
5254 for (c_ptr[0..5]) |*cl| {
5355 expectEqual(@as(u32, 42), cl.*);
......@@ -107,7 +109,9 @@ test "obtaining a null terminated slice" {
107109 const ptr2 = buf[0..runtime_len :0];
108110 // ptr2 is a null-terminated slice
109111 comptime expect(@TypeOf(ptr2) == [:0]u8);
110 comptime expect(@TypeOf(ptr2[0..2]) == []u8);
112 comptime expect(@TypeOf(ptr2[0..2]) == *[2]u8);
113 var runtime_zero: usize = 0;
114 comptime expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
111115}
112116
113117test "empty array to slice" {
......@@ -126,3 +130,172 @@ test "empty array to slice" {
126130 S.doTheTest();
127131 comptime S.doTheTest();
128132}
133
134test "@ptrCast slice to pointer" {
135 const S = struct {
136 fn doTheTest() void {
137 var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
138 var slice: []u8 = &array;
139 var ptr = @ptrCast(*u16, slice);
140 expect(ptr.* == 65535);
141 }
142 };
143
144 S.doTheTest();
145 comptime S.doTheTest();
146}
147
148test "slice syntax resulting in pointer-to-array" {
149 const S = struct {
150 fn doTheTest() void {
151 testArray();
152 testArrayZ();
153 testArray0();
154 testArrayAlign();
155 testPointer();
156 testPointerZ();
157 testPointer0();
158 testPointerAlign();
159 testSlice();
160 testSliceZ();
161 testSlice0();
162 testSliceOpt();
163 testSliceAlign();
164 }
165
166 fn testArray() void {
167 var array = [5]u8{ 1, 2, 3, 4, 5 };
168 var slice = array[1..3];
169 comptime expect(@TypeOf(slice) == *[2]u8);
170 expect(slice[0] == 2);
171 expect(slice[1] == 3);
172 }
173
174 fn testArrayZ() void {
175 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
176 comptime expect(@TypeOf(array[1..3]) == *[2]u8);
177 comptime expect(@TypeOf(array[1..5]) == *[4:0]u8);
178 comptime expect(@TypeOf(array[1..]) == *[4:0]u8);
179 comptime expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
180 }
181
182 fn testArray0() void {
183 {
184 var array = [0]u8{};
185 var slice = array[0..0];
186 comptime expect(@TypeOf(slice) == *[0]u8);
187 }
188 {
189 var array = [0:0]u8{};
190 var slice = array[0..0];
191 comptime expect(@TypeOf(slice) == *[0:0]u8);
192 expect(slice[0] == 0);
193 }
194 }
195
196 fn testArrayAlign() void {
197 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
198 var slice = array[4..5];
199 comptime expect(@TypeOf(slice) == *align(4) [1]u8);
200 expect(slice[0] == 5);
201 comptime expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
202 }
203
204 fn testPointer() void {
205 var array = [5]u8{ 1, 2, 3, 4, 5 };
206 var pointer: [*]u8 = &array;
207 var slice = pointer[1..3];
208 comptime expect(@TypeOf(slice) == *[2]u8);
209 expect(slice[0] == 2);
210 expect(slice[1] == 3);
211 }
212
213 fn testPointerZ() void {
214 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
215 var pointer: [*:0]u8 = &array;
216 comptime expect(@TypeOf(pointer[1..3]) == *[2]u8);
217 comptime expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
218 }
219
220 fn testPointer0() void {
221 var pointer: [*]u0 = &[1]u0{0};
222 var slice = pointer[0..1];
223 comptime expect(@TypeOf(slice) == *[1]u0);
224 expect(slice[0] == 0);
225 }
226
227 fn testPointerAlign() void {
228 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
229 var pointer: [*]align(4) u8 = &array;
230 var slice = pointer[4..5];
231 comptime expect(@TypeOf(slice) == *align(4) [1]u8);
232 expect(slice[0] == 5);
233 comptime expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
234 }
235
236 fn testSlice() void {
237 var array = [5]u8{ 1, 2, 3, 4, 5 };
238 var src_slice: []u8 = &array;
239 var slice = src_slice[1..3];
240 comptime expect(@TypeOf(slice) == *[2]u8);
241 expect(slice[0] == 2);
242 expect(slice[1] == 3);
243 }
244
245 fn testSliceZ() void {
246 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
247 var slice: [:0]u8 = &array;
248 comptime expect(@TypeOf(slice[1..3]) == *[2]u8);
249 comptime expect(@TypeOf(slice[1..]) == [:0]u8);
250 comptime expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
251 }
252
253 fn testSliceOpt() void {
254 var array: [2]u8 = [2]u8{ 1, 2 };
255 var slice: ?[]u8 = &array;
256 comptime expect(@TypeOf(&array, slice) == ?[]u8);
257 comptime expect(@TypeOf(slice.?[0..2]) == *[2]u8);
258 }
259
260 fn testSlice0() void {
261 {
262 var array = [0]u8{};
263 var src_slice: []u8 = &array;
264 var slice = src_slice[0..0];
265 comptime expect(@TypeOf(slice) == *[0]u8);
266 }
267 {
268 var array = [0:0]u8{};
269 var src_slice: [:0]u8 = &array;
270 var slice = src_slice[0..0];
271 comptime expect(@TypeOf(slice) == *[0]u8);
272 }
273 }
274
275 fn testSliceAlign() void {
276 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
277 var src_slice: []align(4) u8 = &array;
278 var slice = src_slice[4..5];
279 comptime expect(@TypeOf(slice) == *align(4) [1]u8);
280 expect(slice[0] == 5);
281 comptime expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
282 }
283 };
284
285 S.doTheTest();
286 comptime S.doTheTest();
287}
288
289test "slice of hardcoded address to pointer" {
290 const S = struct {
291 fn doTheTest() void {
292 const pointer = @intToPtr([*]u8, 0x04)[0..2];
293 comptime expect(@TypeOf(pointer) == *[2]u8);
294 const slice: []const u8 = pointer;
295 expect(@ptrToInt(slice.ptr) == 4);
296 expect(slice.len == 2);
297 }
298 };
299
300 S.doTheTest();
301}
test/stage1/behavior/struct.zig+2-2
......@@ -409,8 +409,8 @@ const Bitfields = packed struct {
409409test "native bit field understands endianness" {
410410 var all: u64 = 0x7765443322221111;
411411 var bytes: [8]u8 = undefined;
412 @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
413 var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
412 @memcpy(&bytes, @ptrCast([*]u8, &all), 8);
413 var bitfields = @ptrCast(*Bitfields, &bytes).*;
414414
415415 expect(bitfields.f1 == 0x1111);
416416 expect(bitfields.f2 == 0x2222);
test/stage1/behavior/union.zig+28
......@@ -1,5 +1,6 @@
11const std = @import("std");
22const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
34
45const Value = union(enum) {
56 Int: u64,
......@@ -638,3 +639,30 @@ test "runtime tag name with single field" {
638639 var v = U{ .A = 42 };
639640 expect(std.mem.eql(u8, @tagName(v), "A"));
640641}
642
643test "cast from anonymous struct to union" {
644 const S = struct {
645 const U = union(enum) {
646 A: u32,
647 B: []const u8,
648 C: void,
649 };
650 fn doTheTest() void {
651 var y: u32 = 42;
652 const t0 = .{ .A = 123 };
653 const t1 = .{ .B = "foo" };
654 const t2 = .{ .C = {} };
655 const t3 = .{ .A = y };
656 const x0: U = t0;
657 var x1: U = t1;
658 const x2: U = t2;
659 var x3: U = t3;
660 expect(x0.A == 123);
661 expect(std.mem.eql(u8, x1.B, "foo"));
662 expect(x2 == .C);
663 expect(x3.A == y);
664 }
665 };
666 S.doTheTest();
667 comptime S.doTheTest();
668}
test/standalone/mix_o_files/test.c+5-3
......@@ -1,10 +1,12 @@
1// This header is generated by zig from base64.zig
2#include "base64.h"
3
41#include <assert.h>
52#include <string.h>
63#include <stdint.h>
74
5// TODO we would like to #include "base64.h" here but this feature has been disabled in
6// the stage1 compiler. Users will have to wait until self-hosted is available for
7// the "generate .h file" feature.
8size_t decode_base_64(uint8_t *dest_ptr, size_t dest_len, const uint8_t *source_ptr, size_t source_len);
9
810extern int *x_ptr;
911
1012int main(int argc, char **argv) {
test/standalone/shared_library/test.c+7-1
......@@ -1,6 +1,12 @@
1#include "mathtest.h"
21#include <assert.h>
32
3// TODO we would like to #include "mathtest.h" here but this feature has been disabled in
4// the stage1 compiler. Users will have to wait until self-hosted is available for
5// the "generate .h file" feature.
6
7#include <stdint.h>
8int32_t add(int32_t a, int32_t b);
9
410int main(int argc, char **argv) {
511 assert(add(42, 1337) == 1379);
612 return 0;
tools/process_headers.zig+11-11
......@@ -1,14 +1,14 @@
1// To get started, run this tool with no args and read the help message.
2//
3// The build systems of musl-libc and glibc require specifying a single target
4// architecture. Meanwhile, Zig supports out-of-the-box cross compilation for
5// every target. So the process to create libc headers that Zig ships is to use
6// this tool.
7// First, use the musl/glibc build systems to create installations of all the
8// targets in the `glibc_targets`/`musl_targets` variables.
9// Next, run this tool to create a new directory which puts .h files into
10// <arch> subdirectories, with `generic` being files that apply to all architectures.
11// You'll then have to manually update Zig source repo with these new files.
1//! To get started, run this tool with no args and read the help message.
2//!
3//! The build systems of musl-libc and glibc require specifying a single target
4//! architecture. Meanwhile, Zig supports out-of-the-box cross compilation for
5//! every target. So the process to create libc headers that Zig ships is to use
6//! this tool.
7//! First, use the musl/glibc build systems to create installations of all the
8//! targets in the `glibc_targets`/`musl_targets` variables.
9//! Next, run this tool to create a new directory which puts .h files into
10//! <arch> subdirectories, with `generic` being files that apply to all architectures.
11//! You'll then have to manually update Zig source repo with these new files.
1212
1313const std = @import("std");
1414const Arch = std.Target.Cpu.Arch;
tools/update_clang_options.zig created+460
......@@ -0,0 +1,460 @@
1//! To get started, run this tool with no args and read the help message.
2//!
3//! Clang has a file "options.td" which describes all of its command line parameter options.
4//! When using `zig cc`, Zig acts as a proxy between the user and Clang. It does not need
5//! to understand all the parameters, but it does need to understand some of them, such as
6//! the target. This means that Zig must understand when a C command line parameter expects
7//! to "consume" the next parameter on the command line.
8//!
9//! For example, `-z -target` would mean to pass `-target` to the linker, whereas `-E -target`
10//! would mean that the next parameter specifies the target.
11
12const std = @import("std");
13const fs = std.fs;
14const assert = std.debug.assert;
15const json = std.json;
16
17const KnownOpt = struct {
18 name: []const u8,
19
20 /// Corresponds to stage.zig ClangArgIterator.Kind
21 ident: []const u8,
22};
23
24const known_options = [_]KnownOpt{
25 .{
26 .name = "target",
27 .ident = "target",
28 },
29 .{
30 .name = "o",
31 .ident = "o",
32 },
33 .{
34 .name = "c",
35 .ident = "c",
36 },
37 .{
38 .name = "l",
39 .ident = "l",
40 },
41 .{
42 .name = "pipe",
43 .ident = "ignore",
44 },
45 .{
46 .name = "help",
47 .ident = "driver_punt",
48 },
49 .{
50 .name = "fPIC",
51 .ident = "pic",
52 },
53 .{
54 .name = "fno-PIC",
55 .ident = "no_pic",
56 },
57 .{
58 .name = "nostdlib",
59 .ident = "nostdlib",
60 },
61 .{
62 .name = "no-standard-libraries",
63 .ident = "nostdlib",
64 },
65 .{
66 .name = "shared",
67 .ident = "shared",
68 },
69 .{
70 .name = "rdynamic",
71 .ident = "rdynamic",
72 },
73 .{
74 .name = "Wl,",
75 .ident = "wl",
76 },
77 .{
78 .name = "E",
79 .ident = "preprocess",
80 },
81 .{
82 .name = "preprocess",
83 .ident = "preprocess",
84 },
85 .{
86 .name = "S",
87 .ident = "driver_punt",
88 },
89 .{
90 .name = "assemble",
91 .ident = "driver_punt",
92 },
93 .{
94 .name = "O1",
95 .ident = "optimize",
96 },
97 .{
98 .name = "O2",
99 .ident = "optimize",
100 },
101 .{
102 .name = "Og",
103 .ident = "optimize",
104 },
105 .{
106 .name = "O",
107 .ident = "optimize",
108 },
109 .{
110 .name = "Ofast",
111 .ident = "optimize",
112 },
113 .{
114 .name = "optimize",
115 .ident = "optimize",
116 },
117 .{
118 .name = "g",
119 .ident = "debug",
120 },
121 .{
122 .name = "debug",
123 .ident = "debug",
124 },
125 .{
126 .name = "g-dwarf",
127 .ident = "debug",
128 },
129 .{
130 .name = "g-dwarf-2",
131 .ident = "debug",
132 },
133 .{
134 .name = "g-dwarf-3",
135 .ident = "debug",
136 },
137 .{
138 .name = "g-dwarf-4",
139 .ident = "debug",
140 },
141 .{
142 .name = "g-dwarf-5",
143 .ident = "debug",
144 },
145 .{
146 .name = "fsanitize",
147 .ident = "sanitize",
148 },
149};
150
151const blacklisted_options = [_][]const u8{};
152
153fn knownOption(name: []const u8) ?[]const u8 {
154 const chopped_name = if (std.mem.endsWith(u8, name, "=")) name[0 .. name.len - 1] else name;
155 for (known_options) |item| {
156 if (std.mem.eql(u8, chopped_name, item.name)) {
157 return item.ident;
158 }
159 }
160 return null;
161}
162
163pub fn main() anyerror!void {
164 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
165 defer arena.deinit();
166
167 const allocator = &arena.allocator;
168 const args = try std.process.argsAlloc(allocator);
169
170 if (args.len <= 1) {
171 usageAndExit(std.io.getStdErr(), args[0], 1);
172 }
173 if (std.mem.eql(u8, args[1], "--help")) {
174 usageAndExit(std.io.getStdOut(), args[0], 0);
175 }
176 if (args.len < 3) {
177 usageAndExit(std.io.getStdErr(), args[0], 1);
178 }
179
180 const llvm_tblgen_exe = args[1];
181 if (std.mem.startsWith(u8, llvm_tblgen_exe, "-")) {
182 usageAndExit(std.io.getStdErr(), args[0], 1);
183 }
184
185 const llvm_src_root = args[2];
186 if (std.mem.startsWith(u8, llvm_src_root, "-")) {
187 usageAndExit(std.io.getStdErr(), args[0], 1);
188 }
189
190 const child_args = [_][]const u8{
191 llvm_tblgen_exe,
192 "--dump-json",
193 try std.fmt.allocPrint(allocator, "{}/clang/include/clang/Driver/Options.td", .{llvm_src_root}),
194 try std.fmt.allocPrint(allocator, "-I={}/llvm/include", .{llvm_src_root}),
195 try std.fmt.allocPrint(allocator, "-I={}/clang/include/clang/Driver", .{llvm_src_root}),
196 };
197
198 const child_result = try std.ChildProcess.exec2(.{
199 .allocator = allocator,
200 .argv = &child_args,
201 .max_output_bytes = 100 * 1024 * 1024,
202 });
203
204 std.debug.warn("{}\n", .{child_result.stderr});
205
206 const json_text = switch (child_result.term) {
207 .Exited => |code| if (code == 0) child_result.stdout else {
208 std.debug.warn("llvm-tblgen exited with code {}\n", .{code});
209 std.process.exit(1);
210 },
211 else => {
212 std.debug.warn("llvm-tblgen crashed\n", .{});
213 std.process.exit(1);
214 },
215 };
216
217 var parser = json.Parser.init(allocator, false);
218 const tree = try parser.parse(json_text);
219 const root_map = &tree.root.Object;
220
221 var all_objects = std.ArrayList(*json.ObjectMap).init(allocator);
222 {
223 var it = root_map.iterator();
224 it_map: while (it.next()) |kv| {
225 if (kv.key.len == 0) continue;
226 if (kv.key[0] == '!') continue;
227 if (kv.value != .Object) continue;
228 if (!kv.value.Object.contains("NumArgs")) continue;
229 if (!kv.value.Object.contains("Name")) continue;
230 for (blacklisted_options) |blacklisted_key| {
231 if (std.mem.eql(u8, blacklisted_key, kv.key)) continue :it_map;
232 }
233 if (kv.value.Object.get("Name").?.value.String.len == 0) continue;
234 try all_objects.append(&kv.value.Object);
235 }
236 }
237 // Some options have multiple matches. As an example, "-Wl,foo" matches both
238 // "W" and "Wl,". So we sort this list in order of descending priority.
239 std.sort.sort(*json.ObjectMap, all_objects.span(), objectLessThan);
240
241 var stdout_bos = std.io.bufferedOutStream(std.io.getStdOut().outStream());
242 const stdout = stdout_bos.outStream();
243 try stdout.writeAll(
244 \\// This file is generated by tools/update_clang_options.zig.
245 \\// zig fmt: off
246 \\usingnamespace @import("clang_options.zig");
247 \\pub const data = blk: { @setEvalBranchQuota(6000); break :blk &[_]CliArg{
248 \\
249 );
250
251 for (all_objects.span()) |obj| {
252 const name = obj.get("Name").?.value.String;
253 var pd1 = false;
254 var pd2 = false;
255 var pslash = false;
256 for (obj.get("Prefixes").?.value.Array.span()) |prefix_json| {
257 const prefix = prefix_json.String;
258 if (std.mem.eql(u8, prefix, "-")) {
259 pd1 = true;
260 } else if (std.mem.eql(u8, prefix, "--")) {
261 pd2 = true;
262 } else if (std.mem.eql(u8, prefix, "/")) {
263 pslash = true;
264 } else {
265 std.debug.warn("{} has unrecognized prefix '{}'\n", .{ name, prefix });
266 std.process.exit(1);
267 }
268 }
269 const syntax = objSyntax(obj);
270
271 if (knownOption(name)) |ident| {
272 try stdout.print(
273 \\.{{
274 \\ .name = "{}",
275 \\ .syntax = {},
276 \\ .zig_equivalent = .{},
277 \\ .pd1 = {},
278 \\ .pd2 = {},
279 \\ .psl = {},
280 \\}},
281 \\
282 , .{ name, syntax, ident, pd1, pd2, pslash });
283 } else if (pd1 and !pd2 and !pslash and syntax == .flag) {
284 try stdout.print("flagpd1(\"{}\"),\n", .{name});
285 } else if (pd1 and !pd2 and !pslash and syntax == .joined) {
286 try stdout.print("joinpd1(\"{}\"),\n", .{name});
287 } else if (pd1 and !pd2 and !pslash and syntax == .joined_or_separate) {
288 try stdout.print("jspd1(\"{}\"),\n", .{name});
289 } else if (pd1 and !pd2 and !pslash and syntax == .separate) {
290 try stdout.print("sepd1(\"{}\"),\n", .{name});
291 } else {
292 try stdout.print(
293 \\.{{
294 \\ .name = "{}",
295 \\ .syntax = {},
296 \\ .zig_equivalent = .other,
297 \\ .pd1 = {},
298 \\ .pd2 = {},
299 \\ .psl = {},
300 \\}},
301 \\
302 , .{ name, syntax, pd1, pd2, pslash });
303 }
304 }
305
306 try stdout.writeAll(
307 \\};};
308 \\
309 );
310
311 try stdout_bos.flush();
312}
313
314// TODO we should be able to import clang_options.zig but currently this is problematic because it will
315// import stage2.zig and that causes a bunch of stuff to get exported
316const Syntax = union(enum) {
317 /// A flag with no values.
318 flag,
319
320 /// An option which prefixes its (single) value.
321 joined,
322
323 /// An option which is followed by its value.
324 separate,
325
326 /// An option which is either joined to its (non-empty) value, or followed by its value.
327 joined_or_separate,
328
329 /// An option which is both joined to its (first) value, and followed by its (second) value.
330 joined_and_separate,
331
332 /// An option followed by its values, which are separated by commas.
333 comma_joined,
334
335 /// An option which consumes an optional joined argument and any other remaining arguments.
336 remaining_args_joined,
337
338 /// An option which is which takes multiple (separate) arguments.
339 multi_arg: u8,
340
341 pub fn format(
342 self: Syntax,
343 comptime fmt: []const u8,
344 options: std.fmt.FormatOptions,
345 out_stream: var,
346 ) !void {
347 switch (self) {
348 .multi_arg => |n| return out_stream.print(".{{.{}={}}}", .{ @tagName(self), n }),
349 else => return out_stream.print(".{}", .{@tagName(self)}),
350 }
351 }
352};
353
354fn objSyntax(obj: *json.ObjectMap) Syntax {
355 const num_args = @intCast(u8, obj.get("NumArgs").?.value.Integer);
356 for (obj.get("!superclasses").?.value.Array.span()) |superclass_json| {
357 const superclass = superclass_json.String;
358 if (std.mem.eql(u8, superclass, "Joined")) {
359 return .joined;
360 } else if (std.mem.eql(u8, superclass, "CLJoined")) {
361 return .joined;
362 } else if (std.mem.eql(u8, superclass, "CLIgnoredJoined")) {
363 return .joined;
364 } else if (std.mem.eql(u8, superclass, "CLCompileJoined")) {
365 return .joined;
366 } else if (std.mem.eql(u8, superclass, "JoinedOrSeparate")) {
367 return .joined_or_separate;
368 } else if (std.mem.eql(u8, superclass, "CLJoinedOrSeparate")) {
369 return .joined_or_separate;
370 } else if (std.mem.eql(u8, superclass, "CLCompileJoinedOrSeparate")) {
371 return .joined_or_separate;
372 } else if (std.mem.eql(u8, superclass, "Flag")) {
373 return .flag;
374 } else if (std.mem.eql(u8, superclass, "CLFlag")) {
375 return .flag;
376 } else if (std.mem.eql(u8, superclass, "CLIgnoredFlag")) {
377 return .flag;
378 } else if (std.mem.eql(u8, superclass, "Separate")) {
379 return .separate;
380 } else if (std.mem.eql(u8, superclass, "JoinedAndSeparate")) {
381 return .joined_and_separate;
382 } else if (std.mem.eql(u8, superclass, "CommaJoined")) {
383 return .comma_joined;
384 } else if (std.mem.eql(u8, superclass, "CLRemainingArgsJoined")) {
385 return .remaining_args_joined;
386 } else if (std.mem.eql(u8, superclass, "MultiArg")) {
387 return .{ .multi_arg = num_args };
388 }
389 }
390 const name = obj.get("Name").?.value.String;
391 if (std.mem.eql(u8, name, "<input>")) {
392 return .flag;
393 } else if (std.mem.eql(u8, name, "<unknown>")) {
394 return .flag;
395 }
396 const kind_def = obj.get("Kind").?.value.Object.get("def").?.value.String;
397 if (std.mem.eql(u8, kind_def, "KIND_FLAG")) {
398 return .flag;
399 }
400 const key = obj.get("!name").?.value.String;
401 std.debug.warn("{} (key {}) has unrecognized superclasses:\n", .{ name, key });
402 for (obj.get("!superclasses").?.value.Array.span()) |superclass_json| {
403 std.debug.warn(" {}\n", .{superclass_json.String});
404 }
405 std.process.exit(1);
406}
407
408fn syntaxMatchesWithEql(syntax: Syntax) bool {
409 return switch (syntax) {
410 .flag,
411 .separate,
412 .multi_arg,
413 => true,
414
415 .joined,
416 .joined_or_separate,
417 .joined_and_separate,
418 .comma_joined,
419 .remaining_args_joined,
420 => false,
421 };
422}
423
424fn objectLessThan(a: *json.ObjectMap, b: *json.ObjectMap) bool {
425 // Priority is determined by exact matches first, followed by prefix matches in descending
426 // length, with key as a final tiebreaker.
427 const a_syntax = objSyntax(a);
428 const b_syntax = objSyntax(b);
429
430 const a_match_with_eql = syntaxMatchesWithEql(a_syntax);
431 const b_match_with_eql = syntaxMatchesWithEql(b_syntax);
432
433 if (a_match_with_eql and !b_match_with_eql) {
434 return true;
435 } else if (!a_match_with_eql and b_match_with_eql) {
436 return false;
437 }
438
439 if (!a_match_with_eql and !b_match_with_eql) {
440 const a_name = a.get("Name").?.value.String;
441 const b_name = b.get("Name").?.value.String;
442 if (a_name.len != b_name.len) {
443 return a_name.len > b_name.len;
444 }
445 }
446
447 const a_key = a.get("!name").?.value.String;
448 const b_key = b.get("!name").?.value.String;
449 return std.mem.lessThan(u8, a_key, b_key);
450}
451
452fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn {
453 file.outStream().print(
454 \\Usage: {} /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
455 \\
456 \\Prints to stdout Zig code which you can use to replace the file src-self-hosted/clang_options_data.zig.
457 \\
458 , .{arg0}) catch std.process.exit(1);
459 std.process.exit(code);
460}
tools/update_glibc.zig+16-13
......@@ -20,6 +20,7 @@ const lib_names = [_][]const u8{
2020 "m",
2121 "pthread",
2222 "rt",
23 "ld",
2324};
2425
2526// fpu/nofpu are hardcoded elsewhere, based on .gnueabi/.gnueabihf with an exception for .arm
......@@ -154,22 +155,24 @@ pub fn main() !void {
154155 const fn_set = &target_funcs_gop.kv.value.list;
155156
156157 for (lib_names) |lib_name, lib_name_index| {
157 const basename = try fmt.allocPrint(allocator, "lib{}.abilist", .{lib_name});
158 const lib_prefix = if (std.mem.eql(u8, lib_name, "ld")) "" else "lib";
159 const basename = try fmt.allocPrint(allocator, "{}{}.abilist", .{ lib_prefix, lib_name });
158160 const abi_list_filename = blk: {
159 if (abi_list.targets[0].abi == .gnuabi64 and std.mem.eql(u8, lib_name, "c")) {
161 const is_c = std.mem.eql(u8, lib_name, "c");
162 const is_m = std.mem.eql(u8, lib_name, "m");
163 const is_ld = std.mem.eql(u8, lib_name, "ld");
164 if (abi_list.targets[0].abi == .gnuabi64 and (is_c or is_ld)) {
160165 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n64", basename });
161 } else if (abi_list.targets[0].abi == .gnuabin32 and std.mem.eql(u8, lib_name, "c")) {
166 } else if (abi_list.targets[0].abi == .gnuabin32 and (is_c or is_ld)) {
162167 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n32", basename });
163168 } else if (abi_list.targets[0].arch != .arm and
164169 abi_list.targets[0].abi == .gnueabihf and
165 (std.mem.eql(u8, lib_name, "c") or
166 (std.mem.eql(u8, lib_name, "m") and abi_list.targets[0].arch == .powerpc)))
170 (is_c or (is_m and abi_list.targets[0].arch == .powerpc)))
167171 {
168172 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "fpu", basename });
169173 } else if (abi_list.targets[0].arch != .arm and
170174 abi_list.targets[0].abi == .gnueabi and
171 (std.mem.eql(u8, lib_name, "c") or
172 (std.mem.eql(u8, lib_name, "m") and abi_list.targets[0].arch == .powerpc)))
175 (is_c or (is_m and abi_list.targets[0].arch == .powerpc)))
173176 {
174177 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "nofpu", basename });
175178 } else if (abi_list.targets[0].arch == .arm) {
......@@ -234,8 +237,8 @@ pub fn main() !void {
234237 const vers_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "vers.txt" });
235238 const vers_txt_file = try fs.cwd().createFile(vers_txt_path, .{});
236239 defer vers_txt_file.close();
237 var buffered = std.io.BufferedOutStream(fs.File.WriteError).init(&vers_txt_file.outStream().stream);
238 const vers_txt = &buffered.stream;
240 var buffered = std.io.bufferedOutStream(vers_txt_file.outStream());
241 const vers_txt = buffered.outStream();
239242 for (global_ver_list) |name, i| {
240243 _ = global_ver_set.put(name, i) catch unreachable;
241244 try vers_txt.print("{}\n", .{name});
......@@ -246,8 +249,8 @@ pub fn main() !void {
246249 const fns_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "fns.txt" });
247250 const fns_txt_file = try fs.cwd().createFile(fns_txt_path, .{});
248251 defer fns_txt_file.close();
249 var buffered = std.io.BufferedOutStream(fs.File.WriteError).init(&fns_txt_file.outStream().stream);
250 const fns_txt = &buffered.stream;
252 var buffered = std.io.bufferedOutStream(fns_txt_file.outStream());
253 const fns_txt = buffered.outStream();
251254 for (global_fn_list) |name, i| {
252255 const kv = global_fn_set.get(name).?;
253256 kv.value.index = i;
......@@ -277,8 +280,8 @@ pub fn main() !void {
277280 const abilist_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "abi.txt" });
278281 const abilist_txt_file = try fs.cwd().createFile(abilist_txt_path, .{});
279282 defer abilist_txt_file.close();
280 var buffered = std.io.BufferedOutStream(fs.File.WriteError).init(&abilist_txt_file.outStream().stream);
281 const abilist_txt = &buffered.stream;
283 var buffered = std.io.bufferedOutStream(abilist_txt_file.outStream());
284 const abilist_txt = buffered.outStream();
282285
283286 // first iterate over the abi lists
284287 for (abi_lists) |*abi_list, abi_index| {