@zigc/lib 0.16.0-test.1 → 0.17.0-dev.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/c/math.zig +135 -35
- package/c/stropts.zig +17 -0
- package/c.zig +1 -0
- package/compiler/aro/aro/Attribute/names.zig +604 -589
- package/compiler/aro/aro/Attribute.zig +202 -116
- package/compiler/aro/aro/Builtins/common.zig +874 -863
- package/compiler/aro/aro/Builtins/eval.zig +15 -7
- package/compiler/aro/aro/Builtins.zig +0 -1
- package/compiler/aro/aro/CodeGen.zig +3 -1
- package/compiler/aro/aro/Compilation.zig +120 -97
- package/compiler/aro/aro/Diagnostics.zig +21 -17
- package/compiler/aro/aro/Driver/GCCDetector.zig +635 -0
- package/compiler/aro/aro/Driver.zig +124 -50
- package/compiler/aro/aro/LangOpts.zig +12 -2
- package/compiler/aro/aro/Parser/Diagnostic.zig +79 -19
- package/compiler/aro/aro/Parser.zig +336 -142
- package/compiler/aro/aro/Preprocessor/Diagnostic.zig +21 -0
- package/compiler/aro/aro/Preprocessor.zig +127 -56
- package/compiler/aro/aro/Target.zig +17 -12
- package/compiler/aro/aro/Tokenizer.zig +31 -14
- package/compiler/aro/aro/Toolchain.zig +4 -7
- package/compiler/aro/aro/Tree.zig +178 -148
- package/compiler/aro/aro/TypeStore.zig +82 -24
- package/compiler/aro/aro/Value.zig +13 -17
- package/compiler/aro/aro/features.zig +1 -0
- package/compiler/aro/aro/pragmas/once.zig +0 -1
- package/compiler/aro/aro/record_layout.zig +3 -3
- package/compiler/aro/assembly_backend/x86_64.zig +3 -4
- package/compiler/aro/backend/Assembly.zig +1 -2
- package/compiler/aro/backend/Interner.zig +2 -2
- package/compiler/aro/backend/Ir.zig +100 -92
- package/compiler/aro/include/ptrcheck.h +49 -0
- package/compiler/aro/main.zig +26 -10
- package/compiler/build_runner.zig +1 -0
- package/compiler/objdump.zig +93 -0
- package/compiler/reduce.zig +5 -1
- package/compiler/resinator/compile.zig +2 -2
- package/compiler/resinator/main.zig +7 -1
- package/compiler/resinator/preprocess.zig +1 -3
- package/compiler/std-docs.zig +8 -1
- package/compiler/test_runner.zig +193 -61
- package/compiler/translate-c/MacroTranslator.zig +80 -11
- package/compiler/translate-c/PatternList.zig +1 -9
- package/compiler/translate-c/Scope.zig +43 -6
- package/compiler/translate-c/Translator.zig +364 -126
- package/compiler/translate-c/ast.zig +19 -11
- package/compiler/translate-c/main.zig +75 -16
- package/compiler_rt/cos.zig +141 -52
- package/compiler_rt/limb64.zig +266 -0
- package/compiler_rt/long_double.zig +37 -0
- package/compiler_rt/mulo.zig +6 -1
- package/compiler_rt/rem_pio2l.zig +173 -0
- package/compiler_rt/sin.zig +140 -55
- package/compiler_rt/sincos.zig +279 -72
- package/compiler_rt/tan.zig +118 -47
- package/compiler_rt/trig.zig +256 -6
- package/compiler_rt.zig +2 -0
- package/fuzzer.zig +855 -307
- package/libc/musl/src/math/pow.c +343 -0
- package/package.json +1 -1
- package/std/Build/Fuzz.zig +6 -19
- package/std/Build/Module.zig +1 -1
- package/std/Build/Step/CheckObject.zig +3 -3
- package/std/Build/Step/Compile.zig +18 -0
- package/std/Build/Step/ConfigHeader.zig +49 -33
- package/std/Build/Step/InstallArtifact.zig +18 -0
- package/std/Build/Step/Run.zig +536 -87
- package/std/Build/Step/TranslateC.zig +0 -6
- package/std/Build/Step.zig +8 -15
- package/std/Build/WebServer.zig +29 -17
- package/std/Build/abi.zig +47 -11
- package/std/Build.zig +17 -14
- package/std/Io/Dispatch.zig +2 -0
- package/std/Io/File/Reader.zig +3 -1
- package/std/Io/File.zig +1 -0
- package/std/Io/Kqueue.zig +2 -2
- package/std/Io/Threaded.zig +181 -143
- package/std/Io/Uring.zig +2 -1
- package/std/Io.zig +970 -2
- package/std/Target.zig +3 -2
- package/std/Thread.zig +8 -3
- package/std/array_hash_map.zig +96 -555
- package/std/array_list.zig +22 -31
- package/std/bit_set.zig +22 -6
- package/std/builtin/assembly.zig +68 -0
- package/std/c.zig +17 -17
- package/std/compress/flate/Compress.zig +3 -3
- package/std/crypto/Certificate/Bundle.zig +15 -1
- package/std/crypto/codecs/asn1.zig +33 -18
- package/std/crypto/codecs/base64_hex_ct.zig +14 -4
- package/std/debug/Dwarf.zig +29 -9
- package/std/debug/Info.zig +4 -0
- package/std/debug/MachOFile.zig +46 -8
- package/std/debug/Pdb.zig +539 -36
- package/std/debug/SelfInfo/Elf.zig +19 -18
- package/std/debug/SelfInfo/MachO.zig +18 -7
- package/std/debug/SelfInfo/Windows.zig +138 -36
- package/std/debug.zig +179 -65
- package/std/enums.zig +25 -19
- package/std/heap/ArenaAllocator.zig +145 -154
- package/std/heap/debug_allocator.zig +7 -7
- package/std/http/Client.zig +10 -6
- package/std/http.zig +11 -9
- package/std/json/Stringify.zig +3 -3
- package/std/json/dynamic.zig +4 -4
- package/std/math/big/int.zig +16 -17
- package/std/mem/Allocator.zig +4 -5
- package/std/mem.zig +48 -0
- package/std/os/emscripten.zig +2 -18
- package/std/os/linux/arc.zig +144 -0
- package/std/os/linux.zig +21 -4
- package/std/os/windows.zig +2 -2
- package/std/pdb.zig +143 -4
- package/std/posix.zig +6 -12
- package/std/priority_dequeue.zig +13 -12
- package/std/priority_queue.zig +5 -4
- package/std/process/Child.zig +1 -1
- package/std/process/Environ.zig +1 -1
- package/std/start.zig +17 -4
- package/std/std.zig +19 -6
- package/std/testing/FailingAllocator.zig +4 -4
- package/std/testing/Smith.zig +37 -2
- package/std/zig/Ast/Render.zig +186 -458
- package/std/zig/Ast.zig +0 -4
- package/std/zig/AstGen.zig +44 -7
- package/std/zig/AstSmith.zig +2602 -0
- package/std/zig/Client.zig +8 -3
- package/std/zig/Parse.zig +83 -74
- package/std/zig/Server.zig +26 -0
- package/std/zig/Zir.zig +17 -0
- package/std/zig/c_translation/helpers.zig +14 -9
- package/std/zig/llvm/Builder.zig +107 -48
- package/std/zig/system.zig +20 -4
- package/std/zig/tokenizer.zig +2 -1
- package/std/zig.zig +6 -0
- package/compiler/aro/aro/Driver/Filesystem.zig +0 -241
- package/libc/mingw/complex/cabs.c +0 -48
- package/libc/mingw/complex/cabsf.c +0 -48
- package/libc/mingw/complex/cacos.c +0 -50
- package/libc/mingw/complex/cacosf.c +0 -50
- package/libc/mingw/complex/carg.c +0 -48
- package/libc/mingw/complex/cargf.c +0 -48
- package/libc/mingw/complex/casin.c +0 -50
- package/libc/mingw/complex/casinf.c +0 -50
- package/libc/mingw/complex/catan.c +0 -50
- package/libc/mingw/complex/catanf.c +0 -50
- package/libc/mingw/complex/ccos.c +0 -50
- package/libc/mingw/complex/ccosf.c +0 -50
- package/libc/mingw/complex/cexp.c +0 -48
- package/libc/mingw/complex/cexpf.c +0 -48
- package/libc/mingw/complex/cimag.c +0 -48
- package/libc/mingw/complex/cimagf.c +0 -48
- package/libc/mingw/complex/clog.c +0 -48
- package/libc/mingw/complex/clog10.c +0 -49
- package/libc/mingw/complex/clog10f.c +0 -49
- package/libc/mingw/complex/clogf.c +0 -48
- package/libc/mingw/complex/conj.c +0 -48
- package/libc/mingw/complex/conjf.c +0 -48
- package/libc/mingw/complex/cpow.c +0 -48
- package/libc/mingw/complex/cpowf.c +0 -48
- package/libc/mingw/complex/cproj.c +0 -48
- package/libc/mingw/complex/cprojf.c +0 -48
- package/libc/mingw/complex/creal.c +0 -48
- package/libc/mingw/complex/crealf.c +0 -48
- package/libc/mingw/complex/csin.c +0 -50
- package/libc/mingw/complex/csinf.c +0 -50
- package/libc/mingw/complex/csqrt.c +0 -48
- package/libc/mingw/complex/csqrtf.c +0 -48
- package/libc/mingw/complex/ctan.c +0 -50
- package/libc/mingw/complex/ctanf.c +0 -50
- package/libc/mingw/math/arm/s_rint.c +0 -86
- package/libc/mingw/math/arm/s_rintf.c +0 -51
- package/libc/mingw/math/arm/sincos.S +0 -30
- package/libc/mingw/math/arm-common/sincosl.c +0 -13
- package/libc/mingw/math/arm64/rint.c +0 -12
- package/libc/mingw/math/arm64/rintf.c +0 -12
- package/libc/mingw/math/arm64/sincos.S +0 -32
- package/libc/mingw/math/bsd_private_base.h +0 -148
- package/libc/mingw/math/frexpf.c +0 -13
- package/libc/mingw/math/frexpl.c +0 -71
- package/libc/mingw/math/x86/acosf.c +0 -29
- package/libc/mingw/math/x86/atanf.c +0 -23
- package/libc/mingw/math/x86/atanl.c +0 -18
- package/libc/mingw/math/x86/cos.def.h +0 -65
- package/libc/mingw/math/x86/cosl.c +0 -46
- package/libc/mingw/math/x86/cosl_internal.S +0 -55
- package/libc/mingw/math/x86/ldexp.c +0 -23
- package/libc/mingw/math/x86/scalbn.S +0 -41
- package/libc/mingw/math/x86/scalbnf.S +0 -40
- package/libc/mingw/math/x86/sin.def.h +0 -65
- package/libc/mingw/math/x86/sinl.c +0 -46
- package/libc/mingw/math/x86/sinl_internal.S +0 -58
- package/libc/mingw/math/x86/tanl.S +0 -62
- package/libc/mingw/misc/btowc.c +0 -28
- package/libc/mingw/misc/wcstof.c +0 -66
- package/libc/mingw/misc/wcstoimax.c +0 -132
- package/libc/mingw/misc/wcstoumax.c +0 -126
- package/libc/mingw/misc/wctob.c +0 -29
- package/libc/mingw/misc/winbs_uint64.c +0 -6
- package/libc/mingw/misc/winbs_ulong.c +0 -6
- package/libc/mingw/misc/winbs_ushort.c +0 -6
- package/libc/mingw/stdio/_Exit.c +0 -10
- package/libc/mingw/stdio/_findfirst64i32.c +0 -21
- package/libc/mingw/stdio/_findnext64i32.c +0 -21
- package/libc/mingw/stdio/_fstat64i32.c +0 -37
- package/libc/mingw/stdio/_stat64i32.c +0 -37
- package/libc/mingw/stdio/_wfindfirst64i32.c +0 -21
- package/libc/mingw/stdio/_wfindnext64i32.c +0 -21
- package/libc/mingw/stdio/_wstat64i32.c +0 -37
- package/libc/musl/src/legacy/isastream.c +0 -7
- package/libc/musl/src/legacy/valloc.c +0 -8
- package/libc/musl/src/math/__cosl.c +0 -96
- package/libc/musl/src/math/__sinl.c +0 -78
- package/libc/musl/src/math/__tanl.c +0 -143
- package/libc/musl/src/math/aarch64/lrint.c +0 -10
- package/libc/musl/src/math/aarch64/lrintf.c +0 -10
- package/libc/musl/src/math/aarch64/rintf.c +0 -7
- package/libc/musl/src/math/cosl.c +0 -39
- package/libc/musl/src/math/fdim.c +0 -10
- package/libc/musl/src/math/finite.c +0 -7
- package/libc/musl/src/math/finitef.c +0 -7
- package/libc/musl/src/math/frexp.c +0 -23
- package/libc/musl/src/math/frexpf.c +0 -23
- package/libc/musl/src/math/frexpl.c +0 -29
- package/libc/musl/src/math/i386/lrint.c +0 -8
- package/libc/musl/src/math/i386/lrintf.c +0 -8
- package/libc/musl/src/math/i386/rintf.c +0 -7
- package/libc/musl/src/math/lrint.c +0 -72
- package/libc/musl/src/math/lrintf.c +0 -8
- package/libc/musl/src/math/powerpc64/lrint.c +0 -16
- package/libc/musl/src/math/powerpc64/lrintf.c +0 -16
- package/libc/musl/src/math/rintf.c +0 -30
- package/libc/musl/src/math/s390x/rintf.c +0 -15
- package/libc/musl/src/math/sincosl.c +0 -60
- package/libc/musl/src/math/sinl.c +0 -41
- package/libc/musl/src/math/tanl.c +0 -29
- package/libc/musl/src/math/x32/lrint.s +0 -5
- package/libc/musl/src/math/x32/lrintf.s +0 -5
- package/libc/musl/src/math/x86_64/lrint.c +0 -8
- package/libc/musl/src/math/x86_64/lrintf.c +0 -8
- package/libc/wasi/libc-bottom-half/sources/reallocarray.c +0 -14
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
-
const Io = std.Io;
|
|
3
2
|
const mem = std.mem;
|
|
4
3
|
const Allocator = mem.Allocator;
|
|
5
4
|
const assert = std.debug.assert;
|
|
@@ -204,6 +203,11 @@ string_ids: struct {
|
|
|
204
203
|
sigjmp_buf: StringId,
|
|
205
204
|
ucontext_t: StringId,
|
|
206
205
|
},
|
|
206
|
+
va_arg_pack_ctx: packed struct {
|
|
207
|
+
valid: bool = false,
|
|
208
|
+
variadic: bool = false,
|
|
209
|
+
typed: bool = false,
|
|
210
|
+
} = .{},
|
|
207
211
|
|
|
208
212
|
/// Checks codepoint for various pedantic warnings
|
|
209
213
|
/// Returns true if diagnostic issued
|
|
@@ -212,7 +216,7 @@ fn checkIdentifierCodepointWarnings(p: *Parser, codepoint: u21, loc: Source.Loca
|
|
|
212
216
|
|
|
213
217
|
const prev_total = p.diagnostics.total;
|
|
214
218
|
var sf = std.heap.stackFallback(1024, p.comp.gpa);
|
|
215
|
-
var allocating: Io.Writer.Allocating = .init(sf.get());
|
|
219
|
+
var allocating: std.Io.Writer.Allocating = .init(sf.get());
|
|
216
220
|
defer allocating.deinit();
|
|
217
221
|
|
|
218
222
|
if (!char_info.isC99IdChar(codepoint)) {
|
|
@@ -426,7 +430,7 @@ pub fn err(p: *Parser, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype)
|
|
|
426
430
|
if (p.diagnostics.effectiveKind(diagnostic) == .off) return;
|
|
427
431
|
|
|
428
432
|
var sf = std.heap.stackFallback(1024, p.comp.gpa);
|
|
429
|
-
var allocating: Io.Writer.Allocating = .init(sf.get());
|
|
433
|
+
var allocating: std.Io.Writer.Allocating = .init(sf.get());
|
|
430
434
|
defer allocating.deinit();
|
|
431
435
|
|
|
432
436
|
p.formatArgs(&allocating.writer, diagnostic.fmt, args) catch return error.OutOfMemory;
|
|
@@ -448,7 +452,7 @@ pub fn err(p: *Parser, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype)
|
|
|
448
452
|
}, p.pp.expansionSlice(tok_i), true);
|
|
449
453
|
}
|
|
450
454
|
|
|
451
|
-
fn formatArgs(p: *Parser, w: *Io.Writer, fmt: []const u8, args: anytype) !void {
|
|
455
|
+
fn formatArgs(p: *Parser, w: *std.Io.Writer, fmt: []const u8, args: anytype) !void {
|
|
452
456
|
var i: usize = 0;
|
|
453
457
|
inline for (std.meta.fields(@TypeOf(args))) |arg_info| {
|
|
454
458
|
const arg = @field(args, arg_info.name);
|
|
@@ -477,13 +481,13 @@ fn formatArgs(p: *Parser, w: *Io.Writer, fmt: []const u8, args: anytype) !void {
|
|
|
477
481
|
try w.writeAll(fmt[i..]);
|
|
478
482
|
}
|
|
479
483
|
|
|
480
|
-
fn formatTokenId(w: *Io.Writer, fmt: []const u8, tok_id: Tree.Token.Id) !usize {
|
|
484
|
+
fn formatTokenId(w: *std.Io.Writer, fmt: []const u8, tok_id: Tree.Token.Id) !usize {
|
|
481
485
|
const i = Diagnostics.templateIndex(w, fmt, "{tok_id}");
|
|
482
486
|
try w.writeAll(tok_id.symbol());
|
|
483
487
|
return i;
|
|
484
488
|
}
|
|
485
489
|
|
|
486
|
-
fn formatQualType(p: *Parser, w: *Io.Writer, fmt: []const u8, qt: QualType) !usize {
|
|
490
|
+
fn formatQualType(p: *Parser, w: *std.Io.Writer, fmt: []const u8, qt: QualType) !usize {
|
|
487
491
|
const i = Diagnostics.templateIndex(w, fmt, "{qt}");
|
|
488
492
|
try w.writeByte('\'');
|
|
489
493
|
try qt.print(p.comp, w);
|
|
@@ -502,7 +506,7 @@ fn formatQualType(p: *Parser, w: *Io.Writer, fmt: []const u8, qt: QualType) !usi
|
|
|
502
506
|
return i;
|
|
503
507
|
}
|
|
504
508
|
|
|
505
|
-
fn formatResult(p: *Parser, w: *Io.Writer, fmt: []const u8, res: Result) !usize {
|
|
509
|
+
fn formatResult(p: *Parser, w: *std.Io.Writer, fmt: []const u8, res: Result) !usize {
|
|
506
510
|
const i = Diagnostics.templateIndex(w, fmt, "{value}");
|
|
507
511
|
switch (res.val.opt_ref) {
|
|
508
512
|
.none => try w.writeAll("(none)"),
|
|
@@ -525,7 +529,7 @@ const Normalized = struct {
|
|
|
525
529
|
return .{ .str = str };
|
|
526
530
|
}
|
|
527
531
|
|
|
528
|
-
pub fn format(ctx: Normalized, w: *Io.Writer, fmt: []const u8) !usize {
|
|
532
|
+
pub fn format(ctx: Normalized, w: *std.Io.Writer, fmt: []const u8) !usize {
|
|
529
533
|
const i = Diagnostics.templateIndex(w, fmt, "{normalized}");
|
|
530
534
|
var it: std.unicode.Utf8Iterator = .{
|
|
531
535
|
.bytes = ctx.str,
|
|
@@ -559,7 +563,7 @@ const Codepoint = struct {
|
|
|
559
563
|
return .{ .codepoint = codepoint };
|
|
560
564
|
}
|
|
561
565
|
|
|
562
|
-
pub fn format(ctx: Codepoint, w: *Io.Writer, fmt: []const u8) !usize {
|
|
566
|
+
pub fn format(ctx: Codepoint, w: *std.Io.Writer, fmt: []const u8) !usize {
|
|
563
567
|
const i = Diagnostics.templateIndex(w, fmt, "{codepoint}");
|
|
564
568
|
try w.print("{X:0>4}", .{ctx.codepoint});
|
|
565
569
|
return i;
|
|
@@ -573,7 +577,7 @@ const Escaped = struct {
|
|
|
573
577
|
return .{ .str = str };
|
|
574
578
|
}
|
|
575
579
|
|
|
576
|
-
pub fn format(ctx: Escaped, w: *Io.Writer, fmt: []const u8) !usize {
|
|
580
|
+
pub fn format(ctx: Escaped, w: *std.Io.Writer, fmt: []const u8) !usize {
|
|
577
581
|
const i = Diagnostics.templateIndex(w, fmt, "{s}");
|
|
578
582
|
try std.zig.stringEscape(ctx.str, w);
|
|
579
583
|
return i;
|
|
@@ -740,6 +744,11 @@ fn getNode(p: *Parser, node: Node.Index, comptime tag: std.meta.Tag(Tree.Node))
|
|
|
740
744
|
}
|
|
741
745
|
}
|
|
742
746
|
|
|
747
|
+
pub fn isAddressOfStringLiteral(p: *Parser, node: Node.Index) bool {
|
|
748
|
+
const addr_of = p.getNode(node, .addr_of_expr) orelse return false;
|
|
749
|
+
return p.nodeIs(addr_of.operand, .string_literal_expr);
|
|
750
|
+
}
|
|
751
|
+
|
|
743
752
|
fn pragma(p: *Parser) Compilation.Error!bool {
|
|
744
753
|
var found_pragma = false;
|
|
745
754
|
while (p.eatToken(.keyword_pragma)) |_| {
|
|
@@ -1070,14 +1079,15 @@ fn decl(p: *Parser) Error!bool {
|
|
|
1070
1079
|
|
|
1071
1080
|
try p.attributeSpecifier();
|
|
1072
1081
|
|
|
1082
|
+
const decl_spec_start = p.tok_i;
|
|
1073
1083
|
var decl_spec = (try p.declSpec()) orelse blk: {
|
|
1074
1084
|
if (p.func.qt != null) {
|
|
1075
1085
|
p.tok_i = first_tok;
|
|
1076
1086
|
return false;
|
|
1077
1087
|
}
|
|
1078
|
-
switch (p.tok_ids[
|
|
1088
|
+
switch (p.tok_ids[decl_spec_start]) {
|
|
1079
1089
|
.asterisk, .l_paren => {},
|
|
1080
|
-
.identifier, .extended_identifier => switch (p.tok_ids[
|
|
1090
|
+
.identifier, .extended_identifier => switch (p.tok_ids[decl_spec_start + 1]) {
|
|
1081
1091
|
.identifier, .extended_identifier => {
|
|
1082
1092
|
// The most likely reason for `identifier identifier` is
|
|
1083
1093
|
// an unknown type name.
|
|
@@ -1087,7 +1097,7 @@ fn decl(p: *Parser) Error!bool {
|
|
|
1087
1097
|
},
|
|
1088
1098
|
else => {},
|
|
1089
1099
|
},
|
|
1090
|
-
else => if (p.tok_i !=
|
|
1100
|
+
else => if (p.tok_i != decl_spec_start) {
|
|
1091
1101
|
try p.err(p.tok_i, .expected_ident_or_l_paren, .{});
|
|
1092
1102
|
return error.ParsingFailed;
|
|
1093
1103
|
} else return false,
|
|
@@ -1167,6 +1177,7 @@ fn decl(p: *Parser) Error!bool {
|
|
|
1167
1177
|
|
|
1168
1178
|
// Collect old style parameter declarations.
|
|
1169
1179
|
if (init_d.d.old_style_func != null) {
|
|
1180
|
+
try p.err(init_d.d.name, .def_no_proto_deprecated, .{});
|
|
1170
1181
|
const param_buf_top = p.param_buf.items.len;
|
|
1171
1182
|
defer p.param_buf.items.len = param_buf_top;
|
|
1172
1183
|
|
|
@@ -1340,7 +1351,7 @@ fn decl(p: *Parser) Error!bool {
|
|
|
1340
1351
|
if (init_d.d.old_style_func) |tok_i| try p.err(tok_i, .invalid_old_style_params, .{});
|
|
1341
1352
|
|
|
1342
1353
|
if (decl_spec.storage_class == .typedef) {
|
|
1343
|
-
try decl_spec.validateDecl(p);
|
|
1354
|
+
try decl_spec.validateDecl(p, init_d.asm_label);
|
|
1344
1355
|
try p.tree.setNode(.{ .typedef = .{
|
|
1345
1356
|
.name_tok = init_d.d.name,
|
|
1346
1357
|
.qt = init_d.d.qt,
|
|
@@ -1357,7 +1368,7 @@ fn decl(p: *Parser) Error!bool {
|
|
|
1357
1368
|
.definition = null,
|
|
1358
1369
|
} }, @intFromEnum(decl_node));
|
|
1359
1370
|
} else {
|
|
1360
|
-
try decl_spec.validateDecl(p);
|
|
1371
|
+
try decl_spec.validateDecl(p, init_d.asm_label);
|
|
1361
1372
|
var node_qt = init_d.d.qt;
|
|
1362
1373
|
if (p.func.qt == null and decl_spec.storage_class != .@"extern") {
|
|
1363
1374
|
if (node_qt.get(p.comp, .array)) |array_ty| {
|
|
@@ -1454,7 +1465,7 @@ fn decl(p: *Parser) Error!bool {
|
|
|
1454
1465
|
return true;
|
|
1455
1466
|
}
|
|
1456
1467
|
|
|
1457
|
-
fn staticAssertMessage(p: *Parser, cond_node: Node.Index, maybe_message: ?Result, allocating: *Io.Writer.Allocating) !?[]const u8 {
|
|
1468
|
+
fn staticAssertMessage(p: *Parser, cond_node: Node.Index, maybe_message: ?Result, allocating: *std.Io.Writer.Allocating) !?[]const u8 {
|
|
1458
1469
|
const w = &allocating.writer;
|
|
1459
1470
|
|
|
1460
1471
|
const cond = cond_node.get(&p.tree);
|
|
@@ -1527,7 +1538,7 @@ fn staticAssert(p: *Parser) Error!bool {
|
|
|
1527
1538
|
} else {
|
|
1528
1539
|
if (!res.val.toBool(p.comp)) {
|
|
1529
1540
|
var sf = std.heap.stackFallback(1024, gpa);
|
|
1530
|
-
var allocating: Io.Writer.Allocating = .init(sf.get());
|
|
1541
|
+
var allocating: std.Io.Writer.Allocating = .init(sf.get());
|
|
1531
1542
|
defer allocating.deinit();
|
|
1532
1543
|
|
|
1533
1544
|
if (p.staticAssertMessage(res_node, str, &allocating) catch return error.OutOfMemory) |message| {
|
|
@@ -1597,13 +1608,16 @@ pub const DeclSpec = struct {
|
|
|
1597
1608
|
if (d.constexpr) |tok_i| try p.err(tok_i, .illegal_storage_on_func, .{});
|
|
1598
1609
|
}
|
|
1599
1610
|
|
|
1600
|
-
fn validateDecl(d: DeclSpec, p: *Parser) Error!void {
|
|
1611
|
+
fn validateDecl(d: DeclSpec, p: *Parser, asm_label: ?Node.Index) Error!void {
|
|
1601
1612
|
if (d.@"inline") |tok_i| try p.err(tok_i, .func_spec_non_func, .{"inline"});
|
|
1602
1613
|
// TODO move to attribute validation
|
|
1603
1614
|
if (d.noreturn) |tok_i| try p.err(tok_i, .func_spec_non_func, .{"_Noreturn"});
|
|
1604
1615
|
switch (d.storage_class) {
|
|
1605
|
-
.auto =>
|
|
1606
|
-
|
|
1616
|
+
.auto => {
|
|
1617
|
+
std.debug.assert(!p.comp.langopts.standard.atLeast(.c23));
|
|
1618
|
+
try p.err(p.tok_i, .auto_on_global, .{});
|
|
1619
|
+
},
|
|
1620
|
+
.register => if (p.func.qt == null and asm_label == null) try p.err(p.tok_i, .register_on_global, .{}),
|
|
1607
1621
|
else => {},
|
|
1608
1622
|
}
|
|
1609
1623
|
}
|
|
@@ -1787,7 +1801,11 @@ fn storageClassSpec(p: *Parser, d: *DeclSpec) Error!bool {
|
|
|
1787
1801
|
return p.tok_i != start;
|
|
1788
1802
|
}
|
|
1789
1803
|
|
|
1790
|
-
const InitDeclarator = struct {
|
|
1804
|
+
const InitDeclarator = struct {
|
|
1805
|
+
d: Declarator,
|
|
1806
|
+
initializer: ?Result = null,
|
|
1807
|
+
asm_label: ?Node.Index = null,
|
|
1808
|
+
};
|
|
1791
1809
|
|
|
1792
1810
|
/// attribute
|
|
1793
1811
|
/// : attrIdentifier
|
|
@@ -1829,18 +1847,18 @@ fn attribute(p: *Parser, kind: Attribute.Kind, namespace: ?[]const u8) Error!?Te
|
|
|
1829
1847
|
if (try p.eatIdentifier()) |ident| {
|
|
1830
1848
|
if (try Attribute.diagnoseIdent(attr, &arguments, ident, p)) {
|
|
1831
1849
|
p.skipTo(.r_paren);
|
|
1832
|
-
return
|
|
1850
|
+
return null;
|
|
1833
1851
|
}
|
|
1834
1852
|
} else {
|
|
1835
1853
|
try p.err(name_tok, .attribute_requires_identifier, .{name});
|
|
1836
|
-
return
|
|
1854
|
+
return null;
|
|
1837
1855
|
}
|
|
1838
1856
|
} else {
|
|
1839
1857
|
const arg_start = p.tok_i;
|
|
1840
1858
|
const first_expr = try p.expect(assignExpr);
|
|
1841
1859
|
if (try p.diagnose(attr, &arguments, arg_idx, first_expr, arg_start)) {
|
|
1842
1860
|
p.skipTo(.r_paren);
|
|
1843
|
-
return
|
|
1861
|
+
return null;
|
|
1844
1862
|
}
|
|
1845
1863
|
}
|
|
1846
1864
|
arg_idx += 1;
|
|
@@ -1851,7 +1869,7 @@ fn attribute(p: *Parser, kind: Attribute.Kind, namespace: ?[]const u8) Error!?Te
|
|
|
1851
1869
|
const arg_expr = try p.expect(assignExpr);
|
|
1852
1870
|
if (try p.diagnose(attr, &arguments, arg_idx, arg_expr, arg_start)) {
|
|
1853
1871
|
p.skipTo(.r_paren);
|
|
1854
|
-
return
|
|
1872
|
+
return null;
|
|
1855
1873
|
}
|
|
1856
1874
|
}
|
|
1857
1875
|
},
|
|
@@ -1861,9 +1879,9 @@ fn attribute(p: *Parser, kind: Attribute.Kind, namespace: ?[]const u8) Error!?Te
|
|
|
1861
1879
|
try p.err(name_tok, .attribute_not_enough_args, .{
|
|
1862
1880
|
@tagName(attr), required_count,
|
|
1863
1881
|
});
|
|
1864
|
-
return
|
|
1882
|
+
return null;
|
|
1865
1883
|
}
|
|
1866
|
-
return
|
|
1884
|
+
return .{ .attr = .{ .tag = attr, .args = arguments, .syntax = kind.toSyntax() }, .tok = name_tok };
|
|
1867
1885
|
}
|
|
1868
1886
|
|
|
1869
1887
|
fn diagnose(p: *Parser, attr: Attribute.Tag, arguments: *Attribute.Arguments, arg_idx: u32, res: Result, arg_start: TokenIndex) !bool {
|
|
@@ -1995,12 +2013,12 @@ fn initDeclarator(p: *Parser, decl_spec: *DeclSpec, attr_buf_top: usize, decl_no
|
|
|
1995
2013
|
defer p.attr_buf.len = this_attr_buf_top;
|
|
1996
2014
|
const gpa = p.comp.gpa;
|
|
1997
2015
|
|
|
1998
|
-
var init_d =
|
|
2016
|
+
var init_d: InitDeclarator = .{
|
|
1999
2017
|
.d = (try p.declarator(decl_spec.qt, .normal)) orelse return null,
|
|
2000
2018
|
};
|
|
2001
2019
|
|
|
2002
2020
|
try p.attributeSpecifierExtra(init_d.d.name);
|
|
2003
|
-
|
|
2021
|
+
init_d.asm_label = try p.assembly(.decl_label);
|
|
2004
2022
|
try p.attributeSpecifierExtra(init_d.d.name);
|
|
2005
2023
|
|
|
2006
2024
|
switch (init_d.d.declarator_type) {
|
|
@@ -2276,14 +2294,13 @@ fn typeSpec(p: *Parser, builder: *TypeStore.Builder) Error!bool {
|
|
|
2276
2294
|
}, .syntax = .keyword },
|
|
2277
2295
|
.tok = align_tok,
|
|
2278
2296
|
});
|
|
2279
|
-
} else {
|
|
2297
|
+
} else check: {
|
|
2280
2298
|
const arg_start = p.tok_i;
|
|
2281
2299
|
const res = try p.integerConstExpr(.no_const_decl_folding);
|
|
2282
2300
|
if (!res.val.isZero(p.comp)) {
|
|
2283
2301
|
var args = Attribute.initArguments(.aligned, align_tok);
|
|
2284
2302
|
if (try p.diagnose(.aligned, &args, 0, res, arg_start)) {
|
|
2285
|
-
|
|
2286
|
-
return error.ParsingFailed;
|
|
2303
|
+
break :check;
|
|
2287
2304
|
}
|
|
2288
2305
|
args.aligned.alignment.?.node = .pack(res.node);
|
|
2289
2306
|
try p.attr_buf.append(gpa, .{
|
|
@@ -2562,7 +2579,7 @@ fn recordSpec(p: *Parser) Error!QualType {
|
|
|
2562
2579
|
|
|
2563
2580
|
if (!any_incomplete) {
|
|
2564
2581
|
const pragma_pack_value = switch (p.comp.langopts.emulate) {
|
|
2565
|
-
.clang => starting_pragma_pack,
|
|
2582
|
+
.clang, .no => starting_pragma_pack,
|
|
2566
2583
|
.gcc => p.pragma_pack,
|
|
2567
2584
|
// TODO: msvc considers `#pragma pack` on a per-field basis
|
|
2568
2585
|
.msvc => p.pragma_pack,
|
|
@@ -3542,7 +3559,6 @@ fn declarator(
|
|
|
3542
3559
|
|
|
3543
3560
|
const pointer_qt = try p.comp.type_store.put(p.comp.gpa, .{ .pointer = .{
|
|
3544
3561
|
.child = d.qt,
|
|
3545
|
-
.decayed = null,
|
|
3546
3562
|
} });
|
|
3547
3563
|
d.qt = try builder.finishQuals(pointer_qt);
|
|
3548
3564
|
}
|
|
@@ -4141,7 +4157,10 @@ fn designation(p: *Parser, il: *InitList, init_qt: QualType, index_list: *IndexL
|
|
|
4141
4157
|
const field = record_ty.fields[field_index];
|
|
4142
4158
|
if (field.name_tok == 0) if (field.qt.getRecord(p.comp)) |field_record_ty| {
|
|
4143
4159
|
// Recurse into anonymous field if it has a field by the name.
|
|
4144
|
-
if (!field_record_ty.hasField(p.comp, target_name))
|
|
4160
|
+
if (!field_record_ty.hasField(p.comp, target_name)) {
|
|
4161
|
+
field_index += 1;
|
|
4162
|
+
continue;
|
|
4163
|
+
}
|
|
4145
4164
|
try index_list.append(gpa, field_index);
|
|
4146
4165
|
cur_il = try il.find(gpa, field_index);
|
|
4147
4166
|
record_ty = field_record_ty;
|
|
@@ -4983,31 +5002,31 @@ fn assembly(p: *Parser, kind: enum { global, decl_label, stmt }) Error!?Node.Ind
|
|
|
4983
5002
|
};
|
|
4984
5003
|
|
|
4985
5004
|
const l_paren = try p.expectToken(.l_paren);
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
.decl_label => {
|
|
5005
|
+
const res = switch (kind) {
|
|
5006
|
+
.decl_label => blk: {
|
|
4989
5007
|
const asm_str = try p.asmStr();
|
|
4990
5008
|
const str = try p.removeNull(asm_str.val);
|
|
4991
5009
|
|
|
4992
5010
|
const attr = Attribute{ .tag = .asm_label, .args = .{ .asm_label = .{ .name = str } }, .syntax = .keyword };
|
|
4993
5011
|
try p.attr_buf.append(p.comp.gpa, .{ .attr = attr, .tok = asm_tok });
|
|
5012
|
+
break :blk asm_str.node;
|
|
4994
5013
|
},
|
|
4995
|
-
.global => {
|
|
5014
|
+
.global => blk: {
|
|
4996
5015
|
const asm_str = try p.asmStr();
|
|
4997
5016
|
try p.checkAsmStr(asm_str.val, l_paren);
|
|
4998
|
-
|
|
5017
|
+
break :blk try p.addNode(.{
|
|
4999
5018
|
.global_asm = .{
|
|
5000
5019
|
.asm_tok = asm_tok,
|
|
5001
5020
|
.asm_str = asm_str.node,
|
|
5002
5021
|
},
|
|
5003
5022
|
});
|
|
5004
5023
|
},
|
|
5005
|
-
.stmt =>
|
|
5006
|
-
}
|
|
5024
|
+
.stmt => try p.gnuAsmStmt(quals, asm_tok, l_paren),
|
|
5025
|
+
};
|
|
5007
5026
|
try p.expectClosing(l_paren, .r_paren);
|
|
5008
5027
|
|
|
5009
5028
|
if (kind != .decl_label) _ = try p.expectToken(.semicolon);
|
|
5010
|
-
return
|
|
5029
|
+
return res;
|
|
5011
5030
|
}
|
|
5012
5031
|
|
|
5013
5032
|
/// Same as stringLiteral but errors on unicode and wide string literals
|
|
@@ -5253,7 +5272,6 @@ fn stmt(p: *Parser) Error!Node.Index {
|
|
|
5253
5272
|
if (!goto_expr.qt.isInvalid() and !goto_expr.qt.isPointer(p.comp)) {
|
|
5254
5273
|
const result_qt = try p.comp.type_store.put(gpa, .{ .pointer = .{
|
|
5255
5274
|
.child = .{ .@"const" = true, ._index = .void },
|
|
5256
|
-
.decayed = null,
|
|
5257
5275
|
} });
|
|
5258
5276
|
if (!goto_expr.qt.isRealInt(p.comp)) {
|
|
5259
5277
|
try p.err(expr_tok, .incompatible_arg, .{ goto_expr.qt, result_qt });
|
|
@@ -5905,6 +5923,7 @@ const CallExpr = union(enum) {
|
|
|
5905
5923
|
.__builtin_reduce_xor,
|
|
5906
5924
|
.__builtin_reduce_max,
|
|
5907
5925
|
.__builtin_reduce_min,
|
|
5926
|
+
.__builtin_constant_p,
|
|
5908
5927
|
=> 1,
|
|
5909
5928
|
|
|
5910
5929
|
.__builtin_complex,
|
|
@@ -5922,13 +5941,15 @@ const CallExpr = union(enum) {
|
|
|
5922
5941
|
|
|
5923
5942
|
.__c11_atomic_store,
|
|
5924
5943
|
.__atomic_store,
|
|
5944
|
+
.__atomic_store_n,
|
|
5945
|
+
.__atomic_load,
|
|
5925
5946
|
.__c11_atomic_exchange,
|
|
5926
|
-
.__atomic_exchange,
|
|
5927
5947
|
.__c11_atomic_fetch_add,
|
|
5928
5948
|
.__c11_atomic_fetch_sub,
|
|
5929
5949
|
.__c11_atomic_fetch_or,
|
|
5930
5950
|
.__c11_atomic_fetch_xor,
|
|
5931
5951
|
.__c11_atomic_fetch_and,
|
|
5952
|
+
.__c11_atomic_fetch_nand,
|
|
5932
5953
|
.__atomic_fetch_add,
|
|
5933
5954
|
.__atomic_fetch_sub,
|
|
5934
5955
|
.__atomic_fetch_and,
|
|
@@ -5948,6 +5969,9 @@ const CallExpr = union(enum) {
|
|
|
5948
5969
|
.__atomic_exchange_n,
|
|
5949
5970
|
=> 3,
|
|
5950
5971
|
|
|
5972
|
+
.__atomic_exchange,
|
|
5973
|
+
=> 4,
|
|
5974
|
+
|
|
5951
5975
|
.__c11_atomic_compare_exchange_strong,
|
|
5952
5976
|
.__c11_atomic_compare_exchange_weak,
|
|
5953
5977
|
=> 5,
|
|
@@ -5964,25 +5988,13 @@ const CallExpr = union(enum) {
|
|
|
5964
5988
|
|
|
5965
5989
|
fn returnType(self: CallExpr, p: *Parser, args: []const Node.Index, func_qt: QualType) !QualType {
|
|
5966
5990
|
if (self == .standard) {
|
|
5991
|
+
if (func_qt.isInvalid()) return .invalid;
|
|
5967
5992
|
return if (func_qt.get(p.comp, .func)) |func_ty| func_ty.return_type else .invalid;
|
|
5968
5993
|
}
|
|
5969
5994
|
const builtin = self.builtin;
|
|
5970
5995
|
const func_ty = func_qt.get(p.comp, .func).?;
|
|
5971
5996
|
return switch (builtin.expanded.tag) {
|
|
5972
5997
|
.common => |tag| switch (tag) {
|
|
5973
|
-
.__c11_atomic_exchange => {
|
|
5974
|
-
if (args.len != 4) return .invalid; // wrong number of arguments; already an error
|
|
5975
|
-
const second_param = args[2];
|
|
5976
|
-
return second_param.qt(&p.tree);
|
|
5977
|
-
},
|
|
5978
|
-
.__c11_atomic_load => {
|
|
5979
|
-
if (args.len != 3) return .invalid; // wrong number of arguments; already an error
|
|
5980
|
-
const first_param = args[1];
|
|
5981
|
-
const qt = first_param.qt(&p.tree);
|
|
5982
|
-
if (!qt.isPointer(p.comp)) return .invalid;
|
|
5983
|
-
return qt.childType(p.comp);
|
|
5984
|
-
},
|
|
5985
|
-
|
|
5986
5998
|
.__atomic_fetch_add,
|
|
5987
5999
|
.__atomic_add_fetch,
|
|
5988
6000
|
.__c11_atomic_fetch_add,
|
|
@@ -6008,15 +6020,38 @@ const CallExpr = union(enum) {
|
|
|
6008
6020
|
.__c11_atomic_fetch_nand,
|
|
6009
6021
|
|
|
6010
6022
|
.__atomic_exchange_n,
|
|
6023
|
+
.__c11_atomic_exchange,
|
|
6024
|
+
=> {
|
|
6025
|
+
const second_param = args[1].qt(&p.tree);
|
|
6026
|
+
return second_param;
|
|
6027
|
+
},
|
|
6028
|
+
|
|
6029
|
+
.__sync_fetch_and_add,
|
|
6030
|
+
.__sync_fetch_and_and,
|
|
6031
|
+
.__sync_fetch_and_nand,
|
|
6032
|
+
.__sync_fetch_and_or,
|
|
6033
|
+
.__sync_fetch_and_sub,
|
|
6034
|
+
.__sync_fetch_and_xor,
|
|
6035
|
+
|
|
6036
|
+
.__sync_add_and_fetch,
|
|
6037
|
+
.__sync_and_and_fetch,
|
|
6038
|
+
.__sync_nand_and_fetch,
|
|
6039
|
+
.__sync_or_and_fetch,
|
|
6040
|
+
.__sync_sub_and_fetch,
|
|
6041
|
+
.__sync_xor_and_fetch,
|
|
6042
|
+
|
|
6043
|
+
.__sync_swap,
|
|
6044
|
+
.__sync_lock_test_and_set,
|
|
6045
|
+
.__sync_val_compare_and_swap,
|
|
6011
6046
|
=> {
|
|
6012
|
-
if (args.len
|
|
6013
|
-
const second_param = args[
|
|
6014
|
-
return second_param
|
|
6047
|
+
if (args.len < 2) return .invalid;
|
|
6048
|
+
const second_param = args[1].qt(&p.tree);
|
|
6049
|
+
return second_param;
|
|
6015
6050
|
},
|
|
6016
6051
|
.__builtin_complex => {
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
return try last_param.
|
|
6052
|
+
const last_param = args[args.len - 1].qt(&p.tree);
|
|
6053
|
+
if (last_param.isInvalid()) return .invalid;
|
|
6054
|
+
return try last_param.toComplex(p.comp);
|
|
6020
6055
|
},
|
|
6021
6056
|
.__atomic_compare_exchange,
|
|
6022
6057
|
.__atomic_compare_exchange_n,
|
|
@@ -6027,9 +6062,8 @@ const CallExpr = union(enum) {
|
|
|
6027
6062
|
.__c11_atomic_compare_exchange_strong,
|
|
6028
6063
|
.__c11_atomic_compare_exchange_weak,
|
|
6029
6064
|
=> {
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
return third_param.qt(&p.tree);
|
|
6065
|
+
const third_param = args[2].qt(&p.tree);
|
|
6066
|
+
return third_param;
|
|
6033
6067
|
},
|
|
6034
6068
|
|
|
6035
6069
|
.__builtin_elementwise_abs,
|
|
@@ -6058,13 +6092,12 @@ const CallExpr = union(enum) {
|
|
|
6058
6092
|
.__builtin_elementwise_sub_sat,
|
|
6059
6093
|
.__builtin_elementwise_fma,
|
|
6060
6094
|
.__builtin_elementwise_popcount,
|
|
6095
|
+
|
|
6061
6096
|
.__builtin_nondeterministic_value,
|
|
6062
6097
|
=> {
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
return last_param.qt(&p.tree);
|
|
6098
|
+
const first_param = args[0].qt(&p.tree);
|
|
6099
|
+
return first_param;
|
|
6066
6100
|
},
|
|
6067
|
-
.__builtin_nontemporal_load,
|
|
6068
6101
|
.__builtin_reduce_add,
|
|
6069
6102
|
.__builtin_reduce_mul,
|
|
6070
6103
|
.__builtin_reduce_and,
|
|
@@ -6073,30 +6106,19 @@ const CallExpr = union(enum) {
|
|
|
6073
6106
|
.__builtin_reduce_max,
|
|
6074
6107
|
.__builtin_reduce_min,
|
|
6075
6108
|
=> {
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6109
|
+
const first_param = args[0].qt(&p.tree);
|
|
6110
|
+
if (first_param.isInvalid()) return .invalid;
|
|
6111
|
+
const vector_ty = first_param.get(p.comp, .vector) orelse return .invalid;
|
|
6112
|
+
return vector_ty.elem;
|
|
6079
6113
|
},
|
|
6080
|
-
.__sync_add_and_fetch,
|
|
6081
|
-
.__sync_and_and_fetch,
|
|
6082
|
-
.__sync_fetch_and_add,
|
|
6083
|
-
.__sync_fetch_and_and,
|
|
6084
|
-
.__sync_fetch_and_nand,
|
|
6085
|
-
.__sync_fetch_and_or,
|
|
6086
|
-
.__sync_fetch_and_sub,
|
|
6087
|
-
.__sync_fetch_and_xor,
|
|
6088
|
-
.__sync_lock_test_and_set,
|
|
6089
|
-
.__sync_nand_and_fetch,
|
|
6090
|
-
.__sync_or_and_fetch,
|
|
6091
|
-
.__sync_sub_and_fetch,
|
|
6092
|
-
.__sync_swap,
|
|
6093
|
-
.__sync_xor_and_fetch,
|
|
6094
|
-
.__sync_val_compare_and_swap,
|
|
6095
6114
|
.__atomic_load_n,
|
|
6115
|
+
.__c11_atomic_load,
|
|
6116
|
+
.__builtin_nontemporal_load,
|
|
6096
6117
|
=> {
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6118
|
+
const first_param = args[0].qt(&p.tree);
|
|
6119
|
+
if (first_param.isInvalid()) return .invalid;
|
|
6120
|
+
if (!first_param.isPointer(p.comp)) return .invalid;
|
|
6121
|
+
return first_param.childType(p.comp);
|
|
6100
6122
|
},
|
|
6101
6123
|
else => func_ty.return_type,
|
|
6102
6124
|
},
|
|
@@ -6104,9 +6126,16 @@ const CallExpr = union(enum) {
|
|
|
6104
6126
|
};
|
|
6105
6127
|
}
|
|
6106
6128
|
|
|
6107
|
-
fn finish(
|
|
6129
|
+
fn finish(
|
|
6130
|
+
self: CallExpr,
|
|
6131
|
+
p: *Parser,
|
|
6132
|
+
func_qt: QualType,
|
|
6133
|
+
list_buf_top: usize,
|
|
6134
|
+
l_paren: TokenIndex,
|
|
6135
|
+
args_ok: bool,
|
|
6136
|
+
) Error!Result {
|
|
6108
6137
|
const args = p.list_buf.items[list_buf_top..];
|
|
6109
|
-
const return_qt = try self.returnType(p, args, func_qt);
|
|
6138
|
+
const return_qt: QualType = if (args_ok) try self.returnType(p, args, func_qt) else .invalid;
|
|
6110
6139
|
switch (self) {
|
|
6111
6140
|
.standard => |func_node| return .{
|
|
6112
6141
|
.qt = return_qt,
|
|
@@ -6118,7 +6147,7 @@ const CallExpr = union(enum) {
|
|
|
6118
6147
|
} }),
|
|
6119
6148
|
},
|
|
6120
6149
|
.builtin => |builtin| return .{
|
|
6121
|
-
.val = try evalBuiltin(builtin.expanded, p, args),
|
|
6150
|
+
.val = if (args_ok) try evalBuiltin(builtin.expanded, p, args) else .{},
|
|
6122
6151
|
.qt = return_qt,
|
|
6123
6152
|
.node = try p.addNode(.{ .builtin_call_expr = .{
|
|
6124
6153
|
.builtin_tok = builtin.builtin_tok,
|
|
@@ -6283,14 +6312,12 @@ pub const Result = struct {
|
|
|
6283
6312
|
if (!adjusted_elem_qt.eqlQualified(a_elem, p.comp)) {
|
|
6284
6313
|
a.qt = try p.comp.type_store.put(gpa, .{ .pointer = .{
|
|
6285
6314
|
.child = adjusted_elem_qt,
|
|
6286
|
-
.decayed = null,
|
|
6287
6315
|
} });
|
|
6288
6316
|
try a.implicitCast(p, .bitcast, tok);
|
|
6289
6317
|
}
|
|
6290
6318
|
if (!adjusted_elem_qt.eqlQualified(b_elem, p.comp)) {
|
|
6291
6319
|
b.qt = try p.comp.type_store.put(gpa, .{ .pointer = .{
|
|
6292
6320
|
.child = adjusted_elem_qt,
|
|
6293
|
-
.decayed = null,
|
|
6294
6321
|
} });
|
|
6295
6322
|
try b.implicitCast(p, .bitcast, tok);
|
|
6296
6323
|
}
|
|
@@ -6478,6 +6505,7 @@ pub const Result = struct {
|
|
|
6478
6505
|
.add => {
|
|
6479
6506
|
// if both aren't arithmetic one should be pointer and the other an integer
|
|
6480
6507
|
if (a_sk.isPointer() == b_sk.isPointer() or a_sk.isInt() == b_sk.isInt()) return a.invalidBinTy(tok, b, p);
|
|
6508
|
+
try p.boundsSafetyCheckPointerArithmetic(a.qt, b.qt, tok, a.node);
|
|
6481
6509
|
|
|
6482
6510
|
if (a_sk == .void_pointer or b_sk == .void_pointer)
|
|
6483
6511
|
try p.err(tok, .gnu_pointer_arith, .{});
|
|
@@ -6496,6 +6524,7 @@ pub const Result = struct {
|
|
|
6496
6524
|
.sub => {
|
|
6497
6525
|
// if both aren't arithmetic then either both should be pointers or just the left one.
|
|
6498
6526
|
if (!a_sk.isPointer() or !(b_sk.isPointer() or b_sk.isInt())) return a.invalidBinTy(tok, b, p);
|
|
6527
|
+
try p.boundsSafetyCheckPointerArithmetic(a.qt, b.qt, tok, a.node);
|
|
6499
6528
|
|
|
6500
6529
|
if (a_sk == .void_pointer)
|
|
6501
6530
|
try p.err(tok, .gnu_pointer_arith, .{});
|
|
@@ -7087,14 +7116,14 @@ pub const Result = struct {
|
|
|
7087
7116
|
} else if (dest_sk.isPointer()) {
|
|
7088
7117
|
if (src_sk.isPointer()) {
|
|
7089
7118
|
cast_kind = .bitcast;
|
|
7119
|
+
} else if (src_sk == .bool) {
|
|
7120
|
+
cast_kind = .bool_to_pointer;
|
|
7090
7121
|
} else if (src_sk.isInt()) {
|
|
7091
7122
|
if (!src_sk.isReal()) {
|
|
7092
7123
|
res.qt = res.qt.toReal(p.comp);
|
|
7093
7124
|
try res.implicitCast(p, .complex_int_to_real, l_paren);
|
|
7094
7125
|
}
|
|
7095
7126
|
cast_kind = .int_to_pointer;
|
|
7096
|
-
} else if (src_sk == .bool) {
|
|
7097
|
-
cast_kind = .bool_to_pointer;
|
|
7098
7127
|
} else if (res.qt.is(p.comp, .array)) {
|
|
7099
7128
|
cast_kind = .array_to_pointer;
|
|
7100
7129
|
} else if (res.qt.is(p.comp, .func)) {
|
|
@@ -7497,7 +7526,16 @@ fn issueDeclaredConstHereNote(p: *Parser, decl_ref: Tree.Node.DeclRef, var_name:
|
|
|
7497
7526
|
try p.err(location, .declared_const_here, .{var_name});
|
|
7498
7527
|
}
|
|
7499
7528
|
|
|
7500
|
-
fn
|
|
7529
|
+
fn issueBoundsDeclaredHereNote(p: *Parser, decl_ref: Tree.Node.DeclRef, var_name: []const u8, bounds: Type.Pointer.Bounds) Compilation.Error!void {
|
|
7530
|
+
const location = switch (decl_ref.decl.get(&p.tree)) {
|
|
7531
|
+
.variable => |variable| variable.name_tok,
|
|
7532
|
+
.param => |param| param.name_tok,
|
|
7533
|
+
else => return,
|
|
7534
|
+
};
|
|
7535
|
+
try p.err(location, .pointer_bounds_declared_here, .{ var_name, @tagName(bounds) });
|
|
7536
|
+
}
|
|
7537
|
+
|
|
7538
|
+
fn issueConstAssignmentDiagnostics(p: *Parser, node_idx: Node.Index, tok: TokenIndex) Compilation.Error!void {
|
|
7501
7539
|
if (p.unwrapNestedOperation(node_idx)) |unwrapped| {
|
|
7502
7540
|
const name = p.tokSlice(unwrapped.name_tok);
|
|
7503
7541
|
try p.err(tok, .const_var_assignment, .{ name, unwrapped.qt });
|
|
@@ -7530,7 +7568,7 @@ fn assignExpr(p: *Parser) Error!?Result {
|
|
|
7530
7568
|
|
|
7531
7569
|
var is_const: bool = undefined;
|
|
7532
7570
|
if (!p.tree.isLvalExtra(lhs.node, &is_const) or is_const) {
|
|
7533
|
-
try p.
|
|
7571
|
+
try p.issueConstAssignmentDiagnostics(lhs.node, tok);
|
|
7534
7572
|
lhs.qt = .invalid;
|
|
7535
7573
|
}
|
|
7536
7574
|
|
|
@@ -8226,7 +8264,7 @@ fn builtinChooseExpr(p: *Parser) Error!Result {
|
|
|
8226
8264
|
return cond;
|
|
8227
8265
|
}
|
|
8228
8266
|
|
|
8229
|
-
///
|
|
8267
|
+
/// vaArg : __builtin_va_arg '(' assignExpr ',' typeName ')'
|
|
8230
8268
|
fn builtinVaArg(p: *Parser, builtin_tok: TokenIndex) Error!Result {
|
|
8231
8269
|
const l_paren = try p.expectToken(.l_paren);
|
|
8232
8270
|
const va_list_tok = p.tok_i;
|
|
@@ -8258,6 +8296,62 @@ fn builtinVaArg(p: *Parser, builtin_tok: TokenIndex) Error!Result {
|
|
|
8258
8296
|
};
|
|
8259
8297
|
}
|
|
8260
8298
|
|
|
8299
|
+
/// vaArgPack : __builtin_va_arg_pack '(' ')'
|
|
8300
|
+
fn builtinVaArgPack(p: *Parser, builtin_tok: TokenIndex) Error!Result {
|
|
8301
|
+
const l_paren = try p.expectToken(.l_paren);
|
|
8302
|
+
try p.expectClosing(l_paren, .r_paren);
|
|
8303
|
+
|
|
8304
|
+
var res_qt: QualType = .invalid;
|
|
8305
|
+
if (!try p.checkVaPackFunc(builtin_tok, "__builtin_va_arg_pack")) {
|
|
8306
|
+
// Only add one error.
|
|
8307
|
+
} else if (!p.va_arg_pack_ctx.valid) {
|
|
8308
|
+
try p.err(builtin_tok, .va_pack_non_call, .{});
|
|
8309
|
+
} else if (!p.va_arg_pack_ctx.variadic) {
|
|
8310
|
+
try p.err(builtin_tok, .va_pack_non_variadic_call, .{});
|
|
8311
|
+
} else if (p.va_arg_pack_ctx.typed) {
|
|
8312
|
+
try p.err(builtin_tok, .va_pack_non_variadic_arg, .{});
|
|
8313
|
+
} else {
|
|
8314
|
+
res_qt = .void;
|
|
8315
|
+
}
|
|
8316
|
+
return .{
|
|
8317
|
+
.qt = res_qt,
|
|
8318
|
+
.node = try p.addNode(.{
|
|
8319
|
+
.builtin_va_arg_pack = .{ .builtin_tok = builtin_tok },
|
|
8320
|
+
}),
|
|
8321
|
+
};
|
|
8322
|
+
}
|
|
8323
|
+
|
|
8324
|
+
/// vaArgPackLen : __builtin_va_arg_pack_len '(' ')'
|
|
8325
|
+
fn builtinVaArgPackLen(p: *Parser, builtin_tok: TokenIndex) Error!Result {
|
|
8326
|
+
const l_paren = try p.expectToken(.l_paren);
|
|
8327
|
+
try p.expectClosing(l_paren, .r_paren);
|
|
8328
|
+
|
|
8329
|
+
_ = try p.checkVaPackFunc(builtin_tok, "__builtin_va_arg_pack_len");
|
|
8330
|
+
|
|
8331
|
+
return .{
|
|
8332
|
+
.qt = .int,
|
|
8333
|
+
.node = try p.addNode(.{
|
|
8334
|
+
.builtin_va_arg_pack_len = .{
|
|
8335
|
+
.builtin_tok = builtin_tok,
|
|
8336
|
+
},
|
|
8337
|
+
}),
|
|
8338
|
+
};
|
|
8339
|
+
}
|
|
8340
|
+
|
|
8341
|
+
fn checkVaPackFunc(p: *Parser, builtin_tok: TokenIndex, va_func_name: []const u8) !bool {
|
|
8342
|
+
const func_qt, _ = (try p.checkVaFunc(builtin_tok, va_func_name)) orelse return false;
|
|
8343
|
+
|
|
8344
|
+
var it = Attribute.Iterator.initType(func_qt, p.comp);
|
|
8345
|
+
while (it.next()) |item| switch (item[0].tag) {
|
|
8346
|
+
.always_inline, .gnu_inline => break,
|
|
8347
|
+
else => {},
|
|
8348
|
+
} else {
|
|
8349
|
+
try p.err(builtin_tok, .va_func_not_always_inline, .{va_func_name});
|
|
8350
|
+
return false;
|
|
8351
|
+
}
|
|
8352
|
+
return true;
|
|
8353
|
+
}
|
|
8354
|
+
|
|
8261
8355
|
const OffsetKind = enum { bits, bytes };
|
|
8262
8356
|
|
|
8263
8357
|
/// offsetof
|
|
@@ -8504,7 +8598,6 @@ fn unExpr(p: *Parser) Error!?Result {
|
|
|
8504
8598
|
|
|
8505
8599
|
operand.qt = try p.comp.type_store.put(gpa, .{ .pointer = .{
|
|
8506
8600
|
.child = operand.qt,
|
|
8507
|
-
.decayed = null,
|
|
8508
8601
|
} });
|
|
8509
8602
|
}
|
|
8510
8603
|
if (p.getNode(operand.node, .decl_ref_expr)) |decl_ref| {
|
|
@@ -8596,6 +8689,9 @@ fn unExpr(p: *Parser) Error!?Result {
|
|
|
8596
8689
|
try p.err(tok, .not_assignable, .{});
|
|
8597
8690
|
return error.ParsingFailed;
|
|
8598
8691
|
}
|
|
8692
|
+
if (operand.qt.get(p.comp, .pointer)) |pointer| {
|
|
8693
|
+
try p.checkPtrArithmeticAllowed(pointer, p.tok_i, operand.node);
|
|
8694
|
+
}
|
|
8599
8695
|
try operand.usualUnaryConversion(p, tok);
|
|
8600
8696
|
|
|
8601
8697
|
if (operand.val.is(.int, p.comp) or operand.val.is(.int, p.comp)) {
|
|
@@ -8624,6 +8720,9 @@ fn unExpr(p: *Parser) Error!?Result {
|
|
|
8624
8720
|
try p.err(tok, .not_assignable, .{});
|
|
8625
8721
|
return error.ParsingFailed;
|
|
8626
8722
|
}
|
|
8723
|
+
if (operand.qt.get(p.comp, .pointer)) |pointer| {
|
|
8724
|
+
try p.checkPtrArithmeticAllowed(pointer, p.tok_i, operand.node);
|
|
8725
|
+
}
|
|
8627
8726
|
try operand.usualUnaryConversion(p, tok);
|
|
8628
8727
|
|
|
8629
8728
|
if (operand.val.is(.int, p.comp) or operand.val.is(.int, p.comp)) {
|
|
@@ -8826,7 +8925,7 @@ fn unExpr(p: *Parser) Error!?Result {
|
|
|
8826
8925
|
} else switch (p.comp.langopts.emulate) {
|
|
8827
8926
|
.msvc => {}, // Doesn't support `_Complex` or `__imag` in the first place
|
|
8828
8927
|
.gcc => operand.val = .zero,
|
|
8829
|
-
.clang => {
|
|
8928
|
+
.clang, .no => {
|
|
8830
8929
|
if (operand.val.is(.int, p.comp) or operand.val.is(.float, p.comp)) {
|
|
8831
8930
|
operand.val = .zero;
|
|
8832
8931
|
} else {
|
|
@@ -8886,7 +8985,7 @@ fn compoundLiteral(p: *Parser, qt_opt: ?QualType, opt_l_paren: ?TokenIndex) Erro
|
|
|
8886
8985
|
try p.err(tok, .invalid_compound_literal_storage_class, .{@tagName(d.storage_class)});
|
|
8887
8986
|
d.storage_class = .none;
|
|
8888
8987
|
},
|
|
8889
|
-
.register => if (p.func.qt == null) try p.err(p.tok_i, .
|
|
8988
|
+
.register => if (p.func.qt == null) try p.err(p.tok_i, .register_on_global_compound_literal, .{}),
|
|
8890
8989
|
else => {},
|
|
8891
8990
|
}
|
|
8892
8991
|
|
|
@@ -8968,6 +9067,9 @@ fn suffixExpr(p: *Parser, lhs: Result) Error!?Result {
|
|
|
8968
9067
|
try p.err(p.tok_i, .not_assignable, .{});
|
|
8969
9068
|
return error.ParsingFailed;
|
|
8970
9069
|
}
|
|
9070
|
+
if (operand.qt.get(p.comp, .pointer)) |pointer| {
|
|
9071
|
+
try p.checkPtrArithmeticAllowed(pointer, p.tok_i, operand.node);
|
|
9072
|
+
}
|
|
8971
9073
|
try operand.usualUnaryConversion(p, p.tok_i);
|
|
8972
9074
|
|
|
8973
9075
|
try operand.un(p, .post_inc_expr, p.tok_i);
|
|
@@ -8989,6 +9091,9 @@ fn suffixExpr(p: *Parser, lhs: Result) Error!?Result {
|
|
|
8989
9091
|
try p.err(p.tok_i, .not_assignable, .{});
|
|
8990
9092
|
return error.ParsingFailed;
|
|
8991
9093
|
}
|
|
9094
|
+
if (operand.qt.get(p.comp, .pointer)) |pointer| {
|
|
9095
|
+
try p.checkPtrArithmeticAllowed(pointer, p.tok_i, operand.node);
|
|
9096
|
+
}
|
|
8992
9097
|
try operand.usualUnaryConversion(p, p.tok_i);
|
|
8993
9098
|
|
|
8994
9099
|
try operand.un(p, .post_dec_expr, p.tok_i);
|
|
@@ -9003,6 +9108,7 @@ fn suffixExpr(p: *Parser, lhs: Result) Error!?Result {
|
|
|
9003
9108
|
const array_before_conversion = lhs;
|
|
9004
9109
|
const index_before_conversion = index;
|
|
9005
9110
|
var ptr = lhs;
|
|
9111
|
+
|
|
9006
9112
|
try ptr.lvalConversion(p, l_bracket);
|
|
9007
9113
|
try index.lvalConversion(p, l_bracket);
|
|
9008
9114
|
if (ptr.qt.get(p.comp, .pointer)) |pointer_ty| {
|
|
@@ -9176,14 +9282,7 @@ fn checkVaStartArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex,
|
|
|
9176
9282
|
return error.ParsingFailed;
|
|
9177
9283
|
}
|
|
9178
9284
|
|
|
9179
|
-
const
|
|
9180
|
-
try p.err(builtin_tok, .va_start_not_in_func, .{});
|
|
9181
|
-
return;
|
|
9182
|
-
};
|
|
9183
|
-
const func_ty = func_qt.get(p.comp, .func) orelse return;
|
|
9184
|
-
if (func_ty.kind != .variadic or func_ty.params.len == 0) {
|
|
9185
|
-
return p.err(builtin_tok, .va_start_fixed_args, .{});
|
|
9186
|
-
}
|
|
9285
|
+
_, const func_ty = (try p.checkVaFunc(builtin_tok, "va_start")) orelse return;
|
|
9187
9286
|
const last_param_name = func_ty.params[func_ty.params.len - 1].name;
|
|
9188
9287
|
const decl_ref = p.getNode(arg.node, .decl_ref_expr);
|
|
9189
9288
|
if (decl_ref == null or last_param_name != try p.comp.internString(p.tokSlice(decl_ref.?.name_tok))) {
|
|
@@ -9191,6 +9290,19 @@ fn checkVaStartArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex,
|
|
|
9191
9290
|
}
|
|
9192
9291
|
}
|
|
9193
9292
|
|
|
9293
|
+
fn checkVaFunc(p: *Parser, builtin_tok: TokenIndex, va_func_name: []const u8) !?struct { QualType, Type.Func } {
|
|
9294
|
+
const func_qt = p.func.qt orelse {
|
|
9295
|
+
try p.err(builtin_tok, .va_func_not_in_func, .{va_func_name});
|
|
9296
|
+
return null;
|
|
9297
|
+
};
|
|
9298
|
+
const func_ty = func_qt.get(p.comp, .func) orelse return null;
|
|
9299
|
+
if (func_ty.kind != .variadic or func_ty.params.len == 0) {
|
|
9300
|
+
try p.err(builtin_tok, .va_func_fixed_args, .{va_func_name});
|
|
9301
|
+
return null;
|
|
9302
|
+
}
|
|
9303
|
+
return .{ func_qt, func_ty };
|
|
9304
|
+
}
|
|
9305
|
+
|
|
9194
9306
|
fn checkArithOverflowArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, idx: u32) !void {
|
|
9195
9307
|
_ = builtin_tok;
|
|
9196
9308
|
_ = first_after;
|
|
@@ -9320,7 +9432,7 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result {
|
|
|
9320
9432
|
|
|
9321
9433
|
// We cannot refer to the function type here because the pointer to
|
|
9322
9434
|
// type_store.extra might get invalidated while parsing args.
|
|
9323
|
-
const func_qt, const
|
|
9435
|
+
const func_qt, const typed_params_len, const func_kind_base = blk: {
|
|
9324
9436
|
var base_qt = lhs.qt;
|
|
9325
9437
|
if (base_qt.get(p.comp, .pointer)) |pointer_ty| base_qt = pointer_ty.child;
|
|
9326
9438
|
if (base_qt.isInvalid()) break :blk .{ base_qt, std.math.maxInt(usize), undefined };
|
|
@@ -9343,9 +9455,44 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result {
|
|
|
9343
9455
|
|
|
9344
9456
|
const call_expr = CallExpr.init(p, lhs.node, func.node);
|
|
9345
9457
|
|
|
9458
|
+
const param_len_override = call_expr.paramCountOverride();
|
|
9459
|
+
const params_len = param_len_override orelse typed_params_len;
|
|
9460
|
+
const func_kind = if (param_len_override != null) .normal else func_kind_base;
|
|
9461
|
+
|
|
9346
9462
|
while (p.eatToken(.r_paren) == null) {
|
|
9347
9463
|
const param_tok = p.tok_i;
|
|
9348
9464
|
if (arg_count == params_len) first_after = p.tok_i;
|
|
9465
|
+
|
|
9466
|
+
// Check for __builtin_va_arg_pack
|
|
9467
|
+
{
|
|
9468
|
+
var i = p.tok_i;
|
|
9469
|
+
loop: switch (p.tok_ids[i]) {
|
|
9470
|
+
.l_paren => {
|
|
9471
|
+
i += 1;
|
|
9472
|
+
continue :loop p.tok_ids[i];
|
|
9473
|
+
},
|
|
9474
|
+
.identifier => if (mem.eql(u8, p.tokSlice(i), "__builtin_va_arg_pack")) {
|
|
9475
|
+
@branchHint(.cold);
|
|
9476
|
+
p.va_arg_pack_ctx = .{
|
|
9477
|
+
.valid = true,
|
|
9478
|
+
.variadic = func_kind != .normal,
|
|
9479
|
+
.typed = arg_count < typed_params_len,
|
|
9480
|
+
};
|
|
9481
|
+
defer p.va_arg_pack_ctx = .{};
|
|
9482
|
+
|
|
9483
|
+
const arg = try p.expect(assignExpr);
|
|
9484
|
+
try p.list_buf.append(gpa, arg.node);
|
|
9485
|
+
arg_count += 1;
|
|
9486
|
+
if (p.eatToken(.comma)) |_| {
|
|
9487
|
+
try p.err(i, .va_pack_non_final_arg, .{});
|
|
9488
|
+
continue;
|
|
9489
|
+
}
|
|
9490
|
+
try p.expectClosing(l_paren, .r_paren);
|
|
9491
|
+
break;
|
|
9492
|
+
},
|
|
9493
|
+
else => {},
|
|
9494
|
+
}
|
|
9495
|
+
}
|
|
9349
9496
|
var arg = try p.expect(assignExpr);
|
|
9350
9497
|
|
|
9351
9498
|
if (call_expr.shouldPerformLvalConversion(arg_count)) {
|
|
@@ -9353,7 +9500,7 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result {
|
|
|
9353
9500
|
}
|
|
9354
9501
|
if ((arg.qt.hasIncompleteSize(p.comp) and !arg.qt.is(p.comp, .void)) or arg.qt.isInvalid()) return error.ParsingFailed;
|
|
9355
9502
|
|
|
9356
|
-
if (arg_count >=
|
|
9503
|
+
if (arg_count >= typed_params_len) {
|
|
9357
9504
|
if (call_expr.shouldPromoteVarArg(arg_count)) switch (arg.qt.base(p.comp).type) {
|
|
9358
9505
|
.int => |int_ty| if (int_ty == .int) try arg.castToInt(p, arg.qt.promoteInt(p.comp), param_tok),
|
|
9359
9506
|
.float => |float_ty| if (float_ty == .double) try arg.castToFloat(p, .double, param_tok),
|
|
@@ -9407,19 +9554,23 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result {
|
|
|
9407
9554
|
}
|
|
9408
9555
|
if (func_qt.isInvalid()) {
|
|
9409
9556
|
// Skip argument count checks.
|
|
9410
|
-
return try call_expr.finish(p, func_qt, list_buf_top, l_paren);
|
|
9557
|
+
return try call_expr.finish(p, func_qt, list_buf_top, l_paren, false);
|
|
9411
9558
|
}
|
|
9412
9559
|
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
}
|
|
9417
|
-
} else switch (func_kind) {
|
|
9560
|
+
const r_paren = p.tok_i - 1;
|
|
9561
|
+
var args_ok = true;
|
|
9562
|
+
switch (func_kind) {
|
|
9418
9563
|
.normal => if (params_len != arg_count) {
|
|
9419
|
-
try p.err(
|
|
9564
|
+
try p.err(
|
|
9565
|
+
if (arg_count < params_len) r_paren else first_after,
|
|
9566
|
+
.expected_arguments,
|
|
9567
|
+
.{ params_len, arg_count },
|
|
9568
|
+
);
|
|
9569
|
+
args_ok = false;
|
|
9420
9570
|
},
|
|
9421
9571
|
.variadic => if (arg_count < params_len) {
|
|
9422
|
-
try p.err(
|
|
9572
|
+
try p.err(r_paren, .expected_at_least_arguments, .{ params_len, arg_count });
|
|
9573
|
+
args_ok = false;
|
|
9423
9574
|
},
|
|
9424
9575
|
.old_style => if (params_len != arg_count) {
|
|
9425
9576
|
if (params_len == 0)
|
|
@@ -9429,10 +9580,60 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result {
|
|
|
9429
9580
|
},
|
|
9430
9581
|
}
|
|
9431
9582
|
|
|
9432
|
-
return try call_expr.finish(p, func_qt, list_buf_top, l_paren);
|
|
9583
|
+
return try call_expr.finish(p, func_qt, list_buf_top, l_paren, args_ok);
|
|
9584
|
+
}
|
|
9585
|
+
|
|
9586
|
+
fn boundsSafetyCheckArrayAccess(p: *Parser, lhs: Result, rhs: Result, l_bracket: TokenIndex) !void {
|
|
9587
|
+
if (!p.comp.hasClangStyleBoundsSafety()) return;
|
|
9588
|
+
|
|
9589
|
+
const ptr_res, const pointer, const index = if (lhs.qt.get(p.comp, .pointer)) |pointer| .{ lhs, pointer, rhs } else .{ rhs, rhs.qt.get(p.comp, .pointer).?, lhs };
|
|
9590
|
+
|
|
9591
|
+
switch (pointer.bounds) {
|
|
9592
|
+
.c, .unsafe_indexable => {},
|
|
9593
|
+
.single => {
|
|
9594
|
+
if (!index.val.isZero(p.comp)) {
|
|
9595
|
+
try p.err(l_bracket, .single_requires_zero_index, .{});
|
|
9596
|
+
if (p.unwrapNestedOperation(ptr_res.node)) |unwrapped| {
|
|
9597
|
+
const name = p.tokSlice(unwrapped.name_tok);
|
|
9598
|
+
try p.issueBoundsDeclaredHereNote(unwrapped, name, pointer.bounds);
|
|
9599
|
+
}
|
|
9600
|
+
}
|
|
9601
|
+
},
|
|
9602
|
+
}
|
|
9603
|
+
}
|
|
9604
|
+
|
|
9605
|
+
fn boundsSafetyCheckPointerArithmetic(p: *Parser, lhs: QualType, rhs: QualType, tok: TokenIndex, node: Tree.Node.Index) !void {
|
|
9606
|
+
if (!p.comp.hasClangStyleBoundsSafety()) return;
|
|
9607
|
+
|
|
9608
|
+
const pointer = if (rhs.isInt(p.comp))
|
|
9609
|
+
lhs.get(p.comp, .pointer) orelse return
|
|
9610
|
+
else if (lhs.isInt(p.comp))
|
|
9611
|
+
rhs.get(p.comp, .pointer) orelse return
|
|
9612
|
+
else
|
|
9613
|
+
return;
|
|
9614
|
+
|
|
9615
|
+
try p.checkPtrArithmeticAllowed(pointer, tok, node);
|
|
9616
|
+
}
|
|
9617
|
+
|
|
9618
|
+
fn checkPtrArithmeticAllowed(p: *Parser, pointer: Type.Pointer, tok: TokenIndex, node: Tree.Node.Index) !void {
|
|
9619
|
+
if (!p.comp.hasClangStyleBoundsSafety()) return;
|
|
9620
|
+
|
|
9621
|
+
switch (pointer.bounds) {
|
|
9622
|
+
.c, .unsafe_indexable => {},
|
|
9623
|
+
.single => {
|
|
9624
|
+
// clang issues this diagnostic even with a constant `0` operand
|
|
9625
|
+
try p.err(tok, .pointer_arith_single, .{});
|
|
9626
|
+
if (p.unwrapNestedOperation(node)) |unwrapped| {
|
|
9627
|
+
const name = p.tokSlice(unwrapped.name_tok);
|
|
9628
|
+
try p.issueBoundsDeclaredHereNote(unwrapped, name, pointer.bounds);
|
|
9629
|
+
}
|
|
9630
|
+
},
|
|
9631
|
+
}
|
|
9433
9632
|
}
|
|
9434
9633
|
|
|
9435
9634
|
fn checkArrayBounds(p: *Parser, index: Result, array: Result, tok: TokenIndex) !void {
|
|
9635
|
+
try p.boundsSafetyCheckArrayAccess(array, index, tok);
|
|
9636
|
+
|
|
9436
9637
|
if (index.val.opt_ref == .none) return;
|
|
9437
9638
|
|
|
9438
9639
|
const array_len = array.qt.arrayLen(p.comp) orelse return;
|
|
@@ -9579,6 +9780,8 @@ fn primaryExpr(p: *Parser) Error!?Result {
|
|
|
9579
9780
|
.common => |tag| switch (tag) {
|
|
9580
9781
|
.__builtin_choose_expr => return try p.builtinChooseExpr(),
|
|
9581
9782
|
.__builtin_va_arg => return try p.builtinVaArg(name_tok),
|
|
9783
|
+
.__builtin_va_arg_pack => return try p.builtinVaArgPack(name_tok),
|
|
9784
|
+
.__builtin_va_arg_pack_len => return try p.builtinVaArgPackLen(name_tok),
|
|
9582
9785
|
.__builtin_offsetof => return try p.builtinOffsetof(name_tok, .bytes),
|
|
9583
9786
|
.__builtin_bitoffsetof => return try p.builtinOffsetof(name_tok, .bits),
|
|
9584
9787
|
.__builtin_types_compatible_p => return try p.typesCompatible(name_tok),
|
|
@@ -9720,7 +9923,7 @@ fn primaryExpr(p: *Parser) Error!?Result {
|
|
|
9720
9923
|
qt = some.qt;
|
|
9721
9924
|
} else if (p.func.qt) |func_qt| {
|
|
9722
9925
|
var sf = std.heap.stackFallback(1024, gpa);
|
|
9723
|
-
var allocating: Io.Writer.Allocating = .init(sf.get());
|
|
9926
|
+
var allocating: std.Io.Writer.Allocating = .init(sf.get());
|
|
9724
9927
|
defer allocating.deinit();
|
|
9725
9928
|
|
|
9726
9929
|
func_qt.printNamed(p.tokSlice(p.func.name), p.comp, &allocating.writer) catch return error.OutOfMemory;
|
|
@@ -10277,16 +10480,13 @@ fn fixedSizeInt(p: *Parser, base: u8, buf: []const u8, suffix: NumberSuffix, tok
|
|
|
10277
10480
|
if (res.qt.intRankOrder(suffix_qt, p.comp).compare(.lt)) continue;
|
|
10278
10481
|
const max_int = try Value.maxInt(res.qt, p.comp);
|
|
10279
10482
|
if (interned_val.compare(.lte, max_int, p.comp)) break;
|
|
10280
|
-
} else {
|
|
10281
|
-
if (p.comp.
|
|
10282
|
-
|
|
10283
|
-
res.qt = .int128;
|
|
10284
|
-
} else {
|
|
10285
|
-
res.qt = .long_long;
|
|
10286
|
-
}
|
|
10483
|
+
} else switch (p.comp.langopts.emulate) {
|
|
10484
|
+
.no, .gcc => if (p.comp.target.hasInt128()) {
|
|
10485
|
+
res.qt = .int128;
|
|
10287
10486
|
} else {
|
|
10288
|
-
res.qt = .
|
|
10289
|
-
}
|
|
10487
|
+
res.qt = .long_long;
|
|
10488
|
+
},
|
|
10489
|
+
.msvc, .clang => res.qt = .ulong_long,
|
|
10290
10490
|
}
|
|
10291
10491
|
|
|
10292
10492
|
res.node = try p.addNode(.{ .int_literal = .{ .qt = res.qt, .literal_tok = tok_i } });
|
|
@@ -10604,12 +10804,7 @@ fn genericSelection(p: *Parser) Error!?Result {
|
|
|
10604
10804
|
}
|
|
10605
10805
|
|
|
10606
10806
|
test "Node locations" {
|
|
10607
|
-
var
|
|
10608
|
-
defer arena_state.deinit();
|
|
10609
|
-
const arena = arena_state.allocator();
|
|
10610
|
-
|
|
10611
|
-
var diagnostics: Diagnostics = .{ .output = .ignore };
|
|
10612
|
-
var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, &diagnostics, Io.Dir.cwd());
|
|
10807
|
+
var comp = try Compilation.init(.testing);
|
|
10613
10808
|
defer comp.deinit();
|
|
10614
10809
|
|
|
10615
10810
|
const file = try comp.addSourceFromBuffer("file.c",
|
|
@@ -10621,7 +10816,7 @@ test "Node locations" {
|
|
|
10621
10816
|
|
|
10622
10817
|
const builtin_macros = try comp.generateBuiltinMacros(.no_system_defines);
|
|
10623
10818
|
|
|
10624
|
-
var pp = Preprocessor.init(&comp, .
|
|
10819
|
+
var pp = try Preprocessor.init(&comp, .testing);
|
|
10625
10820
|
defer pp.deinit();
|
|
10626
10821
|
try pp.addBuiltinMacros();
|
|
10627
10822
|
|
|
@@ -10633,7 +10828,6 @@ test "Node locations" {
|
|
|
10633
10828
|
var tree = try Parser.parse(&pp);
|
|
10634
10829
|
defer tree.deinit();
|
|
10635
10830
|
|
|
10636
|
-
try std.testing.expectEqual(0, comp.diagnostics.total);
|
|
10637
10831
|
for (tree.root_decls.items[tree.root_decls.items.len - 3 ..], 0..) |node, i| {
|
|
10638
10832
|
const slice = tree.tokSlice(node.tok(&tree));
|
|
10639
10833
|
const expected_slice = switch (i) {
|