aboutsummaryrefslogtreecommitdiff
path: root/src/translate_c.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/translate_c.cpp')
-rw-r--r--src/translate_c.cpp40
1 files changed, 31 insertions, 9 deletions
diff --git a/src/translate_c.cpp b/src/translate_c.cpp
index 2a0a31af16..c6a25271b8 100644
--- a/src/translate_c.cpp
+++ b/src/translate_c.cpp
@@ -500,15 +500,31 @@ static bool qual_type_is_ptr(QualType qt) {
return ty->getTypeClass() == Type::Pointer;
}
-static bool qual_type_is_fn_ptr(Context *c, QualType qt) {
+static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) {
const Type *ty = qual_type_canon(qt);
- if (ty->getTypeClass() != Type::Pointer) {
- return false;
+ *is_ptr = false;
+
+ if (ty->getTypeClass() == Type::Pointer) {
+ *is_ptr = true;
+ const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
+ QualType child_qt = pointer_ty->getPointeeType();
+ ty = child_qt.getTypePtr();
+ }
+
+ if (ty->getTypeClass() == Type::FunctionProto) {
+ return static_cast<const FunctionProtoType*>(ty);
}
- const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
- QualType child_qt = pointer_ty->getPointeeType();
- const Type *child_ty = child_qt.getTypePtr();
- return child_ty->getTypeClass() == Type::FunctionProto;
+
+ return nullptr;
+}
+
+static bool qual_type_is_fn_ptr(QualType qt) {
+ bool is_ptr;
+ if (qual_type_get_fn_proto(qt, &is_ptr)) {
+ return is_ptr;
+ }
+
+ return false;
}
static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {
@@ -1871,7 +1887,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);
if (value_node == nullptr)
return nullptr;
- bool is_fn_ptr = qual_type_is_fn_ptr(c, stmt->getSubExpr()->getType());
+ bool is_fn_ptr = qual_type_is_fn_ptr(stmt->getSubExpr()->getType());
if (is_fn_ptr)
return value_node;
AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node);
@@ -2327,8 +2343,10 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
if (callee_raw_node == nullptr)
return nullptr;
+ bool is_ptr = false;
+ const FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr);
AstNode *callee_node = nullptr;
- if (qual_type_is_fn_ptr(c, stmt->getCallee()->getType())) {
+ if (is_ptr && fn_ty) {
if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) {
const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee());
if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) {
@@ -2360,6 +2378,10 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
node->data.fn_call_expr.params.append(arg_node);
}
+ if (result_used == ResultUsedNo && fn_ty && !qual_type_canon(fn_ty->getReturnType())->isVoidType()) {
+ node = trans_create_node_bin_op(c, trans_create_node_symbol_str(c, "_"), BinOpTypeAssign, node);
+ }
+
return node;
}