| ... | @@ -1084,7 +1084,6 @@ fn transStmt( | ... | @@ -1084,7 +1084,6 @@ fn transStmt( |
| 1084 | const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?; | 1084 | const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?; |
| 1085 | const expr = try transExpr(c, scope, source_expr, .used, lrvalue); | 1085 | const expr = try transExpr(c, scope, source_expr, .used, lrvalue); |
| 1086 | return maybeSuppressResult(c, scope, result_used, expr); | 1086 | return maybeSuppressResult(c, scope, result_used, expr); |
| 1087 | const node = try c.arena.create(Node.GroupedExpression); | | |
| 1088 | }, | 1087 | }, |
| 1089 | else => { | 1088 | else => { |
| 1090 | return revertAndWarn( | 1089 | return revertAndWarn( |
| ... | @@ -1389,62 +1388,56 @@ fn transDeclRefExpr( | ... | @@ -1389,62 +1388,56 @@ fn transDeclRefExpr( |
| 1389 | } | 1388 | } |
| 1390 | | 1389 | |
| 1391 | fn transImplicitCastExpr( | 1390 | fn transImplicitCastExpr( |
| 1392 | rp: RestorePoint, | 1391 | c: *Context, |
| 1393 | scope: *Scope, | 1392 | scope: *Scope, |
| 1394 | expr: *const clang.ImplicitCastExpr, | 1393 | expr: *const clang.ImplicitCastExpr, |
| 1395 | result_used: ResultUsed, | 1394 | result_used: ResultUsed, |
| 1396 | ) TransError!*ast.Node { | 1395 | ) TransError!Node { |
| 1397 | const c = rp.c; | | |
| 1398 | const sub_expr = expr.getSubExpr(); | 1396 | const sub_expr = expr.getSubExpr(); |
| 1399 | const dest_type = getExprQualType(c, @ptrCast(*const clang.Expr, expr)); | 1397 | const dest_type = getExprQualType(c, @ptrCast(*const clang.Expr, expr)); |
| 1400 | const src_type = getExprQualType(c, sub_expr); | 1398 | const src_type = getExprQualType(c, sub_expr); |
| 1401 | switch (expr.getCastKind()) { | 1399 | switch (expr.getCastKind()) { |
| 1402 | .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => { | 1400 | .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => { |
| 1403 | const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); | 1401 | const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); |
| 1404 | return try transCCast(rp, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node); | 1402 | const casted = try transCCast(c, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node); |
| | 1403 | return maybeSuppressResult(c, scope, result_used, casted); |
| 1405 | }, | 1404 | }, |
| 1406 | .LValueToRValue, .NoOp, .FunctionToPointerDecay => { | 1405 | .LValueToRValue, .NoOp, .FunctionToPointerDecay => { |
| 1407 | const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); | 1406 | const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); |
| 1408 | return maybeSuppressResult(rp, scope, result_used, sub_expr_node); | 1407 | return maybeSuppressResult(c, scope, result_used, sub_expr_node); |
| 1409 | }, | 1408 | }, |
| 1410 | .ArrayToPointerDecay => { | 1409 | .ArrayToPointerDecay => { |
| 1411 | if (exprIsNarrowStringLiteral(sub_expr)) { | 1410 | if (exprIsNarrowStringLiteral(sub_expr)) { |
| 1412 | const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); | 1411 | const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); |
| 1413 | return maybeSuppressResult(rp, scope, result_used, sub_expr_node); | 1412 | return maybeSuppressResult(c, scope, result_used, sub_expr_node); |
| 1414 | } | 1413 | } |
| 1415 | | 1414 | |
| 1416 | const prefix_op = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); | 1415 | const addr = try Node.address_of.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value)); |
| 1417 | prefix_op.rhs = try transExpr(rp, scope, sub_expr, .used, .r_value); | 1416 | return maybeSuppressResult(c, scope, result_used, addr); |
| 1418 | | | |
| 1419 | return maybeSuppressResult(rp, scope, result_used, &prefix_op.base); | | |
| 1420 | }, | 1417 | }, |
| 1421 | .NullToPointer => { | 1418 | .NullToPointer => { |
| 1422 | return try transCreateNodeNullLiteral(rp.c); | 1419 | return Node.null_literal.init(); |
| 1423 | }, | 1420 | }, |
| 1424 | .PointerToBoolean => { | 1421 | .PointerToBoolean => { |
| 1425 | // @ptrToInt(val) != 0 | 1422 | // @ptrToInt(val) != 0 |
| 1426 | const ptr_to_int = try rp.c.createBuiltinCall("@ptrToInt", 1); | 1423 | const ptr_to_int = try Node.ptr_to_int.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value)); |
| 1427 | ptr_to_int.params()[0] = try transExpr(rp, scope, sub_expr, .used, .r_value); | | |
| 1428 | ptr_to_int.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1429 | | 1424 | |
| 1430 | const op_token = try appendToken(rp.c, .BangEqual, "!="); | 1425 | const ne = try Node.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Node.zero_literal.init() }); |
| 1431 | const rhs_node = try transCreateNodeInt(rp.c, 0); | 1426 | return maybeSuppressResult(c, scope, result_used, ne); |
| 1432 | return transCreateNodeInfixOp(rp, scope, &ptr_to_int.base, .BangEqual, op_token, rhs_node, result_used, false); | | |
| 1433 | }, | 1427 | }, |
| 1434 | .IntegralToBoolean => { | 1428 | .IntegralToBoolean => { |
| 1435 | const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); | 1429 | const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); |
| 1436 | | 1430 | |
| 1437 | // The expression is already a boolean one, return it as-is | 1431 | // The expression is already a boolean one, return it as-is |
| 1438 | if (isBoolRes(sub_expr_node)) | 1432 | if (isBoolRes(sub_expr_node)) |
| 1439 | return sub_expr_node; | 1433 | return maybeSuppressResult(c, scope, result_used, sub_expr_node); |
| 1440 | | 1434 | |
| 1441 | // val != 0 | 1435 | // val != 0 |
| 1442 | const op_token = try appendToken(rp.c, .BangEqual, "!="); | 1436 | const ne = try Node.not_equal.create(c.arena, .{ .lhs = sub_expr_node, .rhs = Node.zero_literal.init() }); |
| 1443 | const rhs_node = try transCreateNodeInt(rp.c, 0); | 1437 | return maybeSuppressResult(c, scope, result_used, ne); |
| 1444 | return transCreateNodeInfixOp(rp, scope, sub_expr_node, .BangEqual, op_token, rhs_node, result_used, false); | | |
| 1445 | }, | 1438 | }, |
| 1446 | .BuiltinFnToFnPtr => { | 1439 | .BuiltinFnToFnPtr => { |
| 1447 | return transExpr(rp, scope, sub_expr, .used, .r_value); | 1440 | return transExpr(rp, scope, sub_expr, result_used, .r_value); |
| 1448 | }, | 1441 | }, |
| 1449 | else => |kind| return revertAndWarn( | 1442 | else => |kind| return revertAndWarn( |
| 1450 | rp, | 1443 | rp, |
| ... | @@ -1468,12 +1461,12 @@ fn transBoolExpr( | ... | @@ -1468,12 +1461,12 @@ fn transBoolExpr( |
| 1468 | if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) { | 1461 | if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) { |
| 1469 | return revertAndWarn(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{}); | 1462 | return revertAndWarn(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{}); |
| 1470 | } | 1463 | } |
| 1471 | return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[is_zero] }; | 1464 | return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[@boolToInt(is_zero)] }; |
| 1472 | } | 1465 | } |
| 1473 | | 1466 | |
| 1474 | var res = try transExpr(c, scope, expr, used, lrvalue); | 1467 | var res = try transExpr(c, scope, expr, used, lrvalue); |
| 1475 | if (isBoolRes(res)) { | 1468 | if (isBoolRes(res)) { |
| 1476 | return res; | 1469 | return maybeSuppressResult(c, scope, used, res); |
| 1477 | } | 1470 | } |
| 1478 | | 1471 | |
| 1479 | const ty = getExprQualType(c, expr).getTypePtr(); | 1472 | const ty = getExprQualType(c, expr).getTypePtr(); |
| ... | @@ -1563,18 +1556,18 @@ fn finishBoolExpr( | ... | @@ -1563,18 +1556,18 @@ fn finishBoolExpr( |
| 1563 | .Float16, | 1556 | .Float16, |
| 1564 | => { | 1557 | => { |
| 1565 | // node != 0 | 1558 | // node != 0 |
| 1566 | return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()}); | 1559 | return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() }); |
| 1567 | }, | 1560 | }, |
| 1568 | .NullPtr => { | 1561 | .NullPtr => { |
| 1569 | // node == null | 1562 | // node == null |
| 1570 | return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()}); | 1563 | return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init() }); |
| 1571 | }, | 1564 | }, |
| 1572 | else => {}, | 1565 | else => {}, |
| 1573 | } | 1566 | } |
| 1574 | }, | 1567 | }, |
| 1575 | .Pointer => { | 1568 | .Pointer => { |
| 1576 | // node == null | 1569 | // node == null |
| 1577 | return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init()}); | 1570 | return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init() }); |
| 1578 | }, | 1571 | }, |
| 1579 | .Typedef => { | 1572 | .Typedef => { |
| 1580 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); | 1573 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); |
| ... | @@ -1584,7 +1577,7 @@ fn finishBoolExpr( | ... | @@ -1584,7 +1577,7 @@ fn finishBoolExpr( |
| 1584 | }, | 1577 | }, |
| 1585 | .Enum => { | 1578 | .Enum => { |
| 1586 | // node != 0 | 1579 | // node != 0 |
| 1587 | return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init()}); | 1580 | return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() }); |
| 1588 | const op_token = try appendToken(c, .BangEqual, "!="); | 1581 | const op_token = try appendToken(c, .BangEqual, "!="); |
| 1589 | }, | 1582 | }, |
| 1590 | .Elaborated => { | 1583 | .Elaborated => { |
| ... | @@ -1653,11 +1646,11 @@ fn transReturnStmt( | ... | @@ -1653,11 +1646,11 @@ fn transReturnStmt( |
| 1653 | } | 1646 | } |
| 1654 | | 1647 | |
| 1655 | fn transStringLiteral( | 1648 | fn transStringLiteral( |
| 1656 | rp: RestorePoint, | 1649 | c: *Context, |
| 1657 | scope: *Scope, | 1650 | scope: *Scope, |
| 1658 | stmt: *const clang.StringLiteral, | 1651 | stmt: *const clang.StringLiteral, |
| 1659 | result_used: ResultUsed, | 1652 | result_used: ResultUsed, |
| 1660 | ) TransError!*ast.Node { | 1653 | ) TransError!Node { |
| 1661 | const kind = stmt.getKind(); | 1654 | const kind = stmt.getKind(); |
| 1662 | switch (kind) { | 1655 | switch (kind) { |
| 1663 | .Ascii, .UTF8 => { | 1656 | .Ascii, .UTF8 => { |
| ... | @@ -1665,55 +1658,28 @@ fn transStringLiteral( | ... | @@ -1665,55 +1658,28 @@ fn transStringLiteral( |
| 1665 | const bytes_ptr = stmt.getString_bytes_begin_size(&len); | 1658 | const bytes_ptr = stmt.getString_bytes_begin_size(&len); |
| 1666 | const str = bytes_ptr[0..len]; | 1659 | const str = bytes_ptr[0..len]; |
| 1667 | | 1660 | |
| 1668 | const token = try appendTokenFmt(rp.c, .StringLiteral, "\"{}\"", .{std.zig.fmtEscapes(str)}); | 1661 | const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(str)}); |
| 1669 | const node = try rp.c.arena.create(ast.Node.OneToken); | 1662 | const node = try Node.string_literal.create(c.arena, str); |
| 1670 | node.* = .{ | 1663 | return maybeSuppressResult(c, scope, result_used, node); |
| 1671 | .base = .{ .tag = .StringLiteral }, | | |
| 1672 | .token = token, | | |
| 1673 | }; | | |
| 1674 | return maybeSuppressResult(rp, scope, result_used, &node.base); | | |
| 1675 | }, | 1664 | }, |
| 1676 | .UTF16, .UTF32, .Wide => { | 1665 | .UTF16, .UTF32, .Wide => { |
| 1677 | const node = try transWideStringLiteral(rp, scope, stmt); | 1666 | const str_type = @tagName(stmt.getKind()); |
| 1678 | return maybeSuppressResult(rp, scope, result_used, node); | 1667 | const name = try std.fmt.allocPrint(c.arena, "zig.{s}_string_{d}", .{ str_type, c.getMangle() }); |
| | 1668 | const lit_array = try transStringLiteralAsArray(c, scope, stmt, stmt.getLength() + 1); |
| | 1669 | |
| | 1670 | const decl = try Node.var_simple.create(c.arena, .{ .name = name, .init = lit_array }); |
| | 1671 | try scope.appendNode(name, decl); |
| | 1672 | const node = try Node.identifier.create(c.arena, name); |
| | 1673 | return maybeSuppressResult(c, scope, result_used, node); |
| 1679 | }, | 1674 | }, |
| 1680 | } | 1675 | } |
| 1681 | } | 1676 | } |
| 1682 | | 1677 | |
| 1683 | /// Translates a wide string literal as a global "anonymous" array of the relevant-sized | | |
| 1684 | /// integer type + null terminator, and returns an identifier node for it | | |
| 1685 | fn transWideStringLiteral(rp: RestorePoint, scope: *Scope, stmt: *const clang.StringLiteral) TransError!*ast.Node { | | |
| 1686 | const str_type = @tagName(stmt.getKind()); | | |
| 1687 | const mangle = rp.c.getMangle(); | | |
| 1688 | const name = try std.fmt.allocPrint(rp.c.arena, "zig.{s}_string_{d}", .{ str_type, mangle }); | | |
| 1689 | | | |
| 1690 | const const_tok = try appendToken(rp.c, .Keyword_const, "const"); | | |
| 1691 | const name_tok = try appendIdentifier(rp.c, name); | | |
| 1692 | const eq_tok = try appendToken(rp.c, .Equal, "="); | | |
| 1693 | var semi_tok: ast.TokenIndex = undefined; | | |
| 1694 | | | |
| 1695 | const lit_array = try transStringLiteralAsArray(rp, scope, stmt, stmt.getLength() + 1); | | |
| 1696 | | | |
| 1697 | semi_tok = try appendToken(rp.c, .Semicolon, ";"); | | |
| 1698 | const var_decl_node = try ast.Node.VarDecl.create(rp.c.arena, .{ | | |
| 1699 | .name_token = name_tok, | | |
| 1700 | .mut_token = const_tok, | | |
| 1701 | .semicolon_token = semi_tok, | | |
| 1702 | }, .{ | | |
| 1703 | .visib_token = null, | | |
| 1704 | .eq_token = eq_tok, | | |
| 1705 | .init_node = lit_array, | | |
| 1706 | }); | | |
| 1707 | try addTopLevelDecl(rp.c, name, &var_decl_node.base); | | |
| 1708 | return transCreateNodeIdentifier(rp.c, name); | | |
| 1709 | } | | |
| 1710 | | | |
| 1711 | /// Parse the size of an array back out from an ast Node. | 1678 | /// Parse the size of an array back out from an ast Node. |
| 1712 | fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { | 1679 | fn zigArraySize(c: *Context, node: Node) TransError!usize { |
| 1713 | if (node.castTag(.ArrayType)) |array| { | 1680 | if (node.castTag(.array_type)) |array| { |
| 1714 | if (array.len_expr.castTag(.IntegerLiteral)) |int_lit| { | 1681 | if (array.data.len.castTag(.int_literal)) |int_lit| { |
| 1715 | const tok = tokenSlice(c, int_lit.token); | 1682 | return std.fmt.parseUnsigned(usize, int_lit.data, 10) catch error.UnsupportedTranslation; |
| 1716 | return std.fmt.parseUnsigned(usize, tok, 10) catch error.UnsupportedTranslation; | | |
| 1717 | } | 1683 | } |
| 1718 | } | 1684 | } |
| 1719 | return error.UnsupportedTranslation; | 1685 | return error.UnsupportedTranslation; |
| ... | @@ -1725,11 +1691,11 @@ fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { | ... | @@ -1725,11 +1691,11 @@ fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { |
| 1725 | /// than the array, truncate the string. If the array is larger than the | 1691 | /// than the array, truncate the string. If the array is larger than the |
| 1726 | /// string literal, pad the array with 0's | 1692 | /// string literal, pad the array with 0's |
| 1727 | fn transStringLiteralAsArray( | 1693 | fn transStringLiteralAsArray( |
| 1728 | rp: RestorePoint, | 1694 | c: *Context, |
| 1729 | scope: *Scope, | 1695 | scope: *Scope, |
| 1730 | stmt: *const clang.StringLiteral, | 1696 | stmt: *const clang.StringLiteral, |
| 1731 | array_size: usize, | 1697 | array_size: usize, |
| 1732 | ) TransError!*ast.Node { | 1698 | ) TransError!Node { |
| 1733 | if (array_size == 0) return error.UnsupportedType; | 1699 | if (array_size == 0) return error.UnsupportedType; |
| 1734 | | 1700 | |
| 1735 | const str_length = stmt.getLength(); | 1701 | const str_length = stmt.getLength(); |
| ... | @@ -1738,40 +1704,21 @@ fn transStringLiteralAsArray( | ... | @@ -1738,40 +1704,21 @@ fn transStringLiteralAsArray( |
| 1738 | const ty = expr_base.getType().getTypePtr(); | 1704 | const ty = expr_base.getType().getTypePtr(); |
| 1739 | const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty); | 1705 | const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty); |
| 1740 | | 1706 | |
| 1741 | const ty_node = try rp.c.arena.create(ast.Node.ArrayType); | 1707 | const arr_type = try transQualType(c, const_arr_ty.getElementType(), expr_base.getBeginLoc()); |
| 1742 | const op_token = try appendToken(rp.c, .LBracket, "["); | 1708 | const init_list = try c.arena.alloc(Node, array_size); |
| 1743 | const len_expr = try transCreateNodeInt(rp.c, array_size); | | |
| 1744 | _ = try appendToken(rp.c, .RBracket, "]"); | | |
| 1745 | | | |
| 1746 | ty_node.* = .{ | | |
| 1747 | .op_token = op_token, | | |
| 1748 | .rhs = try transQualType(rp, const_arr_ty.getElementType(), expr_base.getBeginLoc()), | | |
| 1749 | .len_expr = len_expr, | | |
| 1750 | }; | | |
| 1751 | _ = try appendToken(rp.c, .LBrace, "{"); | | |
| 1752 | var init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, array_size); | | |
| 1753 | init_node.* = .{ | | |
| 1754 | .lhs = &ty_node.base, | | |
| 1755 | .rtoken = undefined, | | |
| 1756 | .list_len = array_size, | | |
| 1757 | }; | | |
| 1758 | const init_list = init_node.list(); | | |
| 1759 | | 1709 | |
| 1760 | var i: c_uint = 0; | 1710 | var i: c_uint = 0; |
| 1761 | const kind = stmt.getKind(); | 1711 | const kind = stmt.getKind(); |
| 1762 | const narrow = kind == .Ascii or kind == .UTF8; | 1712 | const narrow = kind == .Ascii or kind == .UTF8; |
| 1763 | while (i < str_length and i < array_size) : (i += 1) { | 1713 | while (i < str_length and i < array_size) : (i += 1) { |
| 1764 | const code_unit = stmt.getCodeUnit(i); | 1714 | const code_unit = stmt.getCodeUnit(i); |
| 1765 | init_list[i] = try transCreateCharLitNode(rp.c, narrow, code_unit); | 1715 | init_list[i] = try transCreateCharLitNode(c, narrow, code_unit); |
| 1766 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1767 | } | 1716 | } |
| 1768 | while (i < array_size) : (i += 1) { | 1717 | while (i < array_size) : (i += 1) { |
| 1769 | init_list[i] = try transCreateNodeInt(rp.c, 0); | 1718 | init_list[i] = try transCreateNodeInt(c, 0); |
| 1770 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1771 | } | 1719 | } |
| 1772 | init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); | | |
| 1773 | | 1720 | |
| 1774 | return &init_node.base; | 1721 | return Node.array_init.create(c.arena, init_list); |
| 1775 | } | 1722 | } |
| 1776 | | 1723 | |
| 1777 | fn cIsEnum(qt: clang.QualType) bool { | 1724 | fn cIsEnum(qt: clang.QualType) bool { |
| ... | @@ -1790,152 +1737,87 @@ fn cIntTypeForEnum(enum_qt: clang.QualType) clang.QualType { | ... | @@ -1790,152 +1737,87 @@ fn cIntTypeForEnum(enum_qt: clang.QualType) clang.QualType { |
| 1790 | } | 1737 | } |
| 1791 | | 1738 | |
| 1792 | fn transCCast( | 1739 | fn transCCast( |
| 1793 | rp: RestorePoint, | 1740 | c: *Context, |
| 1794 | scope: *Scope, | 1741 | scope: *Scope, |
| 1795 | loc: clang.SourceLocation, | 1742 | loc: clang.SourceLocation, |
| 1796 | dst_type: clang.QualType, | 1743 | dst_type: clang.QualType, |
| 1797 | src_type: clang.QualType, | 1744 | src_type: clang.QualType, |
| 1798 | expr: *ast.Node, | 1745 | expr: Node, |
| 1799 | ) !*ast.Node { | 1746 | ) !Node { |
| 1800 | if (qualTypeCanon(dst_type).isVoidType()) return expr; | 1747 | if (qualTypeCanon(dst_type).isVoidType()) return expr; |
| 1801 | if (dst_type.eq(src_type)) return expr; | 1748 | if (dst_type.eq(src_type)) return expr; |
| 1802 | if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type)) | 1749 | if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type)) |
| 1803 | return transCPtrCast(rp, loc, dst_type, src_type, expr); | 1750 | return transCPtrCast(c, loc, dst_type, src_type, expr); |
| | 1751 | |
| | 1752 | const dst_node = try transQualType(c, dst_type, loc); |
| 1804 | if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) { | 1753 | if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) { |
| 1805 | // 1. If src_type is an enum, determine the underlying signed int type | 1754 | // 1. If src_type is an enum, determine the underlying signed int type |
| 1806 | // 2. Extend or truncate without changing signed-ness. | 1755 | // 2. Extend or truncate without changing signed-ness. |
| 1807 | // 3. Bit-cast to correct signed-ness | 1756 | // 3. Bit-cast to correct signed-ness |
| 1808 | const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type); | 1757 | const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type); |
| 1809 | const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type); | 1758 | const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type); |
| 1810 | var src_int_expr = if (cIsInteger(src_type)) expr else try transEnumToInt(rp.c, expr); | 1759 | var src_int_expr = if (cIsInteger(src_type)) expr else Node.enum_to_int.create(c.arena, expr); |
| 1811 | | | |
| 1812 | // @bitCast(dest_type, intermediate_value) | | |
| 1813 | const cast_node = try rp.c.createBuiltinCall("@bitCast", 2); | | |
| 1814 | cast_node.params()[0] = try transQualType(rp, dst_type, loc); | | |
| 1815 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1816 | | 1760 | |
| 1817 | if (isBoolRes(src_int_expr)) { | 1761 | if (isBoolRes(src_int_expr)) { |
| 1818 | const bool_to_int_node = try rp.c.createBuiltinCall("@boolToInt", 1); | 1762 | src_int_expr = try Node.bool_to_int.create(c.arena, src_int_expr); |
| 1819 | bool_to_int_node.params()[0] = src_int_expr; | | |
| 1820 | bool_to_int_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1821 | src_int_expr = &bool_to_int_node.base; | | |
| 1822 | } | 1763 | } |
| 1823 | | 1764 | |
| 1824 | switch (cIntTypeCmp(dst_type, src_int_type)) { | 1765 | switch (cIntTypeCmp(dst_type, src_int_type)) { |
| 1825 | .lt => { | 1766 | .lt => { |
| 1826 | // @truncate(SameSignSmallerInt, src_int_expr) | 1767 | // @truncate(SameSignSmallerInt, src_int_expr) |
| 1827 | const trunc_node = try rp.c.createBuiltinCall("@truncate", 2); | 1768 | const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed); |
| 1828 | const ty_node = try transQualTypeIntWidthOf(rp.c, dst_type, src_type_is_signed); | 1769 | src_int_expr = try Node.truncate.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr }); |
| 1829 | trunc_node.params()[0] = ty_node; | | |
| 1830 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1831 | trunc_node.params()[1] = src_int_expr; | | |
| 1832 | trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1833 | | | |
| 1834 | cast_node.params()[1] = &trunc_node.base; | | |
| 1835 | }, | 1770 | }, |
| 1836 | .gt => { | 1771 | .gt => { |
| 1837 | // @as(SameSignBiggerInt, src_int_expr) | 1772 | // @as(SameSignBiggerInt, src_int_expr) |
| 1838 | const as_node = try rp.c.createBuiltinCall("@as", 2); | 1773 | const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed); |
| 1839 | const ty_node = try transQualTypeIntWidthOf(rp.c, dst_type, src_type_is_signed); | 1774 | src_int_expr = try Node.as.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr }); |
| 1840 | as_node.params()[0] = ty_node; | | |
| 1841 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1842 | as_node.params()[1] = src_int_expr; | | |
| 1843 | as_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1844 | | | |
| 1845 | cast_node.params()[1] = &as_node.base; | | |
| 1846 | }, | 1775 | }, |
| 1847 | .eq => { | 1776 | .eq => { |
| 1848 | cast_node.params()[1] = src_int_expr; | 1777 | // src_int_expr = src_int_expr |
| 1849 | }, | 1778 | }, |
| 1850 | } | 1779 | } |
| 1851 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 1780 | // @bitCast(dest_type, intermediate_value) |
| 1852 | return &cast_node.base; | 1781 | return Node.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr }); |
| 1853 | } | 1782 | } |
| 1854 | if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) { | 1783 | if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) { |
| 1855 | // @intCast(dest_type, @ptrToInt(val)) | 1784 | // @intCast(dest_type, @ptrToInt(val)) |
| 1856 | const cast_node = try rp.c.createBuiltinCall("@intCast", 2); | 1785 | const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr); |
| 1857 | cast_node.params()[0] = try transQualType(rp, dst_type, loc); | 1786 | return Node.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int }); |
| 1858 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1859 | const builtin_node = try rp.c.createBuiltinCall("@ptrToInt", 1); | | |
| 1860 | builtin_node.params()[0] = expr; | | |
| 1861 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1862 | cast_node.params()[1] = &builtin_node.base; | | |
| 1863 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1864 | return &cast_node.base; | | |
| 1865 | } | 1787 | } |
| 1866 | if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) { | 1788 | if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) { |
| 1867 | // @intToPtr(dest_type, val) | 1789 | // @intToPtr(dest_type, val) |
| 1868 | const builtin_node = try rp.c.createBuiltinCall("@intToPtr", 2); | 1790 | return Node.int_to_ptr.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1869 | builtin_node.params()[0] = try transQualType(rp, dst_type, loc); | | |
| 1870 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1871 | builtin_node.params()[1] = expr; | | |
| 1872 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1873 | return &builtin_node.base; | | |
| 1874 | } | 1791 | } |
| 1875 | if (cIsFloating(src_type) and cIsFloating(dst_type)) { | 1792 | if (cIsFloating(src_type) and cIsFloating(dst_type)) { |
| 1876 | const builtin_node = try rp.c.createBuiltinCall("@floatCast", 2); | 1793 | // @floatCast(dest_type, val) |
| 1877 | builtin_node.params()[0] = try transQualType(rp, dst_type, loc); | 1794 | return Node.float_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1878 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1879 | builtin_node.params()[1] = expr; | | |
| 1880 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1881 | return &builtin_node.base; | | |
| 1882 | } | 1795 | } |
| 1883 | if (cIsFloating(src_type) and !cIsFloating(dst_type)) { | 1796 | if (cIsFloating(src_type) and !cIsFloating(dst_type)) { |
| 1884 | const builtin_node = try rp.c.createBuiltinCall("@floatToInt", 2); | 1797 | // @floatToInt(dest_type, val) |
| 1885 | builtin_node.params()[0] = try transQualType(rp, dst_type, loc); | 1798 | return Node.float_to_int.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1886 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1887 | builtin_node.params()[1] = expr; | | |
| 1888 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1889 | return &builtin_node.base; | | |
| 1890 | } | 1799 | } |
| 1891 | if (!cIsFloating(src_type) and cIsFloating(dst_type)) { | 1800 | if (!cIsFloating(src_type) and cIsFloating(dst_type)) { |
| 1892 | const builtin_node = try rp.c.createBuiltinCall("@intToFloat", 2); | 1801 | // @intToFloat(dest_type, val) |
| 1893 | builtin_node.params()[0] = try transQualType(rp, dst_type, loc); | 1802 | return Node.int_to_float.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1894 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1895 | builtin_node.params()[1] = expr; | | |
| 1896 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1897 | return &builtin_node.base; | | |
| 1898 | } | 1803 | } |
| 1899 | if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) { | 1804 | if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) { |
| 1900 | // @boolToInt returns either a comptime_int or a u1 | 1805 | // @boolToInt returns either a comptime_int or a u1 |
| 1901 | // TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast | 1806 | // TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast |
| 1902 | // instead of @as | 1807 | // instead of @as |
| 1903 | const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1); | 1808 | const bool_to_int = Node.bool_to_int.create(c.arena, expr); |
| 1904 | builtin_node.params()[0] = expr; | 1809 | return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int }); |
| 1905 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1906 | | | |
| 1907 | const as_node = try rp.c.createBuiltinCall("@as", 2); | | |
| 1908 | as_node.params()[0] = try transQualType(rp, dst_type, loc); | | |
| 1909 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1910 | as_node.params()[1] = &builtin_node.base; | | |
| 1911 | as_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1912 | | | |
| 1913 | return &as_node.base; | | |
| 1914 | } | 1810 | } |
| 1915 | if (cIsEnum(dst_type)) { | 1811 | if (cIsEnum(dst_type)) { |
| 1916 | const builtin_node = try rp.c.createBuiltinCall("@intToEnum", 2); | 1812 | // @intToEnum(dest_type, val) |
| 1917 | builtin_node.params()[0] = try transQualType(rp, dst_type, loc); | 1813 | return Node.int_to_enum.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1918 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1919 | builtin_node.params()[1] = expr; | | |
| 1920 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1921 | return &builtin_node.base; | | |
| 1922 | } | 1814 | } |
| 1923 | if (cIsEnum(src_type) and !cIsEnum(dst_type)) { | 1815 | if (cIsEnum(src_type) and !cIsEnum(dst_type)) { |
| 1924 | return transEnumToInt(rp.c, expr); | 1816 | // @enumToInt(val) |
| | 1817 | return Node.enum_to_int.create(c.arena, expr); |
| 1925 | } | 1818 | } |
| 1926 | const cast_node = try rp.c.createBuiltinCall("@as", 2); | 1819 | // @as(dest_type, val) |
| 1927 | cast_node.params()[0] = try transQualType(rp, dst_type, loc); | 1820 | return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1928 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 1929 | cast_node.params()[1] = expr; | | |
| 1930 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 1931 | return &cast_node.base; | | |
| 1932 | } | | |
| 1933 | | | |
| 1934 | fn transEnumToInt(c: *Context, enum_expr: *ast.Node) TypeError!*ast.Node { | | |
| 1935 | const builtin_node = try c.createBuiltinCall("@enumToInt", 1); | | |
| 1936 | builtin_node.params()[0] = enum_expr; | | |
| 1937 | builtin_node.rparen_token = try appendToken(c, .RParen, ")"); | | |
| 1938 | return &builtin_node.base; | | |
| 1939 | } | 1821 | } |
| 1940 | | 1822 | |
| 1941 | fn transExpr( | 1823 | fn transExpr( |
| ... | @@ -1976,13 +1858,12 @@ fn transExprCoercing( | ... | @@ -1976,13 +1858,12 @@ fn transExprCoercing( |
| 1976 | } | 1858 | } |
| 1977 | | 1859 | |
| 1978 | fn transInitListExprRecord( | 1860 | fn transInitListExprRecord( |
| 1979 | rp: RestorePoint, | 1861 | c: *Context, |
| 1980 | scope: *Scope, | 1862 | scope: *Scope, |
| 1981 | loc: clang.SourceLocation, | 1863 | loc: clang.SourceLocation, |
| 1982 | expr: *const clang.InitListExpr, | 1864 | expr: *const clang.InitListExpr, |
| 1983 | ty: *const clang.Type, | 1865 | ty: *const clang.Type, |
| 1984 | used: ResultUsed, | 1866 | ) TransError!Node { |
| 1985 | ) TransError!*ast.Node { | | |
| 1986 | var is_union_type = false; | 1867 | var is_union_type = false; |
| 1987 | // Unions and Structs are both represented as RecordDecl | 1868 | // Unions and Structs are both represented as RecordDecl |
| 1988 | const record_ty = ty.getAsRecordType() orelse | 1869 | const record_ty = ty.getAsRecordType() orelse |
| ... | @@ -1994,13 +1875,11 @@ fn transInitListExprRecord( | ... | @@ -1994,13 +1875,11 @@ fn transInitListExprRecord( |
| 1994 | const record_def = record_decl.getDefinition() orelse | 1875 | const record_def = record_decl.getDefinition() orelse |
| 1995 | unreachable; | 1876 | unreachable; |
| 1996 | | 1877 | |
| 1997 | const ty_node = try transType(rp, ty, loc); | 1878 | const ty_node = try transType(c, ty, loc); |
| 1998 | const init_count = expr.getNumInits(); | 1879 | const init_count = expr.getNumInits(); |
| 1999 | var field_inits = std.ArrayList(*ast.Node).init(rp.c.gpa); | 1880 | var field_inits = std.ArrayList(ast.Payload.ContainerInit.Initializer).init(c.gpa); |
| 2000 | defer field_inits.deinit(); | 1881 | defer field_inits.deinit(); |
| 2001 | | 1882 | |
| 2002 | _ = try appendToken(rp.c, .LBrace, "{"); | | |
| 2003 | | | |
| 2004 | var init_i: c_uint = 0; | 1883 | var init_i: c_uint = 0; |
| 2005 | var it = record_def.field_begin(); | 1884 | var it = record_def.field_begin(); |
| 2006 | const end_it = record_def.field_end(); | 1885 | const end_it = record_def.field_end(); |
| ... | @@ -2018,76 +1897,28 @@ fn transInitListExprRecord( | ... | @@ -2018,76 +1897,28 @@ fn transInitListExprRecord( |
| 2018 | | 1897 | |
| 2019 | // Generate the field assignment expression: | 1898 | // Generate the field assignment expression: |
| 2020 | // .field_name = expr | 1899 | // .field_name = expr |
| 2021 | const period_tok = try appendToken(rp.c, .Period, "."); | 1900 | var raw_name = try c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin()); |
| 2022 | | | |
| 2023 | var raw_name = try rp.c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin()); | | |
| 2024 | if (field_decl.isAnonymousStructOrUnion()) { | 1901 | if (field_decl.isAnonymousStructOrUnion()) { |
| 2025 | const name = rp.c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?; | 1902 | const name = c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?; |
| 2026 | raw_name = try mem.dupe(rp.c.arena, u8, name); | 1903 | raw_name = try mem.dupe(c.arena, u8, name); |
| 2027 | } | 1904 | } |
| 2028 | const field_name_tok = try appendIdentifier(rp.c, raw_name); | | |
| 2029 | | | |
| 2030 | _ = try appendToken(rp.c, .Equal, "="); | | |
| 2031 | | | |
| 2032 | const field_init_node = try rp.c.arena.create(ast.Node.FieldInitializer); | | |
| 2033 | field_init_node.* = .{ | | |
| 2034 | .period_token = period_tok, | | |
| 2035 | .name_token = field_name_tok, | | |
| 2036 | .expr = try transExpr(rp, scope, elem_expr, .used, .r_value), | | |
| 2037 | }; | | |
| 2038 | | 1905 | |
| 2039 | try field_inits.append(&field_init_node.base); | 1906 | try field_inits.append(.{ |
| 2040 | _ = try appendToken(rp.c, .Comma, ","); | 1907 | .name = raw_name, |
| | 1908 | .value = try transExpr(c, scope, elem_expr, .used, .r_value), |
| | 1909 | }); |
| 2041 | } | 1910 | } |
| 2042 | | 1911 | |
| 2043 | const node = try ast.Node.StructInitializer.alloc(rp.c.arena, field_inits.items.len); | 1912 | return Node.container_init.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items)); |
| 2044 | node.* = .{ | | |
| 2045 | .lhs = ty_node, | | |
| 2046 | .rtoken = try appendToken(rp.c, .RBrace, "}"), | | |
| 2047 | .list_len = field_inits.items.len, | | |
| 2048 | }; | | |
| 2049 | mem.copy(*ast.Node, node.list(), field_inits.items); | | |
| 2050 | return &node.base; | | |
| 2051 | } | | |
| 2052 | | | |
| 2053 | fn transCreateNodeArrayType( | | |
| 2054 | rp: RestorePoint, | | |
| 2055 | source_loc: clang.SourceLocation, | | |
| 2056 | ty: *const clang.Type, | | |
| 2057 | len: anytype, | | |
| 2058 | ) !*ast.Node { | | |
| 2059 | const node = try rp.c.arena.create(ast.Node.ArrayType); | | |
| 2060 | const op_token = try appendToken(rp.c, .LBracket, "["); | | |
| 2061 | const len_expr = try transCreateNodeInt(rp.c, len); | | |
| 2062 | _ = try appendToken(rp.c, .RBracket, "]"); | | |
| 2063 | node.* = .{ | | |
| 2064 | .op_token = op_token, | | |
| 2065 | .rhs = try transType(rp, ty, source_loc), | | |
| 2066 | .len_expr = len_expr, | | |
| 2067 | }; | | |
| 2068 | return &node.base; | | |
| 2069 | } | | |
| 2070 | | | |
| 2071 | fn transCreateEmptyArray(rp: RestorePoint, loc: clang.SourceLocation, ty: *const clang.Type) TransError!*ast.Node { | | |
| 2072 | const ty_node = try transCreateNodeArrayType(rp, loc, ty, 0); | | |
| 2073 | _ = try appendToken(rp.c, .LBrace, "{"); | | |
| 2074 | const filler_init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, 0); | | |
| 2075 | filler_init_node.* = .{ | | |
| 2076 | .lhs = ty_node, | | |
| 2077 | .rtoken = try appendToken(rp.c, .RBrace, "}"), | | |
| 2078 | .list_len = 0, | | |
| 2079 | }; | | |
| 2080 | return &filler_init_node.base; | | |
| 2081 | } | 1913 | } |
| 2082 | | 1914 | |
| 2083 | fn transInitListExprArray( | 1915 | fn transInitListExprArray( |
| 2084 | rp: RestorePoint, | 1916 | c: *Context, |
| 2085 | scope: *Scope, | 1917 | scope: *Scope, |
| 2086 | loc: clang.SourceLocation, | 1918 | loc: clang.SourceLocation, |
| 2087 | expr: *const clang.InitListExpr, | 1919 | expr: *const clang.InitListExpr, |
| 2088 | ty: *const clang.Type, | 1920 | ty: *const clang.Type, |
| 2089 | used: ResultUsed, | 1921 | ) TransError!Node { |
| 2090 | ) TransError!*ast.Node { | | |
| 2091 | const arr_type = ty.getAsArrayTypeUnsafe(); | 1922 | const arr_type = ty.getAsArrayTypeUnsafe(); |
| 2092 | const child_qt = arr_type.getElementType(); | 1923 | const child_qt = arr_type.getElementType(); |
| 2093 | const init_count = expr.getNumInits(); | 1924 | const init_count = expr.getNumInits(); |
| ... | @@ -2098,111 +1929,67 @@ fn transInitListExprArray( | ... | @@ -2098,111 +1929,67 @@ fn transInitListExprArray( |
| 2098 | const leftover_count = all_count - init_count; | 1929 | const leftover_count = all_count - init_count; |
| 2099 | | 1930 | |
| 2100 | if (all_count == 0) { | 1931 | if (all_count == 0) { |
| 2101 | return transCreateEmptyArray(rp, loc, child_qt.getTypePtr()); | 1932 | return Node.empty_array.create(c.arena, try transQualType(c, child_qt, source_loc)); |
| 2102 | } | 1933 | } |
| | 1934 | |
| | 1935 | const ty_node = try transType(ty); |
| | 1936 | const init_node = if (init_count != 0) blk: { |
| | 1937 | const init_list = try c.arena.alloc(Node, init_count); |
| 2103 | | 1938 | |
| 2104 | var init_node: *ast.Node.ArrayInitializer = undefined; | 1939 | for (init_list) |*init, i| { |
| 2105 | var cat_tok: ast.TokenIndex = undefined; | | |
| 2106 | if (init_count != 0) { | | |
| 2107 | const ty_node = try transCreateNodeArrayType( | | |
| 2108 | rp, | | |
| 2109 | loc, | | |
| 2110 | child_qt.getTypePtr(), | | |
| 2111 | init_count, | | |
| 2112 | ); | | |
| 2113 | _ = try appendToken(rp.c, .LBrace, "{"); | | |
| 2114 | init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, init_count); | | |
| 2115 | init_node.* = .{ | | |
| 2116 | .lhs = ty_node, | | |
| 2117 | .rtoken = undefined, | | |
| 2118 | .list_len = init_count, | | |
| 2119 | }; | | |
| 2120 | const init_list = init_node.list(); | | |
| 2121 | | | |
| 2122 | var i: c_uint = 0; | | |
| 2123 | while (i < init_count) : (i += 1) { | | |
| 2124 | const elem_expr = expr.getInit(i); | 1940 | const elem_expr = expr.getInit(i); |
| 2125 | init_list[i] = try transExpr(rp, scope, elem_expr, .used, .r_value); | 1941 | init.* = try transExpr(c, scope, elem_expr, .used, .r_value); |
| 2126 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 2127 | } | 1942 | } |
| 2128 | init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); | 1943 | const init_node = try Node.array_init.create(c.arena, init_list); |
| 2129 | if (leftover_count == 0) { | 1944 | if (leftover_count == 0) { |
| 2130 | return &init_node.base; | 1945 | return init_node; |
| 2131 | } | 1946 | } |
| 2132 | cat_tok = try appendToken(rp.c, .PlusPlus, "++"); | 1947 | break :blk init_node; |
| 2133 | } | 1948 | } else null; |
| 2134 | | 1949 | |
| 2135 | const ty_node = try transCreateNodeArrayType(rp, loc, child_qt.getTypePtr(), 1); | | |
| 2136 | _ = try appendToken(rp.c, .LBrace, "{"); | | |
| 2137 | const filler_init_node = try ast.Node.ArrayInitializer.alloc(rp.c.arena, 1); | | |
| 2138 | filler_init_node.* = .{ | | |
| 2139 | .lhs = ty_node, | | |
| 2140 | .rtoken = undefined, | | |
| 2141 | .list_len = 1, | | |
| 2142 | }; | | |
| 2143 | const filler_val_expr = expr.getArrayFiller(); | 1950 | const filler_val_expr = expr.getArrayFiller(); |
| 2144 | filler_init_node.list()[0] = try transExpr(rp, scope, filler_val_expr, .used, .r_value); | 1951 | const filler_node = try Node.array_filler.create(c.arena, .{ |
| 2145 | filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); | 1952 | .type = ty_node, |
| 2146 | | 1953 | .filler = try transExpr(c, scope, filler_val_expr, .used, .r_value), |
| 2147 | const rhs_node = if (leftover_count == 1) | 1954 | .count = leftover_count, |
| 2148 | &filler_init_node.base | 1955 | }); |
| 2149 | else blk: { | | |
| 2150 | const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**"); | | |
| 2151 | const mul_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); | | |
| 2152 | mul_node.* = .{ | | |
| 2153 | .base = .{ .tag = .ArrayMult }, | | |
| 2154 | .op_token = mul_tok, | | |
| 2155 | .lhs = &filler_init_node.base, | | |
| 2156 | .rhs = try transCreateNodeInt(rp.c, leftover_count), | | |
| 2157 | }; | | |
| 2158 | break :blk &mul_node.base; | | |
| 2159 | }; | | |
| 2160 | | 1956 | |
| 2161 | if (init_count == 0) { | 1957 | if (init_node) |some| { |
| 2162 | return rhs_node; | 1958 | return Node.array_cat.create(c.arena, some, filler_node); |
| | 1959 | } else { |
| | 1960 | return filler_node; |
| 2163 | } | 1961 | } |
| 2164 | | | |
| 2165 | const cat_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); | | |
| 2166 | cat_node.* = .{ | | |
| 2167 | .base = .{ .tag = .ArrayCat }, | | |
| 2168 | .op_token = cat_tok, | | |
| 2169 | .lhs = &init_node.base, | | |
| 2170 | .rhs = rhs_node, | | |
| 2171 | }; | | |
| 2172 | return &cat_node.base; | | |
| 2173 | } | 1962 | } |
| 2174 | | 1963 | |
| 2175 | fn transInitListExpr( | 1964 | fn transInitListExpr( |
| 2176 | rp: RestorePoint, | 1965 | c: *Context, |
| 2177 | scope: *Scope, | 1966 | scope: *Scope, |
| 2178 | expr: *const clang.InitListExpr, | 1967 | expr: *const clang.InitListExpr, |
| 2179 | used: ResultUsed, | 1968 | used: ResultUsed, |
| 2180 | ) TransError!*ast.Node { | 1969 | ) TransError!Node { |
| 2181 | const qt = getExprQualType(rp.c, @ptrCast(*const clang.Expr, expr)); | 1970 | const qt = getExprQualType(c, @ptrCast(*const clang.Expr, expr)); |
| 2182 | var qual_type = qt.getTypePtr(); | 1971 | var qual_type = qt.getTypePtr(); |
| 2183 | const source_loc = @ptrCast(*const clang.Expr, expr).getBeginLoc(); | 1972 | const source_loc = @ptrCast(*const clang.Expr, expr).getBeginLoc(); |
| 2184 | | 1973 | |
| 2185 | if (qual_type.isRecordType()) { | 1974 | if (qual_type.isRecordType()) { |
| 2186 | return transInitListExprRecord( | 1975 | return maybeSuppressResult(c, scope, used, try transInitListExprRecord( |
| 2187 | rp, | 1976 | rp, |
| 2188 | scope, | 1977 | scope, |
| 2189 | source_loc, | 1978 | source_loc, |
| 2190 | expr, | 1979 | expr, |
| 2191 | qual_type, | 1980 | qual_type, |
| 2192 | used, | 1981 | )); |
| 2193 | ); | | |
| 2194 | } else if (qual_type.isArrayType()) { | 1982 | } else if (qual_type.isArrayType()) { |
| 2195 | return transInitListExprArray( | 1983 | return maybeSuppressResult(c, scope, used, try transInitListExprArray( |
| 2196 | rp, | 1984 | rp, |
| 2197 | scope, | 1985 | scope, |
| 2198 | source_loc, | 1986 | source_loc, |
| 2199 | expr, | 1987 | expr, |
| 2200 | qual_type, | 1988 | qual_type, |
| 2201 | used, | 1989 | )); |
| 2202 | ); | | |
| 2203 | } else { | 1990 | } else { |
| 2204 | const type_name = rp.c.str(qual_type.getTypeClassName()); | 1991 | const type_name = c.str(qual_type.getTypeClassName()); |
| 2205 | return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name}); | 1992 | return fail(c, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name}); |
| 2206 | } | 1993 | } |
| 2207 | } | 1994 | } |
| 2208 | | 1995 | |
| ... | @@ -2259,15 +2046,15 @@ fn transZeroInitExpr( | ... | @@ -2259,15 +2046,15 @@ fn transZeroInitExpr( |
| 2259 | } | 2046 | } |
| 2260 | | 2047 | |
| 2261 | fn transImplicitValueInitExpr( | 2048 | fn transImplicitValueInitExpr( |
| 2262 | rp: RestorePoint, | 2049 | c: *Context, |
| 2263 | scope: *Scope, | 2050 | scope: *Scope, |
| 2264 | expr: *const clang.Expr, | 2051 | expr: *const clang.Expr, |
| 2265 | used: ResultUsed, | 2052 | used: ResultUsed, |
| 2266 | ) TransError!*ast.Node { | 2053 | ) TransError!Node { |
| 2267 | const source_loc = expr.getBeginLoc(); | 2054 | const source_loc = expr.getBeginLoc(); |
| 2268 | const qt = getExprQualType(rp.c, expr); | 2055 | const qt = getExprQualType(c, expr); |
| 2269 | const ty = qt.getTypePtr(); | 2056 | const ty = qt.getTypePtr(); |
| 2270 | return transZeroInitExpr(rp, scope, source_loc, ty); | 2057 | return transZeroInitExpr(c, scope, source_loc, ty); |
| 2271 | } | 2058 | } |
| 2272 | | 2059 | |
| 2273 | fn transIfStmt( | 2060 | fn transIfStmt( |