Commit e65b9e8f7b

Vexu <git@vexu.eu>
2019-12-18 20:20:38
translate-c-2 stmt expr
1 parent 62bfff5
Changed files (3)
src-self-hosted/clang.zig
@@ -79,6 +79,7 @@ pub const ZigClangPreprocessingRecord = @OpaqueType();
 pub const ZigClangFloatingLiteral = @OpaqueType();
 pub const ZigClangConstantExpr = @OpaqueType();
 pub const ZigClangCharacterLiteral = @OpaqueType();
+pub const ZigClangStmtExpr = @OpaqueType();
 
 pub const ZigClangBO = extern enum {
     PtrMemD,
@@ -1095,3 +1096,5 @@ pub extern fn ZigClangCharacterLiteral_getBeginLoc(*const ZigClangCharacterLiter
 pub extern fn ZigClangCharacterLiteral_getKind(*const ZigClangCharacterLiteral) ZigClangCharacterLiteral_CharacterKind;
 pub extern fn ZigClangCharacterLiteral_getValue(*const ZigClangCharacterLiteral) c_uint;
 
+pub extern fn ZigClangStmtExpr_getSubStmt( *const ZigClangStmtExpr) *const ZigClangCompoundStmt;
+
src-self-hosted/translate_c.zig
@@ -855,6 +855,7 @@ fn transStmt(
         .ConstantExprClass => return transConstantExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
         .PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const ZigClangPredefinedExpr, stmt), result_used),
         .CharacterLiteralClass => return transCharLiteral(rp, scope, @ptrCast(*const ZigClangCharacterLiteral, stmt), result_used),
+        .StmtExprClass => return transStmtExpr(rp, scope, @ptrCast(*const ZigClangStmtExpr, stmt), result_used),
         else => {
             return revertAndWarn(
                 rp,
@@ -1165,12 +1166,9 @@ fn transImplicitCastExpr(
             const src_type = getExprQualType(c, sub_expr);
             return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node);
         },
-        .FunctionToPointerDecay, .ArrayToPointerDecay => {
+        .LValueToRValue, .NoOp, .FunctionToPointerDecay, .ArrayToPointerDecay => {
             return maybeSuppressResult(rp, scope, result_used, sub_expr_node);
         },
-        .LValueToRValue, .NoOp => {
-            return transExpr(rp, scope, sub_expr, .used, .r_value);
-        },
         .NullToPointer => {
             return try transCreateNodeNullLiteral(rp.c);
         },
@@ -1960,6 +1958,38 @@ fn transCharLiteral(
     }
 }
 
+fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr, used: ResultUsed) TransError!*ast.Node {
+    const comp = ZigClangStmtExpr_getSubStmt(stmt);
+    if (used == .unused) {
+        return transCompoundStmt(rp, scope, comp);
+    }
+    const lparen = try appendToken(rp.c, .LParen, "(");
+    const block_scope = try Scope.Block.init(rp.c, scope, "blk");
+    const block = try transCreateNodeBlock(rp.c, "blk");
+    block_scope.block_node = block;
+
+    var it = ZigClangCompoundStmt_body_begin(comp);
+    const end_it = ZigClangCompoundStmt_body_end(comp);
+    while (it != end_it - 1) : (it += 1) {
+        const result = try transStmt(rp, &block_scope.base, it[0], .unused, .r_value);
+        if (result != &block.base)
+            try block.statements.push(result);
+    }
+    const break_node = try transCreateNodeBreak(rp.c, "blk");
+    break_node.rhs = try transStmt(rp, &block_scope.base, it[0], .used, .r_value);
+    _ = try appendToken(rp.c, .Semicolon, ";");
+    try block.statements.push(&break_node.base);
+    block.rbrace = try appendToken(rp.c, .RBrace, "}");
+    const rparen = try appendToken(rp.c, .RParen, ")");
+    const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
+    grouped_expr.* = .{
+        .lparen = lparen,
+        .expr = &block.base,
+        .rparen = rparen,
+    };
+    return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
+}
+
 fn transCPtrCast(
     rp: RestorePoint,
     loc: ZigClangSourceLocation,
test/translate_c.zig
@@ -1476,6 +1476,24 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     });
 
+    cases.add_2("statement expression",
+        \\int foo(void) {
+        \\    return ({
+        \\        int a = 1;
+        \\        a;
+        \\        a;
+        \\    });
+        \\}
+    , &[_][]const u8{
+        \\pub export fn foo() c_int {
+        \\    return (blk: {
+        \\        var a: c_int = 1;
+        \\        _ = a;
+        \\        break :blk a;
+        \\    });
+        \\}
+    });
+
     /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
 
     cases.addAllowWarnings("simple data types",
@@ -1723,22 +1741,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     });
 
-    cases.addC("statement expression",
-        \\int foo(void) {
-        \\    return ({
-        \\        int a = 1;
-        \\        a;
-        \\    });
-        \\}
-    , &[_][]const u8{
-        \\pub export fn foo() c_int {
-        \\    return x: {
-        \\        var a: c_int = 1;
-        \\        break :x a;
-        \\    };
-        \\}
-    });
-
     cases.addC("__extension__ cast",
         \\int foo(void) {
         \\    return __extension__ 1;
@@ -2609,4 +2611,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    return (a & b) ^ (a | b);
         \\}
     });
+
+    cases.addC("statement expression",
+        \\int foo(void) {
+        \\    return ({
+        \\        int a = 1;
+        \\        a;
+        \\    });
+        \\}
+    , &[_][]const u8{
+        \\pub export fn foo() c_int {
+        \\    return x: {
+        \\        var a: c_int = 1;
+        \\        break :x a;
+        \\    };
+        \\}
+    });
 }