Commit 5b34697b21

LemonBoy <thatlemon@gmail.com>
2020-01-08 10:19:04
Cast integer literals to their specified type
1 parent fd7e69a
Changed files (3)
src-self-hosted/translate_c.zig
@@ -2419,7 +2419,29 @@ fn transConstantExpr(rp: RestorePoint, scope: *Scope, expr: *const ZigClangExpr,
     var result: ZigClangExprEvalResult = undefined;
     if (!ZigClangExpr_EvaluateAsConstantExpr(expr, &result, .EvaluateForCodeGen, rp.c.clang_context))
         return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangExpr_getBeginLoc(expr), "invalid constant expression", .{});
-    return maybeSuppressResult(rp, scope, used, try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&result.Val)));
+
+    var val_node: ?*ast.Node = null;
+    switch (ZigClangAPValue_getKind(&result.Val)) {
+        .Int => {
+            // See comment in `transIntegerLiteral` for why this code is here.
+            // @as(T, x)
+            const expr_base = @ptrCast(*const ZigClangExpr, expr);
+            const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
+            const ty_node = try transQualType(rp, ZigClangExpr_getType(expr_base), ZigClangExpr_getBeginLoc(expr_base));
+            try as_node.params.push(ty_node);
+            _ = try appendToken(rp.c, .Comma, ",");
+
+            const int_lit_node = try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&result.Val));
+            try as_node.params.push(int_lit_node);
+
+            as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+
+            return maybeSuppressResult(rp, scope, used, &as_node.base);
+        },
+        else => {
+            return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangExpr_getBeginLoc(expr), "unsupported constant expression kind", .{});
+        },
+    }
 }
 
 fn transPredefinedExpr(rp: RestorePoint, scope: *Scope, expr: *const ZigClangPredefinedExpr, used: ResultUsed) TransError!*ast.Node {
test/run_translated_c.zig
@@ -20,6 +20,25 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
         \\}
     , "");
 
+    cases.add("switch case",
+        \\#include <stdlib.h>
+        \\int lottery(unsigned int x) {
+        \\    switch (x) {
+        \\        case 3: return 0;
+        \\        case -1: return 3;
+        \\        case 8 ... 10: return x;
+        \\        default: return -1;
+        \\    }
+        \\}
+        \\int main(int argc, char **argv) {
+        \\    if (lottery(2) != -1) abort();
+        \\    if (lottery(3) != 0) abort();
+        \\    if (lottery(-1) != 3) abort();
+        \\    if (lottery(9) != 9) abort();
+        \\    return 0;
+        \\}
+    , "");
+
     cases.add("boolean values and expressions",
         \\#include <stdlib.h>
         \\static const _Bool false_val = 0;
test/translate_c.zig
@@ -1468,10 +1468,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\                __case_1: {
         \\                    __case_0: {
         \\                        switch (i) {
-        \\                            0 => break :__case_0,
-        \\                            1...3 => break :__case_1,
+        \\                            @as(c_int, 0) => break :__case_0,
+        \\                            @as(c_int, 1)...@as(c_int, 3) => break :__case_1,
         \\                            else => break :__default,
-        \\                            4 => break :__case_2,
+        \\                            @as(c_int, 4) => break :__case_2,
         \\                        }
         \\                    }
         \\                    res = 1;