authorgravatar for evan@lagerdata.comEvan Haas <evan@lagerdata.com> 2021-07-07 00:11:02-07:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-07-19 12:56:23+03:00
log3e67ef5c9f539d63e93867c0928ad1fdf2658682
tree0e99cee6aa6b700a0b87a182f83acd0ca5a14edc
parentc9050565625bb7a43b8cc10b1103826ffccea69d

translate-c: Handle underscore when used as an identifier

Use `@` syntax to escape `_` when used as an identifier. Remove the stage1 astgen prohibition against assigning from `_` Note: there a few stage1 bugs preventing `_` from being used as an identifier for a local variable or function parameter; these will be fixed by stage2. They are unlikely to arise in real C code since identifiers starting with underscore are reserved for the implementation.

5 files changed, 18 insertions(+), 9 deletions(-)

lib/std/zig/fmt.zig+1
...@@ -23,6 +23,7 @@ pub fn fmtId(bytes: []const u8) std.fmt.Formatter(formatId) {...@@ -23,6 +23,7 @@ pub fn fmtId(bytes: []const u8) std.fmt.Formatter(formatId) {
23}23}
2424
25pub fn isValidId(bytes: []const u8) bool {25pub fn isValidId(bytes: []const u8) bool {
26 if (mem.eql(u8, bytes, "_")) return false;
26 for (bytes) |c, i| {27 for (bytes) |c, i| {
27 switch (c) {28 switch (c) {
28 '_', 'a'...'z', 'A'...'Z' => {},29 '_', 'a'...'z', 'A'...'Z' => {},
src/stage1/astgen.cpp-3
...@@ -3821,9 +3821,6 @@ static Stage1ZirInst *astgen_identifier(Stage1AstGen *ag, Scope *scope, AstNode...@@ -3821,9 +3821,6 @@ static Stage1ZirInst *astgen_identifier(Stage1AstGen *ag, Scope *scope, AstNode
3821 const_instruction->value->special = ConstValSpecialStatic;3821 const_instruction->value->special = ConstValSpecialStatic;
3822 const_instruction->value->data.x_ptr.special = ConstPtrSpecialDiscard;3822 const_instruction->value->data.x_ptr.special = ConstPtrSpecialDiscard;
3823 return &const_instruction->base;3823 return &const_instruction->base;
3824 } else {
3825 add_node_error(ag->codegen, node, buf_sprintf("`_` may only be used to assign things to"));
3826 return ag->codegen->invalid_inst_src;
3827 }3824 }
3828 }3825 }
38293826
src/translate_c.zig-4
...@@ -4951,10 +4951,6 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -4951,10 +4951,6 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
4951 const scope = &c.global_scope.base;4951 const scope = &c.global_scope.base;
49524952
4953 const init_node = try parseCExpr(c, m, scope);4953 const init_node = try parseCExpr(c, m, scope);
4954 if (init_node.castTag(.identifier)) |ident_node| {
4955 if (mem.eql(u8, "_", ident_node.data))
4956 return m.fail(c, "unable to translate C expr: illegal identifier _", .{});
4957 }
4958 const last = m.next().?;4954 const last = m.next().?;
4959 if (last != .Eof and last != .Nl)4955 if (last != .Eof and last != .Nl)
4960 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});4956 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});
test/run_translated_c.zig+12
...@@ -1647,4 +1647,16 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -1647,4 +1647,16 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
1647 \\ if (a != 1) abort();1647 \\ if (a != 1) abort();
1648 \\}1648 \\}
1649 , "");1649 , "");
1650
1651 cases.add("Underscore identifiers",
1652 \\#include <stdlib.h>
1653 \\int _ = 10;
1654 \\typedef struct { int _; } S;
1655 \\int main(void) {
1656 \\ if (_ != 10) abort();
1657 \\ S foo = { ._ = _ };
1658 \\ if (foo._ != _) abort();
1659 \\ return 0;
1660 \\}
1661 , "");
1650}1662}
test/translate_c.zig+5-2
...@@ -3616,9 +3616,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3616,9 +3616,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3616 \\}3616 \\}
3617 });3617 });
36183618
3619 cases.add("Don't allow underscore identifier in macros",3619 cases.add("Use @ syntax for bare underscore identifier in macro or public symbol",
3620 \\#define FOO _3620 \\#define FOO _
3621 \\int _ = 42;
3621 , &[_][]const u8{3622 , &[_][]const u8{
3622 \\pub const FOO = @compileError("unable to translate C expr: illegal identifier _");3623 \\pub const FOO = @"_";
3624 ,
3625 \\pub export var @"_": c_int = 42;
3623 });3626 });
3624}3627}