| ... | @@ -440,6 +440,10 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) | ... | @@ -440,6 +440,10 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) |
| 440 | | 440 | |
| 441 | } | 441 | } |
| 442 | | 442 | |
| | 443 | static const Type *qual_type_canon(QualType qt) { |
| | 444 | return qt.getCanonicalType().getTypePtr(); |
| | 445 | } |
| | 446 | |
| 443 | static QualType get_expr_qual_type(Context *c, const Expr *expr) { | 447 | static QualType get_expr_qual_type(Context *c, const Expr *expr) { |
| 444 | // String literals in C are `char *` but they should really be `const char *`. | 448 | // String literals in C are `char *` but they should really be `const char *`. |
| 445 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { | 449 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { |
| ... | @@ -462,10 +466,7 @@ static AstNode *get_expr_type(Context *c, const Expr *expr) { | ... | @@ -462,10 +466,7 @@ static AstNode *get_expr_type(Context *c, const Expr *expr) { |
| 462 | return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart()); | 466 | return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart()); |
| 463 | } | 467 | } |
| 464 | | 468 | |
| 465 | static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) { | 469 | static bool qual_types_equal(QualType t1, QualType t2) { |
| 466 | QualType t1 = get_expr_qual_type(c, expr1); | | |
| 467 | QualType t2 = get_expr_qual_type(c, expr2); | | |
| 468 | | | |
| 469 | if (t1.isConstQualified() != t2.isConstQualified()) { | 470 | if (t1.isConstQualified() != t2.isConstQualified()) { |
| 470 | return false; | 471 | return false; |
| 471 | } | 472 | } |
| ... | @@ -482,26 +483,27 @@ static bool is_c_void_type(AstNode *node) { | ... | @@ -482,26 +483,27 @@ static bool is_c_void_type(AstNode *node) { |
| 482 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); | 483 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); |
| 483 | } | 484 | } |
| 484 | | 485 | |
| 485 | static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, const QualType &qt, AstNode *expr) { | 486 | static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) { |
| 486 | // TODO: maybe widen to increase size | 487 | QualType t1 = get_expr_qual_type(c, expr1); |
| 487 | // TODO: maybe bitcast to change sign | 488 | QualType t2 = get_expr_qual_type(c, expr2); |
| 488 | // TODO: maybe truncate to reduce size | 489 | |
| 489 | return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr); | 490 | return qual_types_equal(t1, t2); |
| 490 | } | 491 | } |
| 491 | | 492 | |
| 492 | static bool qual_type_is_fn_ptr(Context *c, const QualType &qt) { | 493 | static bool qual_type_is_ptr(QualType qt) { |
| 493 | const Type *ty = qt.getTypePtr(); | 494 | const Type *ty = qual_type_canon(qt); |
| | 495 | return ty->getTypeClass() == Type::Pointer; |
| | 496 | } |
| | 497 | |
| | 498 | static bool qual_type_is_fn_ptr(Context *c, QualType qt) { |
| | 499 | const Type *ty = qual_type_canon(qt); |
| 494 | if (ty->getTypeClass() != Type::Pointer) { | 500 | if (ty->getTypeClass() != Type::Pointer) { |
| 495 | return false; | 501 | return false; |
| 496 | } | 502 | } |
| 497 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | 503 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); |
| 498 | QualType child_qt = pointer_ty->getPointeeType(); | 504 | QualType child_qt = pointer_ty->getPointeeType(); |
| 499 | const Type *child_ty = child_qt.getTypePtr(); | 505 | const Type *child_ty = child_qt.getTypePtr(); |
| 500 | if (child_ty->getTypeClass() != Type::Paren) { | 506 | return child_ty->getTypeClass() == Type::FunctionProto; |
| 501 | return false; | | |
| 502 | } | | |
| 503 | const ParenType *paren_ty = static_cast<const ParenType *>(child_ty); | | |
| 504 | return paren_ty->getInnerType().getTypePtr()->getTypeClass() == Type::FunctionProto; | | |
| 505 | } | 507 | } |
| 506 | | 508 | |
| 507 | static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) { | 509 | static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) { |
| ... | @@ -594,17 +596,26 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) { | ... | @@ -594,17 +596,26 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) { |
| 594 | return false; | 596 | return false; |
| 595 | } | 597 | } |
| 596 | | 598 | |
| 597 | static QualType resolve_any_typedef(Context *c, QualType qt) { | 599 | static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, QualType dest_type, |
| 598 | const Type * ty = qt.getTypePtr(); | 600 | QualType src_type, AstNode *expr) |
| 599 | if (ty->getTypeClass() != Type::Typedef) | 601 | { |
| 600 | return qt; | 602 | if (qual_types_equal(dest_type, src_type)) { |
| 601 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | 603 | return expr; |
| 602 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | 604 | } |
| 603 | return typedef_decl->getUnderlyingType(); | 605 | if (qual_type_is_ptr(dest_type) && qual_type_is_ptr(src_type)) { |
| | 606 | AstNode *ptr_cast_node = trans_create_node_builtin_fn_call_str(c, "ptrCast"); |
| | 607 | ptr_cast_node->data.fn_call_expr.params.append(trans_qual_type(c, dest_type, source_location)); |
| | 608 | ptr_cast_node->data.fn_call_expr.params.append(expr); |
| | 609 | return ptr_cast_node; |
| | 610 | } |
| | 611 | // TODO: maybe widen to increase size |
| | 612 | // TODO: maybe bitcast to change sign |
| | 613 | // TODO: maybe truncate to reduce size |
| | 614 | return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr); |
| 604 | } | 615 | } |
| 605 | | 616 | |
| 606 | static bool c_is_signed_integer(Context *c, QualType qt) { | 617 | static bool c_is_signed_integer(Context *c, QualType qt) { |
| 607 | const Type *c_type = resolve_any_typedef(c, qt).getTypePtr(); | 618 | const Type *c_type = qual_type_canon(qt); |
| 608 | if (c_type->getTypeClass() != Type::Builtin) | 619 | if (c_type->getTypeClass() != Type::Builtin) |
| 609 | return false; | 620 | return false; |
| 610 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | 621 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); |
| ... | @@ -623,7 +634,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) { | ... | @@ -623,7 +634,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) { |
| 623 | } | 634 | } |
| 624 | | 635 | |
| 625 | static bool c_is_unsigned_integer(Context *c, QualType qt) { | 636 | static bool c_is_unsigned_integer(Context *c, QualType qt) { |
| 626 | const Type *c_type = resolve_any_typedef(c, qt).getTypePtr(); | 637 | const Type *c_type = qual_type_canon(qt); |
| 627 | if (c_type->getTypeClass() != Type::Builtin) | 638 | if (c_type->getTypeClass() != Type::Builtin) |
| 628 | return false; | 639 | return false; |
| 629 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | 640 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); |
| ... | @@ -891,6 +902,11 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou | ... | @@ -891,6 +902,11 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 891 | return nullptr; | 902 | return nullptr; |
| 892 | } | 903 | } |
| 893 | // convert c_void to actual void (only for return type) | 904 | // convert c_void to actual void (only for return type) |
| | 905 | // we do want to look at the AstNode instead of QualType, because |
| | 906 | // if they do something like: |
| | 907 | // typedef Foo void; |
| | 908 | // void foo(void) -> Foo; |
| | 909 | // we want to keep the return type AST node. |
| 894 | if (is_c_void_type(proto_node->data.fn_proto.return_type)) { | 910 | if (is_c_void_type(proto_node->data.fn_proto.return_type)) { |
| 895 | proto_node->data.fn_proto.return_type = nullptr; | 911 | proto_node->data.fn_proto.return_type = nullptr; |
| 896 | } | 912 | } |
| ... | @@ -1317,19 +1333,28 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result | ... | @@ -1317,19 +1333,28 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1317 | if (rhs == nullptr) return nullptr; | 1333 | if (rhs == nullptr) return nullptr; |
| 1318 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); | 1334 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1319 | | 1335 | |
| | 1336 | // operation_type(*_ref) |
| | 1337 | AstNode *operation_type_cast = trans_c_cast(c, rhs_location, |
| | 1338 | stmt->getComputationLHSType(), |
| | 1339 | stmt->getLHS()->getType(), |
| | 1340 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| | 1341 | trans_create_node_symbol(c, tmp_var_name))); |
| | 1342 | |
| | 1343 | // result_type(... >> u5(rhs)) |
| | 1344 | AstNode *result_type_cast = trans_c_cast(c, rhs_location, |
| | 1345 | stmt->getComputationResultType(), |
| | 1346 | stmt->getComputationLHSType(), |
| | 1347 | trans_create_node_bin_op(c, |
| | 1348 | operation_type_cast, |
| | 1349 | bin_op, |
| | 1350 | coerced_rhs)); |
| | 1351 | |
| | 1352 | // *_ref = ... |
| 1320 | AstNode *assign_statement = trans_create_node_bin_op(c, | 1353 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1321 | trans_create_node_prefix_op(c, PrefixOpDereference, | 1354 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1322 | trans_create_node_symbol(c, tmp_var_name)), | 1355 | trans_create_node_symbol(c, tmp_var_name)), |
| 1323 | BinOpTypeAssign, | 1356 | BinOpTypeAssign, result_type_cast); |
| 1324 | trans_c_cast(c, rhs_location, | 1357 | |
| 1325 | stmt->getComputationResultType(), | | |
| 1326 | trans_create_node_bin_op(c, | | |
| 1327 | trans_c_cast(c, rhs_location, | | |
| 1328 | stmt->getComputationLHSType(), | | |
| 1329 | trans_create_node_prefix_op(c, PrefixOpDereference, | | |
| 1330 | trans_create_node_symbol(c, tmp_var_name))), | | |
| 1331 | bin_op, | | |
| 1332 | coerced_rhs))); | | |
| 1333 | child_scope->node->data.block.statements.append(assign_statement); | 1358 | child_scope->node->data.block.statements.append(assign_statement); |
| 1334 | | 1359 | |
| 1335 | if (result_used == ResultUsedYes) { | 1360 | if (result_used == ResultUsedYes) { |
| ... | @@ -1474,7 +1499,8 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im | ... | @@ -1474,7 +1499,8 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im |
| 1474 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); | 1499 | AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); |
| 1475 | if (target_node == nullptr) | 1500 | if (target_node == nullptr) |
| 1476 | return nullptr; | 1501 | return nullptr; |
| 1477 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node); | 1502 | return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), |
| | 1503 | stmt->getSubExpr()->getType(), target_node); |
| 1478 | } | 1504 | } |
| 1479 | case CK_FunctionToPointerDecay: | 1505 | case CK_FunctionToPointerDecay: |
| 1480 | case CK_ArrayToPointerDecay: | 1506 | case CK_ArrayToPointerDecay: |
| ... | @@ -2177,9 +2203,23 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2177,9 +2203,23 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2177 | if (callee_raw_node == nullptr) | 2203 | if (callee_raw_node == nullptr) |
| 2178 | return nullptr; | 2204 | return nullptr; |
| 2179 | | 2205 | |
| 2180 | AstNode *callee_node; | 2206 | AstNode *callee_node = nullptr; |
| 2181 | if (qual_type_is_fn_ptr(c, stmt->getCallee()->getType())) { | 2207 | if (qual_type_is_fn_ptr(c, stmt->getCallee()->getType())) { |
| 2182 | callee_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, callee_raw_node); | 2208 | if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) { |
| | 2209 | const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee()); |
| | 2210 | if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) { |
| | 2211 | if (implicit_cast->getSubExpr()->getStmtClass() == Stmt::DeclRefExprClass) { |
| | 2212 | const DeclRefExpr *decl_ref = static_cast<const DeclRefExpr *>(implicit_cast->getSubExpr()); |
| | 2213 | const Decl *decl = decl_ref->getFoundDecl(); |
| | 2214 | if (decl->getKind() == Decl::Function) { |
| | 2215 | callee_node = callee_raw_node; |
| | 2216 | } |
| | 2217 | } |
| | 2218 | } |
| | 2219 | } |
| | 2220 | if (callee_node == nullptr) { |
| | 2221 | callee_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, callee_raw_node); |
| | 2222 | } |
| 2183 | } else { | 2223 | } else { |
| 2184 | callee_node = callee_raw_node; | 2224 | callee_node = callee_raw_node; |
| 2185 | } | 2225 | } |
| ... | @@ -2237,7 +2277,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran | ... | @@ -2237,7 +2277,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran |
| 2237 | if (sub_expr_node == nullptr) | 2277 | if (sub_expr_node == nullptr) |
| 2238 | return nullptr; | 2278 | return nullptr; |
| 2239 | | 2279 | |
| 2240 | return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), sub_expr_node); | 2280 | return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), stmt->getSubExpr()->getType(), sub_expr_node); |
| 2241 | } | 2281 | } |
| 2242 | | 2282 | |
| 2243 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, | 2283 | static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, |