From 2ac7aefe2ff0d2f1a4d58a2baa49a40dfb670732 Mon Sep 17 00:00:00 2001 From: riverbl <94326797+riverbl@users.noreply.github.com> Date: Thu, 30 Dec 2021 22:54:11 +0000 Subject: [PATCH] stage2: do not interpret identifier containing underscores (eg: u3_2) as int primitive type --- src/AstGen.zig | 27 ++++++++++++++++++++++++--- test/behavior/misc.zig | 16 ++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/AstGen.zig b/src/AstGen.zig index a3a63be09f..6035227af0 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -6017,6 +6017,27 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref } } +/// Parses the string `buf` as a base 10 integer of type `u16`. +/// +/// Unlike std.fmt.parseInt, does not allow the '_' character in `buf`. +fn parseBitCount(buf: []const u8) std.fmt.ParseIntError!u16 { + if (buf.len == 0) return error.InvalidCharacter; + + var x: u16 = 0; + + for (buf) |c| { + const digit = switch (c) { + '0'...'9' => c - '0', + else => return error.InvalidCharacter, + }; + + if (x != 0) x = try std.math.mul(u16, x, 10); + x = try std.math.add(u16, x, @as(u16, digit)); + } + + return x; +} + fn identifier( gz: *GenZir, scope: *Scope, @@ -6050,7 +6071,7 @@ fn identifier( true => .signed, false => .unsigned, }; - const bit_count = std.fmt.parseInt(u16, ident_name_raw[1..], 10) catch |err| switch (err) { + const bit_count = parseBitCount(ident_name_raw[1..]) catch |err| switch (err) { error.Overflow => return astgen.failNode( ident, "primitive integer type '{s}' exceeds maximum bit width of 65535", @@ -8864,7 +8885,7 @@ const GenZir = struct { parent: *Scope, /// All `GenZir` scopes for the same ZIR share this. astgen: *AstGen, - /// Keeps track of the list of instructions in this scope. Possibly shared. + /// Keeps track of the list of instructions in this scope. Possibly shared. /// Indexes to instructions in `astgen`. instructions: *ArrayListUnmanaged(Zir.Inst.Index), /// A sub-block may share its instructions ArrayList with containing GenZir, @@ -10098,7 +10119,7 @@ pub fn isPrimitive(name: []const u8) bool { if (name.len < 2) return false; const first_c = name[0]; if (first_c != 'i' and first_c != 'u') return false; - if (std.fmt.parseInt(u16, name[1..], 10)) |_| { + if (parseBitCount(name[1..])) |_| { return true; } else |err| switch (err) { error.Overflow => return true, diff --git a/test/behavior/misc.zig b/test/behavior/misc.zig index 7a248ed320..1c115073af 100644 --- a/test/behavior/misc.zig +++ b/test/behavior/misc.zig @@ -186,3 +186,19 @@ test "lazy typeInfo value as generic parameter" { }; S.foo(@typeInfo(@TypeOf(.{}))); } + +test "variable name containing underscores does not shadow int primitive" { + const _u0 = 0; + const i_8 = 0; + const u16_ = 0; + const i3_2 = 0; + const u6__4 = 0; + const i2_04_8 = 0; + + _ = _u0; + _ = i_8; + _ = u16_; + _ = i3_2; + _ = u6__4; + _ = i2_04_8; +}