| ... | ... | @@ -350,6 +350,21 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, |
| 350 | 350 | return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr); |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | static bool qual_type_is_fn_ptr(Context *c, const QualType &qt) { |
| 354 | const Type *ty = qt.getTypePtr(); |
| 355 | if (ty->getTypeClass() != Type::Pointer) { |
| 356 | return false; |
| 357 | } |
| 358 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); |
| 359 | QualType child_qt = pointer_ty->getPointeeType(); |
| 360 | const Type *child_ty = child_qt.getTypePtr(); |
| 361 | if (child_ty->getTypeClass() != Type::Paren) { |
| 362 | return false; |
| 363 | } |
| 364 | const ParenType *paren_ty = static_cast<const ParenType *>(child_ty); |
| 365 | return paren_ty->getInnerType().getTypePtr()->getTypeClass() == Type::FunctionProto; |
| 366 | } |
| 367 | |
| 353 | 368 | static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) { |
| 354 | 369 | const Type *ty = qt.getTypePtr(); |
| 355 | 370 | switch (ty->getTypeClass()) { |
| ... | ... | @@ -1575,8 +1590,14 @@ static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *bloc |
| 1575 | 1590 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_AddrOf"); |
| 1576 | 1591 | return nullptr; |
| 1577 | 1592 | case UO_Deref: |
| 1578 | | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Deref"); |
| 1579 | | return nullptr; |
| 1593 | { |
| 1594 | bool is_fn_ptr = qual_type_is_fn_ptr(c, stmt->getSubExpr()->getType()); |
| 1595 | AstNode *value_node = trans_expr(c, result_used, block, stmt->getSubExpr(), TransRValue); |
| 1596 | if (is_fn_ptr) |
| 1597 | return value_node; |
| 1598 | AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node); |
| 1599 | return trans_create_node_prefix_op(c, PrefixOpDereference, unwrapped); |
| 1600 | } |
| 1580 | 1601 | case UO_Plus: |
| 1581 | 1602 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus"); |
| 1582 | 1603 | return nullptr; |
| ... | ... | @@ -1919,10 +1940,20 @@ static AstNode *trans_if_statement(Context *c, AstNode *block, IfStmt *stmt) { |
| 1919 | 1940 | |
| 1920 | 1941 | static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, CallExpr *stmt) { |
| 1921 | 1942 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); |
| 1922 | | node->data.fn_call_expr.fn_ref_expr = trans_expr(c, true, block, stmt->getCallee(), TransRValue); |
| 1923 | | if (node->data.fn_call_expr.fn_ref_expr == nullptr) |
| 1943 | |
| 1944 | AstNode *callee_raw_node = trans_expr(c, true, block, stmt->getCallee(), TransRValue); |
| 1945 | if (callee_raw_node == nullptr) |
| 1924 | 1946 | return nullptr; |
| 1925 | 1947 | |
| 1948 | AstNode *callee_node; |
| 1949 | if (qual_type_is_fn_ptr(c, stmt->getCallee()->getType())) { |
| 1950 | callee_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, callee_raw_node); |
| 1951 | } else { |
| 1952 | callee_node = callee_raw_node; |
| 1953 | } |
| 1954 | |
| 1955 | node->data.fn_call_expr.fn_ref_expr = callee_node; |
| 1956 | |
| 1926 | 1957 | unsigned num_args = stmt->getNumArgs(); |
| 1927 | 1958 | Expr **args = stmt->getArgs(); |
| 1928 | 1959 | for (unsigned i = 0; i < num_args; i += 1) { |