Commit 0833c8d06b

Vexu <git@vexu.eu>
2020-09-10 11:58:12
translate-c: support sizeof and _Alignof in macros
Closes #6301
1 parent 78baa16
Changed files (3)
src-self-hosted/translate_c.zig
@@ -5899,6 +5899,10 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
                     saw_l_paren = true;
                     _ = m.next();
                 },
+                // (type)sizeof(x)
+                .Keyword_sizeof,
+                // (type)alignof(x)
+                .Keyword_alignof,
                 // (type)identifier
                 .Identifier => {},
                 // (type)integer
@@ -6309,6 +6313,40 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.
             node.rhs = try parseCPrefixOpExpr(c, m, scope);
             return &node.base;
         },
+        .Keyword_sizeof => {
+            const inner = if (m.peek().? == .LParen) blk: {
+                _ = m.next();
+                const inner = try parseCExpr(c, m, scope);
+                if (m.next().? != .RParen) {
+                    try m.fail(c, "unable to translate C expr: expected ')'", .{});
+                    return error.ParseError;
+                }
+                break :blk inner;
+            } else try parseCPrefixOpExpr(c, m, scope);
+
+            const builtin_call = try c.createBuiltinCall("@sizeOf", 1);
+            builtin_call.params()[0] = inner;
+            builtin_call.rparen_token = try appendToken(c, .RParen, ")");
+            return &builtin_call.base;
+        },
+        .Keyword_alignof => {
+            // TODO this won't work if using <stdalign.h>'s
+            // #define alignof _Alignof
+            if (m.next().? != .LParen) {
+                try m.fail(c, "unable to translate C expr: expected '('", .{});
+                return error.ParseError;
+            }
+            const inner = try parseCExpr(c, m, scope);
+            if (m.next().? != .RParen) {
+                try m.fail(c, "unable to translate C expr: expected ')'", .{});
+                return error.ParseError;
+            }
+
+            const builtin_call = try c.createBuiltinCall("@alignOf", 1);
+            builtin_call.params()[0] = inner;
+            builtin_call.rparen_token = try appendToken(c, .RParen, ")");
+            return &builtin_call.base;
+        },
         else => {
             m.i -= 1;
             return try parseCSuffixOpExpr(c, m, scope);
test/stage1/behavior/translate_c_macros.h
@@ -6,4 +6,7 @@ typedef struct Color {
     unsigned char a;
 } Color;
 #define CLITERAL(type)      (type)
-#define LIGHTGRAY  CLITERAL(Color){ 200, 200, 200, 255 }   // Light Gray
\ No newline at end of file
+#define LIGHTGRAY  CLITERAL(Color){ 200, 200, 200, 255 }   // Light Gray
+
+#define MY_SIZEOF(x) ((int)sizeof(x))
+#define MY_SIZEOF2(x) ((int)sizeof x)
test/stage1/behavior/translate_c_macros.zig
@@ -1,12 +1,18 @@
 const expect = @import("std").testing.expect;
+const expectEqual = @import("std").testing.expectEqual;
 
 const h = @cImport(@cInclude("stage1/behavior/translate_c_macros.h"));
 
 test "initializer list expression" {
-    @import("std").testing.expectEqual(h.Color{
+    expectEqual(h.Color{
         .r = 200,
         .g = 200,
         .b = 200,
         .a = 255,
     }, h.LIGHTGRAY);
 }
+
+test "sizeof in macros" {
+    expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
+    expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
+}