| ... | @@ -522,7 +522,18 @@ static AstNode *trans_create_node_apint(Context *c, const ZigClangAPSInt *aps_in | ... | @@ -522,7 +522,18 @@ static AstNode *trans_create_node_apint(Context *c, const ZigClangAPSInt *aps_in |
| 522 | ZigClangAPSInt_getNumWords(negated), true); | 522 | ZigClangAPSInt_getNumWords(negated), true); |
| 523 | ZigClangAPSInt_free(negated); | 523 | ZigClangAPSInt_free(negated); |
| 524 | return node; | 524 | return node; |
| | 525 | } |
| 525 | | 526 | |
| | 527 | static AstNode *trans_create_node_apfloat(Context *c, const llvm::APFloat &ap_float) { |
| | 528 | uint8_t buf[128]; |
| | 529 | size_t written = ap_float.convertToHexString((char *)buf, 0, false, |
| | 530 | llvm::APFloat::rmNearestTiesToEven); |
| | 531 | AstNode *node = trans_create_node(c, NodeTypeFloatLiteral); |
| | 532 | node->data.float_literal.bigfloat = allocate<BigFloat>(1); |
| | 533 | if (bigfloat_init_buf(node->data.float_literal.bigfloat, buf, written)) { |
| | 534 | node->data.float_literal.overflow = true; |
| | 535 | } |
| | 536 | return node; |
| 526 | } | 537 | } |
| 527 | | 538 | |
| 528 | static const ZigClangType *qual_type_canon(ZigClangQualType qt) { | 539 | static const ZigClangType *qual_type_canon(ZigClangQualType qt) { |
| ... | @@ -1313,6 +1324,46 @@ static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const | ... | @@ -1313,6 +1324,46 @@ static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const |
| 1313 | return maybe_suppress_result(c, result_used, node); | 1324 | return maybe_suppress_result(c, result_used, node); |
| 1314 | } | 1325 | } |
| 1315 | | 1326 | |
| | 1327 | static AstNode *trans_floating_literal(Context *c, ResultUsed result_used, const clang::FloatingLiteral *stmt) { |
| | 1328 | llvm::APFloat result{0.0f}; |
| | 1329 | if (!stmt->EvaluateAsFloat(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) { |
| | 1330 | emit_warning(c, bitcast(stmt->getBeginLoc()), "invalid floating literal"); |
| | 1331 | return nullptr; |
| | 1332 | } |
| | 1333 | AstNode *node = trans_create_node_apfloat(c, result); |
| | 1334 | return maybe_suppress_result(c, result_used, node); |
| | 1335 | } |
| | 1336 | |
| | 1337 | static AstNode *trans_character_literal(Context *c, ResultUsed result_used, const clang::CharacterLiteral *stmt) { |
| | 1338 | switch (stmt->getKind()) { |
| | 1339 | case clang::CharacterLiteral::CharacterKind::Ascii: |
| | 1340 | { |
| | 1341 | unsigned val = stmt->getValue(); |
| | 1342 | // C has a somewhat obscure feature called multi-character character |
| | 1343 | // constant |
| | 1344 | if (val > 255) |
| | 1345 | return trans_create_node_unsigned(c, val); |
| | 1346 | } |
| | 1347 | // fallthrough |
| | 1348 | case clang::CharacterLiteral::CharacterKind::UTF8: |
| | 1349 | { |
| | 1350 | AstNode *node = trans_create_node(c, NodeTypeCharLiteral); |
| | 1351 | node->data.char_literal.value = stmt->getValue(); |
| | 1352 | return maybe_suppress_result(c, result_used, node); |
| | 1353 | } |
| | 1354 | case clang::CharacterLiteral::CharacterKind::UTF16: |
| | 1355 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF16 character literals"); |
| | 1356 | return nullptr; |
| | 1357 | case clang::CharacterLiteral::CharacterKind::UTF32: |
| | 1358 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support UTF32 character literals"); |
| | 1359 | return nullptr; |
| | 1360 | case clang::CharacterLiteral::CharacterKind::Wide: |
| | 1361 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO support wide character literals"); |
| | 1362 | return nullptr; |
| | 1363 | } |
| | 1364 | zig_unreachable(); |
| | 1365 | } |
| | 1366 | |
| 1316 | static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const clang::ConstantExpr *expr) { | 1367 | static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const clang::ConstantExpr *expr) { |
| 1317 | clang::Expr::EvalResult result; | 1368 | clang::Expr::EvalResult result; |
| 1318 | if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen, | 1369 | if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen, |
| ... | @@ -1896,15 +1947,21 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra | ... | @@ -1896,15 +1947,21 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra |
| 1896 | case ZigClangCK_ConstructorConversion: | 1947 | case ZigClangCK_ConstructorConversion: |
| 1897 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ConstructorConversion"); | 1948 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ConstructorConversion"); |
| 1898 | return nullptr; | 1949 | return nullptr; |
| 1899 | case ZigClangCK_IntegralToPointer: | | |
| 1900 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToPointer"); | | |
| 1901 | return nullptr; | | |
| 1902 | case ZigClangCK_PointerToIntegral: | | |
| 1903 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_PointerToIntegral"); | | |
| 1904 | return nullptr; | | |
| 1905 | case ZigClangCK_PointerToBoolean: | 1950 | case ZigClangCK_PointerToBoolean: |
| 1906 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_PointerToBoolean"); | 1951 | { |
| 1907 | return nullptr; | 1952 | const clang::Expr *expr = stmt->getSubExpr(); |
| | 1953 | AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue); |
| | 1954 | if (val == nullptr) |
| | 1955 | return nullptr; |
| | 1956 | |
| | 1957 | AstNode *val_ptr = trans_create_node_builtin_fn_call_str(c, "ptrToInt"); |
| | 1958 | val_ptr->data.fn_call_expr.params.append(val); |
| | 1959 | |
| | 1960 | AstNode *zero = trans_create_node_unsigned(c, 0); |
| | 1961 | |
| | 1962 | // Translate as @ptrToInt((&val) != 0) |
| | 1963 | return trans_create_node_bin_op(c, val_ptr, BinOpTypeCmpNotEq, zero); |
| | 1964 | } |
| 1908 | case ZigClangCK_ToVoid: | 1965 | case ZigClangCK_ToVoid: |
| 1909 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ToVoid"); | 1966 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_ToVoid"); |
| 1910 | return nullptr; | 1967 | return nullptr; |
| ... | @@ -1912,20 +1969,83 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra | ... | @@ -1912,20 +1969,83 @@ static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, Tra |
| 1912 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_VectorSplat"); | 1969 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_VectorSplat"); |
| 1913 | return nullptr; | 1970 | return nullptr; |
| 1914 | case ZigClangCK_IntegralToBoolean: | 1971 | case ZigClangCK_IntegralToBoolean: |
| 1915 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToBoolean"); | 1972 | { |
| 1916 | return nullptr; | 1973 | const clang::Expr *expr = stmt->getSubExpr(); |
| | 1974 | |
| | 1975 | bool expr_val; |
| | 1976 | if (expr->EvaluateAsBooleanCondition(expr_val, *reinterpret_cast<clang::ASTContext *>(c->ctx))) { |
| | 1977 | return trans_create_node_bool(c, expr_val); |
| | 1978 | } |
| | 1979 | |
| | 1980 | AstNode *val = trans_expr(c, ResultUsedYes, scope, bitcast(expr), TransRValue); |
| | 1981 | if (val == nullptr) |
| | 1982 | return nullptr; |
| | 1983 | |
| | 1984 | AstNode *zero = trans_create_node_unsigned(c, 0); |
| | 1985 | |
| | 1986 | // Translate as val != 0 |
| | 1987 | return trans_create_node_bin_op(c, val, BinOpTypeCmpNotEq, zero); |
| | 1988 | } |
| | 1989 | case ZigClangCK_PointerToIntegral: |
| | 1990 | { |
| | 1991 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue); |
| | 1992 | if (target_node == nullptr) |
| | 1993 | return nullptr; |
| | 1994 | |
| | 1995 | AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt); |
| | 1996 | if (dest_type_node == nullptr) |
| | 1997 | return nullptr; |
| | 1998 | |
| | 1999 | AstNode *val_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt"); |
| | 2000 | val_node->data.fn_call_expr.params.append(target_node); |
| | 2001 | // @ptrToInt always returns a usize |
| | 2002 | AstNode *node = trans_create_node_builtin_fn_call_str(c, "intCast"); |
| | 2003 | node->data.fn_call_expr.params.append(dest_type_node); |
| | 2004 | node->data.fn_call_expr.params.append(val_node); |
| | 2005 | |
| | 2006 | return maybe_suppress_result(c, result_used, node); |
| | 2007 | } |
| | 2008 | case ZigClangCK_IntegralToPointer: |
| | 2009 | { |
| | 2010 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue); |
| | 2011 | if (target_node == nullptr) |
| | 2012 | return nullptr; |
| | 2013 | |
| | 2014 | AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt); |
| | 2015 | if (dest_type_node == nullptr) |
| | 2016 | return nullptr; |
| | 2017 | |
| | 2018 | AstNode *node = trans_create_node_builtin_fn_call_str(c, "intToPtr"); |
| | 2019 | node->data.fn_call_expr.params.append(dest_type_node); |
| | 2020 | node->data.fn_call_expr.params.append(target_node); |
| | 2021 | |
| | 2022 | return maybe_suppress_result(c, result_used, node); |
| | 2023 | } |
| 1917 | case ZigClangCK_IntegralToFloating: | 2024 | case ZigClangCK_IntegralToFloating: |
| 1918 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_IntegralToFloating"); | 2025 | case ZigClangCK_FloatingToIntegral: |
| 1919 | return nullptr; | 2026 | { |
| | 2027 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, bitcast(stmt->getSubExpr()), TransRValue); |
| | 2028 | if (target_node == nullptr) |
| | 2029 | return nullptr; |
| | 2030 | |
| | 2031 | AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt); |
| | 2032 | if (dest_type_node == nullptr) |
| | 2033 | return nullptr; |
| | 2034 | |
| | 2035 | char const *fn = (ZigClangCK)stmt->getCastKind() == ZigClangCK_IntegralToFloating ? |
| | 2036 | "intToFloat" : "floatToInt"; |
| | 2037 | AstNode *node = trans_create_node_builtin_fn_call_str(c, fn); |
| | 2038 | node->data.fn_call_expr.params.append(dest_type_node); |
| | 2039 | node->data.fn_call_expr.params.append(target_node); |
| | 2040 | |
| | 2041 | return maybe_suppress_result(c, result_used, node); |
| | 2042 | } |
| 1920 | case ZigClangCK_FixedPointCast: | 2043 | case ZigClangCK_FixedPointCast: |
| 1921 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointCast"); | 2044 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointCast"); |
| 1922 | return nullptr; | 2045 | return nullptr; |
| 1923 | case ZigClangCK_FixedPointToBoolean: | 2046 | case ZigClangCK_FixedPointToBoolean: |
| 1924 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointToBoolean"); | 2047 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FixedPointToBoolean"); |
| 1925 | return nullptr; | 2048 | return nullptr; |
| 1926 | case ZigClangCK_FloatingToIntegral: | | |
| 1927 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToIntegral"); | | |
| 1928 | return nullptr; | | |
| 1929 | case ZigClangCK_FloatingToBoolean: | 2049 | case ZigClangCK_FloatingToBoolean: |
| 1930 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToBoolean"); | 2050 | emit_warning(c, bitcast(stmt->getBeginLoc()), "TODO handle C CK_FloatingToBoolean"); |
| 1931 | return nullptr; | 2051 | return nullptr; |
| ... | @@ -3498,7 +3618,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s | ... | @@ -3498,7 +3618,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s |
| 3498 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBridgedCastExprClass"); | 3618 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBridgedCastExprClass"); |
| 3499 | return ErrorUnexpected; | 3619 | return ErrorUnexpected; |
| 3500 | case ZigClangStmt_CharacterLiteralClass: | 3620 | case ZigClangStmt_CharacterLiteralClass: |
| 3501 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CharacterLiteralClass"); | 3621 | return wrap_stmt(out_node, out_child_scope, scope, |
| | 3622 | trans_character_literal(c, result_used, (const clang::CharacterLiteral *)stmt)); |
| 3502 | return ErrorUnexpected; | 3623 | return ErrorUnexpected; |
| 3503 | case ZigClangStmt_ChooseExprClass: | 3624 | case ZigClangStmt_ChooseExprClass: |
| 3504 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ChooseExprClass"); | 3625 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ChooseExprClass"); |
| ... | @@ -3537,8 +3658,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s | ... | @@ -3537,8 +3658,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *s |
| 3537 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FixedPointLiteralClass"); | 3658 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FixedPointLiteralClass"); |
| 3538 | return ErrorUnexpected; | 3659 | return ErrorUnexpected; |
| 3539 | case ZigClangStmt_FloatingLiteralClass: | 3660 | case ZigClangStmt_FloatingLiteralClass: |
| 3540 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FloatingLiteralClass"); | 3661 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3541 | return ErrorUnexpected; | 3662 | trans_floating_literal(c, result_used, (const clang::FloatingLiteral *)stmt)); |
| 3542 | case ZigClangStmt_ExprWithCleanupsClass: | 3663 | case ZigClangStmt_ExprWithCleanupsClass: |
| 3543 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExprWithCleanupsClass"); | 3664 | emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExprWithCleanupsClass"); |
| 3544 | return ErrorUnexpected; | 3665 | return ErrorUnexpected; |