translate expr++ from c to zig
parent
a5e4e205c8
commit
c10b052cee
|
@ -386,8 +386,17 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static QualType resolve_any_typedef(Context *c, QualType qt) {
|
||||
const Type * ty = qt.getTypePtr();
|
||||
if (ty->getTypeClass() != Type::Typedef)
|
||||
return qt;
|
||||
const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
|
||||
const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
|
||||
return typedef_decl->getUnderlyingType();
|
||||
}
|
||||
|
||||
static bool c_is_signed_integer(Context *c, QualType qt) {
|
||||
const Type *c_type = qt.getTypePtr();
|
||||
const Type *c_type = resolve_any_typedef(c, qt).getTypePtr();
|
||||
if (c_type->getTypeClass() != Type::Builtin)
|
||||
return false;
|
||||
const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
|
||||
|
@ -406,7 +415,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) {
|
|||
}
|
||||
|
||||
static bool c_is_unsigned_integer(Context *c, QualType qt) {
|
||||
const Type *c_type = qt.getTypePtr();
|
||||
const Type *c_type = resolve_any_typedef(c, qt).getTypePtr();
|
||||
if (c_type->getTypeClass() != Type::Builtin)
|
||||
return false;
|
||||
const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
|
||||
|
@ -443,6 +452,16 @@ static bool c_is_float(Context *c, QualType qt) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
|
||||
if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
|
||||
// float and signed integer overflow is undefined behavior.
|
||||
return false;
|
||||
} else {
|
||||
// unsigned integer overflow wraps around.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
enum TransLRValue {
|
||||
TransLValue,
|
||||
TransRValue,
|
||||
|
@ -1286,11 +1305,35 @@ static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue
|
|||
return trans_create_node_symbol(c, symbol_name);
|
||||
}
|
||||
|
||||
static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *stmt) {
|
||||
static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt) {
|
||||
switch (stmt->getOpcode()) {
|
||||
case UO_PostInc:
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostInc");
|
||||
return nullptr;
|
||||
case UO_PostInc: {
|
||||
Expr *op_expr = stmt->getSubExpr();
|
||||
BinOpType bin_op = qual_type_has_wrapping_overflow(c, op_expr->getType())
|
||||
? BinOpTypeAssignPlusWrap
|
||||
: BinOpTypeAssignPlus;
|
||||
|
||||
if (!result_used) {
|
||||
// common case
|
||||
// c: expr++
|
||||
// zig: expr += 1
|
||||
return trans_create_node_bin_op(c,
|
||||
trans_expr(c, true, block, op_expr, TransLValue),
|
||||
bin_op,
|
||||
trans_create_node_unsigned(c, 1));
|
||||
} else {
|
||||
// worst case
|
||||
// c: expr++
|
||||
// zig: {
|
||||
// zig: const _ref = &expr;
|
||||
// zig: const _tmp = *_ref;
|
||||
// zig: *_ref += 1;
|
||||
// zig: _tmp
|
||||
// zig: }
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostInc with result_used");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
case UO_PostDec:
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostDec");
|
||||
return nullptr;
|
||||
|
@ -1312,7 +1355,7 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *
|
|||
case UO_Minus:
|
||||
{
|
||||
Expr *op_expr = stmt->getSubExpr();
|
||||
if (c_is_signed_integer(c, op_expr->getType()) || c_is_float(c, op_expr->getType())) {
|
||||
if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
|
||||
AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
|
||||
node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
|
||||
|
||||
|
@ -1642,7 +1685,7 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s
|
|||
case Stmt::DeclRefExprClass:
|
||||
return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue);
|
||||
case Stmt::UnaryOperatorClass:
|
||||
return trans_unary_operator(c, block, (UnaryOperator *)stmt);
|
||||
return trans_unary_operator(c, result_used, block, (UnaryOperator *)stmt);
|
||||
case Stmt::DeclStmtClass:
|
||||
return trans_local_declaration(c, block, (DeclStmt *)stmt);
|
||||
case Stmt::WhileStmtClass:
|
||||
|
|
Loading…
Reference in New Issue