Skip to content

Commit 6f78207

Browse files
committed
parser: add error for ambiguous operator precedence
1 parent dd189a3 commit 6f78207

File tree

12 files changed

+56
-19
lines changed

12 files changed

+56
-19
lines changed

deps/aro/aro/Driver.zig

+4-4
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ pub const usage =
104104
\\ -fhosted Compilation in a hosted environment
105105
\\ -fms-extensions Enable support for Microsoft extensions
106106
\\ -fno-ms-extensions Disable support for Microsoft extensions
107-
\\ -fdollars-in-identifiers
107+
\\ -fdollars-in-identifiers
108108
\\ Allow '$' in identifiers
109-
\\ -fno-dollars-in-identifiers
109+
\\ -fno-dollars-in-identifiers
110110
\\ Disallow '$' in identifiers
111111
\\ -fmacro-backtrace-limit=<limit>
112112
\\ Set limit on how many macro expansion traces are shown in errors (default 6)
@@ -710,7 +710,7 @@ fn processSource(
710710
d.comp.target.ofmt.fileExt(d.comp.target.cpu.arch),
711711
};
712712
break :blk d.output_name orelse
713-
std.fmt.bufPrint(&name_buf, fmt_template, fmt_args) catch return d.fatal("Filename too long for filesystem: " ++ fmt_template, fmt_args);
713+
(std.fmt.bufPrint(&name_buf, fmt_template, fmt_args) catch return d.fatal("Filename too long for filesystem: " ++ fmt_template, fmt_args));
714714
} else blk: {
715715
const random_bytes_count = 12;
716716
const sub_path_len = comptime std.fs.base64_encoder.calcSize(random_bytes_count);
@@ -725,7 +725,7 @@ fn processSource(
725725
random_name,
726726
d.comp.target.ofmt.fileExt(d.comp.target.cpu.arch),
727727
};
728-
break :blk std.fmt.bufPrint(&name_buf, fmt_template, fmt_args) catch return d.fatal("Filename too long for filesystem: " ++ fmt_template, fmt_args);
728+
break :blk (std.fmt.bufPrint(&name_buf, fmt_template, fmt_args) catch return d.fatal("Filename too long for filesystem: " ++ fmt_template, fmt_args));
729729
};
730730

731731
const out_file = std.fs.cwd().createFile(out_file_name, .{}) catch |er|

deps/aro/aro/char_info.zig

+2-2
Original file line numberDiff line numberDiff line change
@@ -492,15 +492,15 @@ pub fn isXidStart(c: u21) bool {
492492
assert(c > 0x7F);
493493
const idx = c / 8 / tables.chunk;
494494
const chunk: usize = if (idx < tables.trie_start.len) tables.trie_start[idx] else 0;
495-
const offset = chunk * tables.chunk / 2 + c / 8 % tables.chunk;
495+
const offset = chunk * tables.chunk / 2 + (c / 8) % tables.chunk;
496496
return (tables.leaf[offset] >> (@as(u3, @intCast(c % 8)))) & 1 != 0;
497497
}
498498

499499
pub fn isXidContinue(c: u21) bool {
500500
assert(c > 0x7F);
501501
const idx = c / 8 / tables.chunk;
502502
const chunk: usize = if (idx < tables.trie_continue.len) tables.trie_continue[idx] else 0;
503-
const offset = chunk * tables.chunk / 2 + c / 8 % tables.chunk;
503+
const offset = chunk * tables.chunk / 2 + (c / 8) % tables.chunk;
504504
return (tables.leaf[offset] >> (@as(u3, @intCast(c % 8)))) & 1 != 0;
505505
}
506506

lib/compiler_rt/atomics.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ fn wideUpdate(comptime T: type, ptr: *T, val: T, update: anytype) T {
243243
while (true) {
244244
const old = @as(T, @truncate((wide_old & mask) >> inner_shift));
245245
const new = update(val, old);
246-
const wide_new = wide_old & ~mask | (@as(WideAtomic, new) << inner_shift);
246+
const wide_new = (wide_old & ~mask) | (@as(WideAtomic, new) << inner_shift);
247247
if (@cmpxchgWeak(WideAtomic, wide_ptr, wide_old, wide_new, .SeqCst, .SeqCst)) |new_wide_old| {
248248
wide_old = new_wide_old;
249249
} else {

lib/std/math/big/int.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -3752,7 +3752,7 @@ fn llshl(r: []Limb, a: []const Limb, shift: usize) void {
37523752

37533753
// We only need the extra limb if the shift of the last element overflows.
37543754
// This is useful for the implementation of `shiftLeftSat`.
3755-
if (a[a.len - 1] << interior_limb_shift >> interior_limb_shift != a[a.len - 1]) {
3755+
if ((a[a.len - 1] << interior_limb_shift) >> interior_limb_shift != a[a.len - 1]) {
37563756
assert(r.len >= a.len + (shift / limb_bits) + 1);
37573757
} else {
37583758
assert(r.len >= a.len + (shift / limb_bits));

lib/std/zig/Ast.zig

+4-1
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,6 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
452452
.for_input_not_captured => {
453453
return stream.writeAll("for input is not captured");
454454
},
455-
456455
.expected_token => {
457456
const found_tag = token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)];
458457
const expected_symbol = parse_error.extra.expected_tag.symbol();
@@ -465,6 +464,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
465464
}),
466465
}
467466
},
467+
.ambiguous_operator_precedence => {
468+
return stream.writeAll("ambiguous operator precedence; use parentheses to disambiguate");
469+
},
468470
}
469471
}
470472

@@ -2912,6 +2914,7 @@ pub const Error = struct {
29122914
var_const_decl,
29132915
extra_for_capture,
29142916
for_input_not_captured,
2917+
ambiguous_operator_precedence,
29152918

29162919
zig_style_container,
29172920
previous_field,

lib/std/zig/Parse.zig

+19
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,8 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {
16851685
}
16861686

16871687
var banned_prec: i8 = -1;
1688+
var prev_op: Token.Tag = .invalid;
1689+
var prev_prec: i8 = -1;
16881690

16891691
while (true) {
16901692
const tok_tag = p.token_tags[p.tok_i];
@@ -1695,6 +1697,23 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {
16951697
if (info.prec == banned_prec) {
16961698
return p.fail(.chained_comparison_operators);
16971699
}
1700+
if (info.prec > 0) {
1701+
if (tok_tag != prev_op and info.prec == prev_prec) blk: {
1702+
if (prev_op == .plus and tok_tag == .minus) break :blk;
1703+
if (prev_op == .minus and tok_tag == .plus) break :blk;
1704+
if (prev_op == .plus_percent and tok_tag == .minus_percent) break :blk;
1705+
if (prev_op == .minus_percent and tok_tag == .plus_percent) break :blk;
1706+
if (prev_op == .plus_pipe and tok_tag == .minus_pipe) break :blk;
1707+
if (prev_op == .minus_pipe and tok_tag == .plus_pipe) break :blk;
1708+
1709+
if (prev_op == .asterisk and tok_tag == .slash) break :blk;
1710+
if (prev_op == .slash and tok_tag == .asterisk) break :blk;
1711+
1712+
return p.fail(.ambiguous_operator_precedence);
1713+
}
1714+
prev_op = tok_tag;
1715+
prev_prec = info.prec;
1716+
}
16981717

16991718
const oper_token = p.nextToken();
17001719
// Special-case handling for "catch"

lib/std/zig/system/NativeTargetInfo.zig

+5-5
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo {
9292
// Minor * 1(0),000 summed has been convention since FreeBSD 2.2 (1997)
9393
// e.g. 492101 = 4.11-STABLE = 4.(9+2)
9494
const major = value / 100_000;
95-
const minor1 = value % 100_000 / 10_000; // usually 0 since 5.1
96-
const minor2 = value % 10_000 / 1_000; // 0 before 5.1, minor version since
95+
const minor1 = (value % 100_000) / 10_000; // usually 0 since 5.1
96+
const minor2 = (value % 10_000) / 1_000; // 0 before 5.1, minor version since
9797
const patch = value % 1_000;
9898
os.version_range.semver.min = .{ .major = major, .minor = minor1 + minor2, .patch = patch };
9999
os.version_range.semver.max = os.version_range.semver.min;
@@ -106,8 +106,8 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo {
106106
// r = 0 (*)
107107
// p = patchlevel
108108
const major = value / 100_000_000;
109-
const minor = value % 100_000_000 / 1_000_000;
110-
const patch = value % 10_000 / 100;
109+
const minor = (value % 100_000_000) / 1_000_000;
110+
const patch = (value % 10_000) / 100;
111111
os.version_range.semver.min = .{ .major = major, .minor = minor, .patch = patch };
112112
os.version_range.semver.max = os.version_range.semver.min;
113113
},
@@ -118,7 +118,7 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo {
118118
// m = minor; odd-numbers indicate current dev branch
119119
// p = patch
120120
const major = value / 100_000;
121-
const minor = value % 100_000 / 100;
121+
const minor = (value % 100_000) / 100;
122122
const patch = value % 100;
123123
os.version_range.semver.min = .{ .major = major, .minor = minor, .patch = patch };
124124
os.version_range.semver.max = os.version_range.semver.min;

src/Compilation.zig

+2-1
Original file line numberDiff line numberDiff line change
@@ -3538,7 +3538,8 @@ pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Module.File) !void {
35383538
}
35393539
const token_starts = file.tree.tokens.items(.start);
35403540
const start = token_starts[item.data.token] + item.data.byte_offset;
3541-
const end = start + @as(u32, @intCast(file.tree.tokenSlice(item.data.token).len)) - item.data.byte_offset;
3541+
const token_slice_len: u32 = @intCast(file.tree.tokenSlice(item.data.token).len);
3542+
const end = start + token_slice_len - item.data.byte_offset;
35423543
break :blk Module.SrcLoc.Span{ .start = start, .end = end, .main = start };
35433544
};
35443545
const err_loc = std.zig.findLineColumn(file.source, err_span.main);

src/codegen/llvm.zig

+2-2
Original file line numberDiff line numberDiff line change
@@ -11119,7 +11119,7 @@ fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.E
1111911119
const size: u64 = struct_type.size(ip).*;
1112011120
assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
1112111121
if (size % 8 > 0) {
11122-
types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8));
11122+
types_buffer[types_index - 1] = try o.builder.intType(@intCast((size % 8) * 8));
1112311123
}
1112411124
},
1112511125
else => {},
@@ -11401,7 +11401,7 @@ const ParamTypeIterator = struct {
1140111401
assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
1140211402
if (size % 8 > 0) {
1140311403
types_buffer[types_index - 1] =
11404-
try it.object.builder.intType(@intCast(size % 8 * 8));
11404+
try it.object.builder.intType(@intCast((size % 8) * 8));
1140511405
}
1140611406
},
1140711407
else => {},

src/type.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -2954,7 +2954,7 @@ pub const Type = struct {
29542954
/// all the callsites of this function.
29552955
pub fn legacyStructFieldName(ty: Type, i: u32, mod: *Module) InternPool.NullTerminatedString {
29562956
return ty.structFieldName(i, mod).unwrap() orelse
2957-
mod.intern_pool.getOrPutStringFmt(mod.gpa, "{d}", .{i}) catch @panic("OOM");
2957+
(mod.intern_pool.getOrPutStringFmt(mod.gpa, "{d}", .{i}) catch @panic("OOM"));
29582958
}
29592959

29602960
pub fn structFieldCount(ty: Type, mod: *Module) u32 {

test/behavior/math.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn testThreeExprInARow(f: bool, t: bool) !void {
5151
try assertFalse(9 << 1 << 2 != 9 << 3);
5252
try assertFalse(90 >> 1 >> 2 != 90 >> 3);
5353
try assertFalse(100 - 1 + 1000 != 1099);
54-
try assertFalse(5 * 4 / 2 % 3 != 1);
54+
try assertFalse((5 * 4 / 2) % 3 != 1);
5555
try assertFalse(@as(i32, @as(i32, 5)) != 5);
5656
try assertFalse(!!false);
5757
try assertFalse(@as(i32, 7) != --(@as(i32, 7)));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const std = @import("std");
2+
3+
test {
4+
var x: u16 = 0xFF00;
5+
const y: u8 = 0xFF;
6+
x = x | y & 0x0F;
7+
try std.testing.expect(x == 0xFF0F);
8+
}
9+
10+
// error
11+
// backend=stage2
12+
// target=native
13+
//
14+
// :6:15: error: ambiguous operator precedence, must use parentheses to disambiguate

0 commit comments

Comments
 (0)