Commit 6664679c8c

Veikka Tuominen <git@vexu.eu>
2021-06-13 09:56:54
translate-c: don't bother with unwrapping pointers
Dereferencing a c pointer implicitly includes an unwrap, manually adding it just causes bugs.
1 parent 540b529
Changed files (4)
src/translate_c/ast.zig
@@ -2294,7 +2294,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
         .single_pointer,
         .unwrap,
         .deref,
-        .address_of,
         .not,
         .negate,
         .negate_wrap,
@@ -2349,6 +2348,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
         .container_init,
         .container_init_dot,
         .block,
+        .address_of,
         => return c.addNode(.{
             .tag = .grouped_expression,
             .main_token = try c.addToken(.l_paren, "("),
src/translate_c.zig
@@ -1438,7 +1438,7 @@ fn transSimpleOffsetOfExpr(
             }
         }
     }
-    return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "Failed to translate simple OffsetOfExpr", .{});
+    return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "failed to translate simple OffsetOfExpr", .{});
 }
 
 fn transOffsetOfExpr(
@@ -2619,7 +2619,7 @@ fn transInitListExpr(
     const source_loc = @ptrCast(*const clang.Expr, expr).getBeginLoc();
 
     if (qualTypeWasDemotedToOpaque(c, qt)) {
-        return fail(c, error.UnsupportedTranslation, source_loc, "Cannot initialize opaque type", .{});
+        return fail(c, error.UnsupportedTranslation, source_loc, "cannot initialize opaque type", .{});
     }
 
     if (qual_type.isRecordType()) {
@@ -3408,7 +3408,7 @@ fn transUnaryExprOrTypeTraitExpr(
             c,
             error.UnsupportedTranslation,
             loc,
-            "Unsupported type trait kind {}",
+            "unsupported type trait kind {}",
             .{kind},
         ),
     }
@@ -3450,13 +3450,15 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
             return Tag.address_of.create(c.arena, try transExpr(c, scope, op_expr, used));
         },
         .Deref => {
+            if (qualTypeWasDemotedToOpaque(c, stmt.getType()))
+                return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "cannot dereference opaque type", .{});
+
             const node = try transExpr(c, scope, op_expr, used);
             var is_ptr = false;
             const fn_ty = qualTypeGetFnProto(op_expr.getType(), &is_ptr);
             if (fn_ty != null and is_ptr)
                 return node;
-            const unwrapped = try Tag.unwrap.create(c.arena, node);
-            return Tag.deref.create(c.arena, unwrapped);
+            return Tag.deref.create(c.arena, node);
         },
         .Plus => return transExpr(c, scope, op_expr, used),
         .Minus => {
test/run_translated_c.zig
@@ -3,6 +3,16 @@ const tests = @import("tests.zig");
 const nl = std.cstr.line_sep;
 
 pub fn addCases(cases: *tests.RunTranslatedCContext) void {
+    cases.add("dereference address of",
+        \\#include <stdlib.h>
+        \\int main(void) {
+        \\    int i = 0;
+        \\    *&i = 42;
+        \\    if (i != 42) abort();
+        \\	  return 0;
+        \\}
+    , "");
+
     cases.add("division of floating literals",
         \\#define _NO_CRT_STDIO_INLINE 1
         \\#include <stdio.h>
test/translate_c.zig
@@ -1515,7 +1515,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
     , &[_][]const u8{
         \\pub export fn foo() void {
         \\    var x: [*c]c_int = undefined;
-        \\    x.?.* = 1;
+        \\    x.* = 1;
         \\}
     });
 
@@ -1529,7 +1529,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\pub export fn foo() c_int {
         \\    var x: c_int = 1234;
         \\    var ptr: [*c]c_int = &x;
-        \\    return ptr.?.*;
+        \\    return ptr.*;
         \\}
     });
 
@@ -3243,7 +3243,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\            const tmp_2 = ref.*;
         \\            ref.* += 1;
         \\            break :blk_1 tmp_2;
-        \\        }).?.* = tmp;
+        \\        }).* = tmp;
         \\        break :blk tmp;
         \\    };
         \\}
@@ -3583,12 +3583,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    struct my_struct S = {.a = 1, .b = 2};
         \\}
     , &[_][]const u8{
-        \\warning: Cannot initialize opaque type
+        \\warning: cannot initialize opaque type
         ,
         \\warning: unable to translate function, demoted to extern
         \\pub extern fn initialize() void;
     });
 
+    cases.add("Demote function that dereferences opaque type",
+        \\struct my_struct {
+        \\    unsigned a: 1;
+        \\};
+        \\void deref(struct my_struct *s) {
+        \\    *s;
+        \\}
+    , &[_][]const u8{
+        \\warning: cannot dereference opaque type
+        ,
+        \\warning: unable to translate function, demoted to extern
+        \\pub extern fn deref(arg_s: ?*struct_my_struct) void;
+    });
+
     cases.add("Function prototype declared within function",
         \\int foo(void) {
         \\    extern int bar(int, int);