authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-18 01:04:01+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-18 01:04:01+02:00
log21bc3353b8812ea097afb52fef411a4fb32bfea9
tree579c88b542ca6bb61948caf211f776cc25f355b9
parent6d7025d0c5c619773f0f5cc49edbd30713a7328d
signature Commit is signed but in an unrecognized format.

translate-c-2 character literals and more test fixes


4 files changed, 365 insertions(+), 261 deletions(-)

lib/std/fmt.zig+3-1
...@@ -582,7 +582,9 @@ pub fn formatAsciiChar(...@@ -582,7 +582,9 @@ pub fn formatAsciiChar(
582 comptime Errors: type,582 comptime Errors: type,
583 output: fn (@TypeOf(context), []const u8) Errors!void,583 output: fn (@TypeOf(context), []const u8) Errors!void,
584) Errors!void {584) Errors!void {
585 return output(context, @as(*const [1]u8, &c)[0..]);585 if (std.ascii.isPrint(c))
586 return output(context, @as(*const [1]u8, &c)[0..]);
587 return format(context, Errors, output, "\\x{x:0<2}", .{c});
586}588}
587589
588pub fn formatBuf(590pub fn formatBuf(
src-self-hosted/clang.zig+13
...@@ -78,6 +78,7 @@ pub const struct_ZigClangInitListExpr = @OpaqueType();...@@ -78,6 +78,7 @@ pub const struct_ZigClangInitListExpr = @OpaqueType();
78pub const ZigClangPreprocessingRecord = @OpaqueType();78pub const ZigClangPreprocessingRecord = @OpaqueType();
79pub const ZigClangFloatingLiteral = @OpaqueType();79pub const ZigClangFloatingLiteral = @OpaqueType();
80pub const ZigClangConstantExpr = @OpaqueType();80pub const ZigClangConstantExpr = @OpaqueType();
81pub const ZigClangCharacterLiteral = @OpaqueType();
8182
82pub const ZigClangBO = extern enum {83pub const ZigClangBO = extern enum {
83 PtrMemD,84 PtrMemD,
...@@ -712,6 +713,14 @@ pub const ZigClangStringLiteral_StringKind = extern enum {...@@ -712,6 +713,14 @@ pub const ZigClangStringLiteral_StringKind = extern enum {
712 UTF32,713 UTF32,
713};714};
714715
716pub const ZigClangCharacterLiteral_CharacterKind = extern enum {
717 Ascii,
718 Wide,
719 UTF8,
720 UTF16,
721 UTF32,
722};
723
715pub const ZigClangRecordDecl_field_iterator = extern struct {724pub const ZigClangRecordDecl_field_iterator = extern struct {
716 opaque: *c_void,725 opaque: *c_void,
717};726};
...@@ -1077,3 +1086,7 @@ pub extern fn ZigClangExpr_EvaluateAsConstantExpr(*const ZigClangExpr, *ZigClang...@@ -1077,3 +1086,7 @@ pub extern fn ZigClangExpr_EvaluateAsConstantExpr(*const ZigClangExpr, *ZigClang
10771086
1078pub extern fn ZigClangPredefinedExpr_getFunctionName(*const ZigClangPredefinedExpr) *const ZigClangStringLiteral;1087pub extern fn ZigClangPredefinedExpr_getFunctionName(*const ZigClangPredefinedExpr) *const ZigClangStringLiteral;
10791088
1089pub extern fn ZigClangCharacterLiteral_getBeginLoc(*const ZigClangCharacterLiteral) ZigClangSourceLocation;
1090pub extern fn ZigClangCharacterLiteral_getKind(*const ZigClangCharacterLiteral) ZigClangCharacterLiteral_CharacterKind;
1091pub extern fn ZigClangCharacterLiteral_getValue(*const ZigClangCharacterLiteral) c_uint;
1092
src-self-hosted/translate_c.zig+97-68
...@@ -49,7 +49,10 @@ const Scope = struct {...@@ -49,7 +49,10 @@ const Scope = struct {
49 Root,49 Root,
50 Condition,50 Condition,
51 FnDef,51 FnDef,
52
53 /// used when getting a member `a.b`
52 Ref,54 Ref,
55 Loop,
53 };56 };
5457
55 const Switch = struct {58 const Switch = struct {
...@@ -59,11 +62,6 @@ const Scope = struct {...@@ -59,11 +62,6 @@ const Scope = struct {
59 has_default: bool = false,62 has_default: bool = false,
60 };63 };
6164
62 /// used when getting a member `a.b`
63 const Ref = struct {
64 base: Scope,
65 };
66
67 const Block = struct {65 const Block = struct {
68 base: Scope,66 base: Scope,
69 block_node: *ast.Node.Block,67 block_node: *ast.Node.Block,
...@@ -125,10 +123,6 @@ const Scope = struct {...@@ -125,10 +123,6 @@ const Scope = struct {
125 }123 }
126 };124 };
127125
128 const Condition = struct {
129 base: Scope,
130 };
131
132 const FnDef = struct {126 const FnDef = struct {
133 base: Scope,127 base: Scope,
134 params: AliasList,128 params: AliasList,
...@@ -169,7 +163,6 @@ const Scope = struct {...@@ -169,7 +163,6 @@ const Scope = struct {
169 .Root => unreachable,163 .Root => unreachable,
170 .Block => return @fieldParentPtr(Block, "base", scope),164 .Block => return @fieldParentPtr(Block, "base", scope),
171 .Condition => {165 .Condition => {
172 const cond = @fieldParentPtr(Condition, "base", scope);
173 // comma operator used166 // comma operator used
174 return try Block.init(c, scope, "blk");167 return try Block.init(c, scope, "blk");
175 },168 },
...@@ -192,6 +185,7 @@ const Scope = struct {...@@ -192,6 +185,7 @@ const Scope = struct {
192 .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),185 .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),
193 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),186 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),
194 .Switch,187 .Switch,
188 .Loop,
195 .Condition => scope.parent.?.getAlias(name),189 .Condition => scope.parent.?.getAlias(name),
196 };190 };
197 }191 }
...@@ -203,6 +197,7 @@ const Scope = struct {...@@ -203,6 +197,7 @@ const Scope = struct {
203 .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),197 .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),
204 .Block => @fieldParentPtr(Block, "base", scope).contains(name),198 .Block => @fieldParentPtr(Block, "base", scope).contains(name),
205 .Switch,199 .Switch,
200 .Loop,
206 .Condition => scope.parent.?.contains(name),201 .Condition => scope.parent.?.contains(name),
207 };202 };
208 }203 }
...@@ -213,6 +208,7 @@ const Scope = struct {...@@ -213,6 +208,7 @@ const Scope = struct {
213 switch (scope.id) {208 switch (scope.id) {
214 .FnDef => unreachable,209 .FnDef => unreachable,
215 .Switch => return scope,210 .Switch => return scope,
211 .Loop => return scope,
216 else => scope = scope.parent.?,212 else => scope = scope.parent.?,
217 }213 }
218 }214 }
...@@ -434,7 +430,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -434,7 +430,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
434 error.OutOfMemory => |e| return e,430 error.OutOfMemory => |e| return e,
435 };431 };
436 },432 },
437 else => unreachable,433 else => return failDecl(c, fn_decl_loc, fn_name, "unable to resolve function type {}", .{ZigClangType_getTypeClass(fn_type)}),
438 };434 };
439435
440 if (!decl_ctx.has_body) {436 if (!decl_ctx.has_body) {
...@@ -862,6 +858,7 @@ fn transStmt(...@@ -862,6 +858,7 @@ fn transStmt(
862 .DefaultStmtClass => return transDefault(rp, scope, @ptrCast(*const ZigClangDefaultStmt, stmt)),858 .DefaultStmtClass => return transDefault(rp, scope, @ptrCast(*const ZigClangDefaultStmt, stmt)),
863 .ConstantExprClass => return transConstantExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),859 .ConstantExprClass => return transConstantExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
864 .PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const ZigClangPredefinedExpr, stmt), result_used),860 .PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const ZigClangPredefinedExpr, stmt), result_used),
861 .CharacterLiteralClass => return transCharLiteral(rp, scope, @ptrCast(*const ZigClangCharacterLiteral, stmt), result_used),
865 else => {862 else => {
866 return revertAndWarn(863 return revertAndWarn(
867 rp,864 rp,
...@@ -1202,7 +1199,7 @@ fn transStringLiteral(...@@ -1202,7 +1199,7 @@ fn transStringLiteral(
12021199
1203 const token = try appendToken(rp.c, .StringLiteral, buf);1200 const token = try appendToken(rp.c, .StringLiteral, buf);
1204 const node = try rp.c.a().create(ast.Node.StringLiteral);1201 const node = try rp.c.a().create(ast.Node.StringLiteral);
1205 node.* = ast.Node.StringLiteral{1202 node.* = .{
1206 .token = token,1203 .token = token,
1207 };1204 };
1208 return maybeSuppressResult(rp, scope, result_used, &node.base);1205 return maybeSuppressResult(rp, scope, result_used, &node.base);
...@@ -1237,18 +1234,15 @@ fn writeEscapedString(buf: []u8, s: []const u8) void {...@@ -1237,18 +1234,15 @@ fn writeEscapedString(buf: []u8, s: []const u8) void {
12371234
1238// Returns either a string literal or a slice of `buf`.1235// Returns either a string literal or a slice of `buf`.
1239fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {1236fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
1240 // TODO: https://github.com/ziglang/zig/issues/27491237 return switch (c) {
1241 const escaped = switch (c) {1238 '\"' => "\\\""[0..],
1242 // Printable ASCII except for ' " \1239 '\'' => "\\'"[0..],
1243 ' ', '!', '#'...'&', '('...'[', ']'...'~' => ([_]u8{c})[0..],1240 '\\' => "\\\\"[0..],
1244 '\'', '\"', '\\' => ([_]u8{ '\\', c })[0..],1241 '\n' => "\\n"[0..],
1245 '\n' => return "\\n"[0..],1242 '\r' => "\\r"[0..],
1246 '\r' => return "\\r"[0..],1243 '\t' => "\\t"[0..],
1247 '\t' => return "\\t"[0..],1244 else => std.fmt.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable,
1248 else => return std.fmt.bufPrint(char_buf[0..], "\\x{x:2}", .{c}) catch unreachable,
1249 };1245 };
1250 std.mem.copy(u8, char_buf, escaped);
1251 return char_buf[0..escaped.len];
1252}1246}
12531247
1254fn transCCast(1248fn transCCast(
...@@ -1459,13 +1453,11 @@ fn transIfStmt(...@@ -1459,13 +1453,11 @@ fn transIfStmt(
1459 // if (c) t else e1453 // if (c) t else e
1460 const if_node = try transCreateNodeIf(rp.c);1454 const if_node = try transCreateNodeIf(rp.c);
14611455
1462 var cond_scope = Scope.Condition{1456 var cond_scope = Scope{
1463 .base = .{1457 .parent = scope,
1464 .parent = scope,1458 .id = .Condition,
1465 .id = .Condition,
1466 },
1467 };1459 };
1468 if_node.condition = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangIfStmt_getCond(stmt)), .used, .r_value, false);1460 if_node.condition = try transBoolExpr(rp, &cond_scope, @ptrCast(*const ZigClangExpr, ZigClangIfStmt_getCond(stmt)), .used, .r_value, false);
1469 _ = try appendToken(rp.c, .RParen, ")");1461 _ = try appendToken(rp.c, .RParen, ")");
14701462
1471 if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .unused, .r_value);1463 if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .unused, .r_value);
...@@ -1485,16 +1477,18 @@ fn transWhileLoop(...@@ -1485,16 +1477,18 @@ fn transWhileLoop(
1485) TransError!*ast.Node {1477) TransError!*ast.Node {
1486 const while_node = try transCreateNodeWhile(rp.c);1478 const while_node = try transCreateNodeWhile(rp.c);
14871479
1488 var cond_scope = Scope.Condition{1480 var cond_scope = Scope{
1489 .base = .{1481 .parent = scope,
1490 .parent = scope,1482 .id = .Condition,
1491 .id = .Condition,
1492 },
1493 };1483 };
1494 while_node.condition = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangWhileStmt_getCond(stmt)), .used, .r_value, false);1484 while_node.condition = try transBoolExpr(rp, &cond_scope, @ptrCast(*const ZigClangExpr, ZigClangWhileStmt_getCond(stmt)), .used, .r_value, false);
1495 _ = try appendToken(rp.c, .RParen, ")");1485 _ = try appendToken(rp.c, .RParen, ")");
14961486
1497 while_node.body = try transStmt(rp, scope, ZigClangWhileStmt_getBody(stmt), .unused, .r_value);1487 var loop_scope = Scope{
1488 .parent = scope,
1489 .id = .Loop,
1490 };
1491 while_node.body = try transStmt(rp, &loop_scope, ZigClangWhileStmt_getBody(stmt), .unused, .r_value);
1498 return &while_node.base;1492 return &while_node.base;
1499}1493}
15001494
...@@ -1508,6 +1502,10 @@ fn transDoWhileLoop(...@@ -1508,6 +1502,10 @@ fn transDoWhileLoop(
1508 while_node.condition = try transCreateNodeBoolLiteral(rp.c, true);1502 while_node.condition = try transCreateNodeBoolLiteral(rp.c, true);
1509 _ = try appendToken(rp.c, .RParen, ")");1503 _ = try appendToken(rp.c, .RParen, ")");
1510 var new = false;1504 var new = false;
1505 var loop_scope = Scope{
1506 .parent = scope,
1507 .id = .Loop,
1508 };
15111509
1512 const body_node = if (ZigClangStmt_getStmtClass(ZigClangDoStmt_getBody(stmt)) == .CompoundStmtClass) blk: {1510 const body_node = if (ZigClangStmt_getStmtClass(ZigClangDoStmt_getBody(stmt)) == .CompoundStmtClass) blk: {
1513 // there's already a block in C, so we'll append our condition to it.1511 // there's already a block in C, so we'll append our condition to it.
...@@ -1520,7 +1518,7 @@ fn transDoWhileLoop(...@@ -1520,7 +1518,7 @@ fn transDoWhileLoop(
1520 // zig: b;1518 // zig: b;
1521 // zig: if (!cond) break;1519 // zig: if (!cond) break;
1522 // zig: }1520 // zig: }
1523 break :blk (try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?;1521 break :blk (try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?;
1524 } else blk: {1522 } else blk: {
1525 // the C statement is without a block, so we need to create a block to contain it.1523 // the C statement is without a block, so we need to create a block to contain it.
1526 // c: do1524 // c: do
...@@ -1532,20 +1530,18 @@ fn transDoWhileLoop(...@@ -1532,20 +1530,18 @@ fn transDoWhileLoop(
1532 // zig: }1530 // zig: }
1533 new = true;1531 new = true;
1534 const block = try transCreateNodeBlock(rp.c, null);1532 const block = try transCreateNodeBlock(rp.c, null);
1535 try block.statements.push(try transStmt(rp, scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value));1533 try block.statements.push(try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value));
1536 break :blk block;1534 break :blk block;
1537 };1535 };
15381536
1539 // if (!cond) break;1537 // if (!cond) break;
1540 const if_node = try transCreateNodeIf(rp.c);1538 const if_node = try transCreateNodeIf(rp.c);
1541 var cond_scope = Scope.Condition{1539 var cond_scope = Scope{
1542 .base = .{1540 .parent = scope,
1543 .parent = scope,1541 .id = .Condition,
1544 .id = .Condition,
1545 },
1546 };1542 };
1547 const prefix_op = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!");1543 const prefix_op = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!");
1548 prefix_op.rhs = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangDoStmt_getCond(stmt)), .used, .r_value, false);1544 prefix_op.rhs = try transBoolExpr(rp, &cond_scope, @ptrCast(*const ZigClangExpr, ZigClangDoStmt_getCond(stmt)), .used, .r_value, true);
1549 _ = try appendToken(rp.c, .RParen, ")");1545 _ = try appendToken(rp.c, .RParen, ")");
1550 if_node.condition = &prefix_op.base;1546 if_node.condition = &prefix_op.base;
1551 if_node.body = &(try transCreateNodeBreak(rp.c, null)).base;1547 if_node.body = &(try transCreateNodeBreak(rp.c, null)).base;
...@@ -1563,25 +1559,26 @@ fn transForLoop(...@@ -1563,25 +1559,26 @@ fn transForLoop(
1563 scope: *Scope,1559 scope: *Scope,
1564 stmt: *const ZigClangForStmt,1560 stmt: *const ZigClangForStmt,
1565) TransError!*ast.Node {1561) TransError!*ast.Node {
1566 var inner = scope;1562 var loop_scope = Scope{
1563 .parent = scope,
1564 .id = .Loop,
1565 };
1567 var block = false;1566 var block = false;
1568 var block_scope: ?*Scope.Block = null;1567 var block_scope: ?*Scope.Block = null;
1569 if (ZigClangForStmt_getInit(stmt)) |init| {1568 if (ZigClangForStmt_getInit(stmt)) |init| {
1570 block_scope = try Scope.Block.init(rp.c, scope, null);1569 block_scope = try Scope.Block.init(rp.c, scope, null);
1571 block_scope.?.block_node = try transCreateNodeBlock(rp.c, null);1570 block_scope.?.block_node = try transCreateNodeBlock(rp.c, null);
1572 inner = &block_scope.?.base;1571 loop_scope.parent = &block_scope.?.base;
1573 _ = try transStmt(rp, inner, init, .unused, .r_value);1572 _ = try transStmt(rp, &loop_scope, init, .unused, .r_value);
1574 }1573 }
1575 var cond_scope = Scope.Condition{1574 var cond_scope = Scope{
1576 .base = .{1575 .parent = scope,
1577 .parent = inner,1576 .id = .Condition,
1578 .id = .Condition,
1579 },
1580 };1577 };
15811578
1582 const while_node = try transCreateNodeWhile(rp.c);1579 const while_node = try transCreateNodeWhile(rp.c);
1583 while_node.condition = if (ZigClangForStmt_getCond(stmt)) |cond|1580 while_node.condition = if (ZigClangForStmt_getCond(stmt)) |cond|
1584 try transBoolExpr(rp, &cond_scope.base, cond, .used, .r_value, false)1581 try transBoolExpr(rp, &cond_scope, cond, .used, .r_value, false)
1585 else1582 else
1586 try transCreateNodeBoolLiteral(rp.c, true);1583 try transCreateNodeBoolLiteral(rp.c, true);
1587 _ = try appendToken(rp.c, .RParen, ")");1584 _ = try appendToken(rp.c, .RParen, ")");
...@@ -1589,11 +1586,11 @@ fn transForLoop(...@@ -1589,11 +1586,11 @@ fn transForLoop(
1589 if (ZigClangForStmt_getInc(stmt)) |incr| {1586 if (ZigClangForStmt_getInc(stmt)) |incr| {
1590 _ = try appendToken(rp.c, .Colon, ":");1587 _ = try appendToken(rp.c, .Colon, ":");
1591 _ = try appendToken(rp.c, .LParen, "(");1588 _ = try appendToken(rp.c, .LParen, "(");
1592 while_node.continue_expr = try transExpr(rp, &cond_scope.base, incr, .unused, .r_value);1589 while_node.continue_expr = try transExpr(rp, &cond_scope, incr, .unused, .r_value);
1593 _ = try appendToken(rp.c, .RParen, ")");1590 _ = try appendToken(rp.c, .RParen, ")");
1594 }1591 }
15951592
1596 while_node.body = try transStmt(rp, inner, ZigClangForStmt_getBody(stmt), .unused, .r_value);1593 while_node.body = try transStmt(rp, &loop_scope, ZigClangForStmt_getBody(stmt), .unused, .r_value);
1597 if (block_scope != null) {1594 if (block_scope != null) {
1598 try block_scope.?.block_node.statements.push(&while_node.base);1595 try block_scope.?.block_node.statements.push(&while_node.base);
1599 block_scope.?.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");1596 block_scope.?.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
...@@ -1617,13 +1614,11 @@ fn transSwitch(...@@ -1617,13 +1614,11 @@ fn transSwitch(
1617 .pending_block = undefined,1614 .pending_block = undefined,
1618 };1615 };
16191616
1620 var cond_scope = Scope.Condition{1617 var cond_scope = Scope{
1621 .base = .{1618 .parent = scope,
1622 .parent = scope,1619 .id = .Condition,
1623 .id = .Condition,
1624 },
1625 };1620 };
1626 switch_node.expr = try transExpr(rp, &cond_scope.base, ZigClangSwitchStmt_getCond(stmt), .used, .r_value);1621 switch_node.expr = try transExpr(rp, &cond_scope, ZigClangSwitchStmt_getCond(stmt), .used, .r_value);
1627 _ = try appendToken(rp.c, .RParen, ")");1622 _ = try appendToken(rp.c, .RParen, ")");
1628 _ = try appendToken(rp.c, .LBrace, "{");1623 _ = try appendToken(rp.c, .LBrace, "{");
1629 switch_node.rbrace = try appendToken(rp.c, .RBrace, "}");1624 switch_node.rbrace = try appendToken(rp.c, .RBrace, "}");
...@@ -1753,6 +1748,41 @@ fn transPredefinedExpr(rp: RestorePoint, scope: *Scope, expr: *const ZigClangPre...@@ -1753,6 +1748,41 @@ fn transPredefinedExpr(rp: RestorePoint, scope: *Scope, expr: *const ZigClangPre
1753 return transStringLiteral(rp, scope, ZigClangPredefinedExpr_getFunctionName(expr), used);1748 return transStringLiteral(rp, scope, ZigClangPredefinedExpr_getFunctionName(expr), used);
1754}1749}
17551750
1751fn transCharLiteral(
1752 rp: RestorePoint,
1753 scope: *Scope,
1754 stmt: *const ZigClangCharacterLiteral,
1755 result_used: ResultUsed,
1756) TransError!*ast.Node {
1757 const kind = ZigClangCharacterLiteral_getKind(stmt);
1758 switch (kind) {
1759 .Ascii, .UTF8 => {
1760 const val = ZigClangCharacterLiteral_getValue(stmt);
1761 if (kind == .Ascii) {
1762 // C has a somewhat obscure feature called multi-character character
1763 // constant
1764 if (val > 255)
1765 return transCreateNodeInt(rp.c, val);
1766 }
1767 var char_buf: [4]u8 = undefined;
1768 const token = try appendTokenFmt(rp.c, .CharLiteral, "'{}'", .{escapeChar(@intCast(u8, val), &char_buf)});
1769 const node = try rp.c.a().create(ast.Node.CharLiteral);
1770 node.* = .{
1771 .token = token,
1772 };
1773 return maybeSuppressResult(rp, scope, result_used, &node.base);
1774 },
1775 .UTF16, .UTF32, .Wide => return revertAndWarn(
1776 rp,
1777 error.UnsupportedTranslation,
1778 ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)),
1779 "TODO: support character literal kind {}",
1780 .{kind},
1781 ),
1782 else => unreachable,
1783 }
1784}
1785
1756fn transCPtrCast(1786fn transCPtrCast(
1757 rp: RestorePoint,1787 rp: RestorePoint,
1758 loc: ZigClangSourceLocation,1788 loc: ZigClangSourceLocation,
...@@ -1796,6 +1826,7 @@ fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {...@@ -1796,6 +1826,7 @@ fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {
1796 "__switch"1826 "__switch"
1797 else1827 else
1798 null);1828 null);
1829 _ = try appendToken(rp.c, .Semicolon, ";");
1799 return &br.base;1830 return &br.base;
1800}1831}
18011832
...@@ -1813,18 +1844,16 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigCla...@@ -1813,18 +1844,16 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigCla
1813 const gropued = scope.id == .Condition;1844 const gropued = scope.id == .Condition;
1814 const lparen = if (gropued) try appendToken(rp.c, .LParen, "(") else undefined;1845 const lparen = if (gropued) try appendToken(rp.c, .LParen, "(") else undefined;
1815 const if_node = try transCreateNodeIf(rp.c);1846 const if_node = try transCreateNodeIf(rp.c);
1816 var cond_scope = Scope.Condition{1847 var cond_scope = Scope{
1817 .base = .{1848 .parent = scope,
1818 .parent = scope,1849 .id = .Condition,
1819 .id = .Condition,
1820 },
1821 };1850 };
18221851
1823 const cond_expr = ZigClangConditionalOperator_getCond(stmt);1852 const cond_expr = ZigClangConditionalOperator_getCond(stmt);
1824 const true_expr = ZigClangConditionalOperator_getTrueExpr(stmt);1853 const true_expr = ZigClangConditionalOperator_getTrueExpr(stmt);
1825 const false_expr = ZigClangConditionalOperator_getFalseExpr(stmt);1854 const false_expr = ZigClangConditionalOperator_getFalseExpr(stmt);
18261855
1827 if_node.condition = try transBoolExpr(rp, &cond_scope.base, cond_expr, .used, .r_value, false);1856 if_node.condition = try transBoolExpr(rp, &cond_scope, cond_expr, .used, .r_value, false);
1828 _ = try appendToken(rp.c, .RParen, ")");1857 _ = try appendToken(rp.c, .RParen, ")");
18291858
1830 if_node.body = try transExpr(rp, scope, true_expr, .used, .r_value);1859 if_node.body = try transExpr(rp, scope, true_expr, .used, .r_value);
...@@ -3104,7 +3133,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {...@@ -3104,7 +3133,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
31043133
3105 var tok_it = tok_list.iterator(0);3134 var tok_it = tok_list.iterator(0);
3106 const first_tok = tok_it.next().?;3135 const first_tok = tok_it.next().?;
3107 assert(first_tok.id == .Identifier and std.mem.eql(u8, first_tok.bytes, checked_name));3136 assert(first_tok.id == .Identifier and std.mem.eql(u8, first_tok.bytes, name));
3108 const next = tok_it.peek().?;3137 const next = tok_it.peek().?;
3109 switch (next.id) {3138 switch (next.id) {
3110 .Identifier => {3139 .Identifier => {
test/translate_c.zig+252-192
...@@ -600,6 +600,135 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -600,6 +600,135 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
600 \\}600 \\}
601 });601 });
602602
603 cases.add_both("simple union",
604 \\union Foo {
605 \\ int x;
606 \\ double y;
607 \\};
608 , &[_][]const u8{
609 \\pub const union_Foo = extern union {
610 \\ x: c_int,
611 \\ y: f64,
612 \\};
613 ,
614 \\pub const Foo = union_Foo;
615 });
616
617 cases.addC_both("string literal",
618 \\const char *foo(void) {
619 \\ return "bar";
620 \\}
621 , &[_][]const u8{
622 \\pub export fn foo() [*c]const u8 {
623 \\ return "bar";
624 \\}
625 });
626
627 cases.addC_both("return void",
628 \\void foo(void) {
629 \\ return;
630 \\}
631 , &[_][]const u8{
632 \\pub export fn foo() void {
633 \\ return;
634 \\}
635 });
636
637 cases.addC_both("for loop",
638 \\void foo(void) {
639 \\ for (int i = 0; i; i = i + 1) { }
640 \\}
641 , &[_][]const u8{
642 \\pub export fn foo() void {
643 \\ {
644 \\ var i: c_int = 0;
645 \\ while (i != 0) : (i = (i + 1)) {}
646 \\ }
647 \\}
648 });
649
650 cases.addC_both("empty for loop",
651 \\void foo(void) {
652 \\ for (;;) { }
653 \\}
654 , &[_][]const u8{
655 \\pub export fn foo() void {
656 \\ while (true) {}
657 \\}
658 });
659
660 cases.addC_both("break statement",
661 \\void foo(void) {
662 \\ for (;;) {
663 \\ break;
664 \\ }
665 \\}
666 , &[_][]const u8{
667 \\pub export fn foo() void {
668 \\ while (true) {
669 \\ break;
670 \\ }
671 \\}
672 });
673
674 cases.addC_both("continue statement",
675 \\void foo(void) {
676 \\ for (;;) {
677 \\ continue;
678 \\ }
679 \\}
680 , &[_][]const u8{
681 \\pub export fn foo() void {
682 \\ while (true) {
683 \\ continue;
684 \\ }
685 \\}
686 });
687
688 cases.addC_both("pointer casting",
689 \\float *ptrcast(int *a) {
690 \\ return (float *)a;
691 \\}
692 , &[_][]const u8{
693 \\pub export fn ptrcast(a: [*c]c_int) [*c]f32 {
694 \\ return @ptrCast([*c]f32, @alignCast(@alignOf(f32), a));
695 \\}
696 });
697
698 cases.addC_both("pointer conversion with different alignment",
699 \\void test_ptr_cast() {
700 \\ void *p;
701 \\ {
702 \\ char *to_char = (char *)p;
703 \\ short *to_short = (short *)p;
704 \\ int *to_int = (int *)p;
705 \\ long long *to_longlong = (long long *)p;
706 \\ }
707 \\ {
708 \\ char *to_char = p;
709 \\ short *to_short = p;
710 \\ int *to_int = p;
711 \\ long long *to_longlong = p;
712 \\ }
713 \\}
714 , &[_][]const u8{
715 \\pub export fn test_ptr_cast() void {
716 \\ var p: ?*c_void = undefined;
717 \\ {
718 \\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@alignOf(u8), p));
719 \\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@alignOf(c_short), p));
720 \\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@alignOf(c_int), p));
721 \\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@alignOf(c_longlong), p));
722 \\ }
723 \\ {
724 \\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@alignOf(u8), p));
725 \\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@alignOf(c_short), p));
726 \\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@alignOf(c_int), p));
727 \\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@alignOf(c_longlong), p));
728 \\ }
729 \\}
730 });
731
603 /////////////// Cases that pass for only stage2 ////////////////732 /////////////// Cases that pass for only stage2 ////////////////
604733
605 cases.add_2("Parameterless function prototypes",734 cases.add_2("Parameterless function prototypes",
...@@ -957,11 +1086,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -957,11 +1086,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
957 \\ while (true) {1086 \\ while (true) {
958 \\ var a: c_int = 2;1087 \\ var a: c_int = 2;
959 \\ a = 12;1088 \\ a = 12;
960 \\ if (!4 != 0) break;1089 \\ if (!(4 != 0)) break;
961 \\ }1090 \\ }
962 \\ while (true) {1091 \\ while (true) {
963 \\ a = 7;1092 \\ a = 7;
964 \\ if (!4 != 0) break;1093 \\ if (!(4 != 0)) break;
965 \\ }1094 \\ }
966 \\}1095 \\}
967 });1096 });
...@@ -1145,6 +1274,66 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1145,6 +1274,66 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1145 \\}1274 \\}
1146 });1275 });
11471276
1277 cases.add_2("escape sequences",
1278 \\const char *escapes() {
1279 \\char a = '\'',
1280 \\ b = '\\',
1281 \\ c = '\a',
1282 \\ d = '\b',
1283 \\ e = '\f',
1284 \\ f = '\n',
1285 \\ g = '\r',
1286 \\ h = '\t',
1287 \\ i = '\v',
1288 \\ j = '\0',
1289 \\ k = '\"';
1290 \\ return "\'\\\a\b\f\n\r\t\v\0\"";
1291 \\}
1292 \\
1293 , &[_][]const u8{
1294 \\pub export fn escapes() [*c]const u8 {
1295 \\ var a: u8 = @as(u8, '\'');
1296 \\ var b: u8 = @as(u8, '\\');
1297 \\ var c: u8 = @as(u8, '\x07');
1298 \\ var d: u8 = @as(u8, '\x08');
1299 \\ var e: u8 = @as(u8, '\x0c');
1300 \\ var f: u8 = @as(u8, '\n');
1301 \\ var g: u8 = @as(u8, '\r');
1302 \\ var h: u8 = @as(u8, '\t');
1303 \\ var i: u8 = @as(u8, '\x0b');
1304 \\ var j: u8 = @as(u8, '\x00');
1305 \\ var k: u8 = @as(u8, '\"');
1306 \\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
1307 \\}
1308 });
1309
1310 cases.add_2("do loop",
1311 \\void foo(void) {
1312 \\ int a = 2;
1313 \\ do {
1314 \\ a = a - 1;
1315 \\ } while (a);
1316 \\
1317 \\ int b = 2;
1318 \\ do
1319 \\ b = b -1;
1320 \\ while (b);
1321 \\}
1322 , &[_][]const u8{
1323 \\pub export fn foo() void {
1324 \\ var a: c_int = 2;
1325 \\ while (true) {
1326 \\ a = (a - 1);
1327 \\ if (!(a != 0)) break;
1328 \\ }
1329 \\ var b: c_int = 2;
1330 \\ while (true) {
1331 \\ b = (b - 1);
1332 \\ if (!(b != 0)) break;
1333 \\ }
1334 \\}
1335 });
1336
1148 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////1337 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
11491338
1150 cases.addAllowWarnings("simple data types",1339 cases.addAllowWarnings("simple data types",
...@@ -1641,33 +1830,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1641,33 +1830,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1641 \\}1830 \\}
1642 });1831 });
16431832
1644 cases.addC("do loop",
1645 \\void foo(void) {
1646 \\ int a = 2;
1647 \\ do {
1648 \\ a--;
1649 \\ } while (a != 0);
1650 \\
1651 \\ int b = 2;
1652 \\ do
1653 \\ b--;
1654 \\ while (b != 0);
1655 \\}
1656 , &[_][]const u8{
1657 \\pub export fn foo() void {
1658 \\ var a: c_int = 2;
1659 \\ while (true) {
1660 \\ a -= 1;
1661 \\ if (!(a != 0)) break;
1662 \\ }
1663 \\ var b: c_int = 2;
1664 \\ while (true) {
1665 \\ b -= 1;
1666 \\ if (!(b != 0)) break;
1667 \\ }
1668 \\}
1669 });
1670
1671 cases.addC("deref function pointer",1833 cases.addC("deref function pointer",
1672 \\void foo(void) {}1834 \\void foo(void) {}
1673 \\int baz(void) { return 0; }1835 \\int baz(void) { return 0; }
...@@ -1708,20 +1870,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1708,20 +1870,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1708 \\}1870 \\}
1709 });1871 });
17101872
1711 cases.add("simple union",
1712 \\union Foo {
1713 \\ int x;
1714 \\ double y;
1715 \\};
1716 , &[_][]const u8{
1717 \\pub const union_Foo = extern union {
1718 \\ x: c_int,
1719 \\ y: f64,
1720 \\};
1721 ,
1722 \\pub const Foo = union_Foo;
1723 });
1724
1725 cases.add("address of operator",1873 cases.add("address of operator",
1726 \\int foo(void) {1874 \\int foo(void) {
1727 \\ int x = 1234;1875 \\ int x = 1234;
...@@ -1736,77 +1884,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1736,77 +1884,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1736 \\}1884 \\}
1737 });1885 });
17381886
1739 cases.add("string literal",
1740 \\const char *foo(void) {
1741 \\ return "bar";
1742 \\}
1743 , &[_][]const u8{
1744 \\pub fn foo() [*c]const u8 {
1745 \\ return "bar";
1746 \\}
1747 });
1748
1749 cases.add("return void",
1750 \\void foo(void) {
1751 \\ return;
1752 \\}
1753 , &[_][]const u8{
1754 \\pub fn foo() void {
1755 \\ return;
1756 \\}
1757 });
1758
1759 cases.add("for loop",
1760 \\void foo(void) {
1761 \\ for (int i = 0; i < 10; i += 1) { }
1762 \\}
1763 , &[_][]const u8{
1764 \\pub fn foo() void {
1765 \\ {
1766 \\ var i: c_int = 0;
1767 \\ while (i < 10) : (i += 1) {}
1768 \\ }
1769 \\}
1770 });
1771
1772 cases.add("empty for loop",
1773 \\void foo(void) {
1774 \\ for (;;) { }
1775 \\}
1776 , &[_][]const u8{
1777 \\pub fn foo() void {
1778 \\ while (true) {}
1779 \\}
1780 });
1781
1782 cases.add("break statement",
1783 \\void foo(void) {
1784 \\ for (;;) {
1785 \\ break;
1786 \\ }
1787 \\}
1788 , &[_][]const u8{
1789 \\pub fn foo() void {
1790 \\ while (true) {
1791 \\ break;
1792 \\ }
1793 \\}
1794 });
1795
1796 cases.add("continue statement",
1797 \\void foo(void) {
1798 \\ for (;;) {
1799 \\ continue;
1800 \\ }
1801 \\}
1802 , &[_][]const u8{
1803 \\pub fn foo() void {
1804 \\ while (true) {
1805 \\ continue;
1806 \\ }
1807 \\}
1808 });
1809
1810 cases.add("variable name shadowing",1887 cases.add("variable name shadowing",
1811 \\int foo(void) {1888 \\int foo(void) {
1812 \\ int x = 1;1889 \\ int x = 1;
...@@ -1827,16 +1904,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1827,16 +1904,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1827 \\}1904 \\}
1828 });1905 });
18291906
1830 cases.add("pointer casting",
1831 \\float *ptrcast(int *a) {
1832 \\ return (float *)a;
1833 \\}
1834 , &[_][]const u8{
1835 \\fn ptrcast(a: [*c]c_int) [*c]f32 {
1836 \\ return @ptrCast([*c]f32, @alignCast(@alignOf(f32), a));
1837 \\}
1838 });
1839
1840 cases.add("bin not",1907 cases.add("bin not",
1841 \\int foo(int x) {1908 \\int foo(int x) {
1842 \\ return ~x;1909 \\ return ~x;
...@@ -1987,74 +2054,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1987,74 +2054,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1987 \\}2054 \\}
1988 });2055 });
19892056
1990 cases.addC("pointer conversion with different alignment",
1991 \\void test_ptr_cast() {
1992 \\ void *p;
1993 \\ {
1994 \\ char *to_char = (char *)p;
1995 \\ short *to_short = (short *)p;
1996 \\ int *to_int = (int *)p;
1997 \\ long long *to_longlong = (long long *)p;
1998 \\ }
1999 \\ {
2000 \\ char *to_char = p;
2001 \\ short *to_short = p;
2002 \\ int *to_int = p;
2003 \\ long long *to_longlong = p;
2004 \\ }
2005 \\}
2006 , &[_][]const u8{
2007 \\pub export fn test_ptr_cast() void {
2008 \\ var p: ?*c_void = undefined;
2009 \\ {
2010 \\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@alignOf(u8), p));
2011 \\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@alignOf(c_short), p));
2012 \\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@alignOf(c_int), p));
2013 \\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@alignOf(c_longlong), p));
2014 \\ }
2015 \\ {
2016 \\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@alignOf(u8), p));
2017 \\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@alignOf(c_short), p));
2018 \\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@alignOf(c_int), p));
2019 \\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@alignOf(c_longlong), p));
2020 \\ }
2021 \\}
2022 });
2023
2024 cases.addC("escape sequences",
2025 \\const char *escapes() {
2026 \\char a = '\'',
2027 \\ b = '\\',
2028 \\ c = '\a',
2029 \\ d = '\b',
2030 \\ e = '\f',
2031 \\ f = '\n',
2032 \\ g = '\r',
2033 \\ h = '\t',
2034 \\ i = '\v',
2035 \\ j = '\0',
2036 \\ k = '\"';
2037 \\ return "\'\\\a\b\f\n\r\t\v\0\"";
2038 \\}
2039 \\
2040 , &[_][]const u8{
2041 \\pub export fn escapes() [*c]const u8 {
2042 \\ var a: u8 = @as(u8, '\'');
2043 \\ var b: u8 = @as(u8, '\\');
2044 \\ var c: u8 = @as(u8, '\x07');
2045 \\ var d: u8 = @as(u8, '\x08');
2046 \\ var e: u8 = @as(u8, '\x0c');
2047 \\ var f: u8 = @as(u8, '\n');
2048 \\ var g: u8 = @as(u8, '\r');
2049 \\ var h: u8 = @as(u8, '\t');
2050 \\ var i: u8 = @as(u8, '\x0b');
2051 \\ var j: u8 = @as(u8, '\x00');
2052 \\ var k: u8 = @as(u8, '\"');
2053 \\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
2054 \\}
2055 \\
2056 });
2057
2058 if (builtin.os != builtin.Os.windows) {2057 if (builtin.os != builtin.Os.windows) {
2059 // sysv_abi not currently supported on windows2058 // sysv_abi not currently supported on windows
2060 cases.add("Macro qualified functions",2059 cases.add("Macro qualified functions",
...@@ -2386,4 +2385,65 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2386,4 +2385,65 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2386 \\ };2385 \\ };
2387 \\}2386 \\}
2388 });2387 });
2388
2389 cases.addC("escape sequences",
2390 \\const char *escapes() {
2391 \\char a = '\'',
2392 \\ b = '\\',
2393 \\ c = '\a',
2394 \\ d = '\b',
2395 \\ e = '\f',
2396 \\ f = '\n',
2397 \\ g = '\r',
2398 \\ h = '\t',
2399 \\ i = '\v',
2400 \\ j = '\0',
2401 \\ k = '\"';
2402 \\ return "\'\\\a\b\f\n\r\t\v\0\"";
2403 \\}
2404 \\
2405 , &[_][]const u8{
2406 \\pub export fn escapes() [*c]const u8 {
2407 \\ var a: u8 = @as(u8, '\'');
2408 \\ var b: u8 = @as(u8, '\\');
2409 \\ var c: u8 = @as(u8, '\x07');
2410 \\ var d: u8 = @as(u8, '\x08');
2411 \\ var e: u8 = @as(u8, '\x0c');
2412 \\ var f: u8 = @as(u8, '\n');
2413 \\ var g: u8 = @as(u8, '\r');
2414 \\ var h: u8 = @as(u8, '\t');
2415 \\ var i: u8 = @as(u8, '\x0b');
2416 \\ var j: u8 = @as(u8, '\x00');
2417 \\ var k: u8 = @as(u8, '\"');
2418 \\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
2419 \\}
2420 \\
2421 });
2422
2423 cases.addC("do loop",
2424 \\void foo(void) {
2425 \\ int a = 2;
2426 \\ do {
2427 \\ a--;
2428 \\ } while (a != 0);
2429 \\
2430 \\ int b = 2;
2431 \\ do
2432 \\ b--;
2433 \\ while (b != 0);
2434 \\}
2435 , &[_][]const u8{
2436 \\pub export fn foo() void {
2437 \\ var a: c_int = 2;
2438 \\ while (true) {
2439 \\ a -= 1;
2440 \\ if (!(a != 0)) break;
2441 \\ }
2442 \\ var b: c_int = 2;
2443 \\ while (true) {
2444 \\ b -= 1;
2445 \\ if (!(b != 0)) break;
2446 \\ }
2447 \\}
2448 });
2389}2449}