@@ -1499,38 +1499,72 @@ static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue
1499
1499
return trans_create_node_symbol (c, symbol_name);
1500
1500
}
1501
1501
1502
+ static AstNode *trans_create_post_crement (Context *c, bool result_used, AstNode *block, UnaryOperator *stmt, BinOpType assign_op) {
1503
+ Expr *op_expr = stmt->getSubExpr ();
1504
+
1505
+ if (!result_used) {
1506
+ // common case
1507
+ // c: expr++
1508
+ // zig: expr += 1
1509
+ return trans_create_node_bin_op (c,
1510
+ trans_expr (c, true , block, op_expr, TransLValue),
1511
+ assign_op,
1512
+ trans_create_node_unsigned (c, 1 ));
1513
+ } else {
1514
+ // worst case
1515
+ // c: expr++
1516
+ // zig: {
1517
+ // zig: const _ref = &expr;
1518
+ // zig: const _tmp = *_ref;
1519
+ // zig: *_ref += 1;
1520
+ // zig: _tmp
1521
+ // zig: }
1522
+ AstNode *child_block = trans_create_node (c, NodeTypeBlock);
1523
+
1524
+ // const _ref = &expr;
1525
+ AstNode *expr = trans_expr (c, true , child_block, op_expr, TransLValue);
1526
+ if (expr == nullptr ) return nullptr ;
1527
+ AstNode *addr_of_expr = trans_create_node_addr_of (c, false , false , expr);
1528
+ // TODO: avoid name collisions with generated variable names
1529
+ Buf* ref_var_name = buf_create_from_str (" _ref" );
1530
+ AstNode *ref_var_decl = trans_create_node_var_decl_local (c, true , ref_var_name, nullptr , addr_of_expr);
1531
+ child_block->data .block .statements .append (ref_var_decl);
1532
+
1533
+ // const _tmp = *_ref;
1534
+ Buf* tmp_var_name = buf_create_from_str (" _tmp" );
1535
+ AstNode *tmp_var_decl = trans_create_node_var_decl_local (c, true , tmp_var_name, nullptr ,
1536
+ trans_create_node_prefix_op (c, PrefixOpDereference,
1537
+ trans_create_node_symbol (c, ref_var_name)));
1538
+ child_block->data .block .statements .append (tmp_var_decl);
1539
+
1540
+ // *_ref += 1;
1541
+ AstNode *assign_statement = trans_create_node_bin_op (c,
1542
+ trans_create_node_prefix_op (c, PrefixOpDereference,
1543
+ trans_create_node_symbol (c, ref_var_name)),
1544
+ assign_op,
1545
+ trans_create_node_unsigned (c, 1 ));
1546
+ child_block->data .block .statements .append (assign_statement);
1547
+
1548
+ // _tmp
1549
+ child_block->data .block .statements .append (trans_create_node_symbol (c, tmp_var_name));
1550
+ child_block->data .block .last_statement_is_result_expression = true ;
1551
+
1552
+ return child_block;
1553
+ }
1554
+ }
1555
+
1502
1556
static AstNode *trans_unary_operator (Context *c, bool result_used, AstNode *block, UnaryOperator *stmt) {
1503
1557
switch (stmt->getOpcode ()) {
1504
- case UO_PostInc: {
1505
- Expr *op_expr = stmt->getSubExpr ();
1506
- BinOpType bin_op = qual_type_has_wrapping_overflow (c, op_expr->getType ())
1507
- ? BinOpTypeAssignPlusWrap
1508
- : BinOpTypeAssignPlus;
1509
-
1510
- if (!result_used) {
1511
- // common case
1512
- // c: expr++
1513
- // zig: expr += 1
1514
- return trans_create_node_bin_op (c,
1515
- trans_expr (c, true , block, op_expr, TransLValue),
1516
- bin_op,
1517
- trans_create_node_unsigned (c, 1 ));
1518
- } else {
1519
- // worst case
1520
- // c: expr++
1521
- // zig: {
1522
- // zig: const _ref = &expr;
1523
- // zig: const _tmp = *_ref;
1524
- // zig: *_ref += 1;
1525
- // zig: _tmp
1526
- // zig: }
1527
- emit_warning (c, stmt->getLocStart (), " TODO handle C translation UO_PostInc with result_used" );
1528
- return nullptr ;
1529
- }
1530
- }
1558
+ case UO_PostInc:
1559
+ if (qual_type_has_wrapping_overflow (c, stmt->getType ()))
1560
+ return trans_create_post_crement (c, result_used, block, stmt, BinOpTypeAssignPlusWrap);
1561
+ else
1562
+ return trans_create_post_crement (c, result_used, block, stmt, BinOpTypeAssignPlus);
1531
1563
case UO_PostDec:
1532
- emit_warning (c, stmt->getLocStart (), " TODO handle C translation UO_PostDec" );
1533
- return nullptr ;
1564
+ if (qual_type_has_wrapping_overflow (c, stmt->getType ()))
1565
+ return trans_create_post_crement (c, result_used, block, stmt, BinOpTypeAssignMinusWrap);
1566
+ else
1567
+ return trans_create_post_crement (c, result_used, block, stmt, BinOpTypeAssignMinus);
1534
1568
case UO_PreInc:
1535
1569
emit_warning (c, stmt->getLocStart (), " TODO handle C translation UO_PreInc" );
1536
1570
return nullptr ;
0 commit comments