| ... | ... | @@ -1084,7 +1084,6 @@ fn transStmt( |
| 1084 | 1084 | const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?; |
| 1085 | 1085 | const expr = try transExpr(c, scope, source_expr, .used, lrvalue); |
| 1086 | 1086 | return maybeSuppressResult(c, scope, result_used, expr); |
| 1087 | | const node = try c.arena.create(Node.GroupedExpression); |
| 1088 | 1087 | }, |
| 1089 | 1088 | else => { |
| 1090 | 1089 | return revertAndWarn( |
| ... | ... | @@ -1389,62 +1388,56 @@ fn transDeclRefExpr( |
| 1389 | 1388 | } |
| 1390 | 1389 | |
| 1391 | 1390 | fn transImplicitCastExpr( |
| 1392 | | rp: RestorePoint, |
| 1391 | c: *Context, |
| 1393 | 1392 | scope: *Scope, |
| 1394 | 1393 | expr: *const clang.ImplicitCastExpr, |
| 1395 | 1394 | result_used: ResultUsed, |
| 1396 | | ) TransError!*ast.Node { |
| 1397 | | const c = rp.c; |
| 1395 | ) TransError!Node { |
| 1398 | 1396 | const sub_expr = expr.getSubExpr(); |
| 1399 | 1397 | const dest_type = getExprQualType(c, @ptrCast(*const clang.Expr, expr)); |
| 1400 | 1398 | const src_type = getExprQualType(c, sub_expr); |
| 1401 | 1399 | switch (expr.getCastKind()) { |
| 1402 | 1400 | .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => { |
| 1403 | | const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); |
| 1404 | | return try transCCast(rp, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node); |
| 1401 | const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); |
| 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 | 1405 | .LValueToRValue, .NoOp, .FunctionToPointerDecay => { |
| 1407 | | const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); |
| 1408 | | return maybeSuppressResult(rp, scope, result_used, sub_expr_node); |
| 1406 | const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); |
| 1407 | return maybeSuppressResult(c, scope, result_used, sub_expr_node); |
| 1409 | 1408 | }, |
| 1410 | 1409 | .ArrayToPointerDecay => { |
| 1411 | 1410 | if (exprIsNarrowStringLiteral(sub_expr)) { |
| 1412 | | const sub_expr_node = try transExpr(rp, scope, sub_expr, .used, .r_value); |
| 1413 | | return maybeSuppressResult(rp, scope, result_used, sub_expr_node); |
| 1411 | const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value); |
| 1412 | return maybeSuppressResult(c, scope, result_used, sub_expr_node); |
| 1414 | 1413 | } |
| 1415 | 1414 | |
| 1416 | | const prefix_op = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); |
| 1417 | | prefix_op.rhs = try transExpr(rp, scope, sub_expr, .used, .r_value); |
| 1418 | | |
| 1419 | | return maybeSuppressResult(rp, scope, result_used, &prefix_op.base); |
| 1415 | const addr = try Node.address_of.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value)); |
| 1416 | return maybeSuppressResult(c, scope, result_used, addr); |
| 1420 | 1417 | }, |
| 1421 | 1418 | .NullToPointer => { |
| 1422 | | return try transCreateNodeNullLiteral(rp.c); |
| 1419 | return Node.null_literal.init(); |
| 1423 | 1420 | }, |
| 1424 | 1421 | .PointerToBoolean => { |
| 1425 | 1422 | // @ptrToInt(val) != 0 |
| 1426 | | const ptr_to_int = try rp.c.createBuiltinCall("@ptrToInt", 1); |
| 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, ")"); |
| 1423 | const ptr_to_int = try Node.ptr_to_int.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value)); |
| 1429 | 1424 | |
| 1430 | | const op_token = try appendToken(rp.c, .BangEqual, "!="); |
| 1431 | | const rhs_node = try transCreateNodeInt(rp.c, 0); |
| 1432 | | return transCreateNodeInfixOp(rp, scope, &ptr_to_int.base, .BangEqual, op_token, rhs_node, result_used, false); |
| 1425 | const ne = try Node.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Node.zero_literal.init() }); |
| 1426 | return maybeSuppressResult(c, scope, result_used, ne); |
| 1433 | 1427 | }, |
| 1434 | 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 | 1431 | // The expression is already a boolean one, return it as-is |
| 1438 | 1432 | if (isBoolRes(sub_expr_node)) |
| 1439 | | return sub_expr_node; |
| 1433 | return maybeSuppressResult(c, scope, result_used, sub_expr_node); |
| 1440 | 1434 | |
| 1441 | 1435 | // val != 0 |
| 1442 | | const op_token = try appendToken(rp.c, .BangEqual, "!="); |
| 1443 | | const rhs_node = try transCreateNodeInt(rp.c, 0); |
| 1444 | | return transCreateNodeInfixOp(rp, scope, sub_expr_node, .BangEqual, op_token, rhs_node, result_used, false); |
| 1436 | const ne = try Node.not_equal.create(c.arena, .{ .lhs = sub_expr_node, .rhs = Node.zero_literal.init() }); |
| 1437 | return maybeSuppressResult(c, scope, result_used, ne); |
| 1445 | 1438 | }, |
| 1446 | 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 | 1442 | else => |kind| return revertAndWarn( |
| 1450 | 1443 | rp, |
| ... | ... | @@ -1468,12 +1461,12 @@ fn transBoolExpr( |
| 1468 | 1461 | if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) { |
| 1469 | 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 | 1467 | var res = try transExpr(c, scope, expr, used, lrvalue); |
| 1475 | 1468 | if (isBoolRes(res)) { |
| 1476 | | return res; |
| 1469 | return maybeSuppressResult(c, scope, used, res); |
| 1477 | 1470 | } |
| 1478 | 1471 | |
| 1479 | 1472 | const ty = getExprQualType(c, expr).getTypePtr(); |
| ... | ... | @@ -1563,18 +1556,18 @@ fn finishBoolExpr( |
| 1563 | 1556 | .Float16, |
| 1564 | 1557 | => { |
| 1565 | 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 | 1561 | .NullPtr => { |
| 1569 | 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 | 1565 | else => {}, |
| 1573 | 1566 | } |
| 1574 | 1567 | }, |
| 1575 | 1568 | .Pointer => { |
| 1576 | 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 | 1572 | .Typedef => { |
| 1580 | 1573 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); |
| ... | ... | @@ -1584,7 +1577,7 @@ fn finishBoolExpr( |
| 1584 | 1577 | }, |
| 1585 | 1578 | .Enum => { |
| 1586 | 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 | 1581 | const op_token = try appendToken(c, .BangEqual, "!="); |
| 1589 | 1582 | }, |
| 1590 | 1583 | .Elaborated => { |
| ... | ... | @@ -1653,11 +1646,11 @@ fn transReturnStmt( |
| 1653 | 1646 | } |
| 1654 | 1647 | |
| 1655 | 1648 | fn transStringLiteral( |
| 1656 | | rp: RestorePoint, |
| 1649 | c: *Context, |
| 1657 | 1650 | scope: *Scope, |
| 1658 | 1651 | stmt: *const clang.StringLiteral, |
| 1659 | 1652 | result_used: ResultUsed, |
| 1660 | | ) TransError!*ast.Node { |
| 1653 | ) TransError!Node { |
| 1661 | 1654 | const kind = stmt.getKind(); |
| 1662 | 1655 | switch (kind) { |
| 1663 | 1656 | .Ascii, .UTF8 => { |
| ... | ... | @@ -1665,55 +1658,28 @@ fn transStringLiteral( |
| 1665 | 1658 | const bytes_ptr = stmt.getString_bytes_begin_size(&len); |
| 1666 | 1659 | const str = bytes_ptr[0..len]; |
| 1667 | 1660 | |
| 1668 | | const token = try appendTokenFmt(rp.c, .StringLiteral, "\"{}\"", .{std.zig.fmtEscapes(str)}); |
| 1669 | | const node = try rp.c.arena.create(ast.Node.OneToken); |
| 1670 | | node.* = .{ |
| 1671 | | .base = .{ .tag = .StringLiteral }, |
| 1672 | | .token = token, |
| 1673 | | }; |
| 1674 | | return maybeSuppressResult(rp, scope, result_used, &node.base); |
| 1661 | const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(str)}); |
| 1662 | const node = try Node.string_literal.create(c.arena, str); |
| 1663 | return maybeSuppressResult(c, scope, result_used, node); |
| 1675 | 1664 | }, |
| 1676 | 1665 | .UTF16, .UTF32, .Wide => { |
| 1677 | | const node = try transWideStringLiteral(rp, scope, stmt); |
| 1678 | | return maybeSuppressResult(rp, scope, result_used, node); |
| 1666 | const str_type = @tagName(stmt.getKind()); |
| 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 | 1678 | /// Parse the size of an array back out from an ast Node. |
| 1712 | | fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { |
| 1713 | | if (node.castTag(.ArrayType)) |array| { |
| 1714 | | if (array.len_expr.castTag(.IntegerLiteral)) |int_lit| { |
| 1715 | | const tok = tokenSlice(c, int_lit.token); |
| 1716 | | return std.fmt.parseUnsigned(usize, tok, 10) catch error.UnsupportedTranslation; |
| 1679 | fn zigArraySize(c: *Context, node: Node) TransError!usize { |
| 1680 | if (node.castTag(.array_type)) |array| { |
| 1681 | if (array.data.len.castTag(.int_literal)) |int_lit| { |
| 1682 | return std.fmt.parseUnsigned(usize, int_lit.data, 10) catch error.UnsupportedTranslation; |
| 1717 | 1683 | } |
| 1718 | 1684 | } |
| 1719 | 1685 | return error.UnsupportedTranslation; |
| ... | ... | @@ -1725,11 +1691,11 @@ fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { |
| 1725 | 1691 | /// than the array, truncate the string. If the array is larger than the |
| 1726 | 1692 | /// string literal, pad the array with 0's |
| 1727 | 1693 | fn transStringLiteralAsArray( |
| 1728 | | rp: RestorePoint, |
| 1694 | c: *Context, |
| 1729 | 1695 | scope: *Scope, |
| 1730 | 1696 | stmt: *const clang.StringLiteral, |
| 1731 | 1697 | array_size: usize, |
| 1732 | | ) TransError!*ast.Node { |
| 1698 | ) TransError!Node { |
| 1733 | 1699 | if (array_size == 0) return error.UnsupportedType; |
| 1734 | 1700 | |
| 1735 | 1701 | const str_length = stmt.getLength(); |
| ... | ... | @@ -1738,40 +1704,21 @@ fn transStringLiteralAsArray( |
| 1738 | 1704 | const ty = expr_base.getType().getTypePtr(); |
| 1739 | 1705 | const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty); |
| 1740 | 1706 | |
| 1741 | | const ty_node = try rp.c.arena.create(ast.Node.ArrayType); |
| 1742 | | const op_token = try appendToken(rp.c, .LBracket, "["); |
| 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(); |
| 1707 | const arr_type = try transQualType(c, const_arr_ty.getElementType(), expr_base.getBeginLoc()); |
| 1708 | const init_list = try c.arena.alloc(Node, array_size); |
| 1759 | 1709 | |
| 1760 | 1710 | var i: c_uint = 0; |
| 1761 | 1711 | const kind = stmt.getKind(); |
| 1762 | 1712 | const narrow = kind == .Ascii or kind == .UTF8; |
| 1763 | 1713 | while (i < str_length and i < array_size) : (i += 1) { |
| 1764 | 1714 | const code_unit = stmt.getCodeUnit(i); |
| 1765 | | init_list[i] = try transCreateCharLitNode(rp.c, narrow, code_unit); |
| 1766 | | _ = try appendToken(rp.c, .Comma, ","); |
| 1715 | init_list[i] = try transCreateCharLitNode(c, narrow, code_unit); |
| 1767 | 1716 | } |
| 1768 | 1717 | while (i < array_size) : (i += 1) { |
| 1769 | | init_list[i] = try transCreateNodeInt(rp.c, 0); |
| 1770 | | _ = try appendToken(rp.c, .Comma, ","); |
| 1718 | init_list[i] = try transCreateNodeInt(c, 0); |
| 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 | 1724 | fn cIsEnum(qt: clang.QualType) bool { |
| ... | ... | @@ -1790,152 +1737,87 @@ fn cIntTypeForEnum(enum_qt: clang.QualType) clang.QualType { |
| 1790 | 1737 | } |
| 1791 | 1738 | |
| 1792 | 1739 | fn transCCast( |
| 1793 | | rp: RestorePoint, |
| 1740 | c: *Context, |
| 1794 | 1741 | scope: *Scope, |
| 1795 | 1742 | loc: clang.SourceLocation, |
| 1796 | 1743 | dst_type: clang.QualType, |
| 1797 | 1744 | src_type: clang.QualType, |
| 1798 | | expr: *ast.Node, |
| 1799 | | ) !*ast.Node { |
| 1745 | expr: Node, |
| 1746 | ) !Node { |
| 1800 | 1747 | if (qualTypeCanon(dst_type).isVoidType()) return expr; |
| 1801 | 1748 | if (dst_type.eq(src_type)) return expr; |
| 1802 | 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 | 1753 | if (cIsInteger(dst_type) and (cIsInteger(src_type) or cIsEnum(src_type))) { |
| 1805 | 1754 | // 1. If src_type is an enum, determine the underlying signed int type |
| 1806 | 1755 | // 2. Extend or truncate without changing signed-ness. |
| 1807 | 1756 | // 3. Bit-cast to correct signed-ness |
| 1808 | 1757 | const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type); |
| 1809 | 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); |
| 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, ","); |
| 1759 | var src_int_expr = if (cIsInteger(src_type)) expr else Node.enum_to_int.create(c.arena, expr); |
| 1816 | 1760 | |
| 1817 | 1761 | if (isBoolRes(src_int_expr)) { |
| 1818 | | const bool_to_int_node = try rp.c.createBuiltinCall("@boolToInt", 1); |
| 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; |
| 1762 | src_int_expr = try Node.bool_to_int.create(c.arena, src_int_expr); |
| 1822 | 1763 | } |
| 1823 | 1764 | |
| 1824 | 1765 | switch (cIntTypeCmp(dst_type, src_int_type)) { |
| 1825 | 1766 | .lt => { |
| 1826 | 1767 | // @truncate(SameSignSmallerInt, src_int_expr) |
| 1827 | | const trunc_node = try rp.c.createBuiltinCall("@truncate", 2); |
| 1828 | | const ty_node = try transQualTypeIntWidthOf(rp.c, dst_type, src_type_is_signed); |
| 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; |
| 1768 | const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed); |
| 1769 | src_int_expr = try Node.truncate.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr }); |
| 1835 | 1770 | }, |
| 1836 | 1771 | .gt => { |
| 1837 | 1772 | // @as(SameSignBiggerInt, src_int_expr) |
| 1838 | | const as_node = try rp.c.createBuiltinCall("@as", 2); |
| 1839 | | const ty_node = try transQualTypeIntWidthOf(rp.c, dst_type, src_type_is_signed); |
| 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; |
| 1773 | const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed); |
| 1774 | src_int_expr = try Node.as.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr }); |
| 1846 | 1775 | }, |
| 1847 | 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, ")"); |
| 1852 | | return &cast_node.base; |
| 1780 | // @bitCast(dest_type, intermediate_value) |
| 1781 | return Node.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr }); |
| 1853 | 1782 | } |
| 1854 | 1783 | if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) { |
| 1855 | 1784 | // @intCast(dest_type, @ptrToInt(val)) |
| 1856 | | const cast_node = try rp.c.createBuiltinCall("@intCast", 2); |
| 1857 | | cast_node.params()[0] = try transQualType(rp, dst_type, loc); |
| 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; |
| 1785 | const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr); |
| 1786 | return Node.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int }); |
| 1865 | 1787 | } |
| 1866 | 1788 | if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) { |
| 1867 | 1789 | // @intToPtr(dest_type, val) |
| 1868 | | const builtin_node = try rp.c.createBuiltinCall("@intToPtr", 2); |
| 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; |
| 1790 | return Node.int_to_ptr.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1874 | 1791 | } |
| 1875 | 1792 | if (cIsFloating(src_type) and cIsFloating(dst_type)) { |
| 1876 | | const builtin_node = try rp.c.createBuiltinCall("@floatCast", 2); |
| 1877 | | builtin_node.params()[0] = try transQualType(rp, dst_type, loc); |
| 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; |
| 1793 | // @floatCast(dest_type, val) |
| 1794 | return Node.float_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1882 | 1795 | } |
| 1883 | 1796 | if (cIsFloating(src_type) and !cIsFloating(dst_type)) { |
| 1884 | | const builtin_node = try rp.c.createBuiltinCall("@floatToInt", 2); |
| 1885 | | builtin_node.params()[0] = try transQualType(rp, dst_type, loc); |
| 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; |
| 1797 | // @floatToInt(dest_type, val) |
| 1798 | return Node.float_to_int.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1890 | 1799 | } |
| 1891 | 1800 | if (!cIsFloating(src_type) and cIsFloating(dst_type)) { |
| 1892 | | const builtin_node = try rp.c.createBuiltinCall("@intToFloat", 2); |
| 1893 | | builtin_node.params()[0] = try transQualType(rp, dst_type, loc); |
| 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; |
| 1801 | // @intToFloat(dest_type, val) |
| 1802 | return Node.int_to_float.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1898 | 1803 | } |
| 1899 | 1804 | if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) { |
| 1900 | 1805 | // @boolToInt returns either a comptime_int or a u1 |
| 1901 | 1806 | // TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast |
| 1902 | 1807 | // instead of @as |
| 1903 | | const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1); |
| 1904 | | builtin_node.params()[0] = expr; |
| 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; |
| 1808 | const bool_to_int = Node.bool_to_int.create(c.arena, expr); |
| 1809 | return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int }); |
| 1914 | 1810 | } |
| 1915 | 1811 | if (cIsEnum(dst_type)) { |
| 1916 | | const builtin_node = try rp.c.createBuiltinCall("@intToEnum", 2); |
| 1917 | | builtin_node.params()[0] = try transQualType(rp, dst_type, loc); |
| 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; |
| 1812 | // @intToEnum(dest_type, val) |
| 1813 | return Node.int_to_enum.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1922 | 1814 | } |
| 1923 | 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); |
| 1927 | | cast_node.params()[0] = try transQualType(rp, dst_type, loc); |
| 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; |
| 1819 | // @as(dest_type, val) |
| 1820 | return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 1939 | 1821 | } |
| 1940 | 1822 | |
| 1941 | 1823 | fn transExpr( |
| ... | ... | @@ -1976,13 +1858,12 @@ fn transExprCoercing( |
| 1976 | 1858 | } |
| 1977 | 1859 | |
| 1978 | 1860 | fn transInitListExprRecord( |
| 1979 | | rp: RestorePoint, |
| 1861 | c: *Context, |
| 1980 | 1862 | scope: *Scope, |
| 1981 | 1863 | loc: clang.SourceLocation, |
| 1982 | 1864 | expr: *const clang.InitListExpr, |
| 1983 | 1865 | ty: *const clang.Type, |
| 1984 | | used: ResultUsed, |
| 1985 | | ) TransError!*ast.Node { |
| 1866 | ) TransError!Node { |
| 1986 | 1867 | var is_union_type = false; |
| 1987 | 1868 | // Unions and Structs are both represented as RecordDecl |
| 1988 | 1869 | const record_ty = ty.getAsRecordType() orelse |
| ... | ... | @@ -1994,13 +1875,11 @@ fn transInitListExprRecord( |
| 1994 | 1875 | const record_def = record_decl.getDefinition() orelse |
| 1995 | 1876 | unreachable; |
| 1996 | 1877 | |
| 1997 | | const ty_node = try transType(rp, ty, loc); |
| 1878 | const ty_node = try transType(c, ty, loc); |
| 1998 | 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 | 1881 | defer field_inits.deinit(); |
| 2001 | 1882 | |
| 2002 | | _ = try appendToken(rp.c, .LBrace, "{"); |
| 2003 | | |
| 2004 | 1883 | var init_i: c_uint = 0; |
| 2005 | 1884 | var it = record_def.field_begin(); |
| 2006 | 1885 | const end_it = record_def.field_end(); |
| ... | ... | @@ -2018,76 +1897,28 @@ fn transInitListExprRecord( |
| 2018 | 1897 | |
| 2019 | 1898 | // Generate the field assignment expression: |
| 2020 | 1899 | // .field_name = expr |
| 2021 | | const period_tok = try appendToken(rp.c, .Period, "."); |
| 2022 | | |
| 2023 | | var raw_name = try rp.c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin()); |
| 1900 | var raw_name = try c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin()); |
| 2024 | 1901 | if (field_decl.isAnonymousStructOrUnion()) { |
| 2025 | | const name = rp.c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?; |
| 2026 | | raw_name = try mem.dupe(rp.c.arena, u8, name); |
| 1902 | const name = c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?; |
| 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); |
| 2040 | | _ = try appendToken(rp.c, .Comma, ","); |
| 1906 | try field_inits.append(.{ |
| 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); |
| 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; |
| 1912 | return Node.container_init.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items)); |
| 2081 | 1913 | } |
| 2082 | 1914 | |
| 2083 | 1915 | fn transInitListExprArray( |
| 2084 | | rp: RestorePoint, |
| 1916 | c: *Context, |
| 2085 | 1917 | scope: *Scope, |
| 2086 | 1918 | loc: clang.SourceLocation, |
| 2087 | 1919 | expr: *const clang.InitListExpr, |
| 2088 | 1920 | ty: *const clang.Type, |
| 2089 | | used: ResultUsed, |
| 2090 | | ) TransError!*ast.Node { |
| 1921 | ) TransError!Node { |
| 2091 | 1922 | const arr_type = ty.getAsArrayTypeUnsafe(); |
| 2092 | 1923 | const child_qt = arr_type.getElementType(); |
| 2093 | 1924 | const init_count = expr.getNumInits(); |
| ... | ... | @@ -2098,111 +1929,67 @@ fn transInitListExprArray( |
| 2098 | 1929 | const leftover_count = all_count - init_count; |
| 2099 | 1930 | |
| 2100 | 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; |
| 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) { |
| 1939 | for (init_list) |*init, i| { |
| 2124 | 1940 | const elem_expr = expr.getInit(i); |
| 2125 | | init_list[i] = try transExpr(rp, scope, elem_expr, .used, .r_value); |
| 2126 | | _ = try appendToken(rp.c, .Comma, ","); |
| 1941 | init.* = try transExpr(c, scope, elem_expr, .used, .r_value); |
| 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 | 1944 | if (leftover_count == 0) { |
| 2130 | | return &init_node.base; |
| 1945 | return init_node; |
| 2131 | 1946 | } |
| 2132 | | cat_tok = try appendToken(rp.c, .PlusPlus, "++"); |
| 2133 | | } |
| 1947 | break :blk init_node; |
| 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 | 1950 | const filler_val_expr = expr.getArrayFiller(); |
| 2144 | | filler_init_node.list()[0] = try transExpr(rp, scope, filler_val_expr, .used, .r_value); |
| 2145 | | filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}"); |
| 2146 | | |
| 2147 | | const rhs_node = if (leftover_count == 1) |
| 2148 | | &filler_init_node.base |
| 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 | | }; |
| 1951 | const filler_node = try Node.array_filler.create(c.arena, .{ |
| 1952 | .type = ty_node, |
| 1953 | .filler = try transExpr(c, scope, filler_val_expr, .used, .r_value), |
| 1954 | .count = leftover_count, |
| 1955 | }); |
| 2160 | 1956 | |
| 2161 | | if (init_count == 0) { |
| 2162 | | return rhs_node; |
| 1957 | if (init_node) |some| { |
| 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 | 1964 | fn transInitListExpr( |
| 2176 | | rp: RestorePoint, |
| 1965 | c: *Context, |
| 2177 | 1966 | scope: *Scope, |
| 2178 | 1967 | expr: *const clang.InitListExpr, |
| 2179 | 1968 | used: ResultUsed, |
| 2180 | | ) TransError!*ast.Node { |
| 2181 | | const qt = getExprQualType(rp.c, @ptrCast(*const clang.Expr, expr)); |
| 1969 | ) TransError!Node { |
| 1970 | const qt = getExprQualType(c, @ptrCast(*const clang.Expr, expr)); |
| 2182 | 1971 | var qual_type = qt.getTypePtr(); |
| 2183 | 1972 | const source_loc = @ptrCast(*const clang.Expr, expr).getBeginLoc(); |
| 2184 | 1973 | |
| 2185 | 1974 | if (qual_type.isRecordType()) { |
| 2186 | | return transInitListExprRecord( |
| 1975 | return maybeSuppressResult(c, scope, used, try transInitListExprRecord( |
| 2187 | 1976 | rp, |
| 2188 | 1977 | scope, |
| 2189 | 1978 | source_loc, |
| 2190 | 1979 | expr, |
| 2191 | 1980 | qual_type, |
| 2192 | | used, |
| 2193 | | ); |
| 1981 | )); |
| 2194 | 1982 | } else if (qual_type.isArrayType()) { |
| 2195 | | return transInitListExprArray( |
| 1983 | return maybeSuppressResult(c, scope, used, try transInitListExprArray( |
| 2196 | 1984 | rp, |
| 2197 | 1985 | scope, |
| 2198 | 1986 | source_loc, |
| 2199 | 1987 | expr, |
| 2200 | 1988 | qual_type, |
| 2201 | | used, |
| 2202 | | ); |
| 1989 | )); |
| 2203 | 1990 | } else { |
| 2204 | | const type_name = rp.c.str(qual_type.getTypeClassName()); |
| 2205 | | return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name}); |
| 1991 | const type_name = c.str(qual_type.getTypeClassName()); |
| 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 | 2046 | } |
| 2260 | 2047 | |
| 2261 | 2048 | fn transImplicitValueInitExpr( |
| 2262 | | rp: RestorePoint, |
| 2049 | c: *Context, |
| 2263 | 2050 | scope: *Scope, |
| 2264 | 2051 | expr: *const clang.Expr, |
| 2265 | 2052 | used: ResultUsed, |
| 2266 | | ) TransError!*ast.Node { |
| 2053 | ) TransError!Node { |
| 2267 | 2054 | const source_loc = expr.getBeginLoc(); |
| 2268 | | const qt = getExprQualType(rp.c, expr); |
| 2055 | const qt = getExprQualType(c, expr); |
| 2269 | 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 | 2060 | fn transIfStmt( |