| author | |
| committer | |
| log | 21bc3353b8812ea097afb52fef411a4fb32bfea9 |
| tree | 579c88b542ca6bb61948caf211f776cc25f355b9 |
| parent | 6d7025d0c5c619773f0f5cc49edbd30713a7328d |
| signature | Commit is signed but in an unrecognized format. |
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 | } |
| 587 | 589 | ||
| 588 | pub fn formatBuf( | 590 | pub 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(); |
| 78 | pub const ZigClangPreprocessingRecord = @OpaqueType(); | 78 | pub const ZigClangPreprocessingRecord = @OpaqueType(); |
| 79 | pub const ZigClangFloatingLiteral = @OpaqueType(); | 79 | pub const ZigClangFloatingLiteral = @OpaqueType(); |
| 80 | pub const ZigClangConstantExpr = @OpaqueType(); | 80 | pub const ZigClangConstantExpr = @OpaqueType(); |
| 81 | pub const ZigClangCharacterLiteral = @OpaqueType(); | ||
| 81 | 82 | ||
| 82 | pub const ZigClangBO = extern enum { | 83 | pub 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 | }; |
| 714 | 715 | ||
| 716 | pub const ZigClangCharacterLiteral_CharacterKind = extern enum { | ||
| 717 | Ascii, | ||
| 718 | Wide, | ||
| 719 | UTF8, | ||
| 720 | UTF16, | ||
| 721 | UTF32, | ||
| 722 | }; | ||
| 723 | |||
| 715 | pub const ZigClangRecordDecl_field_iterator = extern struct { | 724 | pub 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 |
| 1077 | 1086 | ||
| 1078 | pub extern fn ZigClangPredefinedExpr_getFunctionName(*const ZigClangPredefinedExpr) *const ZigClangStringLiteral; | 1087 | pub extern fn ZigClangPredefinedExpr_getFunctionName(*const ZigClangPredefinedExpr) *const ZigClangStringLiteral; |
| 1079 | 1088 | ||
| 1089 | pub extern fn ZigClangCharacterLiteral_getBeginLoc(*const ZigClangCharacterLiteral) ZigClangSourceLocation; | ||
| 1090 | pub extern fn ZigClangCharacterLiteral_getKind(*const ZigClangCharacterLiteral) ZigClangCharacterLiteral_CharacterKind; | ||
| 1091 | pub 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 | }; |
| 54 | 57 | ||
| 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 | }; |
| 61 | 64 | ||
| 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 | }; |
| 127 | 125 | ||
| 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 used | 166 | // 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 | }; |
| 439 | 435 | ||
| 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( |
| 1202 | 1199 | ||
| 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 { |
| 1237 | 1234 | ||
| 1238 | // Returns either a string literal or a slice of `buf`. | 1235 | // Returns either a string literal or a slice of `buf`. |
| 1239 | fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 { | 1236 | fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 { |
| 1240 | // TODO: https://github.com/ziglang/zig/issues/2749 | 1237 | 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 | } |
| 1253 | 1247 | ||
| 1254 | fn transCCast( | 1248 | fn transCCast( |
| ... | @@ -1459,13 +1453,11 @@ fn transIfStmt( | ... | @@ -1459,13 +1453,11 @@ fn transIfStmt( |
| 1459 | // if (c) t else e | 1453 | // if (c) t else e |
| 1460 | const if_node = try transCreateNodeIf(rp.c); | 1454 | const if_node = try transCreateNodeIf(rp.c); |
| 1461 | 1455 | ||
| 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, ")"); |
| 1470 | 1462 | ||
| 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); |
| 1487 | 1479 | ||
| 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, ")"); |
| 1496 | 1486 | ||
| 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 | } |
| 1500 | 1494 | ||
| ... | @@ -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 | }; | ||
| 1511 | 1509 | ||
| 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: do | 1524 | // 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 | }; |
| 1538 | 1536 | ||
| 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 | }; |
| 1581 | 1578 | ||
| 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 | else | 1582 | 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 | } |
| 1595 | 1592 | ||
| 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 | }; |
| 1619 | 1616 | ||
| 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 | } |
| 1755 | 1750 | ||
| 1751 | fn 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 | |||
| 1756 | fn transCPtrCast( | 1786 | fn 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 | else | 1827 | else |
| 1798 | null); | 1828 | null); |
| 1829 | _ = try appendToken(rp.c, .Semicolon, ";"); | ||
| 1799 | return &br.base; | 1830 | return &br.base; |
| 1800 | } | 1831 | } |
| 1801 | 1832 | ||
| ... | @@ -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 | }; |
| 1822 | 1851 | ||
| 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); |
| 1826 | 1855 | ||
| 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, ")"); |
| 1829 | 1858 | ||
| 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 { |
| 3104 | 3133 | ||
| 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 | }); |
| 602 | 602 | ||
| 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 //////////////// |
| 604 | 733 | ||
| 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 | }); |
| 1147 | 1276 | ||
| 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 //////////////// |
| 1149 | 1338 | ||
| 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 | }); |
| 1643 | 1832 | ||
| 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 | }); |
| 1710 | 1872 | ||
| 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 | }); |
| 1738 | 1886 | ||
| 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 | }); |
| 1829 | 1906 | ||
| 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 | }); |
| 1989 | 2056 | ||
| 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 windows | 2058 | // 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 | } |